1 /* $OpenBSD: memprobe.c,v 1.2 2021/01/28 18:54:50 deraadt Exp $ */ 2 3 /* 4 * Copyright (c) 1997-1999 Michael Shalayeff 5 * Copyright (c) 1997-1999 Tobias Weingartner 6 * All rights reserved. 7 * 8 * Redistribution and use in source and binary forms, with or without 9 * modification, are permitted provided that the following conditions 10 * are met: 11 * 1. Redistributions of source code must retain the above copyright 12 * notice, this list of conditions and the following disclaimer. 13 * 2. Redistributions in binary form must reproduce the above copyright 14 * notice, this list of conditions and the following disclaimer in the 15 * documentation and/or other materials provided with the distribution. 16 * 17 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 18 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 19 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 20 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 21 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 22 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 23 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 24 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 25 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 26 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 27 * SUCH DAMAGE. 28 * 29 */ 30 31 #include <sys/param.h> 32 #include <machine/biosvar.h> 33 #include <dev/isa/isareg.h> 34 #include <stand/boot/bootarg.h> 35 #include "libsa.h" 36 37 u_int cnvmem, extmem; /* XXX - compatibility */ 38 39 extern bios_memmap_t bios_memmap[64]; /* This is easier */ 40 41 void 42 dump_biosmem(bios_memmap_t *tm) 43 { 44 register bios_memmap_t *p; 45 register u_int total = 0; 46 47 if (tm == NULL) 48 tm = bios_memmap; 49 50 for (p = tm; p->type != BIOS_MAP_END; p++) { 51 printf("Region %ld: type %u at 0x%llx for %uKB\n", 52 (long)(p - tm), p->type, p->addr, 53 (u_int)(p->size / 1024)); 54 55 if (p->type == BIOS_MAP_FREE) 56 total += p->size / 1024; 57 } 58 59 printf("Low ram: %dKB High ram: %dKB\n", cnvmem, extmem); 60 printf("Total free memory: %uKB\n", total); 61 } 62 63 int 64 mem_limit(long long ml) 65 { 66 register bios_memmap_t *p; 67 68 for (p = bios_memmap; p->type != BIOS_MAP_END; p++) { 69 register int64_t sp = p->addr, ep = p->addr + p->size; 70 71 if (p->type != BIOS_MAP_FREE) 72 continue; 73 74 /* Wholly above limit, nuke it */ 75 if ((sp >= ml) && (ep >= ml)) { 76 bcopy (p + 1, p, (char *)bios_memmap + 77 sizeof(bios_memmap) - (char *)p); 78 } else if ((sp < ml) && (ep >= ml)) { 79 p->size -= (ep - ml); 80 } 81 } 82 return 0; 83 } 84 85 int 86 mem_delete(long long sa, long long ea) 87 { 88 register bios_memmap_t *p; 89 90 for (p = bios_memmap; p->type != BIOS_MAP_END; p++) { 91 if (p->type == BIOS_MAP_FREE) { 92 register int64_t sp = p->addr, ep = p->addr + p->size; 93 94 /* can we eat it as a whole? */ 95 if ((sa - sp) <= PAGE_SIZE && (ep - ea) <= PAGE_SIZE) { 96 bcopy(p + 1, p, (char *)bios_memmap + 97 sizeof(bios_memmap) - (char *)p); 98 break; 99 /* eat head or legs */ 100 } else if (sa <= sp && sp < ea) { 101 p->addr = ea; 102 p->size = ep - ea; 103 break; 104 } else if (sa < ep && ep <= ea) { 105 p->size = sa - sp; 106 break; 107 } else if (sp < sa && ea < ep) { 108 /* bite in half */ 109 bcopy(p, p + 1, (char *)bios_memmap + 110 sizeof(bios_memmap) - (char *)p - 111 sizeof(bios_memmap[0])); 112 p[1].addr = ea; 113 p[1].size = ep - ea; 114 p->size = sa - sp; 115 break; 116 } 117 } 118 } 119 return 0; 120 } 121 122 int 123 mem_add(long long sa, long long ea) 124 { 125 register bios_memmap_t *p; 126 127 for (p = bios_memmap; p->type != BIOS_MAP_END; p++) { 128 if (p->type == BIOS_MAP_FREE) { 129 register int64_t sp = p->addr, ep = p->addr + p->size; 130 131 /* is it already there? */ 132 if (sp <= sa && ea <= ep) { 133 break; 134 /* join head or legs */ 135 } else if (sa < sp && sp <= ea) { 136 p->addr = sa; 137 p->size = ep - sa; 138 break; 139 } else if (sa <= ep && ep < ea) { 140 p->size = ea - sp; 141 break; 142 } else if (ea < sp) { 143 /* insert before */ 144 bcopy(p, p + 1, (char *)bios_memmap + 145 sizeof(bios_memmap) - (char *)(p - 1)); 146 p->addr = sa; 147 p->size = ea - sa; 148 break; 149 } 150 } 151 } 152 153 /* meaning add new item at the end of the list */ 154 if (p->type == BIOS_MAP_END) { 155 p[1] = p[0]; 156 p->type = BIOS_MAP_FREE; 157 p->addr = sa; 158 p->size = ea - sa; 159 } 160 161 return 0; 162 } 163 164 void 165 mem_pass(void) 166 { 167 bios_memmap_t *p; 168 169 for (p = bios_memmap; p->type != BIOS_MAP_END; p++) 170 ; 171 addbootarg(BOOTARG_MEMMAP, (p - bios_memmap + 1) * sizeof *bios_memmap, 172 bios_memmap); 173 } 174