-
Notifications
You must be signed in to change notification settings - Fork 406
/
bios_detect_memory.S
74 lines (69 loc) · 2.57 KB
/
bios_detect_memory.S
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
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
/* https://github.com/cirosantilli/x86-bare-metal-examples#bios-detect-memory */
#include "common.h"
BEGIN
CLEAR
STAGE2
mov $output, %di
call do_e820
/* Debug aid. */
PRINT_WORD_HEX <%bp>
PRINT_NEWLINE
mov %bp, %ax
mov $0, %dx
/* Each entry is 24 bytes wide. */
mov $24, %cx
mul %cx
PRINT_BYTES $output, <%ax>
hlt
/* This was copy pasted from:
* http://wiki.osdev.org/Detecting_Memory_%28x86%29#Getting_an_E820_Memory_Map
*
* use the INT 0x15, eax= 0xE820 BIOS function to get a memory map
* inputs: es:di -> destination buffer for 24 byte entries
* outputs: bp = entry count, trashes all registers except esi
*/
do_e820:
xorl %ebx,%ebx # ebx must be 0 to start
xorw %bp,%bp # keep an entry count in bp
movl $0x0534D4150,%edx # Place "SMAP" into edx
movl $0xe820,%eax
movl $1, %es:20(%di)
movl $24,%ecx # ask for 24 bytes
int $0x15
jc do_e820.failed # carry set on first call means "unsupported function"
movl $0x0534D4150,%edx # Some BIOSes apparently trash this register?
cmpl %edx,%eax # on success, eax must have been reset to "SMAP"
jne do_e820.failed
testl %ebx,%ebx # ebx = 0 implies list is only 1 entry long (worthless)
je do_e820.failed
jmp do_e820.jmpin
do_e820.e820lp:
movl $0xe820,%eax # eax, ecx get trashed on every int 0x15 call
movl $1, %es:20(%di)
movl $24,%ecx # ask for 24 bytes again
int $0x15
jc do_e820.e820f # carry set means "end of list already reached"
movl $0x0534D4150,%edx # repair potentially trashed register
do_e820.jmpin:
jcxz do_e820.skipent # skip any 0 length entries
cmpb $20,%cl # got a 24 byte ACPI 3.X response?
jbe do_e820.notext
testb $1, %es:29(%di)
je do_e820.skipent
do_e820.notext:
mov %ecx, %es:8(%di)
or %ecx, %es:12(%di)
jz do_e820.skipent # if length uint64_t is 0, skip entry
incw %bp # got a good entry: ++count, move to next storage spot
addw $24,%di
do_e820.skipent:
testl %ebx,%ebx # if ebx resets to 0, list is complete
jne do_e820.e820lp
do_e820.e820f:
#movw %bp,mmap_ent # store the entry count
clc # there is "jc" on end of list to this point, so the carry must be cleared
ret
do_e820.failed:
stc # "function unsupported" error exit
ret
output: