From 8769aaae1ef2f4132aad90c3f3263abb45c26441 Mon Sep 17 00:00:00 2001 From: mintsuki Date: Thu, 25 Feb 2021 23:11:53 +0100 Subject: [PATCH] misc: Move a lot of code from stage 2 to stage 3 --- stage23/Makefile | 2 +- stage23/lib/acpi.c | 3 +++ stage23/lib/blib.c | 3 +++ stage23/lib/bmp.c | 2 ++ stage23/lib/elf.c | 6 ++++++ stage23/lib/image.c | 1 + stage23/lib/rand.c | 4 ++++ stage23/lib/readline.c | 6 ++++++ stage23/lib/time.c | 3 +++ stage23/lib/uri.c | 7 +++++++ stage23/menu.c | 8 ++++++++ stage23/mm/vmm.c | 3 +++ stage23/protos/chainload.c | 1 + stage23/protos/linux.c | 1 + stage23/protos/stivale.c | 4 ++++ stage23/protos/stivale2.c | 5 +++++ stage23/sys/lapic.c | 7 +++++++ stage23/sys/pic.c | 5 +++++ stage23/sys/smp.c | 3 +++ 19 files changed, 73 insertions(+), 1 deletion(-) diff --git a/stage23/Makefile b/stage23/Makefile index 509721f5..9f102cb0 100644 --- a/stage23/Makefile +++ b/stage23/Makefile @@ -62,7 +62,7 @@ limine.sys: limine.elf limine_nomap.elf: $(OBJ) $(LD) $(OBJ) $(LDFLAGS) $(INTERNAL_LDFLAGS) -Wl,--gc-sections -Tlinker_stage2only.ld -o $@ || \ - ( echo "This error means that stage2 was trying to use stage3 symbols before loading stage 3" && \ + ( echo "This error means that stage 2 was trying to use stage 3 symbols before loading stage 3" && \ false ) $(LD) $(OBJ) $(LDFLAGS) $(INTERNAL_LDFLAGS) -Tlinker_nomap.ld -o $@ diff --git a/stage23/lib/acpi.c b/stage23/lib/acpi.c index 15c41c6b..32a93675 100644 --- a/stage23/lib/acpi.c +++ b/stage23/lib/acpi.c @@ -7,6 +7,7 @@ #include // Following function based on https://github.com/qword-os/lai/blob/master/helpers/pc-bios.c's function lai_bios_calc_checksum() +stage3_text uint8_t acpi_checksum(void *ptr, size_t size) { uint8_t sum = 0, *_ptr = ptr; for (size_t i = 0; i < size; i++) @@ -14,6 +15,7 @@ uint8_t acpi_checksum(void *ptr, size_t size) { return sum; } +stage3_text void *acpi_get_rsdp(void) { size_t ebda = EBDA; @@ -32,6 +34,7 @@ void *acpi_get_rsdp(void) { return NULL; } +stage3_text void *acpi_get_table(const char *signature, int index) { int cnt = 0; diff --git a/stage23/lib/blib.c b/stage23/lib/blib.c index 0fb435c8..71325ec9 100644 --- a/stage23/lib/blib.c +++ b/stage23/lib/blib.c @@ -51,6 +51,7 @@ bool stage3_init(struct volume *part) { return true; } +stage3_text bool parse_resolution(int *width, int *height, int *bpp, const char *buf) { int res[3] = {0}; @@ -79,6 +80,7 @@ bool parse_resolution(int *width, int *height, int *bpp, const char *buf) { // This integer sqrt implementation has been adapted from: // https://stackoverflow.com/questions/1100090/looking-for-an-efficient-integer-square-root-algorithm-for-arm-thumb2 +stage3_text uint64_t sqrt(uint64_t a_nInput) { uint64_t op = a_nInput; uint64_t res = 0; @@ -101,6 +103,7 @@ uint64_t sqrt(uint64_t a_nInput) { return res; } +stage3_text uint8_t bcd_to_int(uint8_t val) { return (val & 0x0f) + ((val & 0xf0) >> 4) * 10; } diff --git a/stage23/lib/bmp.c b/stage23/lib/bmp.c index 5c7a1265..a1a283d8 100644 --- a/stage23/lib/bmp.c +++ b/stage23/lib/bmp.c @@ -34,6 +34,7 @@ struct bmp_local { struct bmp_header header; }; +stage3_text static uint32_t get_pixel(struct image *this, int x, int y) { struct bmp_local *local = this->local; struct bmp_header *header = &local->header; @@ -51,6 +52,7 @@ static uint32_t get_pixel(struct image *this, int x, int y) { return composite; } +stage3_text int bmp_open_image(struct image *image, struct file_handle *file) { struct bmp_header header; fread(file, &header, 0, sizeof(struct bmp_header)); diff --git a/stage23/lib/elf.c b/stage23/lib/elf.c index f4c52b9c..cc3861b5 100644 --- a/stage23/lib/elf.c +++ b/stage23/lib/elf.c @@ -114,6 +114,7 @@ struct elf64_rela { uint64_t r_addend; }; +stage3_text int elf_bits(struct file_handle *fd) { struct elf64_hdr hdr; fread(fd, &hdr, 0, 20); @@ -133,6 +134,7 @@ int elf_bits(struct file_handle *fd) { } } +stage3_text static int elf64_apply_relocations(struct file_handle *fd, struct elf64_hdr *hdr, void *buffer, uint64_t vaddr, size_t size, uint64_t slide) { // Find RELA sections for (uint16_t i = 0; i < hdr->sh_num; i++) { @@ -180,6 +182,7 @@ static int elf64_apply_relocations(struct file_handle *fd, struct elf64_hdr *hdr return 0; } +stage3_text int elf64_load_section(struct file_handle *fd, void *buffer, const char *name, size_t limit, uint64_t slide) { struct elf64_hdr hdr; fread(fd, &hdr, 0, sizeof(struct elf64_hdr)); @@ -224,6 +227,7 @@ int elf64_load_section(struct file_handle *fd, void *buffer, const char *name, s return 2; } +stage3_text int elf32_load_section(struct file_handle *fd, void *buffer, const char *name, size_t limit) { struct elf32_hdr hdr; fread(fd, &hdr, 0, sizeof(struct elf32_hdr)); @@ -268,6 +272,7 @@ int elf32_load_section(struct file_handle *fd, void *buffer, const char *name, s return 2; } +stage3_text int elf64_load(struct file_handle *fd, uint64_t *entry_point, uint64_t *top, uint64_t slide, uint32_t alloc_type) { struct elf64_hdr hdr; fread(fd, &hdr, 0, sizeof(struct elf64_hdr)); @@ -329,6 +334,7 @@ int elf64_load(struct file_handle *fd, uint64_t *entry_point, uint64_t *top, uin return 0; } +stage3_text int elf32_load(struct file_handle *fd, uint32_t *entry_point, uint32_t *top, uint32_t alloc_type) { struct elf32_hdr hdr; fread(fd, &hdr, 0, sizeof(struct elf32_hdr)); diff --git a/stage23/lib/image.c b/stage23/lib/image.c index 40d83c3f..a0a40b49 100644 --- a/stage23/lib/image.c +++ b/stage23/lib/image.c @@ -5,6 +5,7 @@ #include #include +stage3_text int open_image(struct image *image, struct file_handle *file) { image->file = file; diff --git a/stage23/lib/rand.c b/stage23/lib/rand.c index 6ce12f39..a981a8aa 100644 --- a/stage23/lib/rand.c +++ b/stage23/lib/rand.c @@ -52,6 +52,7 @@ static bool rand_initialised = false; static uint32_t *status; static int ctr; +stage3_text static void init_rand(void) { uint32_t seed = ((uint32_t)0xc597060c * rdtsc(uint32_t)) * ((uint32_t)0xce86d624) @@ -73,12 +74,14 @@ static void init_rand(void) { rand_initialised = true; } +stage3_text void srand(uint32_t s) { status[0] = s; for (ctr = 1; ctr < n; ctr++) status[ctr] = (1812433253 * (status[ctr - 1] ^ (status[ctr - 1] >> 30)) + ctr); } +stage3_text uint32_t rand32(void) { if (!rand_initialised) init_rand(); @@ -112,6 +115,7 @@ uint32_t rand32(void) { return res; } +stage3_text uint64_t rand64(void) { return (((uint64_t)rand32()) << 32) | (uint64_t)rand32(); } diff --git a/stage23/lib/readline.c b/stage23/lib/readline.c index 42713d90..f79fd268 100644 --- a/stage23/lib/readline.c +++ b/stage23/lib/readline.c @@ -6,6 +6,7 @@ #include #include +stage3_text int getchar_internal(uint32_t eax) { switch ((eax >> 8) & 0xff) { case 0x44: @@ -37,12 +38,14 @@ int getchar_internal(uint32_t eax) { return c; } +stage3_text int getchar(void) { struct rm_regs r = {0}; rm_int(0x16, &r, &r); return getchar_internal(r.eax); } +stage3_text static void reprint_string(int x, int y, const char *s) { int orig_x, orig_y; disable_cursor(); @@ -53,6 +56,7 @@ static void reprint_string(int x, int y, const char *s) { enable_cursor(); } +stage3_text static void cursor_back(void) { int x, y; get_cursor_pos(&x, &y); @@ -65,6 +69,7 @@ static void cursor_back(void) { set_cursor_pos(x, y); } +stage3_text static void cursor_fwd(void) { int x, y; get_cursor_pos(&x, &y); @@ -77,6 +82,7 @@ static void cursor_fwd(void) { set_cursor_pos(x, y); } +stage3_text void readline(const char *orig_str, char *buf, size_t limit) { size_t orig_str_len = strlen(orig_str); memmove(buf, orig_str, orig_str_len); diff --git a/stage23/lib/time.c b/stage23/lib/time.c index 7120dc95..fb6d52cc 100644 --- a/stage23/lib/time.c +++ b/stage23/lib/time.c @@ -5,6 +5,7 @@ #include // Julian date calculation from https://en.wikipedia.org/wiki/Julian_day +stage3_text static uint64_t get_jdn(uint8_t days, uint8_t months, uint16_t years) { return (1461 * (years + 4800 + (months - 14)/12))/4 + (367 * (months - 2 - 12 * ((months - 14)/12)))/12 - @@ -12,6 +13,7 @@ static uint64_t get_jdn(uint8_t days, uint8_t months, uint16_t years) { + days - 32075; } +stage3_text static uint64_t get_unix_epoch(uint8_t seconds, uint8_t minutes, uint8_t hours, uint8_t days, uint8_t months, uint16_t years) { uint64_t jdn_current = get_jdn(days, months, years); @@ -22,6 +24,7 @@ static uint64_t get_unix_epoch(uint8_t seconds, uint8_t minutes, uint8_t hours, return (jdn_diff * (60 * 60 * 24)) + hours * 3600 + minutes * 60 + seconds; } +stage3_text uint64_t time(void) { struct rm_regs r = {0}; diff --git a/stage23/lib/uri.c b/stage23/lib/uri.c index 883dc09e..e879899b 100644 --- a/stage23/lib/uri.c +++ b/stage23/lib/uri.c @@ -12,6 +12,7 @@ // A URI takes the form of: resource://root/path // The following function splits up a URI into its componenets +stage3_text bool uri_resolve(char *uri, char **resource, char **root, char **path) { size_t length = strlen(uri) + 1; char *buf = ext_mem_alloc(length); @@ -56,6 +57,7 @@ bool uri_resolve(char *uri, char **resource, char **root, char **path) { // BIOS partitions are specified in the : form. // The drive may be omitted, the partition cannot. +stage3_text static bool parse_bios_partition(char *loc, uint8_t *drive, uint8_t *partition) { uint64_t val; @@ -91,6 +93,7 @@ static bool parse_bios_partition(char *loc, uint8_t *drive, uint8_t *partition) return true; } +stage3_text static bool uri_bios_dispatch(struct file_handle *fd, char *loc, char *path) { uint8_t drive, partition; @@ -107,6 +110,7 @@ static bool uri_bios_dispatch(struct file_handle *fd, char *loc, char *path) { return true; } +stage3_text static bool uri_guid_dispatch(struct file_handle *fd, char *guid_str, char *path) { struct guid guid; if (!string_to_guid_be(&guid, guid_str)) @@ -127,6 +131,7 @@ static bool uri_guid_dispatch(struct file_handle *fd, char *guid_str, char *path return true; } +stage3_text static bool uri_tftp_dispatch(struct file_handle *fd, char *root, char *path) { uint32_t ip; if (!strcmp(root, "")) { @@ -150,6 +155,7 @@ static bool uri_tftp_dispatch(struct file_handle *fd, char *root, char *path) { return true; } +stage3_text static bool uri_boot_dispatch(struct file_handle *fd, char *s_part, char *path) { if (booted_from_pxe) return uri_tftp_dispatch(fd, s_part, path); @@ -178,6 +184,7 @@ static bool uri_boot_dispatch(struct file_handle *fd, char *s_part, char *path) return true; } +stage3_text bool uri_open(struct file_handle *fd, char *uri) { bool ret; diff --git a/stage23/menu.c b/stage23/menu.c index 51c12455..e855a7a0 100644 --- a/stage23/menu.c +++ b/stage23/menu.c @@ -12,10 +12,12 @@ #include #include +stage3_data static char *menu_branding = NULL; #define EDITOR_MAX_BUFFER_SIZE 4096 +stage3_text static size_t get_line_offset(size_t *displacement, size_t index, const char *buffer) { size_t offset = 0; size_t _index = index; @@ -30,12 +32,14 @@ static size_t get_line_offset(size_t *displacement, size_t index, const char *bu return offset; } +stage3_text static size_t get_line_length(size_t index, const char *buffer) { size_t i; for (i = index; buffer[i] != '\n' && buffer[i] != 0; i++); return i - index; } +stage3_text static size_t get_next_line(size_t index, const char *buffer) { if (buffer[index] == 0) return index; @@ -53,6 +57,7 @@ static size_t get_next_line(size_t index, const char *buffer) { return index + displacement; } +stage3_text static size_t get_prev_line(size_t index, const char *buffer) { size_t offset, displacement, prev_line_offset, prev_line_length; offset = get_line_offset(&displacement, index, buffer); @@ -66,6 +71,7 @@ static size_t get_prev_line(size_t index, const char *buffer) { return offset; } +stage3_text static char *config_entry_editor(const char *orig_entry) { size_t cursor_offset = 0; size_t entry_size = strlen(orig_entry); @@ -275,6 +281,7 @@ refresh: goto refresh; } +stage3_text static int print_tree(int level, int base_index, int selected_entry, struct menu_entry *current_entry, struct menu_entry **selected_menu_entry) { @@ -321,6 +328,7 @@ static int print_tree(int level, int base_index, int selected_entry, return max_entries; } +stage3_text char *menu(char **cmdline) { menu_branding = config_get_value(NULL, 0, "MENU_BRANDING"); if (menu_branding == NULL) diff --git a/stage23/mm/vmm.c b/stage23/mm/vmm.c index 46c59eb6..841b96fb 100644 --- a/stage23/mm/vmm.c +++ b/stage23/mm/vmm.c @@ -8,6 +8,7 @@ typedef uint64_t pt_entry_t; +stage3_text static pt_entry_t *get_next_level(pt_entry_t *current_level, size_t entry) { pt_entry_t *ret; @@ -24,6 +25,7 @@ static pt_entry_t *get_next_level(pt_entry_t *current_level, size_t entry) { return ret; } +stage3_text pagemap_t new_pagemap(int lv) { pagemap_t pagemap; pagemap.levels = lv; @@ -31,6 +33,7 @@ pagemap_t new_pagemap(int lv) { return pagemap; } +stage3_text void map_page(pagemap_t pagemap, uint64_t virt_addr, uint64_t phys_addr, uint64_t flags) { // Calculate the indices in the various tables using the virtual address size_t pml5_entry = (virt_addr & ((uint64_t)0x1ff << 48)) >> 48; diff --git a/stage23/protos/chainload.c b/stage23/protos/chainload.c index 8bcc66eb..5a7061a7 100644 --- a/stage23/protos/chainload.c +++ b/stage23/protos/chainload.c @@ -46,6 +46,7 @@ static void spinup(uint8_t drive) { ); } +stage3_text void chainload(char *config) { uint64_t val; diff --git a/stage23/protos/linux.c b/stage23/protos/linux.c index 86cafdbe..0d3ef312 100644 --- a/stage23/protos/linux.c +++ b/stage23/protos/linux.c @@ -54,6 +54,7 @@ static void spinup(uint16_t real_mode_code_seg, uint16_t kernel_entry_seg, ); } +stage3_text void linux_load(char *config, char *cmdline) { struct file_handle *kernel = ext_mem_alloc(sizeof(struct file_handle)); diff --git a/stage23/protos/stivale.c b/stage23/protos/stivale.c index 26baef6d..fda9ea71 100644 --- a/stage23/protos/stivale.c +++ b/stage23/protos/stivale.c @@ -24,8 +24,10 @@ #define KASLR_SLIDE_BITMASK 0x000FFF000u +stage3_data struct stivale_struct stivale_struct = {0}; +stage3_text void stivale_load(char *config, char *cmdline) { stivale_struct.flags |= (1 << 0); // set bit 0 since we are BIOS and not UEFI stivale_struct.flags |= (1 << 1); // we give colour information @@ -203,6 +205,7 @@ void stivale_load(char *config, char *cmdline) { entry_point, &stivale_struct, stivale_hdr.stack); } +stage3_text pagemap_t stivale_build_pagemap(bool level5pg) { pagemap_t pagemap = new_pagemap(level5pg ? 5 : 4); uint64_t higher_half_base = level5pg ? 0xff00000000000000 : 0xffff800000000000; @@ -244,6 +247,7 @@ pagemap_t stivale_build_pagemap(bool level5pg) { return pagemap; } +stage3_text __attribute__((noreturn)) void stivale_spinup( int bits, bool level5pg, pagemap_t pagemap, uint64_t entry_point, void *stivale_struct, uint64_t stack) { diff --git a/stage23/protos/stivale2.c b/stage23/protos/stivale2.c index 6f354ff1..74ac617c 100644 --- a/stage23/protos/stivale2.c +++ b/stage23/protos/stivale2.c @@ -27,14 +27,17 @@ #define KASLR_SLIDE_BITMASK 0x000FFF000u +stage3_data struct stivale2_struct stivale2_struct = {0}; +stage3_text inline static size_t get_phys_addr(uint64_t addr) { if (addr & ((uint64_t)1 << 63)) return addr - FIXED_HIGHER_HALF_OFFSET_64; return addr; } +stage3_text static void *get_tag(struct stivale2_header *s, uint64_t id) { struct stivale2_tag *tag = (void*)get_phys_addr(s->tags); for (;;) { @@ -46,11 +49,13 @@ static void *get_tag(struct stivale2_header *s, uint64_t id) { } } +stage3_text static void append_tag(struct stivale2_struct *s, struct stivale2_tag *tag) { tag->next = s->tags; s->tags = (uint64_t)(size_t)tag; } +stage3_text void stivale2_load(char *config, char *cmdline, bool pxe) { struct file_handle *kernel = ext_mem_alloc(sizeof(struct file_handle)); diff --git a/stage23/sys/lapic.c b/stage23/sys/lapic.c index b6d20640..6aefc725 100644 --- a/stage23/sys/lapic.c +++ b/stage23/sys/lapic.c @@ -14,6 +14,7 @@ struct dmar { symbol remapping_structures; } __attribute__((packed)); +stage3_text bool lapic_check(void) { uint32_t eax, ebx, ecx, edx; if (!cpuid(1, 0, &eax, &ebx, &ecx, &edx)) @@ -25,16 +26,19 @@ bool lapic_check(void) { return true; } +stage3_text uint32_t lapic_read(uint32_t reg) { size_t lapic_mmio_base = (size_t)(rdmsr(0x1b) & 0xfffff000); return mmind(lapic_mmio_base + reg); } +stage3_text void lapic_write(uint32_t reg, uint32_t data) { size_t lapic_mmio_base = (size_t)(rdmsr(0x1b) & 0xfffff000); mmoutd(lapic_mmio_base + reg, data); } +stage3_text bool x2apic_check(void) { uint32_t eax, ebx, ecx, edx; if (!cpuid(1, 0, &eax, &ebx, &ecx, &edx)) @@ -57,6 +61,7 @@ bool x2apic_check(void) { return true; } +stage3_text bool x2apic_enable(void) { if (!x2apic_check()) return false; @@ -68,10 +73,12 @@ bool x2apic_enable(void) { return true; } +stage3_text uint64_t x2apic_read(uint32_t reg) { return rdmsr(0x800 + (reg >> 4)); } +stage3_text void x2apic_write(uint32_t reg, uint64_t data) { wrmsr(0x800 + (reg >> 4), data); } diff --git a/stage23/sys/pic.c b/stage23/sys/pic.c index f8ee32d9..61280be9 100644 --- a/stage23/sys/pic.c +++ b/stage23/sys/pic.c @@ -3,7 +3,9 @@ #include #include #include +#include +stage3_text void pic_eoi(int irq) { if (irq >= 8) { outb(0xa0, 0x20); @@ -13,11 +15,13 @@ void pic_eoi(int irq) { } // Flush all potentially pending IRQs +stage3_text void pic_flush(void) { for (int i = 0; i < 16; i++) pic_eoi(i); } +stage3_text void pic_set_mask(int line, bool status) { uint16_t port; uint8_t value; @@ -37,6 +41,7 @@ void pic_set_mask(int line, bool status) { outb(port, value); } +stage3_text void pic_mask_all(void) { outb(0xa1, 0xff); outb(0x21, 0xff); diff --git a/stage23/sys/smp.c b/stage23/sys/smp.c index 6b5d166f..ece20745 100644 --- a/stage23/sys/smp.c +++ b/stage23/sys/smp.c @@ -42,6 +42,7 @@ struct gdtr { uint32_t ptr; } __attribute__((packed)); +stage3_text static void delay(uint32_t cycles) { for (uint32_t i = 0; i < cycles; i++) inb(0x80); @@ -54,6 +55,7 @@ uint8_t smp_tpl_booted_flag; uint32_t smp_tpl_pagemap; uint8_t smp_tpl_target_mode; +stage3_text static bool smp_start_ap(uint32_t lapic_id, struct gdtr *gdtr, struct smp_information *info_struct, bool longmode, bool lv5, uint32_t pagemap, @@ -95,6 +97,7 @@ static bool smp_start_ap(uint32_t lapic_id, struct gdtr *gdtr, return false; } +stage3_text struct smp_information *init_smp(size_t header_hack_size, void **header_ptr, size_t *cpu_count,