summaryrefslogtreecommitdiff
path: root/boot/memmap.asm
blob: d101557985c6bc187bf09254dfbc213fe3f8f505 (plain)
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
;---------------------------------------------
;	Get memory map from bios
;	/in es:di->destination buffer for entries
;	/ret bp=entry count
;---------------------------------------------

; stolen from: http://www.brokenthorn.com/Resources/OSDev17.html
struc	MemoryMapEntry
    .baseAddress	resq	1	; base address of address range
    .length		resq	1	; length of address range in bytes
    .type		resd	1	; type of address range
    .acpi_null	resd	1	; reserved
endstruc
 
[bits 16]

BiosGetMemoryMap:
    pushad
    xor	ebx, ebx
    xor	bp, bp			; number of entries stored here
    mov	edx, 'PAMS'		; 'SMAP'
    mov	eax, 0xe820
    mov	ecx, 24			; memory map entry struct is 24 bytes
    int	0x15			; get first entry
    jc	.error	
    cmp	eax, 'PAMS'		; bios returns SMAP in eax
    jne	.error
    test	ebx, ebx		; if ebx=0 then list is one entry long; bail out
    je	.error
    jmp	.start
.next_entry:
    mov	edx, 'PAMS'		; some bios's trash this register
    mov	ecx, 24			; entry is 24 bytes
    mov	eax, 0xe820
    int	0x15			; get next entry
.start:
    jcxz	.skip_entry		; if actual returned bytes is 0, skip entry
.notext:
    mov	ecx, [es:di + MemoryMapEntry.length]	; get length (low dword)
    test	ecx, ecx		; if length is 0 skip it
    jne	short .good_entry
    mov	ecx, [es:di + MemoryMapEntry.length + 4]; get length (upper dword)
    jecxz	.skip_entry		; if length is 0 skip it
.good_entry:
    inc	bp			; increment entry count
    add	di, 24			; point di to next entry in buffer
.skip_entry:
    cmp	ebx, 0			; if ebx return is 0, list is done
    jne	.next_entry		; get next entry
    jmp	.done
.error:
    stc
.done:
    
    mov [MEMMAP_SIZE_OFFSET],bp
    popad
    ret