From 6dcc13d175740afc8ca12314be7d695f5eb67f45 Mon Sep 17 00:00:00 2001 From: G3bE Date: Fri, 31 Jan 2020 16:47:27 +1000 Subject: [PATCH 1/4] Improve docs on creating a simple kernel --- docs/README.md | 48 ++++++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 46 insertions(+), 2 deletions(-) diff --git a/docs/README.md b/docs/README.md index 22bbd19..429924b 100644 --- a/docs/README.md +++ b/docs/README.md @@ -64,14 +64,58 @@ void _start(void) { } ``` +The kernel needs a linker script to be loaded to 1 MiB, replacing NASMs `ORG` instruction. +The file can be called `kernel.ld`. + +``` +OUTPUT_FORMAT("binary") +OUTPUT_ARCH("i386:x86-64") + +SECTIONS +{ + . = 0x100000; + .text : { + *(.text) + } + .data : { + *(.data) + } + .rodata : { + *(.rodata) + } + .bss : { + *(.bss) + } +} + +``` + Compile is like this: ``` -gcc kernel.c -o kernel -mno-red-zone -fno-stack-protector -fomit-frame-pointer +gcc -c kernel.c -o kernel.o -mno-red-zone -fno-stack-protector -fomit-frame-pointer +ld -T kernel.ld -o kernel.bin kernel.o ``` -The flags added to the command are there to help GCC produce could that will run in kernel space. +The flags added to the first command are there to help GCC produce could that will run in kernel space. +The second command simply takes kernel.o and orders it as the linker script tells it to. + +## Creating a bootable image + +After creating a kernel this is a possible routine to create a bootable image. +The commands require Pure64 to be build and `pure64.sys` and `mbr.sys` to be in the same directory +as your kernel with the name `kernel.bin` + +``` +dd if=/dev/zero of=disk.img count=128 bs=1048576 +cat pure64.sys kernel.bin > software.sys + +dd if=mbr.sys of=disk.img conv=notrunc +dd if=software.sys of=disk.img bs=512 seek=16 conv=notrunc +``` +After creating a bootable image it can be tested using qemu: +`qemu-system-x86_64 -drive format=raw,file=disk.img` ## Memory Map From 1bcc79a7e3485864953937c59bb7ae6744c77330 Mon Sep 17 00:00:00 2001 From: G3bE <32980656+G3bE@users.noreply.github.com> Date: Fri, 31 Jan 2020 18:23:08 +1000 Subject: [PATCH 2/4] Fix indentation --- docs/README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/README.md b/docs/README.md index 429924b..4e1f4be 100644 --- a/docs/README.md +++ b/docs/README.md @@ -73,8 +73,8 @@ OUTPUT_ARCH("i386:x86-64") SECTIONS { - . = 0x100000; - .text : { + . = 0x100000; + .text : { *(.text) } .data : { From 6a91f1cdd95a526a3445b1cdc2c553d0adb2964b Mon Sep 17 00:00:00 2001 From: G3bE <32980656+G3bE@users.noreply.github.com> Date: Fri, 31 Jan 2020 19:47:14 +1000 Subject: [PATCH 3/4] Add notice about entry point symbol linkage --- docs/README.md | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/docs/README.md b/docs/README.md index 4e1f4be..6505bf4 100644 --- a/docs/README.md +++ b/docs/README.md @@ -100,6 +100,23 @@ ld -T kernel.ld -o kernel.bin kernel.o The flags added to the first command are there to help GCC produce could that will run in kernel space. The second command simply takes kernel.o and orders it as the linker script tells it to. +## Contributors note + +After a bit of testing I found out that the entry symbol (defaults to \_start) must always be in front of anything - even includes. This is probably due to Pure64 loading pure binaries which don't store the entry points address. +The best solutions I could come up with is to create a seperate file (e.g `start.c`) that calls the `main` function. +``` +extern int main(void); + +void _start(void) +{ + main(); +} +``` +This file would **always** have to be linked in front of everything else. For the above example that would mean the linker command would have to become: +``` +ld -T kernel.ld -o kernel.bin start.o kernel.o +``` + ## Creating a bootable image After creating a kernel this is a possible routine to create a bootable image. From a8bd937798ac7de085c934dbd077187dce0395aa Mon Sep 17 00:00:00 2001 From: G3bE <32980656+G3bE@users.noreply.github.com> Date: Sat, 1 Feb 2020 10:22:59 +1000 Subject: [PATCH 4/4] Remove first person form --- docs/README.md | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/docs/README.md b/docs/README.md index 6505bf4..233793e 100644 --- a/docs/README.md +++ b/docs/README.md @@ -102,8 +102,7 @@ The second command simply takes kernel.o and orders it as the linker script tell ## Contributors note -After a bit of testing I found out that the entry symbol (defaults to \_start) must always be in front of anything - even includes. This is probably due to Pure64 loading pure binaries which don't store the entry points address. -The best solutions I could come up with is to create a seperate file (e.g `start.c`) that calls the `main` function. +The `_start` symbol must always appear first within flat binaries as Pure64 will call the start of the file so it must contain executable code. Function definitions (such as inline ones) in header files could interfere with the placement of the `_start` symbol. The best solution is to put the entry point in a separate file that calls the main function. Such a file could be called `start.c`. ``` extern int main(void); @@ -112,7 +111,7 @@ void _start(void) main(); } ``` -This file would **always** have to be linked in front of everything else. For the above example that would mean the linker command would have to become: +This file would **always** have to be linked in front of everything else. For the above example that would mean the linker command above would have to become: ``` ld -T kernel.ld -o kernel.bin start.o kernel.o ```