|
|
4 months ago | |
|---|---|---|
| Development | 6 months ago | |
| LICENSES | 10 months ago | |
| M2-Mesoplanet@4bf3e2eded | 4 months ago | |
| M2-Planet@f02aaaf67b | 4 months ago | |
| M2libc@1139b2bbf5 | 4 months ago | |
| amd64 | 4 months ago | |
| bootstrap-seeds@491b485769 | 7 months ago | |
| mescc-tools@3f94182467 | 4 months ago | |
| mescc-tools-extra@5a334713fa | 5 months ago | |
| .gitignore | 9 months ago | |
| .gitmodules | 5 months ago | |
| Makefile | 5 months ago | |
| README.md | 4 months ago | |
| amd64.answers | 4 months ago | |
| kaem.amd64 | 5 months ago | |
README.md
stage0-uefi
This is a port of stage0-posix (https://github.com/oriansj/stage0-posix) to UEFI. Its purpose is to start with a tiny binary seed that can be manually inspected and use it to build C toolchain and some extra tools.
Usage
make build/disk.img will create bootable images with stage0-uefi. You can use dd to write them on bootable media.
make qemu will create disk image and launch it in QEMU. To test this in QEMU, you need to provide some QEMU compatible UEFI implementation. In particular, you can use Tianocore's OVMF. make qemu is looking for it in a few paths where distros tend to install it. If not you can specify it via make qemu OVMF_IMG=/path/to/OVMF_CODE.fd
Minimal images
It is possible to create images without kaem-optional-seed.efi that contain only hex0-seed.efi. Those are a bit less automated but if your UEFI implementation lets you pass command line arguments, you can recreate kaem using just hex0.
make MINIMAL=1 qemu.- Open UEFI settings (often F2 but it varies from system to system).
- Go to
Add Boot optionand pick appropriate boot volume that containshex0-seed.efi. - Pick
\bootstrap-seeds\UEFI\amd64\hex0-seed.efi. - Description can be anything, say
kaem-seed. - Optional Data has to be
hex0 amd64\kaem-minimal.hex0 EFI\BOOT\BOOTX64.efi. - Save boot entry and boot it. This will build kaem-minimal and exit.
- Now boot normally from bootable media.
Stages
kaem-optional (Optional "shell")
kaem-optional is a trivial shell that can read list of commands together with their command line arguments from a file and executes them. It also supports line comments but has no other features.
hex0
hex0 is fairly trivial to implement and for each pair of hexadecimals characters it outputs a byte. We have also added two types of line comments (# and ;) to create a well commented lines like
# :loop_options [_start + 0x6F]
4839D3 ; cmp_rbx,rdx # Check if we are done
74 14 ; je !loop_options_done # We are done
4883EB 02 ; sub_rbx, !2 # --options
In the first steps we use initial hex0 binary seed to rebuild kaem-optional and hex0 from their source.
hex0 code is somewhat tedious to read and write as it is basically a well documented machine code. We have to manually calculate all jumps in the code.
hex1
This is the last program that has to be written in hex0 language. hex1 is a simple extension of hex0 and adds a single character labels and allows calculating 32-bit offsets from current position in the code to the label. hex1 code might look like
:a #:loop_options
4839D3 ; cmp_rbx,rdx # Check if we are done
0F84 %b ; je %loop_options_done # We are done
4883EB 02 ; sub_rbx, !2 # --options
hex2
hex2 is our final hex language that adds support for labels of arbitrary length. It also allows accessing them via 8, 16, 32-bit relative addresses (!, @, %) and via 16-bit or 32-bit ($, &) absolute addresses though only the former addressing mode is used in stage0-uefi.
:loop_options
4839D3 ; cmp_rbx,rdx # Check if we are done
74 !loop_options_done ; je8 !loop_options_done # We are done
4883EB 02 ; sub_rbx, !2 # --options
catm
catm allows concatenating files via catm.efi output_file input1 input2 ... inputN. This allows us to split shared code into separate files. We will first use it to append PE header to .hex2 files. Before this step PE header had to be included in the source file itself.
M0
The M0 assembly language is the simplest assembly language you can create that enables the creation of real world programs with practical application. It includes only a single keyword: DEFINE and leverages the language properties of hex2 along with extending the behavior to populate immediate values of various sizes and formats.
Thus M0 code looks like
DEFINE cmp_rbx,rdx 4839D3
DEFINE je 0F84
DEFINE sub_rbx, 4881EB
:loop_options
cmp_rbx,rdx # Check if we are done
je %loop_options_done # We are done
sub_rbx, %2 # --options
cc_amd64
The cc_amd64 implements a subset of the C language designed in M0 assembly. It is somewhat limited subset of C but complete enough to make it easy to write a real C compiler written in the C subset that cc_amd64 supports.
At this stage we start using M2libc (https://github.com/oriansj/M2libc/) as our C library. In fact, M2libc ships two versions of C library. At this stage we use a single-file (bootstrap.c) C library that contains just enough to build M2-Planet.
M2-Planet
This is the only C program that we build with cc_amd64. M2-Planet (https://github.com/oriansj/M2-Planet) supports a larger subset of C than cc_amd64 and we are somewhat closer to C89 (it does not implement all C89 features but on the other hand it does have some C99 features). M2-Planet also includes a very basic preprocessor, so we can use stuff like #define, #ifdef.
M2-Planet supports generating code for various architectures including x86, amd64, armv7, aarch64, riscv32 and riscv64.
M2-Planet is also capable of using full M2libc C library that has more features and optimizations compared to bootstrap version of M2libc.
M2libc hides all UEFI specific bits inside it, so that applications written for POSIX (such as M2-Planet) can run without any source modifications.
C versions of linker and assembler
We then build C version of hex2 (also called hex2) and C version of M0 called M1. These are more capable than their platform specific hex counterparts and are fully cross-platform. Thus we can now have the whole toolchain written in C.
kaem
We now build kaem which is a more capable version of kaem-optional and adds support for variables, environmental variables, conditionals, aliases. It also has various built-ins such as cd and echo.
M2-Planet (built against full M2libc)
We can now rebuild M2-Planet so that it itself can benefit from full M2libc.
M2-Mesoplanet
M2-Mesoplanet is a preprocessor that is more capable than M2-Planet and supports #include statements. It can also launch compiler, assembler and linker, so we don't need to invoke them
manually.
blood-elf
blood-elf is a tool that can generate a bit of debug info for POSIX binaries. It is not immediately useful for UEFI but
it might be useful if one wants to build debuggable POSIX binaries on UEFI.
mescc-tools-extra
Some extra tools such as sha256sum, untar, ungz, unbz2, mkdir, rm and a few others.