:: commit 524829370d27f82f4d9a111c15a298b91a4248c9

mintsuki <mintsuki@protonmail.com> — 2021-02-20 22:04

parents: 5d75f5213c

misc: Initial 3-stage bootloader work

diff --git a/Makefile b/Makefile
index 3d3b559a..fac6d112 100644
--- a/Makefile
+++ b/Makefile
@@ -10,12 +10,15 @@ PATH := $(shell pwd)/toolchain/bin:$(PATH)
 
 all: limine-install
 
-limine-install: limine-install.c limine.o
-	$(CC) $(CFLAGS) -std=c11 limine.o limine-install.c -o limine-install
+limine-install: limine-install.c limine.o limine_sys.o
+	$(CC) $(CFLAGS) -std=c11 limine.o limine_sys.o limine-install.c -o limine-install
 
 limine.o: limine.bin
 	$(OBJCOPY) -B i8086 -I binary -O default limine.bin limine.o
 
+limine_sys.o: limine.bin
+	$(OBJCOPY) -B i8086 -I binary -O default limine.sys limine_sys.o
+
 clean:
 	rm -f limine.o limine-install
 
@@ -28,6 +31,7 @@ bootloader: stage2 decompressor
 	cd bootsect && nasm bootsect.asm -fbin -o ../limine.bin
 	cd pxeboot && nasm bootsect.asm -fbin -o ../limine-pxe.bin
 	cp stage2/stage2.map ./
+	cp stage2/stage3.bin ./limine.sys
 
 bootloader-clean: stage2-clean decompressor-clean test-clean
 	rm -f stage2/stage2.bin.gz test/stage2.map test.hdd
@@ -72,8 +76,8 @@ echfs-test: test.hdd bootloader | all
 	echfs-utils -g -p0 test.hdd import stage2.map boot/stage2.map
 	echfs-utils -g -p0 test.hdd import test/test.elf boot/test.elf
 	echfs-utils -g -p0 test.hdd import test/bg.bmp boot/bg.bmp
-	echfs-utils -g -p0 test.hdd import test/font.bin boot/font.bin
-	./limine-install test.hdd
+	./limine-install ./ test.hdd
+	echfs-utils -g -p0 test.hdd import ./limine.sys boot/limine.sys
 	qemu-system-x86_64 -net none -smp 4 -enable-kvm -cpu host -hda test.hdd -debugcon stdio
 
 ext2-test: test.hdd bootloader | all
diff --git a/limine-install.c b/limine-install.c
index e672f540..74cf034d 100644
--- a/limine-install.c
+++ b/limine-install.c
@@ -260,34 +260,53 @@ static bool _device_write(const void *buffer, uint64_t loc, size_t count) {
     } while (0)
 
 extern uint8_t _binary_limine_bin_start[], _binary_limine_bin_end[];
