Code is not correct on Kernel entrypoint - custom bootloader

Question about which tools to use, bugs, the best way to implement a function, etc should go here. Don't forget to see if your question is answered in the wiki first! When in doubt post here.
Post Reply
batatonana
Posts: 2
Joined: Sun Jan 19, 2025 8:18 am

Code is not correct on Kernel entrypoint - custom bootloader

Post by batatonana »

Hi,
I am new to OS development, for the past few days I have been trying to develop a very simple bootloader that can jump to my kernel entrypoint.
I have several details in the repository, including the desired memory map: https://github.com/fx310ferreira/operat ... bootloader
Right now I am loading the kernel on the address 0x10000, the kernel has a ELF header so when linking I am using the address 0x11000 for the ".text" segment.
Before I was using normal gcc and not i686-elf-gcc. Everything was working, using GCC I verified that on the address 0x11000 my _start function was loaded. When I changed to the cross-compiler it stop working.

Does someone have an idea why? Did I misunderstand something related to ELF headers?

Thank you in advance.
Octocontrabass
Member
Member
Posts: 5623
Joined: Mon Mar 25, 2013 7:01 pm

Re: Code is not correct on Kernel entrypoint - custom bootloader

Post by Octocontrabass »

batatonana wrote: Sun Jan 19, 2025 8:58 amRight now I am loading the kernel on the address 0x10000,
No you aren't.
batatonana wrote: Sun Jan 19, 2025 8:58 amthe kernel has a ELF header
No it doesn't.
batatonana wrote: Sun Jan 19, 2025 8:58 amDoes someone have an idea why?
It's hard to help you when you show us the wrong code.
batatonana wrote: Sun Jan 19, 2025 8:58 amDid I misunderstand something related to ELF headers?
Did you try using tools like readelf or objdump or just a plain hex editor to see if your binary is laid out the way you expect?
batatonana
Posts: 2
Joined: Sun Jan 19, 2025 8:18 am

Re: Code is not correct on Kernel entrypoint - custom bootloader

Post by batatonana »

I am so sorry, you are completely right, it seems I forgot to push the correct version.
I have pushed the correct, one.
The on the version that you have seen everything was working fine I was loading a plain .asm file instead of the compiled C version, I have used both readelf and objdump, I will try the plain hex editor to see if there is a difference between the compiled version with normal GCC and cross-compiler (with both objdump and readleaf it seems to be the exact same file).
Other thing I have question about is that most of the implementations of the bootloader and kernel I have is to use a "boot.asm" file to call an external "kernel.c" function. Is this a better practice than calling directly the C function?
Octocontrabass
Member
Member
Posts: 5623
Joined: Mon Mar 25, 2013 7:01 pm

Re: Code is not correct on Kernel entrypoint - custom bootloader

Post by Octocontrabass »

batatonana wrote: Mon Jan 20, 2025 2:47 amI have pushed the correct, one.
Does your entire kernel get copied to your disk image?
batatonana wrote: Mon Jan 20, 2025 2:47 amOther thing I have question about is that most of the implementations of the bootloader and kernel I have is to use a "boot.asm" file to call an external "kernel.c" function. Is this a better practice than calling directly the C function?
Most implementations have that because they won't work correctly without it. If your bootloader works correctly without it, you don't need it.
MichaelPetch
Member
Member
Posts: 801
Joined: Fri Aug 26, 2016 1:41 pm
Libera.chat IRC: mpetch

Re: Code is not correct on Kernel entrypoint - custom bootloader

Post by MichaelPetch »

Octocontrabass is correct that you aren't copying your entire kernel to the disk image. You need to round up to the nearest with something like:

Code: Select all

dd conv=notrunc if=$(OS) of=$(DISK_IMG) bs=512 count=$$((($(shell stat --printf="%s" $(OS))+511)/512)) seek=1
You have another problem in bootloader.asm:

Code: Select all

  ; Load the 32 bit addres to jump to
  mov si, 0x18
  mov eax, dword [es:si]
  jmp eax
You are still running in 16-bit real mode. You will end up loading 0x00011000 into EAX. The problem is that JMP is still a real mode jump. If the CS segment limit is 64KiB then this will cause a #GP fault and will likely hang because 0x11000 is >= 64KiB. It may be the CS segment limit is 4GiB in some cases, or there is no segment limit checking (QEMU doesn't check segment limits for performance reasons) so you may not get a #GP exception and the JMP will work. You are relying on an unknown CPU state that may or may not allow the JMP to work.

Note: In 16-bit real-mode If you can successfully do JMP EAX with an EIP>=0x10000 (64Kib) you can't reliably run with EIP>=0x10000 unless you add a 32-bit operand override to each instruction that reloads EIP. Example: `jmp $` would fail as it would reload EIP and clear the upper 16-bits of EIP yielding a jump to the wrong location. `o32 jmp $` would work. QEMU's software emulation is somewhat non-compliant with the Intel system development manuals so code that appears to work in QEMU may not work on real hardware. The same code may fail if you run QEMU with option `--enable-kvm`. Moral of this story: Don't JMP to an EIP>=0x10000 in 16-bit real mode unless you know what you are doing.

Since you will need to enter 32-bit protected mode before trying to run 32-bit code - entering protected mode with a flat 4GiB memory model for CS/DS/ES/SS (typical) would put the CPU in a state where you can properly JMP to 0x11000 (or any address < 4GiB) without strange side effects.
nullplan
Member
Member
Posts: 1804
Joined: Wed Aug 30, 2017 8:24 am

Re: Code is not correct on Kernel entrypoint - custom bootloader

Post by nullplan »

MichaelPetch wrote: Mon Jan 20, 2025 5:09 pm Octocontrabass is correct that you aren't copying your entire kernel to the disk image. You need to round up to the nearest with something like:

Code: Select all

dd conv=notrunc if=$(OS) of=$(DISK_IMG) bs=512 count=$$((($(shell stat --printf="%s" $(OS))+511)/512)) seek=1
Might be simpler to just leave out the count= argument. Then it'll just keep reading the input file until it ends.
Carpe diem!
Post Reply