Reputation: 93
I am currently writing a 32bit operating system, and while trying to get the memory map in order to write a memory manager, I am using the following function from the brokenthorn tutorial
memmap.asm
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
BiosGetMemoryMap:
pushad
xor ebx, ebx
xor bp, bp ; number of entries stored here
mov edx, 'PAMS'
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:
popad
ret
loader.asm
; Fortress Bootloader
; The quasar bootloader is a bare metal bootloader
; It can load 128 sectors, and is meant to load a
; tiny but powerful kernel
[bits 16]
[extern kernel]
[global isr_stub_table]
[global IDT_load]
[extern FortressLoader_IdtInit]
[extern FortressLoader_ChecmMemMap]
[extern X86TTY_Init]
[extern X86TTY_Clear]
[extern printf]
[global startKernel]
section .boot
global boot
KERNEL_SIZE_SECTORS equ 128
jmp $boot
bpbBytesPerSector: DW 512
bpbSectorsPerCluster: DB 1
bpbReservedSectors: DW 1
bpbNumberOfFATs: DB 2
bpbRootEntries: DW 224
bpbTotalSectors: DW 2880
bpbMedia: DB 0xF0
bpbSectorsPerFAT: DW 9
bpbSectorsPerTrack: DW 18
bpbHeadsPerCylinder: DW 2
bpbHiddenSectors: DD 0
bpbTotalSectorsBig: DD 0
bsDriveNumber: DB 0
bsUnused: DB 0
bsExtBootSignature: DB 0x29
bsSerialNumber: DD 0xa0a1a2a3
bsVolumeLabel: DB "6STAR OS "
bsFileSystem: DB "FAT12 "
%include "./fortressloader/memory.asm"
%include "./fortressloader/memmap.asm"
%include "./fortressloader/multiboot.asm"
test_message db "test", 0
boot:
cld
xor ax, ax
mov ds, ax
mov ss, ax
mov sp, 0x7c00
mov di, 0x7c00
cli
mov [disk], dl
mov ax, 0x2401
int 0x15
mov ax, 0x3 ;Set the VGA mode, unknown at boot
int 0x10
mov ah, 42h ;Do modern disk reading (no fuckery)
mov dl, [disk] ;Account for cosmic bit flips
mov si, dap ;Load disk address packet
int 0x13
jc disk_err ;Jump if disk read error
jmp disk_target ;
print:
pusha
start:
mov al, [bx]
cmp al, 0
je done
mov ah, 0x0e
int 0x10
add bx, 1
jmp start
done:
popa
ret
print_nl:
pusha
mov ah, 0x0e
mov al, 0x0a
int 0x10
mov al, 0x0d
int 0x10
popa
ret
print_hex:
pusha
mov cx, 0
hex_loop:
cmp cx, 4
je end
mov ax, dx
and ax, 0x000f
add al, 0x30
cmp al, 0x39
jle step2
add al, 7
step2:
mov bx, HEX_OUT + 5
sub bx, cx
mov [bx], al
ror dx, 4
add cx, 1
jmp hex_loop
end:
mov bx, HEX_OUT
call print
popa
ret
disk_err: ;Label for any disk errors
mov bx, disk_read_error ;Print the disk error
call print
call print_nl
mov dh, ah ;Load error code in ah register
call print_hex
jmp $
GDT_START:
dq 0x0
GDT_CODE: ;base = 0x00000000, length = 0xfffff
dw 0xffff ;segment length, bits 0-15
dw 0x0 ;segment base, bits 0-15
db 0x0 ;segment base, bits 16-23
db 10011010b ;flags (8 bits)
db 11001111b ;flags (4 bits) + segment length
db 0x0 ;segment base, bits 24-31
GDT_DATA:
dw 0xFFFF
dw 0x0
db 0x0
db 10010010b
db 11001111b
db 0x0
GDT_END:
GDT_POINTER:
dw GDT_END - GDT_START
dd GDT_START
CODE_SEG equ GDT_CODE - GDT_START
DATA_SEG equ GDT_DATA - GDT_START
disk:
db 0x0
dap:
db 0x10
db 0
dw KERNEL_SIZE_SECTORS
dw 0 ;
dw 0x07e0 ;value recommended by a friend
dq 1 ;start second sector read
HEX_OUT:
db '0x0000',0
disk_read_error: db "Disk read error!", 0
times 510 - ($-$$) db 0
dw 0xAA55
disk_target:
call BiosGetMemorySize64MB ;Load the memory size
mov [mbInfo+mbInfo.memoryHi], bx
mov [mbInfo+mbInfo.memoryLo], ax
mov word [mbInfo+mbInfo.bootDevice], 0x0
call BiosGetMemoryMap
mov word [mbInfo+mbInfo.mmap_length], ax
mov word [mbInfo+mbInfo.mmap_addr], 0x2000
cli ;Clear the interrupts
lgdt [GDT_POINTER] ;Load the GDT using a gdt pointer
mov eax, cr0
or eax, 0x1
mov cr0, eax
jmp CODE_SEG:boot2
[bits 32]
startKernel:
boot2:
mov ax, DATA_SEG
mov ds, ax
mov es, ax
mov fs, ax
mov gs, ax
mov ss, ax
mov esi, loaded_msg
mov ebx, 0xb8000
.loop: ;Print a message using a loop
lodsb
or al, al
jz load_kernel ;Load kern when msg finished
or eax,0x0F00
mov word [ebx], ax
add ebx,2
jmp .loop
load_kernel:
mov esp, kernel_stack_top ;Load the stack to call C functions
call X86TTY_Init ;Initalize the TTY
call X86TTY_Clear ;Clear everything on the screen
call FortressLoader_IdtInit ;Initalize the IDT
mov eax, 0x2BADB002 ;Multiboot magic number
mov ebx, mbInfo
mov ebx, 0
call kernel ;Call the actual kernel
halt:
cli
hlt
loaded_msg: db "Operating system loaded",0 ;Message here to verify disk read
section .bss
align 4
kernel_stack_bottom: equ $ ;equ the current address for the stack
resb 16384 ;Use 16kb for stack size
kernel_stack_top: ;Top of the stack
section .text ;Fuck bss and asm sections
Hoever, my problem is that this causes Qemu to never call the kernel, or what seems like anything after this
I have tried commenting out certain lines out of the bootloader, and have realized that it is the specific instruction mov edx, 'PAMS'
on line 12. When commenting out that specific line, there are no issues. What can I do to solve this?
Upvotes: 0
Views: 76
Reputation: 93
Fixed! I was missing a mov edi, 0x2000
right after mov word [mbInfo+mbInfo.bootDevice], 0x0
Upvotes: 2