Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Support for other architectures #299

Open
JakubGawron1 opened this issue Dec 20, 2022 · 12 comments
Open

Support for other architectures #299

JakubGawron1 opened this issue Dec 20, 2022 · 12 comments

Comments

@JakubGawron1
Copy link

Hi. Overall, I am impressed with this project, and I am in great admiration. But I have a question, are there any plans to create a bootloader for other processor architectures, e.g. AARCH64, RISC-V? I'm not saying right away that in this repository, maybe a separate bootloader in a separate repository? If such an idea was possible, could I help in some way?
Thank you in advance for your answer and best regards. 😊

@phil-opp
Copy link
Member

phil-opp commented Jan 2, 2023

I don't have plans to port the crate to other CPU architectures right now, but I would like to see this as well!

As far as I know, @tsoutsman is currently working on an UEFI bootloader for the Theseus OS project with the goal to support both x86_64 and aarch64 booting. Maybe they can use some help?

(As a side note, I would love to integrate this into the bootloader crate at some point if possible.)

@tsoutsman
Copy link
Contributor

Yea, the UEFI bootloader supports x86_64 and should support aarch64 fairly soon.

I would love to upstream the changes (especially considering a lot of the code is taken from bootloader, which I have yet to give credit to), but quite a few of the changes are Theseus-specific.

The big changes that were necessary for the bootloader to work on Theseus were:

  • Respecting the load address of the kernel segments
  • Adding support for arbitrary files in the UEFI image and providing information about them in the boot info
  • Adding kernel ELF sections to the boot info

Only the first point would be a significant hurdle to overcome, which is more a problem with Theseus than the bootloader. Ideally, I'd make Theseus work when loaded at an arbitrary physical address, at which point I could port the changes from uefi-bootloader to this repo.

If such an idea was possible, could I help in some way?

The way I approached it in uefi-bootloader is I took all the x86_64 specific code and placed it in a separate arch directory (akin to std::sys). Then, depending on the target_arch, mod.rs exports a different module. arch/unsupported contains the skeleton API that the other modules should export.

You could start by doing a similar thing for this repo.

@phil-opp
Copy link
Member

phil-opp commented Jan 2, 2023

  • Respecting the load address of the kernel segments

Interesting, so you load the kernel directly at the physical address specified in the ELF file? What happens if that address is already in used or not available (e.g. marked as reserved by the hardware)?

  • Adding support for arbitrary files in the UEFI image and providing information about them in the boot info

We have an open PR at #302 that tries to do something similar, but limited to a single file. Maybe we should generalize this to allow multiple, arbitrary files...

  • Adding kernel ELF sections to the boot info

You mean a list of all the sections and their start addresses and sizes? I'm fine with adding something like this.

@bjorn3
Copy link
Contributor

bjorn3 commented Jan 2, 2023

  • Adding kernel ELF sections to the boot info

You mean a list of all the sections and their start addresses and sizes? I'm fine with adding something like this.

You only need to point to the program header (and if you relocate, the offset by which it was relocated), right? Then the kernel itself can parse the program header to find the location of each segment as well as other program table entries (like the dynamic table location, notes, ...) if necessary. This is what is done on for example Linux for userspace programs to allow the dynamic linker access to this information.

@tsoutsman
Copy link
Contributor

tsoutsman commented Jan 2, 2023

Interesting, so you load the kernel directly at the physical address specified in the ELF file? What happens if that address is already in used or not available (e.g. marked as reserved by the hardware)?

We give up. It's a problem in Theseus that needs to be fixed.

We have an open PR at #302 that tries to do something similar, but limited to a single file. Maybe we should generalize this to allow multiple, arbitrary files...

FWIW here's my janky implementation. It iterates over a directory called modules (this could obv be changed) and loads all the files into a singular region of memory with a custom memory type. For each "module" (i.e. file), it records the offset into the memory region, name (jankily stored in an array), and length. These modules are then stored in the boot info. When parsing the modules in Theseus, we add the module offset to the start of the region to get the starting address of the module.

You only need to point to the program header (and if you relocate, the offset by which it was relocated), right? Then the kernel can parse the program header to find the location of each segment's location and other program table entries (like the dynamic table location, notes, ...) if necessary. This is what is done on for example Linux for userspace programs to allow the dynamic linker access to this information.

Theseus specifically needs the section headers, which it has no way of accessing since AFAICT the section header table/.shstrtab aren't included in the load segments and, thus, aren't loaded by the bootloader. FWIW multiboot2 provides the ELF sections tag.

I don't think it can parse the program headers because they wouldn't be loaded, either.

@bjorn3
Copy link
Contributor

bjorn3 commented Jan 2, 2023

Theseus specifically needs the section headers, which it has no way of accessing since AFAICT the section header table/.shstrtab aren't included in the load segments and, thus, aren't loaded by the bootloader. FWIW multiboot2 provides the ELF sections tag.

