From 23e6ba8ef9f9967e0c15c6245fd92cdd5f60fc55 Mon Sep 17 00:00:00 2001 From: Wojtek Kosior Date: Fri, 11 Oct 2019 11:59:59 +0200 Subject: add initial bootloader work --- Makefile | 26 +++++++++++++++++++++++++- 1 file changed, 25 insertions(+), 1 deletion(-) (limited to 'Makefile') diff --git a/Makefile b/Makefile index b1b15c4..da43892 100644 --- a/Makefile +++ b/Makefile @@ -17,13 +17,37 @@ kernel.elf : boot.o kernel.o uart.o kernel7.img : kernel.elf arm-none-eabi-objcopy $^ -O binary $@ +loader_stage2.o : loader_stage2.c + arm-none-eabi-gcc $(CFLAGS) -c $^ -o $@ + +loader_stage2.elf : loader_stage2.o uart.o + arm-none-eabi-gcc -T loader_stage2.ld -o $@ -ffreestanding -O2 -nostdlib $^ -lgcc + +loader_stage2.img : loader_stage2.elf + arm-none-eabi-objcopy $^ -O binary $@ + +loader_stage2_embeddable.o : loader_stage2.img + arm-none-eabi-objcopy -I binary -O elf32-littlearm -B arm --rename-section .data=.rodata $^ $@ + +loader_stage1.o : loader_stage1.c + arm-none-eabi-gcc $(CFLAGS) -c $^ -o $@ + +loader.elf : boot.o loader_stage1.o uart.o loader_stage2_embeddable.o + arm-none-eabi-gcc -T loader_stage1.ld -o $@ -ffreestanding -O2 -nostdlib $^ -lgcc + +loader.img : loader.elf + arm-none-eabi-objcopy $^ -O binary $@ + qemu-elf : kernel.elf qemu-system-arm -m 256 -M raspi2 -serial stdio -kernel $^ qemu-bin : kernel7.img qemu-system-arm -m 256 -M raspi2 -serial stdio -kernel $^ +qemu-loader : loader.img + qemu-system-arm -m 256 -M raspi2 -serial stdio -kernel $^ + clean : - -rm kernel7.img kernel.elf boot.o kernel.o uart.o + -rm *.img *.elf *.o .PHONY: all qemu-elf qemu-bin clean -- cgit v1.2.3 From e056312b52faf9eff2a88b1c751fb06824263b14 Mon Sep 17 00:00:00 2001 From: Wojtek Kosior Date: Fri, 11 Oct 2019 18:36:14 +0200 Subject: add simple piping program for host --- Makefile | 5 ++++- pipe_image.c | 55 +++++++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 59 insertions(+), 1 deletion(-) create mode 100644 pipe_image.c (limited to 'Makefile') diff --git a/Makefile b/Makefile index da43892..6ced357 100644 --- a/Makefile +++ b/Makefile @@ -47,7 +47,10 @@ qemu-bin : kernel7.img qemu-loader : loader.img qemu-system-arm -m 256 -M raspi2 -serial stdio -kernel $^ +pipe_image : pipe_image.c + gcc -Wall -std=gnu99 -O3 $^ -o $@ + clean : - -rm *.img *.elf *.o + -rm *.img *.elf *.o pipe_image .PHONY: all qemu-elf qemu-bin clean diff --git a/pipe_image.c b/pipe_image.c new file mode 100644 index 0000000..7e24ea7 --- /dev/null +++ b/pipe_image.c @@ -0,0 +1,55 @@ +#include +#include +#include +#include +#include + +#define ANSI_FG_RED "\033[0;31m" + +/* This program pipes it's argument file to stdout prepending it */ +/* with it's size (4 bytes, little endian). It is intended to be used */ +/* with our bootloader (i.e. by piping kernel image to UART). */ + +int main(int argc, char **argv) { + char *image_file_name = argc > 1 ? argv[1] : "kernel7.img"; + + FILE *image_file_handle = fopen(image_file_name, "r"); + + if (!image_file_handle) + err(-1, "couldn't open" ANSI_FG_RED "%s", image_file_name); + + if (fseek(image_file_handle, 0, SEEK_END)) + err(-1, "error navigating through file"); + + ssize_t image_size = ftell(image_file_handle); + if (image_size < 0) + err(-1, "couldn't get image file size"); + + if (image_size >> 32) + err(-1, "file to big (should be smaller than 4G)"); + + if (fseek(image_file_handle, 0, SEEK_SET)) + err(-1, "error navigating through file"); + + uint32_t image_size_le = htole32(image_size); + + if (fwrite(&image_size_le, 4, 1, stdout) != 1) + err(-1, "couldn't write to stdout"); + + ssize_t bytes_left = image_size; + + char buf[1024]; + + while (bytes_left) + { + size_t bytes_read; + if ((bytes_read = fread(buf, 1, sizeof(buf), image_file_handle)) + < 1) + err(-1, "error reading the file"); + + if (fwrite(buf, bytes_read, 1, stdout) != 1) + err(-1, "error writing to stdout"); + + bytes_left -= bytes_read; + } +} -- cgit v1.2.3 From b452b0edbc784722c25014a20f554737d64ba758 Mon Sep 17 00:00:00 2001 From: Wojtek Kosior Date: Fri, 11 Oct 2019 18:53:13 +0200 Subject: use bootloader in qemu --- Makefile | 4 ++-- linker.ld | 13 ++++++++----- 2 files changed, 10 insertions(+), 7 deletions(-) (limited to 'Makefile') diff --git a/Makefile b/Makefile index 6ced357..2fbb0aa 100644 --- a/Makefile +++ b/Makefile @@ -41,8 +41,8 @@ loader.img : loader.elf qemu-elf : kernel.elf qemu-system-arm -m 256 -M raspi2 -serial stdio -kernel $^ -qemu-bin : kernel7.img - qemu-system-arm -m 256 -M raspi2 -serial stdio -kernel $^ +qemu-bin : loader.img kernel7.img pipe_image + ./pipe_image | qemu-system-arm -m 256 -M raspi2 -serial stdio -kernel $< qemu-loader : loader.img qemu-system-arm -m 256 -M raspi2 -serial stdio -kernel $^ diff --git a/linker.ld b/linker.ld index 0cbd1fb..c9a91df 100644 --- a/linker.ld +++ b/linker.ld @@ -2,12 +2,15 @@ ENTRY(_start) SECTIONS { - /* Starts at LOADER_ADDR. */ - /* Warning! Internet says RPis in 32-bit mode load kernel at 0x8000! */ + /* Starts at LOADER_ADDR, which is 0x8000 - that's where RPis in */ + /* 32-bit mode load kernel at. */ /* My experiments do, however, show, that qemu emulating RPi2 */ - /* Loads the kernel at 0x10000! (took some pain to find out) */ - . = 0x10000; - /* For AArch64, use . = 0x80000; Unless this too is wrong */ + /* loads the kernel at 0x10000! (took some pain to find out). */ + /* Since we're using a bootloader now, we can compile the kernel */ + /* for 0x8000 and bootloader will load it properly (although it */ + /* itself still has to be compiled for 0x10000) */ + . = 0x8000; + /* For AArch64, use . = 0x80000; Unless this too is wrong in qemu… */ __start = .; __text_start = .; .text : -- cgit v1.2.3 From bc9ee9f0acc0ec26acda4ffd8f5fdcd04a6375c5 Mon Sep 17 00:00:00 2001 From: Wojtek Kosior Date: Fri, 11 Oct 2019 18:59:16 +0200 Subject: initialize uart in bootloader's stage2, not stage1 --- Makefile | 2 +- loader_stage1.c | 5 ----- loader_stage2.c | 2 +- 3 files changed, 2 insertions(+), 7 deletions(-) (limited to 'Makefile') diff --git a/Makefile b/Makefile index 2fbb0aa..7632283 100644 --- a/Makefile +++ b/Makefile @@ -32,7 +32,7 @@ loader_stage2_embeddable.o : loader_stage2.img loader_stage1.o : loader_stage1.c arm-none-eabi-gcc $(CFLAGS) -c $^ -o $@ -loader.elf : boot.o loader_stage1.o uart.o loader_stage2_embeddable.o +loader.elf : boot.o loader_stage1.o loader_stage2_embeddable.o arm-none-eabi-gcc -T loader_stage1.ld -o $@ -ffreestanding -O2 -nostdlib $^ -lgcc loader.img : loader.elf diff --git a/loader_stage1.c b/loader_stage1.c index 9492747..d209c15 100644 --- a/loader_stage1.c +++ b/loader_stage1.c @@ -1,6 +1,5 @@ #include #include -#include #include char *const stage2_addr = ((void*) 0x4000); @@ -15,10 +14,6 @@ extern char void kernel_main(uint32_t r0, uint32_t r1, uint32_t atags) { - // uart_init() call to be moved to stage2... - uart_init(); - uart_puts("Hello, bootloader World!\r\n"); - // stage2 of the bootloader is a blob embedded in executable; // copy it over to it's destination place // TODO implement a memcpy() somewhere and use it instead of loops diff --git a/loader_stage2.c b/loader_stage2.c index 98ce571..e221dda 100644 --- a/loader_stage2.c +++ b/loader_stage2.c @@ -13,7 +13,7 @@ stage2(uint32_t r0, uint32_t r1, uint32_t atags) (void) r1; (void) atags; - uart_puts("hello stage2!\n\r"); + uart_init(); // get kernel size via uart (little endian) uint32_t b0, b1, b2, b3; -- cgit v1.2.3