This source file includes following definitions.
- checkA20
- bios_E820
- bios_E801
- bios_8800
- bios_int12
- addrprobe
- badprobe
- memprobe
- dump_biosmem
- mem_delete
- mem_add
- mem_pass
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
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;
38
39
40
41
42
43
44 static __inline int
45 checkA20(void)
46 {
47 register char *p = (char *)0x100000;
48 register char *q = (char *)0x000000;
49 int st;
50
51
52 if (*p != *q)
53 return 1;
54
55
56 *p = ~(*p);
57 st = (*p != *q);
58 *p = ~(*p);
59
60 return st;
61 }
62
63
64
65
66
67 static __inline bios_memmap_t *
68 bios_E820(bios_memmap_t *mp)
69 {
70 int rc, off = 0, sig, gotcha = 0;
71
72 do {
73 BIOS_regs.biosr_es = ((u_int)(mp) >> 4);
74
75 __asm __volatile(DOINT(0x15) "; setc %b1"
76 : "=a" (sig), "=d" (rc), "=b" (off)
77 : "0" (0xE820), "1" (0x534d4150), "b" (off),
78 "c" (sizeof(*mp)), "D" (((u_int)mp) & 0xF)
79 : "cc", "memory");
80 off = BIOS_regs.biosr_bx;
81
82 if (rc & 0xff || sig != 0x534d4150)
83 break;
84 gotcha++;
85 if (!mp->type)
86 mp->type = BIOS_MAP_RES;
87 mp++;
88 } while (off);
89
90 if (!gotcha)
91 return NULL;
92 #ifdef DEBUG
93 printf("0x15[E820] ");
94 #endif
95 return mp;
96 }
97
98 #if 0
99
100
101
102
103
104
105
106
107 static __inline bios_memmap_t *
108 bios_E801(bios_memmap_t *mp)
109 {
110 int rc, m1, m2, m3, m4;
111 u_int8_t *info;
112
113
114 info = getSYSCONFaddr();
115 if (!info)
116 return NULL;
117
118 printf("model(%d,%d,%d)", info[2], info[3], info[4]);
119
120
121 info = (void *)0xFFFFB;
122 if (info[0] == '9' && info[1] <= '3')
123 return NULL;
124
125
126 __asm __volatile(DOINT(0x15) "; mov %%ax, %%si; setc %b0"
127 : "=a" (rc), "=S" (m1), "=b" (m2), "=c" (m3), "=d" (m4)
128 : "0" (0xE801));
129
130
131 if (rc & 0xff)
132 return NULL;
133
134
135 if (m1 == 0) {
136 m1 = m3;
137 m2 = m4;
138 }
139 #ifdef DEBUG
140 printf("0x15[E801] ");
141 #endif
142
143 mp->addr = (1024 * 1024);
144 mp->size = (m1 & 0xffff) * 1024;
145 mp->type = BIOS_MAP_FREE;
146
147 mp++;
148 mp->addr = (1024 * 1024) * 16;
149 mp->size = (m2 & 0xffff) * 64L * 1024;
150 mp->type = BIOS_MAP_FREE;
151
152 return ++mp;
153 }
154 #endif
155
156
157
158
159
160
161 static __inline bios_memmap_t *
162 bios_8800(bios_memmap_t *mp)
163 {
164 int rc, mem;
165
166 __asm __volatile(DOINT(0x15) "; setc %b0"
167 : "=c" (rc), "=a" (mem) : "a" (0x8800));
168
169 if (rc & 0xff)
170 return NULL;
171 #ifdef DEBUG
172 printf("0x15[8800] ");
173 #endif
174
175 mp->addr = 1024 * 1024;
176 mp->size = (mem & 0xffff) * 1024;
177 mp->type = BIOS_MAP_FREE;
178
179 return ++mp;
180 }
181
182
183
184
185
186 static __inline bios_memmap_t *
187 bios_int12(bios_memmap_t *mp)
188 {
189 int mem;
190 #ifdef DEBUG
191 printf("0x12 ");
192 #endif
193 __asm __volatile(DOINT(0x12) : "=a" (mem) :: "%ecx", "%edx", "cc");
194
195
196 mp->addr = 0;
197 mp->size = (mem & 0xffff) * 1024;
198 mp->type = BIOS_MAP_FREE;
199
200 return ++mp;
201 }
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217 const u_int addrprobe_pat[] = {
218 0x00000000, 0xFFFFFFFF,
219 0x01010101, 0x10101010,
220 0x55555555, 0xCCCCCCCC
221 };
222 static int
223 addrprobe(u_int kloc)
224 {
225 __volatile u_int *loc;
226 register u_int i, ret = 0;
227 u_int save[NENTS(addrprobe_pat)];
228
229
230 loc = (int *)(kloc * 1024);
231
232 save[0] = *loc;
233
234 for (i = 0; i < NENTS(addrprobe_pat); i++) {
235 *loc = addrprobe_pat[i];
236 if (*loc != addrprobe_pat[i])
237 ret++;
238 }
239 *loc = save[0];
240
241 if (!ret) {
242
243 for (i = 0; i < NENTS(addrprobe_pat); i++) {
244 save[i] = loc[i];
245 loc[i] = addrprobe_pat[i];
246 }
247
248
249 for (i = 0; i < NENTS(addrprobe_pat); i++) {
250 if (loc[i] != addrprobe_pat[i])
251 ret++;
252 loc[i] = save[i];
253 }
254 }
255
256 return ret;
257 }
258
259
260
261
262
263
264
265
266
267
268 static __inline bios_memmap_t *
269 badprobe(bios_memmap_t *mp)
270 {
271 u_int64_t ram;
272 #ifdef DEBUG
273 printf("scan ");
274 #endif
275
276
277
278
279
280 for (ram = 1024; ram < 512 * 1024; ram += 4)
281 if (addrprobe(ram))
282 break;
283
284 mp->addr = 1024 * 1024;
285 mp->size = (ram - 1024) * 1024;
286 mp->type = BIOS_MAP_FREE;
287
288 return ++mp;
289 }
290
291 bios_memmap_t bios_memmap[32];
292 #ifndef _TEST
293 void
294 memprobe(void)
295 {
296 bios_memmap_t *pm = bios_memmap, *im;
297
298 #ifdef DEBUG
299 printf(" mem(");
300 #else
301 printf(" mem[");
302 #endif
303
304 if ((pm = bios_E820(bios_memmap)) == NULL) {
305 im = bios_int12(bios_memmap);
306 #if 0
307 pm = bios_E801(im);
308 if (pm == NULL)
309 #endif
310 pm = bios_8800(im);
311 if (pm == NULL)
312 pm = badprobe(im);
313 if (pm == NULL) {
314 printf(" No Extended memory detected.");
315 pm = im;
316 }
317 }
318 pm->type = BIOS_MAP_END;
319
320
321
322
323 apmfixmem();
324
325 #ifdef DEBUG
326 printf(")[");
327 #endif
328
329
330 extmem = cnvmem = 0;
331 for (im = bios_memmap; im->type != BIOS_MAP_END; im++) {
332
333 if ((im->type == BIOS_MAP_FREE) && (im->size >= 12*1024)) {
334 if (im->size > 1024 * 1024)
335 printf("%uM ", (u_int)(im->size /
336 (1024 * 1024)));
337 else
338 printf("%uK ", (u_int)im->size / 1024);
339
340
341
342
343
344
345
346
347
348
349
350 if (im->addr < IOM_BEGIN)
351 cnvmem = max(cnvmem,
352 im->addr + im->size) / 1024;
353 if (im->addr >= IOM_END)
354 extmem += im->size / 1024;
355 }
356 }
357
358
359 printf("a20=o%s] ", checkA20()? "n" : "ff!");
360 }
361 #endif
362
363 void
364 dump_biosmem(bios_memmap_t *tm)
365 {
366 register bios_memmap_t *p;
367 register u_int total = 0;
368
369 if (tm == NULL)
370 tm = bios_memmap;
371
372 for (p = tm; p->type != BIOS_MAP_END; p++) {
373 printf("Region %ld: type %u at 0x%llx for %uKB\n",
374 (long)(p - tm), p->type, p->addr,
375 (u_int)(p->size / 1024));
376
377 if (p->type == BIOS_MAP_FREE)
378 total += p->size / 1024;
379 }
380
381 printf("Low ram: %dKB High ram: %dKB\n", cnvmem, extmem);
382 printf("Total free memory: %uKB\n", total);
383 }
384
385 int
386 mem_delete(long long sa, long long ea)
387 {
388 register bios_memmap_t *p;
389
390 for (p = bios_memmap; p->type != BIOS_MAP_END; p++) {
391 if (p->type == BIOS_MAP_FREE) {
392 register int64_t sp = p->addr, ep = p->addr + p->size;
393
394
395 if ((sa - sp) <= NBPG && (ep - ea) <= NBPG) {
396 bcopy(p + 1, p, (char *)bios_memmap +
397 sizeof(bios_memmap) - (char *)p);
398 break;
399
400 } else if (sa <= sp && sp < ea) {
401 p->addr = ea;
402 p->size = ep - ea;
403 break;
404 } else if (sa < ep && ep <= ea) {
405 p->size = sa - sp;
406 break;
407 } else if (sp < sa && ea < ep) {
408
409 bcopy(p, p + 1, (char *)bios_memmap +
410 sizeof(bios_memmap) - (char *)p -
411 sizeof(bios_memmap[0]));
412 p[1].addr = ea;
413 p[1].size = ep - ea;
414 p->size = sa - sp;
415 break;
416 }
417 }
418 }
419 return 0;
420 }
421
422 int
423 mem_add(long long sa, long long ea)
424 {
425 register bios_memmap_t *p;
426
427 for (p = bios_memmap; p->type != BIOS_MAP_END; p++) {
428 if (p->type == BIOS_MAP_FREE) {
429 register int64_t sp = p->addr, ep = p->addr + p->size;
430
431
432 if (sp <= sa && ea <= ep) {
433 break;
434
435 } else if (sa < sp && sp <= ea) {
436 p->addr = sa;
437 p->size = ep - sa;
438 break;
439 } else if (sa <= ep && ep < ea) {
440 p->size = ea - sp;
441 break;
442 } else if (ea < sp) {
443
444 bcopy(p, p + 1, (char *)bios_memmap +
445 sizeof(bios_memmap) - (char *)(p - 1));
446 p->addr = sa;
447 p->size = ea - sa;
448 break;
449 }
450 }
451 }
452
453
454 if (p->type == BIOS_MAP_END) {
455 p[1] = p[0];
456 p->type = BIOS_MAP_FREE;
457 p->addr = sa;
458 p->size = ea - sa;
459 }
460
461 return 0;
462 }
463
464 void
465 mem_pass(void)
466 {
467 bios_memmap_t *p;
468
469 for (p = bios_memmap; p->type != BIOS_MAP_END; p++)
470 ;
471 addbootarg(BOOTARG_MEMMAP, (p - bios_memmap + 1) * sizeof *bios_memmap,
472 bios_memmap);
473 }