UEFI Haiku boot loader for x86 (32-bit)

some more progress on the memory map:

  • add “page hole” - I didn’t know about this trick yet
  • initialize GDT

now we get to the 3rd icon on the splash screen, then a crash in the USB driver.

Screenshot from 2021-12-10 21-46-07

INIT: Add preloaded old-style drivers
legacy_driver_add_preloaded: adding driver /boot/system/add-ons/kernel/usb_disk
usb_disk: init_hardware()
usb_disk: init_driver()
usb_disk: trying module bus_managers/usb/v3
usb module: init
usb stack 0: stack init

trying to clean up the memory map but still getting crashes/reboots, mostly in _MapChunk. probably something’s getting overwritten…

it seems that the early paging setup relies on some quirky assumptions around the memory layout and physical-virtual mapping.

is there a document describing the kernel’s memory map and requirements on initial page tables and how arch_args shall be filled in? (e.g. i just noticed that num_pgtables and pgtables[] are not referenced in any file in src/system/kernel/ subtree. i also suspect there are some further assumptions around how the early page tables are allocated in MapEarly)

for anyone interested:
my development branch can be found on github here


Probably depends on the linker scripts. The X86 setup might be a bit quirky due to BeOS compability and BIOS.

1 Like

perhaps my build dir was stale… after redoing my dev branch, now the bootup reaches the 4th icon and stops there, apparently waiting for the ATA interface. (no crashes or restarts any more, so maybe I was able to compose a better memory map. or I’m just lucky that none of the kernel gets overwritten :wink: )

number of disk systems: 20
PCI-ATA: Controller in legacy mode: cmd 0x1f0, ctrl 0x3f6, irq 14
PCI-ATA: init channel...
PCI-ATA: channel index 0
PCI-ATA: bus master base 0xc040
PCI-ATA: init channel done

At least for RISC-V there are no assumptions about kernel memory layout. Kernel itself is loaded at dynamically allocated address. But some x86-specific assumptions may exist.


I have 32 bit x86 UEFI tablet.

1 Like

Does it work with USB or VirtIO boot disk?

nope, but actually it was not a driver issue. I still had come garbage in the page tables. Once I clean that up, I’m able to get a boot to desktop with qemu + edk2-ovmf-ia32 + 32-bit Haiku UEFI loader.

Most of the SMP stuff was also quite easy, msotly copy-paste from 64-bit. (good candidate for a refactor)

I still have some limitations on the memory layout though, as I see we currently rely on identity mapping for a few things related to kernel startup:

  • trampoline code
  • kernel_args
  • initial GDT

So it probably still causes some trouble with >2G RAM… maybe I’ll just copy them to lower 1M. Or perhaps EFI allocate_pages with EFI_ALLOCATE_MAX_ADDRESS.


I’m wondering if it is possible to build 32 bit x86 loader on x86_64 Haiku?

It should be possible, we already do this with the bios loader which is also 32 bit code, IIRC that is the reason that the buildtools include a 32bit targeting gcc aswell.

Keep up the good work and keep us up-to-date. Looking forward to install Haiku on a black MacBook.

You can install haiku with refind there in any case… but native EFI would be cool!

yes, that should be possible… but first I’m trying to solve the simpler task of loading the 32-bit kernel using 32-bit UEFI loader.

the BIOS loader already works this way, i.e. there’s a single BIOS loader that can load either 32-bit or 64-bit kernel
the 64-bit EFI loader is able to load only 64-bit kernel
my initial code for 32-bit EFI loader works with 32-bit kernel, the “hybrid mode” can be a next step.

some code cleanup and refactoring stil to be done.


Great work and I think this is something that could make it into a blog post? I’d love to read how it all works internally for a wider audience :slight_smile: Thanks!


Code cleanup mostly done, I’ve uploaded the code for gerrit review.
One thing remaining, the SMP startup - the code is ready just I have to do some more formatting to align with the coding standards.

There’s also a regression that I’m still trying to track down: depending on memory size, sometimes I get a panic during kernel loading:

"platform_free_region: Unknown region to free??"

A double free somewhere?


That’s what I was suspecting, but then it turned out to be a sign extension issue.

When converting from void* to phys_addr_t ( = uint64), the upper bits are repeated.
e.g. 0xb0000000 → 0xffffffffb0000000 etc.

If I convert from void* to addr_t and then to phys_addr_t then I get better results.

phys_addr_t addr = (phys_addr_t)(addr_t)address;

There’s still an issue with PAE though. If there’s any physical memory region above 4G, the kernel initialization crashes with a KDL when trying to parse the ACPI tables. (no problem with ACPI table init if we have <=4G mem)

Stack looks like this:

 8 825cfd48 (+ 136) 820c0572   <acpi> AcpiTbPrintTableHeader() + 0x1e
 9 825cfdd0 (+  80) 820aef2f   <acpi> AcpiTbParseRootTable() + 0x43
10 825cfe20 (+  48) 820af28b   <acpi> AcpiInitializeTables() + 0x83
11 825cfe50 (+  80) 820a2623   <acpi> _ZL12acpi_std_opslz() + 0x163
12 825cfea0 (+ 128) 800615bd   <kernel_x86> get_module() + 0x48d
13 825cff20 (+ 144) 80148584   <kernel_x86> _Z11ioapic_initP11kernel_args() + 0x54
14 825cffb0 (+  32) 80142df8   <kernel_x86> arch_int_init_io() + 0x18
15 825cffd0 (+  32) 8005d022   <kernel_x86> _start() + 0x242

I wish good luck to invent better - working - memory management :slight_smile:

Once my tablet might be driven by Haiku. :wink:

However it has lesser memory than 4.00 GB, surely … :laughing:

nothing new to be invented here, just a bit more of the good old debugging was needed.

the PAE issue turned out to be one more bad sign extension
as a first idea, I’ve added one more double cast - this time in the ACPI driver:


not very beautiful, but now I get successful bootup also with >=4GB RAM

that’s still in qemu so far
but we’re getting closer to be able to try it on real hardware


Would love to give this a spin on my tiny atom laptop