diff --git a/boot1.s b/boot1.s index a3f96f0..ab16baa 100644 --- a/boot1.s +++ b/boot1.s @@ -250,7 +250,11 @@ main: call mem_detect jc .mem_detect_fail + call print_memmap + +.hlt_loop: hlt + jmp .hlt_loop .mem_detect_fail: panic PANIC_TYPE_MEM_DETECT @@ -605,6 +609,38 @@ nybble_to_hex_char: ret +; Copy a null-terminated string from ds:cx to es:ax. +; - es: output buffer segment +; - ax: output buffer offset +; - ds: input buffer segment +; - cx: input buffer offset +; Return: +; - ax: the address of the null terminator that was written +; Clobber: none +strcpy: + fnstart + push si + push di + + mov di, ax + mov si, cx + +.loop: + mov al, [si] + mov es:[di], al + test al, al + jz .done + inc si + inc di + jmp .loop + +.done: + mov ax, di + pop di + pop si + fnret + + ; Check whether the A20 line is enabled. Writes to the boot sector identifier. ; Arguments: none ; Return: @@ -711,10 +747,6 @@ enable_a20_intel_8042: mem_detect: - %if MEMMAP_CAP < 1 - %error "memmap buffer too small" - %endif - fnstart push es @@ -731,39 +763,43 @@ mem_detect: xor ebx, ebx ; Buffer (es:di) mov di, MEMMAP - mov dword [di + 0x20], 0x1 - ; Entry size - mov ecx, MEMMAP_ENT_SIZE - ; Magic number - mov edx, E820_MAGIC - ; Detect memory - mov eax, 0xe820 - clc - int 0x15 - jc .fail - cmp eax, E820_MAGIC - jne .fail - - inc word [GLOBALS + MEMMAP_ENTRIES] .loop: cmp word [GLOBALS + MEMMAP_ENTRIES], MEMMAP_CAP jae .done - add di, MEMMAP_ENT_SIZE - mov dword [di + 0x20], 0x1 - mov ecx, MEMMAP_ENT_SIZE + ; Init extended field to 0x1 in case e820 doesn't populate it. + mov dword [di + MEMMAP_ENT_FIELD_EXT], 0x1 + ; Size of entry for e820 to write + mov ecx, E820_ENTRY_SIZE + ; Magic number + mov edx, E820_MAGIC + ; Detect memory mov eax, 0xe820 clc int 0x15 ; Carry flag will be set if we'd already reached the end of the entries. jc .done + ; Test magic number + cmp eax, E820_MAGIC + jne .fail + inc word [GLOBALS + MEMMAP_ENTRIES] + ; Calculate and cache the entry end address. + mov eax, [di + MEMMAP_ENT_FIELD_BASE] + add eax, [di + MEMMAP_ENT_FIELD_LEN] + mov [di + MEMMAP_ENT_FIELD_END], eax + mov eax, [di + MEMMAP_ENT_FIELD_BASE + 4] + adc eax, [di + MEMMAP_ENT_FIELD_LEN + 4] + mov [di + MEMMAP_ENT_FIELD_END + 4], eax + + ; e820 _may_ return ebx=0 once we reach the last entry. test ebx, ebx jz .done + add di, MEMMAP_ENT_SIZE jmp .loop .fail: @@ -771,6 +807,9 @@ mem_detect: jmp .return .done: + mov ax, [GLOBALS + MEMMAP_ENTRIES] + test ax, ax + jz .fail clc .return: @@ -778,12 +817,107 @@ mem_detect: fnret +print_memmap: + fnstart + + sub sp, VGA_WIDTH + push eax + push ebx + push ecx + push edx + + mov si, MEMMAP + mov dx, [GLOBALS + MEMMAP_ENTRIES] + +.loop: + test dx, dx + jz .done + dec dx + + push es + mov ax, ss + mov es, ax + + ; Calculate region end + ; mov eax, [si] + ; mov ecx, [si + 8] + ; add eax, ecx + ; push eax + ; mov eax, [si + 4] + ; mov eax, [si + 12] + ; adc eax, ecx + ; push eax + + lea ax, [bp - VGA_WIDTH] + + mov cx, msg_memmap_base + call strcpy + + mov ecx, [si + MEMMAP_ENT_FIELD_BASE + 4] + call dump_reg + mov ecx, [si + MEMMAP_ENT_FIELD_BASE] + call dump_reg + + mov cx, msg_sep + call strcpy + mov cx, msg_memmap_len + call strcpy + + mov ecx, [si + MEMMAP_ENT_FIELD_LEN + 4] + call dump_reg + mov ecx, [si + MEMMAP_ENT_FIELD_LEN] + call dump_reg + + mov cx, msg_sep + call strcpy + mov cx, msg_memmap_end + call strcpy + + mov ecx, [si + MEMMAP_ENT_FIELD_END + 4] + call dump_reg + mov ecx, [si + MEMMAP_ENT_FIELD_END] + call dump_reg + + mov cx, msg_sep + call strcpy + mov cx, msg_memmap_type + call strcpy + + mov ecx, [si + MEMMAP_ENT_FIELD_TYPE] + call dump_reg + + mov bx, ax + mov byte [bx], 0 + + lea ax, [bp - VGA_WIDTH] + call vga_println + + pop es + add si, MEMMAP_ENT_SIZE + jmp .loop + +.done: + pop edx + pop ecx + pop ebx + pop eax + add sp, VGA_WIDTH + fnret + + msg_boot1_loaded db "boot1 loaded. hello!", 0 msg_a20_enabled db "a20 enabled", 0 msg_a20_disabled db "a20 not enabled", 0 msg_a20_8042 db "trying 8042", 0 msg_panic db "panic!", 0 +msg_sep db ",", 0 +msg_memmap_base db "base=", 0 +msg_memmap_end db "end=", 0 +msg_memmap_len db "len=", 0 +msg_memmap_type db "type=", 0 +msg_memmap_ext db "ext=", 0 + msg_reg_eip db "eip", 0 msg_reg_eax db "eax", 0 msg_reg_ebx db "ebx", 0 diff --git a/defines.s b/defines.s index 40d3897..c77ed10 100644 --- a/defines.s +++ b/defines.s @@ -1,10 +1,10 @@ %define BOOT0_LOADPOINT 0x7c00 %define BOOT1_LOADPOINT 0x8200 -%define MEMMAP 0x6a00 -%define MEMMAP_END BOOT0_LOADPOINT -%define MEMMAP_ENT_SIZE 24 -%define MEMMAP_CAP ((MEMMAP_END - MEMMAP) / MEMMAP_ENT_SIZE) +%define MEMMAP 0x6a00 +%define MEMMAP_END BOOT0_LOADPOINT +%define MEMMAP_ENT_SIZE 32 +%define MEMMAP_CAP ((MEMMAP_END - MEMMAP) / MEMMAP_ENT_SIZE) %define GLOBALS 0x4000 %define GLOBALS_END MEMMAP @@ -33,6 +33,15 @@ ; ASCII string "SMAP", which is used by e820 as a magic number argument and return value. %define E820_MAGIC 0x534d4150 +; Size of entry returned by e820. This is less than MEMMAP_ENT_SIZE because we add some fields of +; our own. +%define E820_ENTRY_SIZE 24 + +%define MEMMAP_ENT_FIELD_BASE 0x00 +%define MEMMAP_ENT_FIELD_LEN 0x08 +%define MEMMAP_ENT_FIELD_TYPE 0x10 +%define MEMMAP_ENT_FIELD_EXT 0x14 +%define MEMMAP_ENT_FIELD_END 0x18 ; boot0 base stack frame variable offsets / globals ; (we use the same offsets once we copy the variables to the globals section)