Cdev wrote:Hey bzt.
This is a general questions post (very much on-topic, but possibly these are repeated - though I could not find answers), and I apologize in advance if it's a bit too lengthy or feature a few "stupid questions".
Have no worries, it's better if you ask even if the question is stupid than not to ask at all. You can only learn if you have questions.
It was hard to figure out what you mean, because mmap and paging are two totally different things, but you seem to mix those badly. The first is a list of memory areas provided by the firmware (no 4G nor 16G limit for that, as a matter of fact records could hold any value up to 64 bits), and the latter is set up by BOOTBOOT and used by the MMU to place your kernel in higher-half.
Cdev wrote:1. Is the 4GiB mmap limit on x86_64 BIOS concrete; is there any hope of change there ? The logic seems to be that it loads in protected mode, so what if I chain-load it from Grub or such a thing ? I'm not too worried about the other features of level 2 , just this one matters to me ATM.
There's no such thing, "4GiB mmap limit". First, Grub does not set the paging for you, as multiboot is for prot-mode. BOOTBOOT loads a long-mode kernel in higher half, and for that, paging is a must (different to mmap).
Second, chainloading through Grub works out-of-the-box. But you could also load bootboot.bin as a multiboot "kernel", and then BOOTBOOT will set up the paging for you. (The reason why only 4G is mapped with the BIOS loader is, because it loads in protmode, it can't access more memory than that, so it surely loads the initrd in the first 4G. There's nothing it could pass to the kernel above 4G, everything it sets up must be in the first 4G because of the protmode addressing.)
Cdev wrote:2. Why does BOOTBOOT restrict the mmap to 16GiB on other platforms; is there any hope of change there ?
It does not restrict anything. Your kernel supposed to set up its paging tables the way it wants them; BOOTBOOT only provides a minimal paging which is mandatory to enter long mode. Your kernel not supposed to use that for long, only in the initialization phase. (Same way like you don't rely on Grub's GDT nor stack, instead you set them up for your kernel as soon as possible.)
Cdev wrote:3. AFAIK, upon last check a few weeks back, the "mkbootimg" binary is making BIOS-only images
I have absolutely no clue what makes you think that.
Cdev wrote:(tried VBox UEFI and real hw UEFI, didn't boot) ?
Then there were something else, misconfiguration perhaps. I would need the exact error messages to help you, for example, did you set up the boot devices to boot from your device?
FYI, I test BOOTBOOT with bochs, qemu, and VirtualBox too. Works for me. There are lot of people using BOOTBOOT on real machines with UEFI, that works too.
Cdev wrote:I would like to generate x86 images that could boot on UEFI + BIOS
Then this is your lucky day, that's exactly what BOOTBOOT's mkbootimg does.
Cdev wrote:(I believe the term is El-Torito ?). How can this be done ?
Nope, El-Torito is for CD and DVD-ROMs. Basically mkbootimg creates a special hybrid image which you can boot from an USB stick on BIOS machines as well as on UEFI machines; or you could burn the image to a CD-ROM and boot that disc on BIOS machines or UEFI machines (there are 4 different booting mechanisms here, BIOS+disk, UEFI+disk, BIOS+cdrom, UEFI+cdrom). This has been tested very throughfully by many people, not just by me, even in the wildest scenarios. For example last time I had to modify the loader was for someone who used Grub-mkrescue to have a boot manager, loaded BOOTBOOT as a multiboot kernel from the CDROM to provide long mode enviroment, but wanted to load the initrd from the ESP on the hard-drive. Quite extravagant configuration if you ask me, but even this works.
Cdev wrote:Also, how would one use mkbootimg to generate an image for other archs than x86_64 ?
That's simple. Take a look at the
Makefile in the images directory. The one and only difference between generating the x86 bootable image and the ARM bootable image is
which kernel is copied into the initrd. Everything else is automated and taken care for you.
Cdev wrote:4. I could not understand the spec PDF (it seemed a bit too concise to me

) on how one should go about getting the mmap or dealing with SMP, is this covered elsewhere ?
It is covered in the PDF pretty detailed. About the mmap, you can find all the information you need on page 16. About paging, see page 18. For the SMP, you can even find example codes in the Appendix on page 28 on how to tell APs from BP apart.
In a nutshell, memory map is passed in the bootboot struct, as an array of (start,length) pairs, and you have convenience macros to deal with it (oh, there are comments in the bootboot.h too explaining those macros), and you don't have to worry about SMP because your kernel is started on all cores in parallel. If you want different code to run on each core, then you have to query the core id (that's what you can find in the Appendix), but also mentioned in the README.md
Cdev wrote:5. Why does mkbootimg need two configuration files ? Is it necessary to have a JSON + a .txt ? Maybe it is for some reason, I just found it odd.
It doesn't. The text config file is for the loader, parsed
during boot. The JSON is for the mkbootimg, parsed
in compilation time when the disk image is constructed. Mkbootimg needs the boot-time config so that it can save it into the image for the loader (otherwise mkbootimg checks that config to get the name of the kernel should you use a non-standard name for it).
Cdev wrote:6. By RasPi 3+ support, do you include the RasPi 400 (the one with the keyboard) ?
I don't have that hardware, so I cannot test it. If someone can provide me detailed feedback, then I'm willing to add support for the RPi 400.
Cdev wrote:7. Is it possible to specify a stack size for the kernel in the BOOTBOOT protocol ?
Yes, for the level 2 loaders (basically all except the BIOS version). But you should not rely on the boot environment for too long, the boot stacks are small, because their only purpose to allow your kernel init to run to set up the final stacks. BOOTBOOT does not tell you how to write your OS, it only provides a minimal environment so that you can start your kernel without Assembly hacks and trampoline codes. But you still have to write your OS.
Cdev wrote:8. Does BOOTBOOT supply some way to handle SMP cross platform , or is this left to the kernel to handle ?
BOOTBOOT supports SMP in a cross-platform way, your kernel is started on all cores in parallel, no matter the architecture (and this will be the same even when new architectures will be added to BOOTBOOT in the future).
Cdev wrote:9. The spec says something about the x86_64 BIOS Initrd is restricted to "~96k" ; is there any hope for change there ?
Nope, the initrd size is restricted to 16M. That ~96k limitation is only for the BIOS Expansion ROM image, and that limitation is mandated by the BIOS Boot Specification, so unlikely to change. If that's not enough for you, then don't load the initrd from ROM; you can load the initrd from other sources like from disk for example. Since you're not planning to create an embedded appliance, do not mind ROM boot, focus on ESP:\BOOTBOOT\INITRD only.
Cdev wrote:10. The mmap is said to not be in order; is there any hope for change there ? Because (maybe there is a workaround but) I use an explicit free list allocator with entires in ascending order (similar to the one in K&R unit

, and to sort a variable number of mmap entries would itself require a malloc() , but the mmap is needed to do a malloc (ouch).
Just as with all the other things, you're not supposed to use the boot environment as-is. You should parse the mmap and build up your memory allocator's lists the way you seem them fit. (Sorting in place does not need malloc BTW)
For the records, there's a 99.99999% chance that BOOTBOOT passes the mmap in order, because both E820 and UEFI MemoryMap should be sorted. However since BOOTBOOT passes the mmap in the exact order the firmware gave it the map, it cannot guarantee that all firmware will only report ordered entries. If your memory allocator depends on an ordered list, then it's better if you sort it yourself just to be on the safe side. For example when you copy the free memory records from the BOOTBOOT mmap to your allocator's free list, you could use
insertion sort. That's fast and simple. Or you could use quick-sort, but that's harder to port. Neither of these require malloc.
Cdev wrote:Thanks a lot for enduring this rather long post, and thanks for putting in the time and effort to make a viable no-nonsense bootloader for those targeting 64-bit RasPi. If the mmap limitations are permanent , I might have to (much to my disliking) have two source files for dealing with the x86 btldr (limine) and the RasPi/ btldr (bootboot) - or arrange some sort of abstraction for the kernel to work regardless of bootloader - so before I did that, I though I should consult you.
You're welcome, took me a while to answer. And again,
there's absolutely no limitations on the paging, nor on the memory map. It is totally up to your kernel how you do it.
Cheers,
bzt