You can write a linker script that marks the section table as allocated and thus produces a load segment for it. I can understand that it is less convenient though.

I don't think it can parse the program headers because they wouldn't be loaded, either.

They are loaded by default. Here /bin/ls on my system as example:

ProgramHeaders(11):
  Idx   Type              Flags   Offset     Vaddr      Paddr      Filesz     Memsz      Align   
  0     PT_PHDR           R       0x40       0x40       0x40       0x268      0x268      0x8     
  1     PT_INTERP         R       0x2a8      0x2a8      0x2a8      0x1c       0x1c       0x1     
  2     PT_LOAD           R       0x0        0x0        0x0        0x3538     0x3538     0x1000  
  3     PT_LOAD           R+X     0x4000     0x4000     0x4000     0x141a9    0x141a9    0x1000  
  4     PT_LOAD           R       0x19000    0x19000    0x19000    0x8f08     0x8f08     0x1000  
  5     PT_LOAD           RW      0x22350    0x23350    0x23350    0x1278     0x2568     0x1000  
  6     PT_DYNAMIC        RW      0x22dd8    0x23dd8    0x23dd8    0x1f0      0x1f0      0x8     
  7     PT_NOTE           R       0x2c4      0x2c4      0x2c4      0x44       0x44       0x4     
  8     PT_GNU_EH_FRAME   R       0x1e324    0x1e324    0x1e324    0x944      0x944      0x4     
  9     PT_GNU_STACK      RW      0x0        0x0        0x0        0x0        0x0        0x10    
  10    PT_GNU_RELRO      R       0x22350    0x23350    0x23350    0xcb0      0xcb0      0x1     

The first PT_LOAD covers the elf header, the program headers and some other things. The PT_PHDR points to the program header itself.

@jasoncouture
Copy link
Contributor

jasoncouture commented Jan 2, 2023

Adding support for arbitrary files in the UEFI image and providing information about them in the boot info

We have an open PR at #302 that tries to do something similar, but limited to a single file. Maybe we should generalize this to allow multiple, arbitrary files...

Do we really want to load multiple files? Would some kind of image file do instead?
If we use an archive, kernels will be more portable to other bootloaders, such as multiboot2
This also allows kernels to use whatever format they desire, such as CPIO, or something native that has (in my case) security information (Not *NIX UID/GID, more akin to SELinux/Windows NT).

Trade off thoughts comment here: #302 (comment)

@bjorn3
Copy link
Contributor

bjorn3 commented Jan 2, 2023

I assume the idea is that the archive is more like concatenating multiple files together + some metadata to know where the individual members start and end (and possibly a name), where this archive is parsed by the bootloader and then each individual member is passed separately to the kernel. Not a full fledged filesystem with directories, timestamps and security information. If you want that you did still make your own archive and treat it as a single extra file that could get wrapped into the archive format of the bootloader if there are multiple extra files.

Multiboot2 already has support for multiple files in the form of boot modules. I think grub2 allows reading them from separate files using the multiboot2_module command.

@jasoncouture
Copy link
Contributor

I assume the idea is that the archive is more like concatenating multiple files together + some metadata to know where the individual members start and end (and possibly a name), where this archive is parsed by the bootloader and then each individual member is passed separately to the kernel. Not a full fledged filesystem with directories, timestamps and security information. If you want that you did still make your own archive and treat it as a single extra file that could get wrapped into the archive format of the bootloader if there are multiple extra files.

Multiboot2 already has support for multiple files in the form of boot modules. I think grub2 allows reading them from separate files using the multiboot2_module command.

I was unable to locate anything in either the grub2 code, or mutliple microkenrels on github. (Doesn't mean it doesn't exist)

Everything I can find supports loading a single file (such as linux's initrd). And the bootloader does zero parsing on the file, it simply loads it into ram, and feeds a pointer to it to the kerenl.

@tsoutsman
Copy link
Contributor

tsoutsman commented Jan 3, 2023

I was unable to locate anything in either the grub2 code, or mutliple microkenrels on github. (Doesn't mean it doesn't exist)

https://github.com/rhboot/grub2/blob/c2e640266247e3e0d3268f5ef20a734f5800f577/grub-core/loader/multiboot.c#L362-L442

I'm not against an archive/ramdisk because it would simplify the code in the bootloader a fair bit. I only implemented "modules" for UEFI, and I'd imagine it's quite a bit harder for BIOS.

@jasoncouture
Copy link
Contributor

Wow, you learn something new every day!

I'll take a stab at it after #301 is merged. Maybe we can get both?

@phil-opp
Copy link
Member

phil-opp commented Jan 4, 2023

I'm fine with merging a simple ramdisk first since this is a commonly used feature. We can generalize this to a set of multiple files/modules later if needed.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

5 participants