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
dump_biosmem(bios_memmap_t * tm)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
mem_limit(long long ml)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
mem_delete(long long sa,long long ea)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
mem_add(long long sa,long long ea)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
mem_pass(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