forked from cirosantilli/x86-bare-metal-examples
-
Notifications
You must be signed in to change notification settings - Fork 0
/
bios_detect_memory.S
108 lines (91 loc) · 3.44 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
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
/*
# Detecte memory
# int 15
TODO Seems to be outputting trash :-)
http://wiki.osdev.org/Detecting_Memory_%28x86%29
Determine how much memory you've got, and how much of it is low memory.
This is important in particular so that you can start your stack there
when you enter protected mode, since the stack grows down.
In 16-bit mode, it does not matter much,
since most modern machines have all addressable memory there,
but in 32-bit protected it does, as our emulator usually does not have all 4Gb.
And of course, 64-bit RAM is currently larger than the total RAM in the world.
`int 15` returns a list:
each time you call it a new memory region is returned.
The format is not too complicated, and documented at:
http://wiki.osdev.org/Detecting_Memory_%28x86%29#Detecting_Upper_Memory
- 8 bytes: base address of region.
- 8 bytes: length of region.
- 4 bytes: type or region. 1 for usable RAM.
- 4 bytes: some ACPI stuff that no one uses?
## Low memory
TODO what is it?
*/
#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: