rust-osdev / bootloader

An experimental pure-Rust x86 bootloader
Apache License 2.0
1.39k stars 212 forks source link

Cannot boot higher-half kernel with custom linker script #402

Closed SnowyCoder closed 11 months ago

SnowyCoder commented 1 year ago

Hello, I have a custom kernel that I tried to update to bootloader v0.11, you can find it here. First, I must say, thanks for this project, it has been really useful and the last update seems to simplify a lot of the workflow.

While migrating from v0.10 I found two problems, first the linker script had to align sections to pages (this isn't really a "problem", more it is not written in the migration guide).

Second, and more interesting is that, after correctly loading the kernel sections, it does not jump to the correct entrypoint. The kernel entry point is at 0xffff800000101de0 (read from the ELF), but since the virtual address offset is 0xffffffffffffffff0000807fffeff000 the sum overflows and it jumps to 0x8000000de0. I don't have any more clues on where the problem might be, I'm sorry if this is a problem with my setup.

Bootloader output:

INFO: Framebuffer info: FrameBufferInfo { byte_len: 2764800, width: 1280, height: 720, pixel_format: Bgr, bytes_per_pixel: 3, stride: 1280 }
INFO: 4th Stage
INFO: BiosInfo { stage 4: Region { start: 130000, len: 28d90 }, kernel: Region { start: 1000000, len: 3f83e8 }, ramdisk: Region { start: 13f9 000, len: 0 }, config_file: Region { start: 13f9000, len: 0 }, last_used_addr: 13f8fff, framebuffer: Bios FramebufferInfo { region: Region { st art: fd000000, len: 2a3000 }, width: 500, height: 2d0, bytes_per_pixel: 3, stride: 500, pixel_format: Bgr }, memory_map_addr: e7e0, memory_map_len: 7 }
INFO: BIOS boot
INFO: Elf file loaded at 0x0000000001000000
INFO: virtual_address_offset: 0xffffffffffffffff0000807fffeff000
INFO: Handling Segment: Ph64 (ProgramHeader64 {type_: Ok (Load), flags: Flags(5), offset: 1000, virtual_addr: ffff800000101000, physical_addr: 1000, file_size: 51000, mem_size: 51000, align: 1000 })
INFO: Handling Segment: Ph64 (ProgramHeader64 { type_: Ok (Load), flags: Flags (4), offset: 52000, virtual_addr: ffff800000152000, physical_addr : 52000, file_size: e5e0, mem_size: e5e0, align: 1000 })
INFO: Handling Segment: Ph64 (ProgramHeader64 { type_: Ok (Load), flags: Flags (4), offset: 61000, virtual_addr: ffff800000161000, physical_addr 61000, file_size: 21907c, mem_size: 21907c, align: 1000 })
INFO: Handling Segment: Ph64 (ProgramHeader64 { type_: Ok (Load), flags: Flags (6), offset: 27b000, virtual_addr: ffff80000037b000, physical_add r: 27b000, file_size: a0e0, mem_size: a0e0, align: 1000 })
INFO: Handling Segment: Ph64 (ProgramHeader64 { type_: Ok (Load), flags: Flags (6), offset: 286000, virtual_addr: ffff800000386000, physical_add r: 286000, file_size: 6000, mem_size: 6000, align: 1000 })
INFO: Entry point at: 0x8000000de0
INFO: Creating GDT at PhysAddr(0x1420000)
INFO: Map framebuffer
INFO: Map physical memory
INFO: Allocate bootinfo
INFO: Create Memory Map
INFO: Create bootinfo
INFO: Jumping to kernel entry point at VirtAddr(0x8000000de0)

(might be wrong, I used an image-to-text site)

If I can help with anything I'd be happy to, I just don't have enough knowledge to know where the bug is.

Freax13 commented 12 months ago

AFAICT everything in the bootloader is working as intended. IIUC you compiiled your kernel using the x86_64-unknown-none target which emits position independent executable by default. For those we currently don't make any guarantees about where the kernel is loaded. I compiled your kernel and attached a debugger to QEMU and it seems to me that the entrypoint is mapped and jumped to correctly. I assume that something eventually breaks because your code assumes a specific kernel base.

If you don't want your kernel to be a position independent executable you can pass -C relocation-model=static via rustflags.

SnowyCoder commented 11 months ago

I'm sorry you are correct, I assumed my kernel was broken because it was loaded to a lower-half location but that is not the case.

Still, you should not say that you support higher-half kernel if you still load it in a lower-half virtual memory offset.

Freax13 commented 11 months ago

Still, you should not say that you support higher-half kernel if you still load it in a lower-half virtual memory offset.

We support higher-half kernels compiled with -C relocation-model=static.