Browse Source

Update README and licensing information.

Giovanni Mascellani 4 years ago
parent
commit
01ae2c5b0a
14 changed files with 581 additions and 718 deletions
  1. 34 348
      README.md
  2. 325 0
      README.old.md
  3. 16 0
      diskfs/asmc_api.h
  4. 16 0
      diskfs/coros.h
  5. 16 0
      diskfs/ipxe_asmc.h
  6. 16 0
      diskfs/ipxe_asmc_structs.h
  7. 17 0
      diskfs/ipxe_handover.h
  8. 16 0
      diskfs/run_ipxe.c
  9. 16 0
      diskfs/run_tcc.c
  10. 17 0
      diskfs/run_tcc.h
  11. 16 0
      diskfs/run_tcc_ipxe.c
  12. 16 0
      diskfs/run_tcc_sc.c
  13. 16 0
      http/continue.c
  14. 44 370
      http/continue2.c

+ 34 - 348
README.md

@@ -95,264 +95,13 @@ Then:
 (if your host system supports it, you can add `-enable-kvm` to benefit
 of KVM acceleration)
 
-WARNING! ATTENTION! Remember that you are giving full control over you
-hardware to an experimental program whose author is not an expert
-operating system programmer: it could have bugs and overwrite your
-disk, damage the hardware and whatever. I only run it on an old
-otherwise unused laptop that once belonged to my grandmother. No
-problem has ever become apparent, but care is never too much!
-
-### How to interpret all the writings
-
-For the full story, read below and the code. However, just to have an
-idea of what is happening, if you use the command above to boot
-`boot_asmg.x86` the following will happen:
-
- * The first log lines are written by the bootloader. At this point it
-   is mostly concerned with loading to RAM the actual kernel, enabling
-   some obscure features of the PC platform used to boot properly and
-   entering the CPU's protected mode.
-
- * At some point `asmc` kernel is finally ran, and it writes `Hello, asmc!`
-   to the log. There is where the `asmc` binary seed first
-   enters execution. It will just initialize some data structures and
-   then invoke its embedded G compiler to compile the file `main.g`
-   and then call the `main` routine.
-
- * This is the point where for the first time code that has just been
-   compiled is fed to the CPU, so in a sense the binary seed is not in
-   control of the main program any more (but still gets called as a
-   library, for example to compile other G sources). The message
-   `Hello, G!` is written to the log and immediately after other G
-   sources are compiled, first to introduce some library code (like
-   malloc/free, code for handling dynamic vectors and maps, some basic
-   disk/filesystem driver and other utilities) and then to compile an
-   assembler and a C compiler. These two compilers are not meant to be
-   complete: they are just enough to build the following step, which
-   is tinycc.
-
- * Then a suite of C test programs is compiled and executed. They test
-   part of the C compiler and the C standard library. In line of
-   principle all the test should pass and all `malloc`-s should be
-   `free`-ed.
-
- * After all tests have passed, tinycc is finally compiled. This takes
-   a bit (around 20 seconds on my machine, my KVM enable), because the
-   previous C compiler is quite inefficient. During preprocessing
-   progress is indicated by open and closed square brackets, which
-   indicate when a new file is included or finished to include. During
-   compilation (which consists of three stages), progress is indicated
-   by dots, where each dot correspons to a thousands tokens processed.
-
- * At last, tinycc is ran, by mean of its `libtcc` interface. A small
-   test program is compiled and executed, showing a glimpse of the
-   third level of compiled code from the beginning of the `asmc` run.
-
- * In the end some statistics are printed, hopefully showing that all
-   allocated memory have been deallocated (not that it matters much,
-   since the machine is going to be powered off anyway, but I like
-   resources to be deinitialized properly).
-
-### How to fiddle with flags
-
-`asmg`'s behaviour can be customized thanks to some flags at the
-beginning of the `asmg/main.g` file. There you can enable:
-
- * `RUN_ASM`: it will compile an assembler and then run it on the file
-   `test/test.asm`. The assembler is not complete at all, but ideally
-   it should be more or less enough to assemble a [lightly
-   patched](https://gitlab.com/giomasce/fasm) version of
-   [FASM](https://flatassembler.net/) (see next point).
-
- * `RUN_FASM` (currently unmaintained): compile the assembler and then
-   use it to assemble FASM, as mentioned above. In theory it should
-   work, but in practice it does not: the assembled FASM crashes for
-   some reason I could not understand. There is definitely a bug in my
-   assembler (or at least some unmet FASM assumption), but I could not
-   find it so far. However, the bulk of the project is not here.
-
- * `RUN_C`: it will compile the assembler and the C compiler and then
-   use them to compile the program in `diskfs/tests/test.c`. In the
-   source code there are flags to dump debugging information,
-   including a dump of the machine code itself. It is useful to debug
-   the C compiler itself. Also, feel free to edit the test program to
-   test your own C programs (but expect frequent breakages!).
-
- * `RUN_MESCC` (currently unmaintained; only this port is
-   unmaintained, the original project is going on): it will compile a
-   port of the
-   [mescc](https://github.com/oriansj/mescc-tools)/[M2-Planet](https://github.com/oriansj/M2-Planet)
-   toolchain, which is basically an indepdendent C compiler with
-   different features and bugs than mine. This port just tracks the
-   upstream program, no original development is done here. See below
-   from more precise links. The test program in `test/test_mes.c` will
-   then be compiled and executed.
-
- * `RUN_MCPP` (currently unmaintained): it will compile the assembler
-   and the C compiler and then use them to try compiling a [lightly
-   patched](https://gitlab.com/giomasce/mcpp) version of
-   [mcpp](http://mcpp.sourceforge.net/), which is a complete C
-   preprocessor. Since the preprocessor embedded in `asmc`'s C
-   compiler is rather lacking, the idea is that mcpp could be used
-   instead to compile C sources that require deep preprocessing
-   capabilities. However, at this point, mcpp itself does not compile,
-   so at some point `asmc` with die with a failed assertion. Also, it
-   nowadays seems that `asmc` is able to preprocess tinycc by itself,
-   so there is no point anymore in going forward with this subproject.
-
- * `RUN_TINYCC`: here is where the juice stays! This will compile the
-   assembler and the C compiler, and then compile tinycc, as mentioned
-   above. Then it will use tinycc to compile and execute a little C
-   program. In the future the bootstrapping chain will continue here.
-
- * `TEST_MAP`: there are three implementation of an associative array
-   in `asmc`, of increasing complexity (see below). This tests the
-   implementation, and was used in the past to check new
-   implementations for correctness.
-
- * `TEST_INT64`: implementing 64 bits integers on a 32 bits platform
-   is somewhat tricky. The G language itself only supports 32 bits
-   numbers, so some additional Assembly code was required to implement
-   64 bits operations. Also, the division code is particularly
-   tricky. However, 64 bits integers are required by tinycc, which
-   needs support for `long long` types, so they were implemented at
-   some point. This enables some tests on the resulting implemntation.
-
- * `TEST_C`: it will compile the C compiler and run the test
-   suite.
-
-By default thre three `TEST_*` flags and `RUN_TINYCC` are enabled in
-`asmc`.
-
-There is also another pack of flags that control which `malloc`
-implementation `asmg` is going to use. There are four at this
-point. All of them gather memory with the `platform_allocate` call
-(see below), which is similary to UNIX' `brk` (and does not permit to
-release memory back).
-
- * `USE_TRIVIAL_MALLOC`: just map `malloc` to `platform_allocate` and
-   discard `free`. Very quick, but wastes all `free`-ed memory.
-
- * `USE_SIMPLE_MALLOC`: a simple freelist implementation, ported from
-   [here](https://github.com/andrestc/linux-prog/blob/master/ch7/malloc.c),
-   which is probably rather memory efficient, but can be linear in
-   time, so it easily becomes a bottleneck.
-
- * `USE_CHECKED_MALLOC`: somewhat similar to `USE_TRIVIAL_MALLOC`, but
-   checks that your program uses `malloc` and `free` correctly (i.e.,
-   that you not overflow or underflow your allocations, that you do
-   not double `free`, or use after `free`). As a result it is very
-   slow and memory-inefficient, but if your program runs with it it
-   most probably means that it is correctly allocating and
-   deallocating memory. It is a kind of `valgrind` checker.
-
- * `USE_KMALLOC`: a port (with some modifications, mainly due to the
-   fact that there is no paging in `asmc`) of
-   [kmalloc](https://github.com/emeryberger/Malloc-Implementations/blob/master/allocators/kmalloc/kmalloc.c). Very
-   quick and rather memory-efficient. Basically to better option
-   currently available in `asmc` (unless you want to debug memory
-   allocation), so also the default one.
-
-A third pack of flags is for controlling the associative array (map)
-implementation used by `asmc`.
-
- * `USE_SIMPLE_MAP`: the original map implementation, based on lineary
-   arrays, which require a full trasversal of the array for basically
-   every operation. Very slow.
-
- * `USE_AVL_MAP`: a new implementation based on AVL trees. In the end
-   it was never finished (because at some point I decided to switch to
-   red-black trees), so it implements a binary search tree, but
-   without rebalancing. Not guaranteed to be balanced, but probably,
-   since most of the times data arrive in random order, it ususally
-   is. Practical performance are comparable with red-black trees.
-
- * `USE_RB_MAP`: the final and default implementation, using properly
-   balanced red-black trees.
-
-In theory all three of them should work, with different
-performances. In practice, only the red-black tree is routinely used
-and thus tested.
-
-## What is inside this repository
-
- * `lib` contains a very small kernel, designed to run on a i386 CPU
-   in protected mode (with a flat memory model and without memory
-   paging). The kernel offers an interface for writing to the console
-   and to the serial port, a simple read-only ramdisk and some library
-   routines for later stages.
-
-   The kernel can be booted with multiboot, or can simply be loaded at
-   1 MB and jumped in at its very beginning. The ramdisk must be
-   appended to it in the `ar` format.
-
-   The kernel must be compiled with payload, inside which it jumps
-   after loading. Three payloads are provided, detailed later.
-
-   In this directory there are also some C files that in theory enable
-   you to host a payload directly in a Linux process. They were mostly
-   useful in the beginning to test the code in a more friendly
-   environment than a virtual machine, but they are far from being
-   perfect and not very useful nowadays.
-
- * `asmg` is an G compiler written in Assembly. G is a custom language
-   I invented for this project, described below in more details. As
-   soon as it is ready, it compiles the file `main.g` and jumps to
-   `main`. Here is where most of the development is concentrated
-   nowadays. `asmg` can be compiled by `asmasm`. See above for what is
-   implemented in the G environment.
-
- * `asmg0` is an effort at reducing even more `asmg` binary seed, by
-   introducing a smaller language called G0 between the binary seed
-   and the G language. It is currently a very experimental effort
-   (even more experimental than the rest) and it does not work at all.
-
- * `boot` contains a simple bootloader that can be used to boot all of
-   the above (in the minimalistic style of the rest of the
-   project). For the moment is cannot be compiled with `asmasm`,
-   because it must use some system level opcodes that are not
-   supported by `asmasm`, so you have to use NASM. It works under QEMU
-   and in line of principle it also work under bare metal, at least
-   those that I tried (old computers that I had around). As already
-   outlined above, this is not tested software, you should never run
-   it on computer that you cannot afford to be erased.
-
- * `attic` contains some earlier test code, that is not used any more
-   and it is also probably broken. They are probably not very
-   interesting to most users, and might be removed altogether at some
-   point.
-
- * `test` contains some test programs for the Assembly and C compilers
-   contained in `asmg`.
-
- * `diskfs` contains the file that are made available to the virtual
-   file system in `asmg`.
-
-## Design considerations
-
-Ideally the system seed written in Assembly should be as simple and
-small as possible. Since that is the part that must be already build
-when the system boots, it should be verifiable by hand, i.e., it
-should be so simple that a human being can take a printout of the code
-and of the binary hex dump and check opcode by opcode that the code
-was translated correctly. This is very tedious, so everything that is
-not strictly necessary for building later stages should be moved to
-later stages.
-
-All other design criteria are of smaller concern: in particular
-efficiency is not a target (all first stages compilers are definitely
-not efficient, both in terms of their execution time and of the
-generated code; however, ideally they are meant to be dropped as soon
-as a real compiler is built).
-
-Also coding style is very inhomogeneus, mostly because I am working
-with languages with which I had very small prior experience before
-starting this project (I had never written more than a few Assembly
-lines together; the G language did not even exist when I started this,
-because I invented it, so I could not possibly have prior
-experience). During writing I established my own style, but never went
-back to fix already written code. So in theory looking at the style
-you can probably reconstruct the order in which a wrote code.
+WARNING! ATTENTION! `asmc` can also be ran on real hardware. However,
+remember that you are giving full control over you hardware to an
+experimental program whose author is not an expert operating system
+programmer: it could have bugs and overwrite your disk, damage the
+hardware and whatever. I only run it on an old otherwise unused laptop
+that once belonged to my grandmother. No problem has ever become
+apparent, but care is never too much!
 
 ## Why all of this?
 
@@ -409,85 +158,37 @@ stripped down version of the Linux kernel at boot time and then
 executes it, which is kind of what `asmc` is trying to do, expect that
 `asmc` is trying to compile the compiler as well.
 
-## The platform interface exposed by the kernel
-
-The kernel and library in the directory `lib` offer some simple API to
-later stages, which is described here. All calls follow the usual
-`cdecl` ABI (arguments pushed right to left; caller cleans up; return
-value in EAX or EDX:EAX; stack aligned to 4; EAX, ECX and EDX are
-caller-saved and the other registers are callee-saved; objects are
-returned via additional first argument).
-
- * `platform_exit()` Exit successfully; it will never return.
-
- * `platform_panic()` Exit unsuccessfully, writing a panic error
-   message; it will never return. In the earlier stages there is
-   nearly no error diagnosing facility, so if the program terminates
-   with a panic message you are on your own finding the problem. Next
-   time you want an easy life please write in Java.
-
- * `platform_write_char(int fd, int c)` Write character `c` in file
-   `fd`. Writing on a filesystem is not supported yet. There are only
-   two virtual files: file `0`, which writes in memory, at the address
-   contained in `write_mem_ptr`, and then increment the address; and
-   file `1`, which writes on the console and on the serial port. There
-   is also file `2`, which just maps to `1`.
-
- * `platform_log(int fd, char *s)` Write a NULL terminated string `s`
-   into `fd`, by repeatedly calling `platform_write_char`.
-
- * `platform_open_file(char *fname)` Open file `fname` for reading,
-   returning the associated `fd` number. Opened files cannot be
-   closed, for the moment.
-
- * `platform_read_char(int fd)` Read a char and return from file
-   `fd`. Return -1 (i.e., 0xffffffff) at EOF.
-
- * `platform_reset_file(int fd)` Seek back to the beginning of the
-   file. Other seeks are not supported.
-
- * `platform_allocate(int size)` Simple memory allocator returning a
-   pointer to a memory region of at least `size` bytes. It works in a
-   similar way to `sbrk` on UNIX platforms, so you cannot return a
-   memory region to the pool, unless it is the last one that was
-   allocated. But you can implement your own `malloc`/`free` on top of
-   it, as it is actually later done in G.
-
- * `platform_get_symbol(char *name, int *arity)` Return the address of
-   symbol `name`, panicking if it does not exist. If `arity` is not
-   NULL, return there the symbol arity (i.e., the number of
-   parameters, which is relevant for the G language, but not for
-   Assembly). The number -1 (0xffffffff) is returned if arity is
-   undefined.
-
- * `platform_setjmp(void *env)` Copy the content of the general
-   purpose registers in the buffer pointed by `env` (which must be at
-   least 26 bytes long). This is used to implement the `setjmp` call
-   in the C compiler.
-
- * `platform_longjmp(void *env, int status)` Restore the content of
-   the general purpose registers from the buffer pointed by `env`,
-   except EAX which is set to `status`. This is used to implement the
-   `longjmp` call in the C compiler.
-
-Another routine is provided when compiling the kernel with `asmg`:
+## Design considerations
 
- * `platform_g_compile(char *filename)` Compile the G program in
-   `filename`, panicking if an error is found.
+Ideally the system seed written in Assembly should be as simple and
+small as possible. Since that is the part that must be already build
+when the system boots, it should be verifiable by hand, i.e., it
+should be so simple that a human being can take a printout of the code
+and of the binary hex dump and check opcode by opcode that the code
+was translated correctly. This is very tedious, so everything that is
+not strictly necessary for building later stages should be moved to
+later stages.
 
-Symbols generated by any of the two compilers can be recovered with
-`platform_get_symbol`.
+All other design criteria are of smaller concern: in particular
+efficiency is not a target (all first stages compilers are definitely
+not efficient, both in terms of their execution time and of the
+generated code; however, ideally they are meant to be dropped as soon
+as a real compiler is built).
 
-The G compiler also exports a few internal calls to give the G program
-a little introspection capabilities, used to generate stack traces on
-assertions. They are not documented and are not to be used other that
-in these debugging utilities.
+Also coding style is very inhomogeneus, mostly because I am working
+with languages with which I had very small prior experience before
+starting this project (I had never written more than a few Assembly
+lines together; the G language did not even exist when I started this,
+because I invented it, so I could not possibly have prior
+experience). During writing I established my own style, but never went
+back to fix already written code. So in theory looking at the style
+you can probably reconstruct the order in which a wrote code.
 
 ## The G language
 
 My initial idea, when I begun working on `asmc`, was to embed an
-Assembly compiler in the initial seed and then use Assembly to write a
-C compiler. At some point I realized that bridging the gap between
+assembler in the initial seed and then use Assembly to write a C
+compiler. At some point I realized that bridging the gap between
 Assembly and C with just one jump is very hard: Assembly is very low
 level, and C, when you try to write its compiler, is much higher level
 that one would expect in the beginning. At the same time, Assembly is
@@ -514,25 +215,10 @@ not meant to do much else.
 The syntax of the G language is exaplained in [a dedicated
 document](G_LANGUAGE.md).
 
-## Ported programs
-
-This repository contains the following code ported to G:
-
- * `mescc_hex2.g` is ported from `hex2_linker.c` in repository
-   <https://github.com/oriansj/mescc-tools>. It is synchronized with
-   commit `40537c0200ad28cd5090bc0776251d5983ef56e3`.
-
- * `mescc_m1.g` is ported from `M1-macro.c` in repository
-   <https://github.com/oriansj/mescc-tools>. It is synchronized with
-   commit `40537c0200ad28cd5090bc0776251d5983ef56e3`.
-
- * `mescc_m2.g` is ported from many files in repository
-   <https://github.com/oriansj/M2-Planet>. It is synchronized with
-   commit `2e1148fe3e83c684769d4e73b441a64f34115b4f`.
+## Other material
 
-Other programs are used by mean of Git submodules (see the `contrib`
-directory), so their exact version is encoded in the Git repository
-itself and it is not repeated here.
+Some older or more technical documentation is mantained in [another
+file](README.old.md).
 
 ## License
 

+ 325 - 0
README.old.md

@@ -0,0 +1,325 @@
+# Older documentation for `asmc`
+
+This file contains additional documentation for `asmc`. Some of the
+things here might not be completely up-to-date, but they can be useful
+anyway to figure out what's happening inside `asmc`.
+
+## How to interpret all the writings
+
+For the full story, read below and the code. However, just to have an
+idea of what is happening, if you use the command above to boot
+`boot_asmg.x86` the following will happen:
+
+ * The first log lines are written by the bootloader. At this point it
+   is mostly concerned with loading to RAM the actual kernel, enabling
+   some obscure features of the PC platform used to boot properly and
+   entering the CPU's protected mode.
+
+ * At some point `asmc` kernel is finally ran, and it writes `Hello, asmc!`
+   to the log. There is where the `asmc` binary seed first
+   enters execution. It will just initialize some data structures and
+   then invoke its embedded G compiler to compile the file `main.g`
+   and then call the `main` routine.
+
+ * This is the point where for the first time code that has just been
+   compiled is fed to the CPU, so in a sense the binary seed is not in
+   control of the main program any more (but still gets called as a
+   library, for example to compile other G sources). The message
+   `Hello, G!` is written to the log and immediately after other G
+   sources are compiled, first to introduce some library code (like
+   malloc/free, code for handling dynamic vectors and maps, some basic
+   disk/filesystem driver and other utilities) and then to compile an
+   assembler and a C compiler. These two compilers are not meant to be
+   complete: they are just enough to build the following step, which
+   is tinycc.
+
+ * Then a suite of C test programs is compiled and executed. They test
+   part of the C compiler and the C standard library. In line of
+   principle all the test should pass and all `malloc`-s should be
+   `free`-ed.
+
+ * After all tests have passed, tinycc is finally compiled. This takes
+   a bit (around 20 seconds on my machine, my KVM enable), because the
+   previous C compiler is quite inefficient. During preprocessing
+   progress is indicated by open and closed square brackets, which
+   indicate when a new file is included or finished to include. During
+   compilation (which consists of three stages), progress is indicated
+   by dots, where each dot correspons to a thousands tokens processed.
+
+ * At last, tinycc is ran, by mean of its `libtcc` interface. A small
+   test program is compiled and executed, showing a glimpse of the
+   third level of compiled code from the beginning of the `asmc` run.
+
+ * In the end some statistics are printed, hopefully showing that all
+   allocated memory have been deallocated (not that it matters much,
+   since the machine is going to be powered off anyway, but I like
+   resources to be deinitialized properly).
+
+## How to fiddle with flags
+
+`asmg`'s behaviour can be customized thanks to some flags at the
+beginning of the `asmg/main.g` file. There you can enable:
+
+ * `RUN_ASM`: it will compile an assembler and then run it on the file
+   `test/test.asm`. The assembler is not complete at all, but ideally
+   it should be more or less enough to assemble a [lightly
+   patched](https://gitlab.com/giomasce/fasm) version of
+   [FASM](https://flatassembler.net/) (see next point).
+
+ * `RUN_FASM` (currently unmaintained): compile the assembler and then
+   use it to assemble FASM, as mentioned above. In theory it should
+   work, but in practice it does not: the assembled FASM crashes for
+   some reason I could not understand. There is definitely a bug in my
+   assembler (or at least some unmet FASM assumption), but I could not
+   find it so far. However, the bulk of the project is not here.
+
+ * `RUN_C`: it will compile the assembler and the C compiler and then
+   use them to compile the program in `diskfs/tests/test.c`. In the
+   source code there are flags to dump debugging information,
+   including a dump of the machine code itself. It is useful to debug
+   the C compiler itself. Also, feel free to edit the test program to
+   test your own C programs (but expect frequent breakages!).
+
+ * `RUN_MESCC` (currently unmaintained; only this port is
+   unmaintained, the original project is going on): it will compile a
+   port of the
+   [mescc](https://github.com/oriansj/mescc-tools)/[M2-Planet](https://github.com/oriansj/M2-Planet)
+   toolchain, which is basically an indepdendent C compiler with
+   different features and bugs than mine. This port just tracks the
+   upstream program, no original development is done here. See below
+   from more precise links. The test program in `test/test_mes.c` will
+   then be compiled and executed.
+
+ * `RUN_MCPP` (currently unmaintained): it will compile the assembler
+   and the C compiler and then use them to try compiling a [lightly
+   patched](https://gitlab.com/giomasce/mcpp) version of
+   [mcpp](http://mcpp.sourceforge.net/), which is a complete C
+   preprocessor. Since the preprocessor embedded in `asmc`'s C
+   compiler is rather lacking, the idea is that mcpp could be used
+   instead to compile C sources that require deep preprocessing
+   capabilities. However, at this point, mcpp itself does not compile,
+   so at some point `asmc` with die with a failed assertion. Also, it
+   nowadays seems that `asmc` is able to preprocess tinycc by itself,
+   so there is no point anymore in going forward with this subproject.
+
+ * `RUN_TINYCC`: here is where the juice stays! This will compile the
+   assembler and the C compiler, and then compile tinycc, as mentioned
+   above. Then it will use tinycc to compile and execute a little C
+   program. In the future the bootstrapping chain will continue here.
+
+ * `TEST_MAP`: there are three implementation of an associative array
+   in `asmc`, of increasing complexity (see below). This tests the
+   implementation, and was used in the past to check new
+   implementations for correctness.
+
+ * `TEST_INT64`: implementing 64 bits integers on a 32 bits platform
+   is somewhat tricky. The G language itself only supports 32 bits
+   numbers, so some additional Assembly code was required to implement
+   64 bits operations. Also, the division code is particularly
+   tricky. However, 64 bits integers are required by tinycc, which
+   needs support for `long long` types, so they were implemented at
+   some point. This enables some tests on the resulting implemntation.
+
+ * `TEST_C`: it will compile the C compiler and run the test
+   suite.
+
+By default thre three `TEST_*` flags and `RUN_TINYCC` are enabled in
+`asmc`.
+
+There is also another pack of flags that control which `malloc`
+implementation `asmg` is going to use. There are four at this
+point. All of them gather memory with the `platform_allocate` call
+(see below), which is similary to UNIX' `brk` (and does not permit to
+release memory back).
+
+ * `USE_TRIVIAL_MALLOC`: just map `malloc` to `platform_allocate` and
+   discard `free`. Very quick, but wastes all `free`-ed memory.
+
+ * `USE_SIMPLE_MALLOC`: a simple freelist implementation, ported from
+   [here](https://github.com/andrestc/linux-prog/blob/master/ch7/malloc.c),
+   which is probably rather memory efficient, but can be linear in
+   time, so it easily becomes a bottleneck.
+
+ * `USE_CHECKED_MALLOC`: somewhat similar to `USE_TRIVIAL_MALLOC`, but
+   checks that your program uses `malloc` and `free` correctly (i.e.,
+   that you not overflow or underflow your allocations, that you do
+   not double `free`, or use after `free`). As a result it is very
+   slow and memory-inefficient, but if your program runs with it it
+   most probably means that it is correctly allocating and
+   deallocating memory. It is a kind of `valgrind` checker.
+
+ * `USE_KMALLOC`: a port (with some modifications, mainly due to the
+   fact that there is no paging in `asmc`) of
+   [kmalloc](https://github.com/emeryberger/Malloc-Implementations/blob/master/allocators/kmalloc/kmalloc.c). Very
+   quick and rather memory-efficient. Basically to better option
+   currently available in `asmc` (unless you want to debug memory
+   allocation), so also the default one.
+
+A third pack of flags is for controlling the associative array (map)
+implementation used by `asmc`.
+
+ * `USE_SIMPLE_MAP`: the original map implementation, based on lineary
+   arrays, which require a full trasversal of the array for basically
+   every operation. Very slow.
+
+ * `USE_AVL_MAP`: a new implementation based on AVL trees. In the end
+   it was never finished (because at some point I decided to switch to
+   red-black trees), so it implements a binary search tree, but
+   without rebalancing. Not guaranteed to be balanced, but probably,
+   since most of the times data arrive in random order, it ususally
+   is. Practical performance are comparable with red-black trees.
+
+ * `USE_RB_MAP`: the final and default implementation, using properly
+   balanced red-black trees.
+
+In theory all three of them should work, with different
+performances. In practice, only the red-black tree is routinely used
+and thus tested.
+
+## What is inside this repository
+
+ * `lib` contains a very small kernel, designed to run on a i386 CPU
+   in protected mode (with a flat memory model and without memory
+   paging). The kernel offers an interface for writing to the console
+   and to the serial port, a simple read-only ramdisk and some library
+   routines for later stages.
+
+   The kernel can be booted with multiboot, or can simply be loaded at
+   1 MB and jumped in at its very beginning. The ramdisk must be
+   appended to it in the `ar` format.
+
+   The kernel must be compiled with payload, inside which it jumps
+   after loading. Three payloads are provided, detailed later.
+
+   In this directory there are also some C files that in theory enable
+   you to host a payload directly in a Linux process. They were mostly
+   useful in the beginning to test the code in a more friendly
+   environment than a virtual machine, but they are far from being
+   perfect and not very useful nowadays.
+
+ * `asmg` is an G compiler written in Assembly. G is a custom language
+   I invented for this project, described below in more details. As
+   soon as it is ready, it compiles the file `main.g` and jumps to
+   `main`. Here is where most of the development is concentrated
+   nowadays. `asmg` can be compiled by `asmasm`. See above for what is
+   implemented in the G environment.
+
+ * `asmg0` is an effort at reducing even more `asmg` binary seed, by
+   introducing a smaller language called G0 between the binary seed
+   and the G language. It is currently a very experimental effort
+   (even more experimental than the rest) and it does not work at all.
+
+ * `boot` contains a simple bootloader that can be used to boot all of
+   the above (in the minimalistic style of the rest of the
+   project). For the moment is cannot be compiled with `asmasm`,
+   because it must use some system level opcodes that are not
+   supported by `asmasm`, so you have to use NASM. It works under QEMU
+   and in line of principle it also work under bare metal, at least
+   those that I tried (old computers that I had around). As already
+   outlined above, this is not tested software, you should never run
+   it on computer that you cannot afford to be erased.
+
+ * `attic` contains some earlier test code, that is not used any more
+   and it is also probably broken. They are probably not very
+   interesting to most users, and might be removed altogether at some
+   point.
+
+ * `test` contains some test programs for the Assembly and C compilers
+   contained in `asmg`.
+
+ * `diskfs` contains the file that are made available to the virtual
+   file system in `asmg`.
+
+## The platform interface exposed by the kernel
+
+The kernel and library in the directory `lib` offer some simple API to
+later stages, which is described here. All calls follow the usual
+`cdecl` ABI (arguments pushed right to left; caller cleans up; return
+value in EAX or EDX:EAX; stack aligned to 4; EAX, ECX and EDX are
+caller-saved and the other registers are callee-saved; objects are
+returned via additional first argument).
+
+ * `platform_exit()` Exit successfully; it will never return.
+
+ * `platform_panic()` Exit unsuccessfully, writing a panic error
+   message; it will never return. In the earlier stages there is
+   nearly no error diagnosing facility, so if the program terminates
+   with a panic message you are on your own finding the problem. Next
+   time you want an easy life please write in Java.
+
+ * `platform_write_char(int fd, int c)` Write character `c` in file
+   `fd`. Writing on a filesystem is not supported yet. There are only
+   two virtual files: file `0`, which writes in memory, at the address
+   contained in `write_mem_ptr`, and then increment the address; and
+   file `1`, which writes on the console and on the serial port. There
+   is also file `2`, which just maps to `1`.
+
+ * `platform_log(int fd, char *s)` Write a NULL terminated string `s`
+   into `fd`, by repeatedly calling `platform_write_char`.
+
+ * `platform_open_file(char *fname)` Open file `fname` for reading,
+   returning the associated `fd` number. Opened files cannot be
+   closed, for the moment.
+
+ * `platform_read_char(int fd)` Read a char and return from file
+   `fd`. Return -1 (i.e., 0xffffffff) at EOF.
+
+ * `platform_reset_file(int fd)` Seek back to the beginning of the
+   file. Other seeks are not supported.
+
+ * `platform_allocate(int size)` Simple memory allocator returning a
+   pointer to a memory region of at least `size` bytes. It works in a
+   similar way to `sbrk` on UNIX platforms, so you cannot return a
+   memory region to the pool, unless it is the last one that was
+   allocated. But you can implement your own `malloc`/`free` on top of
+   it, as it is actually later done in G.
+
+ * `platform_get_symbol(char *name, int *arity)` Return the address of
+   symbol `name`, panicking if it does not exist. If `arity` is not
+   NULL, return there the symbol arity (i.e., the number of
+   parameters, which is relevant for the G language, but not for
+   Assembly). The number -1 (0xffffffff) is returned if arity is
+   undefined.
+
+ * `platform_setjmp(void *env)` Copy the content of the general
+   purpose registers in the buffer pointed by `env` (which must be at
+   least 26 bytes long). This is used to implement the `setjmp` call
+   in the C compiler.
+
+ * `platform_longjmp(void *env, int status)` Restore the content of
+   the general purpose registers from the buffer pointed by `env`,
+   except EAX which is set to `status`. This is used to implement the
+   `longjmp` call in the C compiler.
+
+Another routine is provided when compiling the kernel with `asmg`:
+
+ * `platform_g_compile(char *filename)` Compile the G program in
+   `filename`, panicking if an error is found.
+
+Symbols generated by any of the two compilers can be recovered with
+`platform_get_symbol`.
+
+The G compiler also exports a few internal calls to give the G program
+a little introspection capabilities, used to generate stack traces on
+assertions. They are not documented and are not to be used other that
+in these debugging utilities.
+
+## Ported programs
+
+This repository contains the following code ported to G:
+
+ * `mescc_hex2.g` is ported from `hex2_linker.c` in repository
+   <https://github.com/oriansj/mescc-tools>. It is synchronized with
+   commit `40537c0200ad28cd5090bc0776251d5983ef56e3`.
+
+ * `mescc_m1.g` is ported from `M1-macro.c` in repository
+   <https://github.com/oriansj/mescc-tools>. It is synchronized with
+   commit `40537c0200ad28cd5090bc0776251d5983ef56e3`.
+
+ * `mescc_m2.g` is ported from many files in repository
+   <https://github.com/oriansj/M2-Planet>. It is synchronized with
+   commit `2e1148fe3e83c684769d4e73b441a64f34115b4f`.
+
+Other programs are used by mean of Git submodules (see the `contrib`
+directory), so their exact version is encoded in the Git repository
+itself and it is not repeated here.

+ 16 - 0
diskfs/asmc_api.h

@@ -1,3 +1,19 @@
+/* This file is part of asmc, a bootstrapping OS with minimal seed
+   Copyright (C) 2019 Giovanni Mascellani <gio@debian.org>
+   https://gitlab.com/giomasce/asmc
+
+   This program is free software: you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation, either version 3 of the License, or
+   (at your option) any later version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program.  If not, see <https://www.gnu.org/licenses/>. */
 
 #include "asmc.h"
 #include "ipxe_asmc_structs.h"

+ 16 - 0
diskfs/coros.h

@@ -1,3 +1,19 @@
+/* This file is part of asmc, a bootstrapping OS with minimal seed
+   Copyright (C) 2019 Giovanni Mascellani <gio@debian.org>
+   https://gitlab.com/giomasce/asmc
+
+   This program is free software: you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation, either version 3 of the License, or
+   (at your option) any later version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program.  If not, see <https://www.gnu.org/licenses/>. */
 
 #include <assert.h>
 #include <stdbool.h>

+ 16 - 0
diskfs/ipxe_asmc.h

@@ -1,3 +1,19 @@
+/* This file is part of asmc, a bootstrapping OS with minimal seed
+   Copyright (C) 2019 Giovanni Mascellani <gio@debian.org>
+   https://gitlab.com/giomasce/asmc
+
+   This program is free software: you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation, either version 3 of the License, or
+   (at your option) any later version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program.  If not, see <https://www.gnu.org/licenses/>. */
 
 #include "ipxe_asmc_structs.h"
 

+ 16 - 0
diskfs/ipxe_asmc_structs.h

@@ -1,3 +1,19 @@
+/* This file is part of asmc, a bootstrapping OS with minimal seed
+   Copyright (C) 2019 Giovanni Mascellani <gio@debian.org>
+   https://gitlab.com/giomasce/asmc
+
+   This program is free software: you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation, either version 3 of the License, or
+   (at your option) any later version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program.  If not, see <https://www.gnu.org/licenses/>. */
 
 #ifndef __ASMC_TYPES_H
 typedef unsigned int size_t;

+ 17 - 0
diskfs/ipxe_handover.h

@@ -1,3 +1,20 @@
+/* This file is part of asmc, a bootstrapping OS with minimal seed
+   Copyright (C) 2019 Giovanni Mascellani <gio@debian.org>
+   https://gitlab.com/giomasce/asmc
+
+   This program is free software: you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation, either version 3 of the License, or
+   (at your option) any later version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program.  If not, see <https://www.gnu.org/licenses/>. */
+
 #ifndef __IPXE_HANDOVER_H
 #define __IPXE_HANDOVER_H
 

+ 16 - 0
diskfs/run_ipxe.c

@@ -1,3 +1,19 @@
+/* This file is part of asmc, a bootstrapping OS with minimal seed
+   Copyright (C) 2019 Giovanni Mascellani <gio@debian.org>
+   https://gitlab.com/giomasce/asmc
+
+   This program is free software: you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation, either version 3 of the License, or
+   (at your option) any later version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program.  If not, see <https://www.gnu.org/licenses/>. */
 
 /* Stuff is a bit complicated here, because we are already in iPXE
    namespace, so we cannot use asmc's stdlib, because it would clash

+ 16 - 0
diskfs/run_tcc.c

@@ -1,3 +1,19 @@
+/* This file is part of asmc, a bootstrapping OS with minimal seed
+   Copyright (C) 2019 Giovanni Mascellani <gio@debian.org>
+   https://gitlab.com/giomasce/asmc
+
+   This program is free software: you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation, either version 3 of the License, or
+   (at your option) any later version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program.  If not, see <https://www.gnu.org/licenses/>. */
 
 #include "run_tcc.h"
 

+ 17 - 0
diskfs/run_tcc.h

@@ -1,3 +1,20 @@
+/* This file is part of asmc, a bootstrapping OS with minimal seed
+   Copyright (C) 2019 Giovanni Mascellani <gio@debian.org>
+   https://gitlab.com/giomasce/asmc
+
+   This program is free software: you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation, either version 3 of the License, or
+   (at your option) any later version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program.  If not, see <https://www.gnu.org/licenses/>. */
+
 #ifndef __RUN_TCC_H
 #define __RUN_TCC_H
 

+ 16 - 0
diskfs/run_tcc_ipxe.c

@@ -1,3 +1,19 @@
+/* This file is part of asmc, a bootstrapping OS with minimal seed
+   Copyright (C) 2019 Giovanni Mascellani <gio@debian.org>
+   https://gitlab.com/giomasce/asmc
+
+   This program is free software: you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation, either version 3 of the License, or
+   (at your option) any later version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program.  If not, see <https://www.gnu.org/licenses/>. */
 
 #include <stdio.h>
 #include <stdlib.h>

+ 16 - 0
diskfs/run_tcc_sc.c

@@ -1,3 +1,19 @@
+/* This file is part of asmc, a bootstrapping OS with minimal seed
+   Copyright (C) 2019 Giovanni Mascellani <gio@debian.org>
+   https://gitlab.com/giomasce/asmc
+
+   This program is free software: you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation, either version 3 of the License, or
+   (at your option) any later version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program.  If not, see <https://www.gnu.org/licenses/>. */
 
 #include "run_tcc.h"
 

+ 16 - 0
http/continue.c

@@ -1,3 +1,19 @@
+/* This file is part of asmc, a bootstrapping OS with minimal seed
+   Copyright (C) 2019 Giovanni Mascellani <gio@debian.org>
+   https://gitlab.com/giomasce/asmc
+
+   This program is free software: you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation, either version 3 of the License, or
+   (at your option) any later version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program.  If not, see <https://www.gnu.org/licenses/>. */
 
 #include <stdio.h>
 #include <asmc_api.h>

+ 44 - 370
http/continue2.c

@@ -1,3 +1,19 @@
+/* This file is part of asmc, a bootstrapping OS with minimal seed
+   Copyright (C) 2019 Giovanni Mascellani <gio@debian.org>
+   https://gitlab.com/giomasce/asmc
+
+   This program is free software: you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation, either version 3 of the License, or
+   (at your option) any later version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program.  If not, see <https://www.gnu.org/licenses/>. */
 
 #include <stdint.h>
 #include <assert.h>
@@ -5,339 +21,6 @@
 #include <string.h>
 #include <asmc_api.h>
 
-typedef uint8_t __u8;
-typedef uint16_t __u16;
-typedef uint32_t __u32;
-typedef uint64_t __u64;
-
-// From include/uapi/linux/screen_info.h
-struct screen_info {
-	__u8  orig_x;		/* 0x00 */
-	__u8  orig_y;		/* 0x01 */
-	__u16 ext_mem_k;	/* 0x02 */
-	__u16 orig_video_page;	/* 0x04 */
-	__u8  orig_video_mode;	/* 0x06 */
-	__u8  orig_video_cols;	/* 0x07 */
-	__u8  flags;		/* 0x08 */
-	__u8  unused2;		/* 0x09 */
-	__u16 orig_video_ega_bx;/* 0x0a */
-	__u16 unused3;		/* 0x0c */
-	__u8  orig_video_lines;	/* 0x0e */
-	__u8  orig_video_isVGA;	/* 0x0f */
-	__u16 orig_video_points;/* 0x10 */
-
-	/* VESA graphic mode -- linear frame buffer */
-	__u16 lfb_width;	/* 0x12 */
-	__u16 lfb_height;	/* 0x14 */
-	__u16 lfb_depth;	/* 0x16 */
-	__u32 lfb_base;		/* 0x18 */
-	__u32 lfb_size;		/* 0x1c */
-	__u16 cl_magic, cl_offset; /* 0x20 */
-	__u16 lfb_linelength;	/* 0x24 */
-	__u8  red_size;		/* 0x26 */
-	__u8  red_pos;		/* 0x27 */
-	__u8  green_size;	/* 0x28 */
-	__u8  green_pos;	/* 0x29 */
-	__u8  blue_size;	/* 0x2a */
-	__u8  blue_pos;		/* 0x2b */
-	__u8  rsvd_size;	/* 0x2c */
-	__u8  rsvd_pos;		/* 0x2d */
-	__u16 vesapm_seg;	/* 0x2e */
-	__u16 vesapm_off;	/* 0x30 */
-	__u16 pages;		/* 0x32 */
-	__u16 vesa_attributes;	/* 0x34 */
-	__u32 capabilities;     /* 0x36 */
-	__u32 ext_lfb_base;	/* 0x3a */
-	__u8  _reserved[2];	/* 0x3e */
-} __attribute__((packed));
-
-#define VIDEO_TYPE_MDA		0x10	/* Monochrome Text Display	*/
-#define VIDEO_TYPE_CGA		0x11	/* CGA Display 			*/
-#define VIDEO_TYPE_EGAM		0x20	/* EGA/VGA in Monochrome Mode	*/
-#define VIDEO_TYPE_EGAC		0x21	/* EGA in Color Mode		*/
-#define VIDEO_TYPE_VGAC		0x22	/* VGA+ in Color Mode		*/
-#define VIDEO_TYPE_VLFB		0x23	/* VESA VGA in graphic mode	*/
-
-#define VIDEO_TYPE_PICA_S3	0x30	/* ACER PICA-61 local S3 video	*/
-#define VIDEO_TYPE_MIPS_G364	0x31    /* MIPS Magnum 4000 G364 video  */
-#define VIDEO_TYPE_SGI          0x33    /* Various SGI graphics hardware */
-
-#define VIDEO_TYPE_TGAC		0x40	/* DEC TGA */
-
-#define VIDEO_TYPE_SUN          0x50    /* Sun frame buffer. */
-#define VIDEO_TYPE_SUNPCI       0x51    /* Sun PCI based frame buffer. */
-
-#define VIDEO_TYPE_PMAC		0x60	/* PowerMacintosh frame buffer. */
-
-#define VIDEO_TYPE_EFI		0x70	/* EFI graphic mode		*/
-
-#define VIDEO_FLAGS_NOCURSOR	(1 << 0) /* The video mode has no cursor set */
-
-#define VIDEO_CAPABILITY_SKIP_QUIRKS	(1 << 0)
-#define VIDEO_CAPABILITY_64BIT_BASE	(1 << 1) /* Frame buffer base is 64-bit */
-
-// From include/uapi/linux/apm_bios.h
-struct apm_bios_info {
-	__u16	version;
-	__u16	cseg;
-	__u32	offset;
-	__u16	cseg_16;
-	__u16	dseg;
-	__u16	flags;
-	__u16	cseg_len;
-	__u16	cseg_16_len;
-	__u16	dseg_len;
-};
-
-// From arch/x86/include/uapi/asm/ist.h
-struct ist_info {
-	__u32 signature;
-	__u32 command;
-	__u32 event;
-	__u32 perf_level;
-};
-
-// From include/uapi/linux/edd.h
-#define EDD_MBR_SIG_MAX 16
-#define EDDMAXNR 6
-
-struct edd_device_params {
-	__u16 length;
-	__u16 info_flags;
-	__u32 num_default_cylinders;
-	__u32 num_default_heads;
-	__u32 sectors_per_track;
-	__u64 number_of_sectors;
-	__u16 bytes_per_sector;
-	__u32 dpte_ptr;		/* 0xFFFFFFFF for our purposes */
-	__u16 key;		/* = 0xBEDD */
-	__u8 device_path_info_length;	/* = 44 */
-	__u8 reserved2;
-	__u16 reserved3;
-	__u8 host_bus_type[4];
-	__u8 interface_type[8];
-	union {
-		struct {
-			__u16 base_address;
-			__u16 reserved1;
-			__u32 reserved2;
-		} __attribute__ ((packed)) isa;
-		struct {
-			__u8 bus;
-			__u8 slot;
-			__u8 function;
-			__u8 channel;
-			__u32 reserved;
-		} __attribute__ ((packed)) pci;
-		/* pcix is same as pci */
-		struct {
-			__u64 reserved;
-		} __attribute__ ((packed)) ibnd;
-		struct {
-			__u64 reserved;
-		} __attribute__ ((packed)) xprs;
-		struct {
-			__u64 reserved;
-		} __attribute__ ((packed)) htpt;
-		struct {
-			__u64 reserved;
-		} __attribute__ ((packed)) unknown;
-	} interface_path;
-	union {
-		struct {
-			__u8 device;
-			__u8 reserved1;
-			__u16 reserved2;
-			__u32 reserved3;
-			__u64 reserved4;
-		} __attribute__ ((packed)) ata;
-		struct {
-			__u8 device;
-			__u8 lun;
-			__u8 reserved1;
-			__u8 reserved2;
-			__u32 reserved3;
-			__u64 reserved4;
-		} __attribute__ ((packed)) atapi;
-		struct {
-			__u16 id;
-			__u64 lun;
-			__u16 reserved1;
-			__u32 reserved2;
-		} __attribute__ ((packed)) scsi;
-		struct {
-			__u64 serial_number;
-			__u64 reserved;
-		} __attribute__ ((packed)) usb;
-		struct {
-			__u64 eui;
-			__u64 reserved;
-		} __attribute__ ((packed)) i1394;
-		struct {
-			__u64 wwid;
-			__u64 lun;
-		} __attribute__ ((packed)) fibre;
-		struct {
-			__u64 identity_tag;
-			__u64 reserved;
-		} __attribute__ ((packed)) i2o;
-		struct {
-			__u32 array_number;
-			__u32 reserved1;
-			__u64 reserved2;
-		} __attribute__ ((packed)) raid;
-		struct {
-			__u8 device;
-			__u8 reserved1;
-			__u16 reserved2;
-			__u32 reserved3;
-			__u64 reserved4;
-		} __attribute__ ((packed)) sata;
-		struct {
-			__u64 reserved1;
-			__u64 reserved2;
-		} __attribute__ ((packed)) unknown;
-	} device_path;
-	__u8 reserved4;
-	__u8 checksum;
-} __attribute__ ((packed));
-
-struct edd_info {
-	__u8 device;
-	__u8 version;
-	__u16 interface_support;
-	__u16 legacy_max_cylinder;
-	__u8 legacy_max_head;
-	__u8 legacy_sectors_per_track;
-	struct edd_device_params params;
-} __attribute__ ((packed));
-
-// From include/uapi/video/edid.h
-struct edid_info {
-	unsigned char dummy[128];
-};
-
-// From arch/x86/include/uapi/asm/bootparam.h
-struct setup_header {
-	__u8	setup_sects;
-	__u16	root_flags;
-	__u32	syssize;
-	__u16	ram_size;
-	__u16	vid_mode;
-	__u16	root_dev;
-	__u16	boot_flag;
-	__u16	jump;
-	__u32	header;
-	__u16	version;
-	__u32	realmode_swtch;
-	__u16	start_sys_seg;
-	__u16	kernel_version;
-	__u8	type_of_loader;
-	__u8	loadflags;
-	__u16	setup_move_size;
-	__u32	code32_start;
-	__u32	ramdisk_image;
-	__u32	ramdisk_size;
-	__u32	bootsect_kludge;
-	__u16	heap_end_ptr;
-	__u8	ext_loader_ver;
-	__u8	ext_loader_type;
-	__u32	cmd_line_ptr;
-	__u32	initrd_addr_max;
-	__u32	kernel_alignment;
-	__u8	relocatable_kernel;
-	__u8	min_alignment;
-	__u16	xloadflags;
-	__u32	cmdline_size;
-	__u32	hardware_subarch;
-	__u64	hardware_subarch_data;
-	__u32	payload_offset;
-	__u32	payload_length;
-	__u64	setup_data;
-	__u64	pref_address;
-	__u32	init_size;
-	__u32	handover_offset;
-} __attribute__((packed));
-
-struct sys_desc_table {
-	__u16 length;
-	__u8  table[14];
-};
-
-struct olpc_ofw_header {
-	__u32 ofw_magic;	/* OFW signature */
-	__u32 ofw_version;
-	__u32 cif_handler;	/* callback into OFW */
-	__u32 irq_desc_table;
-} __attribute__((packed));
-
-struct efi_info {
-	__u32 efi_loader_signature;
-	__u32 efi_systab;
-	__u32 efi_memdesc_size;
-	__u32 efi_memdesc_version;
-	__u32 efi_memmap;
-	__u32 efi_memmap_size;
-	__u32 efi_systab_hi;
-	__u32 efi_memmap_hi;
-};
-
-#define E820_MAX_ENTRIES_ZEROPAGE 128
-
-struct boot_e820_entry {
-	__u64 addr;
-	__u64 size;
-	__u32 type;
-} __attribute__((packed));
-
-struct boot_params {
-	struct screen_info screen_info;			/* 0x000 */
-	struct apm_bios_info apm_bios_info;		/* 0x040 */
-	__u8  _pad2[4];					/* 0x054 */
-	__u64  tboot_addr;				/* 0x058 */
-	struct ist_info ist_info;			/* 0x060 */
-	__u64 acpi_rsdp_addr;				/* 0x070 */
-	__u8  _pad3[8];					/* 0x078 */
-	__u8  hd0_info[16];	/* obsolete! */		/* 0x080 */
-	__u8  hd1_info[16];	/* obsolete! */		/* 0x090 */
-	struct sys_desc_table sys_desc_table; /* obsolete! */	/* 0x0a0 */
-	struct olpc_ofw_header olpc_ofw_header;		/* 0x0b0 */
-	__u32 ext_ramdisk_image;			/* 0x0c0 */
-	__u32 ext_ramdisk_size;				/* 0x0c4 */
-	__u32 ext_cmd_line_ptr;				/* 0x0c8 */
-	__u8  _pad4[116];				/* 0x0cc */
-	struct edid_info edid_info;			/* 0x140 */
-	struct efi_info efi_info;			/* 0x1c0 */
-	__u32 alt_mem_k;				/* 0x1e0 */
-	__u32 scratch;		/* Scratch field! */	/* 0x1e4 */
-	__u8  e820_entries;				/* 0x1e8 */
-	__u8  eddbuf_entries;				/* 0x1e9 */
-	__u8  edd_mbr_sig_buf_entries;			/* 0x1ea */
-	__u8  kbd_status;				/* 0x1eb */
-	__u8  secure_boot;				/* 0x1ec */
-	__u8  _pad5[2];					/* 0x1ed */
-	/*
-	 * The sentinel is set to a nonzero value (0xff) in header.S.
-	 *
-	 * A bootloader is supposed to only take setup_header and put
-	 * it into a clean boot_params buffer. If it turns out that
-	 * it is clumsy or too generous with the buffer, it most
-	 * probably will pick up the sentinel variable too. The fact
-	 * that this variable then is still 0xff will let kernel
-	 * know that some variables in boot_params are invalid and
-	 * kernel should zero out certain portions of boot_params.
-	 */
-	__u8  sentinel;					/* 0x1ef */
-	__u8  _pad6[1];					/* 0x1f0 */
-	struct setup_header hdr;    /* setup header */	/* 0x1f1 */
-	__u8  _pad7[0x290-0x1f1-sizeof(struct setup_header)];
-	__u32 edd_mbr_sig_buffer[EDD_MBR_SIG_MAX];	/* 0x290 */
-	struct boot_e820_entry e820_table[E820_MAX_ENTRIES_ZEROPAGE]; /* 0x2d0 */
-	__u8  _pad8[48];				/* 0xcd0 */
-	struct edd_info eddbuf[EDDMAXNR];		/* 0xd00 */
-	__u8  _pad9[276];				/* 0xeec */
-} __attribute__((packed));
-
 struct gdt_entry {
     unsigned int limit_low : 16;
     unsigned int base_low : 24;
@@ -468,26 +151,19 @@ void prepare_real_mode_gdt() {
     gdt[3].base_high = 0x00;
 }
 
-//struct boot_params boot_params __attribute__((aligned(16)));
-
-void prepare_setup_header(struct setup_header *hdr, void *initrd, size_t initrd_size) {
-    hdr->vid_mode = 0xffff;
-    hdr->type_of_loader = 0xff;
-    hdr->loadflags = 0x81;
-    hdr->ramdisk_image = (uint32_t) initrd;
-    hdr->ramdisk_size = initrd_size;
-    hdr->heap_end_ptr = 0xde00;
-    hdr->cmd_line_ptr = 0x1e000;
+void prepare_setup_header(void *zero_page, void *initrd, size_t initrd_size) {
+    char *czp = (char*) zero_page;
+    *((uint16_t*)(czp+0x1fa)) = 0xffff;
+    *((uint8_t*)(czp+0x210)) = 0xff;
+    *((uint8_t*)(czp+0x211)) = 0x81;
+    *((void**)(czp+0x218)) = initrd;
+    *((uint32_t*)(czp+0x21c)) = initrd_size;
+    *((uint16_t*)(czp+0x224)) = 0xde00;
+    *((void**)(czp+0x228)) = (void*) 0x1e000;
 }
 
-void prepare_boot_params(struct boot_params *real_mode, void *initrd, size_t initrd_size) {
-    prepare_setup_header(&real_mode->hdr, initrd, initrd_size);
-    //real_mode->screen_info.ext_mem_k = 0xf000;
-    //real_mode->alt_mem_k = 0x1234;
-    real_mode->e820_entries = 1;
-    real_mode->e820_table[0].addr = 0x100000;
-    real_mode->e820_table[0].size = 128 * 1024 * 1024;
-    real_mode->e820_table[0].type = 1;
+void prepare_boot_params(void *zero_page, void *initrd, size_t initrd_size) {
+    prepare_setup_header(zero_page, initrd, initrd_size);
 }
 
 #define SECT_SIZE 512
@@ -497,19 +173,18 @@ void load_linux32() {
     download_file("http://10.0.2.2:8080/initrd.img", "/ram/cont/initrd.img");
     printf("Loading Linux kernel\n");
     FILE *fin = fopen("/ram/cont/bzImage", "rb");
-    struct boot_params *real_mode = malloc(SECT_SIZE);
+    void *real_mode = malloc(SECT_SIZE);
     size_t res = fread(real_mode, SECT_SIZE, 1, fin);
     assert(res == 1);
-    if (real_mode->hdr.setup_sects == 0) {
-        real_mode->hdr.setup_sects = 4;
-    }
-    size_t real_mode_size = SECT_SIZE * (1 + real_mode->hdr.setup_sects);
+    uint8_t setup_sects = *((uint8_t*)(((char*)real_mode)+0x1f1));
+    setup_sects = setup_sects == 0 ? 4 : setup_sects;
+    size_t real_mode_size = SECT_SIZE * (1 + setup_sects);
     printf("Real mode code/data is 0x%x bytes long\n", real_mode_size);
     real_mode = realloc(real_mode, real_mode_size);
-    res = fread(((char*)real_mode) + SECT_SIZE, SECT_SIZE, real_mode->hdr.setup_sects, fin);
-    assert(res == real_mode->hdr.setup_sects);
-    assert(real_mode->hdr.boot_flag == 0xaa55);
-    assert(real_mode->hdr.header == 0x53726448);
+    res = fread(((char*)real_mode) + SECT_SIZE, SECT_SIZE, setup_sects, fin);
+    assert(res == setup_sects);
+    assert(*((uint16_t*)(((char*)real_mode)+0x1fe)) == 0xaa55);
+    assert(*((uint32_t*)(((char*)real_mode)+0x202)) == 0x53726448);
     size_t prot_mode_size;
     void *prot_mode = read_whole_file(fin, &prot_mode_size);
     printf("Protected mode code/data is 0x%x bytes long\n", prot_mode_size);
@@ -557,24 +232,23 @@ void load_linux() {
     download_file("http://10.0.2.2:8080/realmode.bin", "/ram/cont/realmode.bin");
     printf("Loading Linux kernel\n");
     FILE *fin = fopen("/ram/cont/bzImage", "rb");
-    struct boot_params *real_mode = malloc(SECT_SIZE);
+    void *real_mode = malloc(SECT_SIZE);
     size_t res = fread(real_mode, SECT_SIZE, 1, fin);
     assert(res == 1);
-    if (real_mode->hdr.setup_sects == 0) {
-        real_mode->hdr.setup_sects = 4;
-    }
-    size_t real_mode_size = SECT_SIZE * (1 + real_mode->hdr.setup_sects);
+    uint8_t setup_sects = *((uint8_t*)(((char*)real_mode)+0x1f1));
+    setup_sects = setup_sects == 0 ? 4 : setup_sects;
+    size_t real_mode_size = SECT_SIZE * (1 + setup_sects);
     printf("Real mode code/data is 0x%x bytes long\n", real_mode_size);
     real_mode = realloc(real_mode, real_mode_size);
-    res = fread(((char*)real_mode) + SECT_SIZE, SECT_SIZE, real_mode->hdr.setup_sects, fin);
-    assert(res == real_mode->hdr.setup_sects);
-    assert(real_mode->hdr.boot_flag == 0xaa55);
-    assert(real_mode->hdr.header == 0x53726448);
+    res = fread(((char*)real_mode) + SECT_SIZE, SECT_SIZE, setup_sects, fin);
+    assert(res == setup_sects);
+    assert(*((uint16_t*)(((char*)real_mode)+0x1fe)) == 0xaa55);
+    assert(*((uint32_t*)(((char*)real_mode)+0x202)) == 0x53726448);
     size_t prot_mode_size;
     void *prot_mode = read_whole_file(fin, &prot_mode_size);
     printf("Protected mode code/data is 0x%x bytes long\n", prot_mode_size);
     fclose(fin);
-    prepare_setup_header(&real_mode->hdr, 0, 0);
+    prepare_setup_header(real_mode, 0, 0);
     //load_linux_gdt();
     fin = fopen("/ram/cont/realmode.bin", "rb");
     size_t trampoline_size;