123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138 |
- [bits 16]
- main:
- jmp far 0x000:0x7c05
- main2:
- mov ax, 0x0000
- mov ds, ax
- mov ss, ax
- mov ax, 0x7b00
- mov sp, ax
- mov ax, 0x0500
- mov es, ax
- clc
- int 0x12
- mov [lower_mem], ax
- ; memory scan
- mov di, 0x0
- call do_e820
- jc hang
- cli
- ; a20
- in al, 0x92
- or al, 2
- out 0x92, al
- ; basic flat GDT
- xor eax, eax
- mov ax, ds
- shl eax, 4
- add eax, gdt_base
- mov [gdtr+2], eax
- mov eax, gdt_end
- sub eax, gdt_base
- mov [gdtr], ax
- lgdt [gdtr]
- ; protected mode enable flag
- mov eax, cr0
- or eax, 1
- mov cr0, eax
- ; set segments
- mov ax, 0x10
- mov ds, ax
- mov es, ax
- mov fs, ax
- mov gs, ax
- mov ss, ax
- ; jump to protected mode entry
- extern kmain
- jmp far 0x08:(kmain)
- hang:
- jmp hang
- do_e820:
- xor ebx, ebx ; ebx must be 0 to start
- xor bp, bp ; keep an entry count in bp
- mov edx, 0x0534D4150 ; Place "SMAP" into edx
- mov eax, 0xe820
- mov [es:di + 20], dword 1 ; force a valid ACPI 3.X entry
- mov ecx, 24 ; ask for 24 bytes
- int 0x15
- jc short .failed ; carry set on first call means "unsupported function"
- mov edx, 0x0534D4150 ; Some BIOSes apparently trash this register?
- cmp eax, edx ; on success, eax must have been reset to "SMAP"
- jne short .failed
- test ebx, ebx ; ebx = 0 implies list is only 1 entry long (worthless)
- je short .failed
- jmp short .jmpin
- .e820lp:
- mov eax, 0xe820 ; eax, ecx get trashed on every int 0x15 call
- mov [es:di + 20], dword 1 ; force a valid ACPI 3.X entry
- mov ecx, 24 ; ask for 24 bytes again
- int 0x15
- jc short .e820f ; carry set means "end of list already reached"
- mov edx, 0x0534D4150 ; repair potentially trashed register
- .jmpin:
- jcxz .skipent ; skip any 0 length entries
- cmp cl, 20 ; got a 24 byte ACPI 3.X response?
- jbe short .notext
- test byte [es:di + 20], 1 ; if so: is the "ignore this data" bit clear?
- je short .skipent
- .notext:
- mov ecx, [es:di + 8] ; get lower uint32_t of memory region length
- or ecx, [es:di + 12] ; "or" it with upper uint32_t to test for zero
- jz .skipent ; if length uint64_t is 0, skip entry
- inc bp ; got a good entry: ++count, move to next storage spot
- add di, 24
- .skipent:
- test ebx, ebx ; if ebx resets to 0, list is complete
- jne short .e820lp
- .e820f:
- mov [mmap_ent], bp ; store the entry count
- clc ; there is "jc" on end of list to this point, so the carry must be cleared
- ret
- .failed:
- stc ; "function unsupported" error exit
- ret
- align 8
- ; GDT pointer
- gdtr
- dw 0
- dd 0
- ; GDT (null, code, data)
- gdt_base
- ; null
- dq 0
- ; code
- dw 0xFFFF
- dw 0
- db 0
- db 0x9a
- db 0xcf
- db 0
- ; data
- dw 0xffff
- dw 0
- db 0
- db 0x92
- db 0xcf
- db 0
- gdt_end
- ; memory map entry count
- global mmap_ent
- mmap_ent db 0, 0
- global lower_mem
- lower_mem db 0, 0
|