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 < 2) { - printf("Usage: %s [GPT partition index]\n", argv[0]); + if (argc < 3) { + printf("Usage: %s [GPT partition index]\n", argv[0]); goto cleanup; } - device = open(argv[1], O_RDWR); + #define MAX_STAGE3_PATH 1024 + + limine_sys_path = malloc(MAX_STAGE3_PATH); + if (limine_sys_path == NULL) { + perror("ERROR"); + goto cleanup; + } + + 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[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*)) - KEEP(*(.realmode*)) - *(.text*) } - .rodata : { + .realmode : { + KEEP(*(.realmode*)) + } + + .stage2 : { + *(.text*) + *(.data*) *(.rodata*) } - .data : { - *(.data*) + .stage3 : { + stage3_addr = .; + *(.stage3_text*) + *(.stage3_data*) } .bss : {