I notice that you aren't using a cross compiler. You should. with that being said if you look at the objdump output you'll notice that the multiboot.hdr is actually placed at offset 0x2000 in the file. This is beyond the first 8k and why it can't be found by GRUB. You should observe that in the section just before it there is a build-id section that was placed there:
Code: Select all
Sections:
Idx Name Size VMA LMA File off Algn
0 .note.gnu.build-id 00000024 00000000 00000000 00001000 2**2
CONTENTS, ALLOC, LOAD, READONLY, DATA
1 .multiboot.hdr 0000000c 00100000 00100000 00002000 2**2
CONTENTS, ALLOC, LOAD, READONLY, DATA
You can eliminate this by modifying your linking line (g++) by adding the option
-Wl,--build-id=none Code: Select all
g++ -o "<output>" -m32 -T ~/projects/Kernel/linkscript.ld -Wl,--build-id=none -ffreestanding -O2 -nostdlib ~/projects/Kernel/obj/x86/*.asm.o <other input files>
By eliminating the build id during the linking process we can get rid of this section. This may allow your multiboot header to be placed starting at 0x1000 instead of 0x2000. As well you have a typo in this line
section .mutliboot.data it should be:
In your updated code you have a bug setting up paging:
Code: Select all
mov ecx, (KernelPageDirectory - KERNEL_VIRTUAL_BASE)
needs to be:
. This is because with the linker script I gave you KernelPageDirectory isalready a low memory address so you don't adjust it. There is a typo here:
Code: Select all
mov ecx, cr4
or ecx, 0x00000010
mov cr0, ecx
should be
Code: Select all
mov ecx, cr4
or ecx, 0x00000010
mov cr4, ecx
In your VGA.CPP use use the low memory address 0xb8000 for video memory. Since you unmapped the identity mapping for the first page of RAM you need to use the high memory address. The address now is:
Code: Select all
uint8_t* video_memory = (uint8_t*)0xC00B8000;
You also have created a large sized structure for your page tables. This line in paging.cpp:
will require a fair amount of BSS space and will make your code and data exceed the 4MB page that has been mapped. You are now in a position where if you keep the code this way you'll need to map more than the first 4MB of ram to high memory. If you don't you'll fault the processor when it tries to access any data outside the first 4MB of the kernel. You could add an additional 4MB to the initial mapping by changing the initial kernel page table to appear as:
Code: Select all
KERNEL_NUM_PAGES equ 2
section .multiboot.data
align 4096
KernelPageDirectory:
dd 0x00000083 | 0<<22 ; Identity map 0x00000000-0x003fffff
times (KERNEL_PAGE_NUMBER - 1) dd 0 ; Pages before kernel space
dd 0x00000083 | 0<<22 ; Map 0xc0000000-0xc03fffff to 0x00000000-0x003fffff
dd 0x00000083 | 1<<22 ; Map 0xc0400000-0xc07fffff to 0x00400000-0x007fffff
times (1024 - KERNEL_PAGE_NUMBER - KERNEL_NUM_PAGES) dd 0
; Pages after kernel space
---
When compiling your files without a cross compiler you may find that the code generated will be position independent. That will cause issues for the code generated. You should add the option
-fno-pic along side
-ffreestanding. I also noticed that you have a typo in your answer above. The line you are using to compile is using
--freestanding when it should be
-ffreestanding