+extern uint8_t _binary_limine_sys_start[], _binary_limine_sys_end[];
 
 int main(int argc, char *argv[]) {
     int      ok = 1;
     uint8_t *bootloader_img = _binary_limine_bin_start;
     size_t   bootloader_file_size =
         (size_t)_binary_limine_bin_end - (size_t)_binary_limine_bin_start;
+    uint8_t *stage3_img = _binary_limine_sys_start;
+    size_t   stage3_file_size =
+        (size_t)_binary_limine_sys_end - (size_t)_binary_limine_sys_start;
     uint8_t  orig_mbr[70], timestamp[6];
+    char *limine_sys_path = NULL;
+    int   limine_sys = -1;
 
     if (sizeof(off_t) != 8) {
         fprintf(stderr, "ERROR: off_t type is not 64-bit.\n");
         goto cleanup;
     }
 
-    if (argc > 1 && strstr(argv[1], "limine.bin") != NULL) {
-        fprintf(stderr,
-            "WARNING: Passing the bootloader binary as a file argument is\n"
-            "         deprecated and should be avoided in the future.\n");
-        argc--;
-        argv[1] = argv[0];
-        argv++;
+    if (argc < 3) {
+        printf("Usage: %s <boot directory> <device> [GPT partition index]\n", argv[0]);
+        goto cleanup;
+    }
+
+    #define MAX_STAGE3_PATH 1024
+
+    limine_sys_path = malloc(MAX_STAGE3_PATH);
+    if (limine_sys_path == NULL) {
+        perror("ERROR");
+        goto cleanup;
     }
 
-    if (argc < 2) {
-        printf("Usage: %s <device> [GPT partition index]\n", argv[0]);
+    snprintf(limine_sys_path, MAX_STAGE3_PATH, "%s/limine.sys", argv[1]);
+
+    limine_sys = creat(limine_sys_path, 0644);
+    if (limine_sys == -1) {
+        perror("ERROR");
+        goto cleanup;
+    }
+
+    if (write(limine_sys, stage3_img, stage3_file_size) !=
+        (ssize_t)stage3_file_size) {
+        perror("ERROR");
         goto cleanup;
     }
 
-    device = open(argv[1], O_RDWR);
+    device = open(argv[2], O_RDWR);
     if (device == -1) {
         perror("ERROR");
         goto cleanup;
@@ -483,6 +502,10 @@ cleanup:
         free(cache);
     if (device != -1)
         close(device);
+    if (limine_sys_path != NULL)
+        free(limine_sys_path);
+    if (limine_sys != -1)
+        close(limine_sys);
 
     return ok;
 }
diff --git a/limine-pxe.bin b/limine-pxe.bin
index a0664bdd..405cc4e7 100644
Binary files a/limine-pxe.bin and b/limine-pxe.bin differ
diff --git a/limine.bin b/limine.bin
index 94f837c2..05615af0 100644
Binary files a/limine.bin and b/limine.bin differ
diff --git a/limine.sys b/limine.sys
new file mode 100644
index 00000000..54d47749
Binary files /dev/null and b/limine.sys differ
diff --git a/stage2.map b/stage2.map
index 5a8a0beb..7bde8641 100644
Binary files a/stage2.map and b/stage2.map differ
diff --git a/stage2/Makefile b/stage2/Makefile
index f0c325b2..e11c98f9 100644
--- a/stage2/Makefile
+++ b/stage2/Makefile
@@ -2,6 +2,7 @@ CC = i386-elf-gcc
 LD = i386-elf-gcc
 OBJCOPY = i386-elf-objcopy
 OBJDUMP = i386-elf-objdump
+READELF = i386-elf-readelf
 
 LIMINE_VERSION := $(shell git branch --show-current | sed 's/-branch//')
 WERROR = -Werror
@@ -44,13 +45,19 @@ ASM_FILES := $(shell find ./ -type f -name '*.asm' | sort)
 OBJ := $(ASM_FILES:.asm=.o) $(C_FILES:.c=.o)
 HEADER_DEPS := $(C_FILES:.c=.d)
 
-all: stage2.map stage2.bin
+all: stage2.map stage2.bin stage3.bin
+
+stage2.bin: stages.bin
+	dd if=stages.bin bs=$$(( 0x$$($(READELF) -S stage2.elf | grep .stage3 | sed 's/^.*] //' | awk '{print $$3}' | sed 's/^0*//') - 0x8000 )) count=1 of=$@
+
+stage3.bin: stages.bin
+	dd if=stages.bin bs=$$(( 0x$$($(READELF) -S stage2.elf | grep .stage3 | sed 's/^.*] //' | awk '{print $$3}' | sed 's/^0*//') - 0x8000 )) skip=1 of=$@
 
 stage2.map: stage2.elf
 	./gensyms.sh $(OBJDUMP)
 	nasm symlist.gen -f bin -o $@
 
-stage2.bin: stage2.elf
+stages.bin: stage2.elf
 	$(OBJCOPY) -O binary $< $@
 
 stage2.elf: $(OBJ)
@@ -65,4 +72,4 @@ stage2.elf: $(OBJ)
 	nasm $< -f elf32 -o $@
 
 clean:
-	rm -f symlist.gen stage2.map stage2.bin stage2.elf $(OBJ) $(HEADER_DEPS)
+	rm -f symlist.gen stage2.map stage2.bin stage2.elf stage3.bin $(OBJ) $(HEADER_DEPS)
diff --git a/stage2/drivers/vbe.c b/stage2/drivers/vbe.c
index d5b2f5cf..5d2e7df2 100644
--- a/stage2/drivers/vbe.c
+++ b/stage2/drivers/vbe.c
@@ -17,9 +17,9 @@
 #define VGA_FONT_GLYPHS 256
 #define VGA_FONT_MAX    (VGA_FONT_HEIGHT * VGA_FONT_GLYPHS)
 
-static uint8_t *vga_font;
+stage3_data static uint8_t *vga_font;
 
-static void vga_font_retrieve(void) {
+stage3_text static void vga_font_retrieve(void) {
     struct rm_regs r = {0};
 
     r.eax = 0x1130;
@@ -31,37 +31,37 @@ static void vga_font_retrieve(void) {
     memcpy(vga_font, (void *)rm_desegment(r.es, r.ebp), VGA_FONT_MAX);
 }
 
-static uint32_t ansi_colours[8];
+stage3_data static uint32_t ansi_colours[8];
 
-static struct vbe_framebuffer_info fbinfo;
-static uint32_t *vbe_framebuffer;
-static uint16_t  vbe_pitch;
-static uint16_t  vbe_width;
-static uint16_t  vbe_height;
-static uint16_t  vbe_bpp;
+stage3_data static struct vbe_framebuffer_info fbinfo;
+stage3_data static uint32_t *vbe_framebuffer;
+stage3_data static uint16_t  vbe_pitch;
+stage3_data static uint16_t  vbe_width;
+stage3_data static uint16_t  vbe_height;
+stage3_data static uint16_t  vbe_bpp;
 
-static int frame_height, frame_width;
+stage3_data static int frame_height, frame_width;
 
-static struct image *background;
+stage3_data static struct image *background;
 
-static struct vbe_char *grid;
-static struct vbe_char *front_grid;
+stage3_data static struct vbe_char *grid;
+stage3_data static struct vbe_char *front_grid;
 
-static bool double_buffer_enabled = false;
+stage3_data static bool double_buffer_enabled = false;
 
-static bool cursor_status = true;
+stage3_data static bool cursor_status = true;
 
-static int cursor_x;
-static int cursor_y;
+stage3_data static int cursor_x;
+stage3_data static int cursor_y;
 
-static uint32_t cursor_fg = 0x00000000;
-static uint32_t cursor_bg = 0x00ffffff;
-static uint32_t text_fg;
-static uint32_t text_bg;
+stage3_data static uint32_t cursor_fg = 0x00000000;
+stage3_data static uint32_t cursor_bg = 0x00ffffff;
+stage3_data static uint32_t text_fg;
+stage3_data static uint32_t text_bg;
 
-static int rows;
-static int cols;
-static int margin_gradient;
+stage3_data static int rows;
+stage3_data static int cols;
+stage3_data static int margin_gradient;
 
 #define A(rgb) (uint8_t)(rgb >> 24)
 #define R(rgb) (uint8_t)(rgb >> 16)
@@ -69,7 +69,7 @@ static int margin_gradient;
 #define B(rgb) (uint8_t)(rgb)
 #define ARGB(a, r, g, b) (a << 24) | ((r & 0xFF) << 16) | ((g & 0xFF) << 8) | (b & 0xFF)
 
-static inline uint32_t colour_blend(uint32_t fg, uint32_t bg) {
+stage3_text static inline uint32_t colour_blend(uint32_t fg, uint32_t bg) {
     unsigned alpha = 255 - A(fg);
     unsigned inv_alpha = A(fg) + 1;
 
@@ -80,19 +80,19 @@ static inline uint32_t colour_blend(uint32_t fg, uint32_t bg) {
     return ARGB(0, r, g, b);
 }
 
-void vbe_plot_px(int x, int y, uint32_t hex) {
+stage3_text void vbe_plot_px(int x, int y, uint32_t hex) {
     size_t fb_i = x + (vbe_pitch / sizeof(uint32_t)) * y;
 
     vbe_framebuffer[fb_i] = hex;
 }
 
-static void _vbe_plot_bg_blent_px(int x, int y, uint32_t hex) {
+stage3_text static void _vbe_plot_bg_blent_px(int x, int y, uint32_t hex) {
     vbe_plot_px(x, y, colour_blend(hex, background->get_pixel(background, x, y)));
 }
 
-void (*vbe_plot_bg_blent_px)(int x, int y, uint32_t hex) = vbe_plot_px;
+stage3_data void (*vbe_plot_bg_blent_px)(int x, int y, uint32_t hex) = vbe_plot_px;
 
-static uint32_t blend_gradient_from_box(int x, int y, uint32_t hex) {
+stage3_text static uint32_t blend_gradient_from_box(int x, int y, uint32_t hex) {
     if (x >= frame_width  && x < frame_width  + VGA_FONT_WIDTH  * cols
      && y >= frame_height && y < frame_height + VGA_FONT_HEIGHT * rows) {
         return hex;
@@ -133,7 +133,7 @@ static uint32_t blend_gradient_from_box(int x, int y, uint32_t hex) {
     return colour_blend((hex & 0xffffff) | (new_alpha << 24), bg_px);
 }
 
-void vbe_plot_background(int x, int y, int width, int height) {
+stage3_text void vbe_plot_background(int x, int y, int width, int height) {
     if (background) {
         for (int yy = 0; yy < height; yy++) {
             for (int xx = 0; xx < width; xx++) {
@@ -149,7 +149,7 @@ void vbe_plot_background(int x, int y, int width, int height) {
     }
 }
 
-void vbe_plot_rect(int x, int y, int width, int height, uint32_t hex) {
+stage3_text void vbe_plot_rect(int x, int y, int width, int height, uint32_t hex) {
     for (int yy = 0; yy < height; yy++) {
         for (int xx = 0; xx < width; xx++) {
             vbe_plot_px(x + xx, y + yy, hex);
@@ -157,7 +157,7 @@ void vbe_plot_rect(int x, int y, int width, int height, uint32_t hex) {
     }
 }
 
-void vbe_plot_bg_blent_rect(int x, int y, int width, int height, uint32_t hex) {
+stage3_text void vbe_plot_bg_blent_rect(int x, int y, int width, int height, uint32_t hex) {
     for (int yy = 0; yy < height; yy++) {
         for (int xx = 0; xx < width; xx++) {
             vbe_plot_bg_blent_px(x + xx, y + yy, hex);
@@ -171,7 +171,7 @@ struct vbe_char {
     uint32_t bg;
 };
 
-void vbe_plot_char(struct vbe_char *c, int x, int y) {
+stage3_text void vbe_plot_char(struct vbe_char *c, int x, int y) {
     uint8_t *glyph = &vga_font[(size_t)c->c * VGA_FONT_HEIGHT];
 
     vbe_plot_bg_blent_rect(x, y, VGA_FONT_WIDTH, VGA_FONT_HEIGHT, c->bg);
@@ -184,7 +184,7 @@ void vbe_plot_char(struct vbe_char *c, int x, int y) {
     }
 }
 
-static void plot_char_grid(struct vbe_char *c, int x, int y) {
+stage3_text static void plot_char_grid(struct vbe_char *c, int x, int y) {
     if (!double_buffer_enabled) {
         vbe_plot_char(c, x * VGA_FONT_WIDTH + frame_width,
                          y * VGA_FONT_HEIGHT + frame_height);
@@ -192,14 +192,14 @@ static void plot_char_grid(struct vbe_char *c, int x, int y) {
     grid[x + y * cols] = *c;
 }
 
-static void clear_cursor(void) {
+stage3_text static void clear_cursor(void) {
     struct vbe_char c = grid[cursor_x + cursor_y * cols];
     c.fg = text_fg;
     c.bg = text_bg;
     plot_char_grid(&c, cursor_x, cursor_y);
 }
 
-static void draw_cursor(void) {
+stage3_text static void draw_cursor(void) {
     if (cursor_status) {
         struct vbe_char c = grid[cursor_x + cursor_y * cols];
         c.fg = cursor_fg;
@@ -208,7 +208,7 @@ static void draw_cursor(void) {
     }
 }
 
-static void scroll(void) {
+stage3_text static void scroll(void) {
     clear_cursor();
 
     for (int i = cols; i < rows * cols; i++) {
@@ -227,7 +227,7 @@ static void scroll(void) {
     draw_cursor();
 }
 
-void vbe_clear(bool move) {
+stage3_text void vbe_clear(bool move) {
     clear_cursor();
 
     struct vbe_char empty;
@@ -246,37 +246,37 @@ void vbe_clear(bool move) {
     draw_cursor();
 }
 
-void vbe_enable_cursor(void) {
+stage3_text void vbe_enable_cursor(void) {
     cursor_status = true;
     draw_cursor();
 }
 
-void vbe_disable_cursor(void) {
+stage3_text void vbe_disable_cursor(void) {
     clear_cursor();
     cursor_status = false;
 }
 
-void vbe_set_cursor_pos(int x, int y) {
+stage3_text void vbe_set_cursor_pos(int x, int y) {
     clear_cursor();
     cursor_x = x;
     cursor_y = y;
     draw_cursor();
 }
 
-void vbe_get_cursor_pos(int *x, int *y) {
+stage3_text void vbe_get_cursor_pos(int *x, int *y) {
     *x = cursor_x;
     *y = cursor_y;
 }
 
-void vbe_set_text_fg(int fg) {
+stage3_text void vbe_set_text_fg(int fg) {
     text_fg = ansi_colours[fg];
 }
 
-void vbe_set_text_bg(int bg) {
+stage3_text void vbe_set_text_bg(int bg) {
     text_bg = ansi_colours[bg];
 }
 
-void vbe_double_buffer_flush(void) {
+stage3_text void vbe_double_buffer_flush(void) {
     for (size_t i = 0; i < (size_t)rows * cols; i++) {
         if (!memcmp(&grid[i], &front_grid[i], sizeof(struct vbe_char)))
             continue;
@@ -291,7 +291,7 @@ void vbe_double_buffer_flush(void) {
     }
 }
 
-void vbe_double_buffer(bool state) {
+stage3_text void vbe_double_buffer(bool state) {
     if (state) {
         memcpy(front_grid, grid, rows * cols * sizeof(struct vbe_char));
         double_buffer_enabled = true;
@@ -308,7 +308,7 @@ void vbe_double_buffer(bool state) {
     }
 }
 
-void vbe_putchar(uint8_t c) {
+stage3_text void vbe_putchar(uint8_t c) {
     switch (c) {
         case '\b':
             if (cursor_x || cursor_y) {
@@ -354,7 +354,7 @@ void vbe_putchar(uint8_t c) {
     }
 }
 
-bool vbe_tty_init(int *_rows, int *_cols, uint32_t *_colours, int _margin, int _margin_gradient, struct image *_background) {
+stage3_text bool vbe_tty_init(int *_rows, int *_cols, uint32_t *_colours, int _margin, int _margin_gradient, struct image *_background) {
     int req_width = 0, req_height = 0, req_bpp = 0;
 
     char *menu_resolution = config_get_value(NULL, 0, "MENU_RESOLUTION");
@@ -495,7 +495,7 @@ struct vbe_mode_info_struct {
     uint8_t  reserved2[189];
 } __attribute__((packed));
 
-static void get_vbe_info(struct vbe_info_struct *buf) {
+stage3_text static void get_vbe_info(struct vbe_info_struct *buf) {
     struct rm_regs r = {0};
 
     r.eax = 0x4f00;
@@ -503,7 +503,7 @@ static void get_vbe_info(struct vbe_info_struct *buf) {
     rm_int(0x10, &r, &r);
 }
 
-static void get_vbe_mode_info(struct vbe_mode_info_struct *buf,
+stage3_text static void get_vbe_mode_info(struct vbe_mode_info_struct *buf,
                               uint16_t mode) {
     struct rm_regs r = {0};
 
@@ -513,7 +513,7 @@ static void get_vbe_mode_info(struct vbe_mode_info_struct *buf,
     rm_int(0x10, &r, &r);
 }
 
-static int set_vbe_mode(uint16_t mode) {
+stage3_text static int set_vbe_mode(uint16_t mode) {
     struct rm_regs r = {0};
 
     r.eax = 0x4f02;
@@ -550,7 +550,7 @@ struct edid_info_struct {
     uint8_t checksum;
 } __attribute__((packed));
 
-static int get_edid_info(struct edid_info_struct *buf) {
+stage3_text static int get_edid_info(struct edid_info_struct *buf) {
     struct rm_regs r = {0};
 
     r.eax = 0x4f15;
@@ -572,13 +572,13 @@ struct resolution {
     uint16_t bpp;
 };
 
-static struct resolution fallback_resolutions[] = {
+stage3_data static struct resolution fallback_resolutions[] = {
     { 1024, 768, 32 },
     { 800,  600, 32 },
     { 640,  480, 32 }
 };
 
-bool init_vbe(struct vbe_framebuffer_info *ret,
+stage3_text bool init_vbe(struct vbe_framebuffer_info *ret,
               uint16_t target_width, uint16_t target_height, uint16_t target_bpp) {
     print("vbe: Initialising...\n");
 
diff --git a/stage2/lib/blib.h b/stage2/lib/blib.h
index 0d327b01..5f8ddf44 100644
--- a/stage2/lib/blib.h
+++ b/stage2/lib/blib.h
@@ -43,4 +43,7 @@ uint64_t strtoui(const char *s, const char **end, int base);
 
 typedef void *symbol[];
 
+#define stage3_text __attribute__((section(".stage3_text")))
+#define stage3_data __attribute__((section(".stage3_data")))
+
 #endif
diff --git a/stage2/lib/config.c b/stage2/lib/config.c
index c9c7fa9b..df60239f 100644
--- a/stage2/lib/config.c
+++ b/stage2/lib/config.c
@@ -16,7 +16,18 @@ bool config_ready = false;
 
 static char *config_addr;
 
+extern symbol stage3_addr;
+
 int init_config_disk(struct volume *part) {
+    struct file_handle stage3;
+
+    if (fopen(&stage3, part, "/limine.sys")
+     && fopen(&stage3, part, "/boot/limine.sys")) {
+        panic("Could not open stage 3");
+    }
+
+    fread(&stage3, stage3_addr, 0, stage3.size);
+
     struct file_handle f;
 
     if (fopen(&f, part, "/limine.cfg")
@@ -35,6 +46,12 @@ int init_config_disk(struct volume *part) {
 }
 
 int init_config_pxe(void) {
+    struct tftp_file_handle stage3;
+    if (tftp_open(&stage3, 0, 69, "limine.sys")) {
+        panic("Could not open stage 3");
+    }
+    tftp_read(&stage3, stage3_addr, 0, stage3.file_size);
+
     struct tftp_file_handle cfg;
     if (tftp_open(&cfg, 0, 69, "limine.cfg")
      && tftp_open(&cfg, 0, 69, "tomatboot.cfg")) {
diff --git a/stage2/linker.ld b/stage2/linker.ld
index 8551fe38..b4cf68e2 100644
--- a/stage2/linker.ld
+++ b/stage2/linker.ld
@@ -5,18 +5,24 @@ SECTIONS
 {
     . = 0x8000;
 
-    .text : {
+    .entry : {
         KEEP(*(.entry*))
+    }
+
+    .realmode : {
         KEEP(*(.realmode*))
-        *(.text*)
     }
 
-    .rodata : {
+    .stage2 : {
+        *(.text*)
+        *(.data*)
         *(.rodata*)
     }
 
-    .data : {
-        *(.data*)
+    .stage3 : {
+        stage3_addr = .;
+        *(.stage3_text*)
+        *(.stage3_data*)
     }
 
     .bss : {
tab: 248 wrap: offon