-
Notifications
You must be signed in to change notification settings - Fork 90
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge branch 'main' of https://github.com/mariapana/docs into gsoc-bl…
…og-3
- Loading branch information
Showing
39 changed files
with
1,291 additions
and
137 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,128 @@ | ||
--- | ||
title: "Multiboot2 Support in Unikraft" | ||
description: | | ||
In my previous blog post, I focused on the first steps of the project: understanding the Multiboot2 protocol and preparing the development environment. Over the following three weeks, I progressed to implementing the necessary changes/additions and then testing the code. | ||
publishedDate: 2024-07-10 | ||
tags: | ||
- gsoc | ||
- gsoc24 | ||
- multiboot2 | ||
- booting | ||
authors: | ||
- Maria Pana | ||
--- | ||
|
||
<img width="100px" src="https://summerofcode.withgoogle.com/assets/media/gsoc-generic-badge.svg" align="right" /> | ||
|
||
In my [previous blog post](https://unikraft.org/blog/2024-06-17-gsoc-multiboot2), I outlined a general strategy for software enhancement, focusing on the first steps of the project: understanding the Multiboot2 protocol and preparing the development environment. | ||
Naturally, over the following three weeks, I progressed to the next stages: implementing the necessary changes/additions and then testing the code. | ||
|
||
## Structuring for Seamless Integration | ||
|
||
In order to have Multiboot2 integrated in Unikraft, I mirrored the existing file organization established for Multiboot and extended it to accommodate the new protocol. | ||
Three core files handle the protocol itself, while the rest of the codebase is updated around them to ensure proper integration and functionality. | ||
Let's take a closer look: | ||
|
||
### `multiboot.S` | ||
|
||
This assembly file plays a pivotal role in preparing a standardized operating environment. | ||
It verifies the system is booted through a compliant Multiboot/Multiboot2 bootloader and manages essential memory relocations. | ||
In this context, the only modifications required were replacing `multiboot.h` and `MULTIBOOT_BOOTLOADER_MAGIC` with their Multiboot2 counterparts, featured depending on the chosen configurations. | ||
|
||
### `multiboot2.py` | ||
|
||
The Python script generates and adds the Multiboot2 and updated ELF headers to the original ELF file. | ||
This ensures that the bootloader information is strategically positioned at the start, facilitating correct system initialization. | ||
Since the Multiboot protocol is limited to 32-bit systems, the `multiboot.py` script also required transforming 64-bit ELFs into 32-bit ones. | ||
This is no longer the case when it comes to Multiboot2, only needing to incorporate the Multiboot2 and updated ELF headers into the file, without any other alterations. | ||
|
||
### `multiboot2.c` | ||
|
||
This C program is responsible for processing boot information from a Multiboot2-compliant bootloader. | ||
It meticulously manages memory regions, integrates boot parameters, and prepares the system for kernel execution by consolidating memory configurations and allocating essential resources. | ||
|
||
Alongside these core files, I made adjustments to adjacent files to seamlessly link everything together and ensure successful booting under Multiboot2 (e.g. duplicating the `mkukimg` script's menuentry to use `multiboot2` instead of `multiboot` etc.). | ||
|
||
## Testing the Waters: Progress and Challenges | ||
|
||
My initial focus was to lay the groundwork by creating the `multiboot.S` and `multiboot2.py` files and testing them with the simple `helloworld` application. | ||
This allowed me to verify that the Multiboot2 header was inserted correctly and the system could boot without major hiccups. | ||
|
||
Of course, debugging became my constant companion during this process. | ||
Tools like `hexdump` and attaching `gdb` to my custom GRUB build proved invaluable. | ||
|
||
I encountered an initial hurdle regarding the ELF file. | ||
After playing around with GRUB error messages and making a "comparative study" of the binaries with Multiboot, Multiboot2, or no additional header, I realized the ELF was lacking the Multiboot2 header altogether. | ||
Some detective work later, I traced the issue to an unlinked `multiboot2.py` script. | ||
|
||
## Multiboot2 Header: A Deep Dive | ||
|
||
So far, I really emphasized the need of the Multiboot2 header. | ||
But what is its role? | ||
|
||
The Multiboot2 header is a structured data block embedded within the bootable system image. | ||
Its purpose is to facilitate the transition of control and information from the bootloader to the kernel during the boot process. | ||
This header acts as a standardized communication channel, ensuring the kernel can access essential details about the system's hardware, memory layout, and other boot-related parameters. | ||
|
||
### Format and Contents | ||
|
||
The Multiboot2 header follows a specific format, starting with a fixed-size header followed by a series of variable-length tags. | ||
|
||
The fixed-size header includes: | ||
|
||
- The magic number `0xE85250D6` indicating a Multiboot2-compliant image | ||
- The target architecture (e.g. `i386`, `x86_64`) | ||
- The header length, including all tags | ||
- The checksum of the header, used for error detection | ||
|
||
I talked a little about the tags in my previous blog post, but to recap, they provide detailed information about the system's memory layout, boot command line, and other essential parameters. | ||
Commonly, each tag has a type, size and payload. | ||
There is a multitude of tags to choose from, depending on the specific requirements of the system, adding to the flexibility of Multiboot2. | ||
|
||
In the context of this project, it may be valuable to note that simply adding the Multiboot2 header to the ELF file is not sufficient. | ||
On top of that, both `multiboot.py` and `multiboot2.py` scripts add an extra ELF header with updated offsets, "sandwiching" the Multiboot2 header between it and the original ELF. | ||
To better visualize this, we can refer to the following diagram: | ||
|
||
```text | ||
┌────────────────────┐ | ||
┌───────│ Updated EHDR |─────────────┐ | ||
| ├────────────────────┤ | | ||
└──────>| Updated PHDR | | | ||
├────────────────────┤ | | ||
| MB2HDR | | | ||
├────────────────────┤ | | ||
┌───────| Original EHDR |────────┐ | | ||
| ├────────────────────┤ | | | ||
└──────>| Original PHDR | | | | ||
├────────────────────┤ | | | ||
| Original SHDR |<───────┘ | | ||
├────────────────────┤ | | ||
| ... | | | ||
├────────────────────┤ | | ||
| Updated SHDR |<────────────┘ | ||
└────────────────────┘ | ||
``` | ||
|
||
This ensures that GRUB identifies the overall file as an ELF and avoids any potential complications along the way. | ||
|
||
### Interaction between Bootloader and Kernel | ||
|
||
The bootloader locates the Multiboot2 header within the ELF file. | ||
After verifying the magic number and architecture compatibility, it parses the header and tags. | ||
Next, the information requested by the tags is placed into the kernel memory and the bootloader passes control to the kernel. | ||
|
||
The kernel, in turn, accesses the Multiboot2 header using the information provided by the bootloader. | ||
It iterates through the tags to extract the necessary data, such as memory regions, boot command line, and other parameters. | ||
This information is used to initialize its own data structures, set up memory management, and configure the system for execution. | ||
|
||
## Next Steps | ||
|
||
With the Multiboot2 header issue resolved, the ELF file is now generated correctly. | ||
However, the system still encounters a roadblock, getting stuck in what appears to be an infinite loop. | ||
More debugging using `gdb` for me it is! | ||
|
||
After I pinpoint and fix the problem, I will move on to: | ||
|
||
- Refactoring `multiboot2.py` to handle tag inclusion more generically | ||
- Implementing the `multiboot2.c` file | ||
- Testing the new modifications once again |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,60 @@ | ||
--- | ||
title: "GSoC'24: UEFI Graphics Output Protocol Support in Unikraft, Part II" | ||
description: | | ||
This is the second post in a series of posts where I talk about my progress with the project. | ||
publishedDate: 2024-07-10 | ||
image: /images/unikraft-gsoc24.png | ||
authors: | ||
- Sriprad Potukuchi | ||
tags: | ||
- gsoc | ||
- gsoc24 | ||
- uefi | ||
- booting | ||
--- | ||
|
||
## Project Overview | ||
|
||
The widely available and standardized [UEFI Graphics Output Protocol](https://uefi.org/specs/UEFI/2.10/12_Protocols_Console_Support.html#efi-graphics-output-protocol) (GOP) interface is an excellent alternative to VGA or serial port consoles for printing logs to the screen. | ||
|
||
This project aims to implement a UEFI GOP based console. | ||
For more information, check out [Part I](https://unikraft.org/blog/2024-06-18-gsoc-uefi-gop) of this series. | ||
|
||
## Progress | ||
|
||
- Using a placeholder [font](https://github.com/dhepper/font8x8), it is now possible to print null-terminated strings to the screens. | ||
<Image | ||
src="/images/uefi-gop-first-text-render.png" | ||
/> | ||
|
||
- It is also possible to scale the font in both the axes independently | ||
- No scaling | ||
<Image | ||
src="/images/uefi-gop-scaled-text-1.png" | ||
/> | ||
- Scaled Y-axis | ||
<Image | ||
src="/images/uefi-gop-scaled-text-2.png" | ||
/> | ||
|
||
- I've also implemented scrolling. When all the lines are filled and a new log needs to be printed, the current logs on the screen are scrolled up (using `memcpy`) | ||
<Image | ||
src="/images/uefi-gop-before-scrolling.png" | ||
/> | ||
<Image | ||
src="/images/uefi-gop-after-scrolling.png" | ||
/> | ||
|
||
Right now, scrolling moves all the framebuffer data in place. | ||
Reads and writes in framebuffer memory are slower because the video adapter actually syncs the framebuffer with the screen. | ||
This needs to be optimized! | ||
|
||
## Next Steps | ||
|
||
- Finalize a font! | ||
- Optimize scrolling (by maintaining an additional buffer) | ||
- Look into [this PR](https://github.com/unikraft/unikraft/pull/1464), which adds a generic console interface. | ||
|
||
## Acknowledgement | ||
|
||
I would like to thank all the great Unikraft folk for being a great community! |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,86 @@ | ||
--- | ||
title: "GSoC'24: Linux x86 Boot Protocol Support" | ||
description: | | ||
The Linux boot protocol plays an important role in the initialization of the Linux operating system, emphasizing the importance of system optimization and scalability. | ||
publishedDate: 2024-07-10 | ||
image: /images/unikraft-gsoc24.png | ||
tags: | ||
- gsoc | ||
- gsoc24 | ||
- booting | ||
authors: | ||
- Mihnea Firoiu | ||
--- | ||
|
||
As I wrote in the previous blog post, my first objective is to make Unikraft boot on QEMU using the Linux x86 boot protocol. | ||
Here I will present my progress so far and different challenges I faced while working towards my goal. | ||
|
||
## Where does QEMU handle the lxboot header? | ||
|
||
By using the `git grep` command, I found that `QEMU 9.0.1` handles the Linux x86 boot protocol in the [x86.c](https://github.com/qemu/qemu/blob/stable-9.0/hw/i386/x86.c) file. | ||
Everything happens in the `x86_load_linux` function. | ||
|
||
### Fields used by QEMU | ||
|
||
These are as follows: | ||
|
||
* 0x202: HEADER | ||
* 0x206: VERSION | ||
* 0x211: LOADFLAGS | ||
* 0x236: XLOADFLAGS | ||
* 0x22c: INITRD_ADDR_MAX | ||
* 0x228: CMD_LINE_PTR | ||
* 0x1fa: VID_MODE | ||
* 0x210: TYPE_OF_LOADER | ||
* 0x224: HEAP_END_PTR | ||
* 0x1f1: SETUP_SECTS | ||
* 0x250: SETUP_DATA | ||
* 0x218: RAMDISK_IMAGE | ||
* 0x21c: RAMDISK_SIZE | ||
|
||
As you can see, only 13 out of 39 fields are used. | ||
Out of these, 6 are read by QEMU: | ||
|
||
* 0x202: HEADER | ||
* 0x206: VERSION | ||
* 0x211: LOADFLAGS | ||
* 0x236: XLOADFLAGS | ||
* 0x22c: INITRD_ADDR_MAX | ||
* 0x1f1: SETUP_SECTS | ||
|
||
And 7 are written by QEMU: | ||
|
||
* 0x228: CMD_LINE_PTR | ||
* 0x1fa: VID_MODE | ||
* 0x210: TYPE_OF_LOADER | ||
* 0x224: HEAP_END_PTR | ||
* 0x250: SETUP_DATA | ||
* 0x218: RAMDISK_IMAGE | ||
* 0x21c: RAMDISK_SIZE | ||
|
||
## Debugging and testing | ||
|
||
The application I am using to test the `mklinux_x86.py` file is [app-helloworld](https://github.com/unikraft/app-helloworld/tree/stable). | ||
By using multiple `printf` and `exit` calls inside the `x86_load_linux` function, I was able to determine the way QEMU uses the header. | ||
Another useful tool was `hexdump`,that was used to look at how my script builds the header. | ||
|
||
## Challenges | ||
|
||
For starters, I could not figure out why the header created by the script did not align to what QEMU expected. | ||
The problem was that the header, as presented in the documentation, starts at offset `0x1f1`, not `0x0`. | ||
To fix it I had to add 0x1f1 zeros. | ||
|
||
Another issue was with integrating it in Unikraft. | ||
Eventually I figured it out, with help from my mentors. | ||
|
||
## Integration with Unikraft | ||
|
||
Although debugging could be done only by running the `mklinux_x86.py` script and looking at the header, I wanted to test by integrating everything in Unikraft. | ||
For doing this I had to modify the following files: [Linker.uk](https://github.com/unikraft/unikraft/blob/staging/plat/kvm/Linker.uk), [Config.uk](https://github.com/unikraft/unikraft/blob/staging/plat/kvm/Config.uk) and [Makefile.rules](https://github.com/unikraft/unikraft/blob/staging/plat/common/Makefile.rules). | ||
|
||
## Next steps | ||
|
||
At the moment, when I try to run, it loops indefinitely. | ||
I have to debug and find out what does not work. | ||
|
||
Additionally I am going to look into SeaBIOS/qboot/GRUB2 to see how the jumping to the kernel happens and I will write the needed 16-bit and 32-bit assembly stubs. |
Oops, something went wrong.