From 93cd5b1de349816979326ccf6e589f535ed62327 Mon Sep 17 00:00:00 2001 From: mintsuki Date: Sun, 7 Nov 2021 12:29:58 +0100 Subject: [PATCH] bootboot: General cleanup --- stage23/lib/blib.c | 24 ++++ stage23/lib/blib.h | 3 + stage23/protos/bootboot.c | 217 +++++++++++++++++-------------- stage23/protos/bootboot/cpio.c | 56 ++++---- stage23/protos/bootboot/initrd.c | 59 ++++----- stage23/protos/bootboot/initrd.h | 16 +-- stage23/protos/bootboot/jamesm.c | 43 +++--- stage23/protos/bootboot/ustar.c | 37 +++--- 8 files changed, 259 insertions(+), 196 deletions(-) diff --git a/stage23/lib/blib.c b/stage23/lib/blib.c index 12f2f7fb..0611d7fa 100644 --- a/stage23/lib/blib.c +++ b/stage23/lib/blib.c @@ -140,6 +140,30 @@ uint32_t get_crc32(void *_stream, size_t len) { return ret; } +uint32_t oct2bin(uint8_t *str, uint32_t max) { + uint32_t value = 0; + while (max-- > 0) { + value <<= 3; + value += *str++ - '0'; + } + return value; +} + +uint32_t hex2bin(uint8_t *str, uint32_t size) { + uint32_t value = 0; + while (size-- > 0) { + value <<= 4; + if (*str >= '0' && *str <= '9') + value += (uint32_t)((*str) - '0'); + else if (*str >= 'A' && *str <= 'F') + value += (uint32_t)((*str) - 'A' + 10); + else if (*str >= 'a' && *str <= 'f') + value += (uint32_t)((*str) - 'a' + 10); + str++; + } + return value; +} + #if uefi == 1 bool efi_boot_services_exited = false; diff --git a/stage23/lib/blib.h b/stage23/lib/blib.h index f626d625..4e8a4704 100644 --- a/stage23/lib/blib.h +++ b/stage23/lib/blib.h @@ -38,6 +38,9 @@ bool parse_resolution(size_t *width, size_t *height, size_t *bpp, const char *bu uint32_t get_crc32(void *_stream, size_t len); +uint32_t oct2bin(uint8_t *str, uint32_t max); +uint32_t hex2bin(uint8_t *str, uint32_t size); + uint64_t sqrt(uint64_t a_nInput); size_t get_trailing_zeros(uint64_t val); diff --git a/stage23/protos/bootboot.c b/stage23/protos/bootboot.c index a477ca04..b3b90508 100644 --- a/stage23/protos/bootboot.c +++ b/stage23/protos/bootboot.c @@ -25,16 +25,15 @@ #include #include -__attribute__((noreturn)) void bootboot_spinup( - pagemap_t *pagemap, - uint64_t entry_point, uint64_t stack, - size_t numcores, struct smp_information* cores); - -#define BOOTBOOT_FB 0xfffffffffc000000 -#define BOOTBOOT_INFO 0xffffffffffe00000 -#define BOOTBOOT_ENV 0xffffffffffe01000 -#define BOOTBOOT_CORE 0xffffffffffe02000 +#define _emitenv(e) do { \ + if (envoff >= 4095) { \ + panic("bootboot: too much env data!"); \ + } \ + env[envoff++] = e; \ + } while (false); +#define KOFFSET(type, off) (type)&kernel[(off)] +#define ESECTION(idx) KOFFSET(struct elf64_shdr*, elf_header->shoff + elf_header->shdr_size * (idx)) __attribute__((noreturn)) void bootboot_spinup_32( uint32_t pagemap_top_lv, @@ -42,37 +41,34 @@ __attribute__((noreturn)) void bootboot_spinup_32( uint32_t stack_lo, uint32_t stack_hi); void bootboot_load(char *config) { -#if bios - void *efi_system_table = NULL; -#elif uefi - void *efi_system_table = gST; -#endif uint64_t fb_vaddr = BOOTBOOT_FB; uint64_t struct_vaddr = BOOTBOOT_INFO; uint64_t env_vaddr = BOOTBOOT_ENV; - uint64_t init_stack_size = ~0; + uint64_t init_stack_size = (uint64_t)-1; /// Config /// char *kernel_path = config_get_value(config, 0, "KERNEL_PATH"); - + char *initrd = config_get_value(config, 0, "INITRD_PATH"); if (initrd == NULL) { initrd = kernel_path; kernel_path = NULL; } - if (kernel_path == NULL && initrd == NULL) + if (kernel_path == NULL && initrd == NULL) { panic("bootboot: no KERNEL_PATH or INITRD_PATH specified!"); + } /// Initrd loading /// - file_t bootboot_initrd_file; + struct initrd_file bootboot_initrd_file; uint64_t initrd_start = 0, initrd_size = 0; if (initrd) { - struct file_handle* initrd_file; - if ((initrd_file = uri_open(initrd)) == NULL) - panic("bootboot: Failed to open initrd with path `%s`. Is the path correct?\n", initrd); + struct file_handle *initrd_file; + if ((initrd_file = uri_open(initrd)) == NULL) { + panic("bootboot: Failed to open initrd with path `%s`. Is the path correct?", initrd); + } - uint8_t* initrd_data = freadall(initrd_file, MEMMAP_KERNEL_AND_MODULES); + uint8_t *initrd_data = freadall(initrd_file, MEMMAP_KERNEL_AND_MODULES); initrd_size = initrd_file->size; initrd_start = (uint64_t)(size_t)initrd_data; fclose(initrd_file); @@ -83,15 +79,13 @@ void bootboot_load(char *config) { } /// Load bootboot config /// -#define _emitenv(e) do { \ - if(envoff >= 4095) panic("bootboot: too much env data!"); \ - env[envoff++] = e; \ - } while (false); - uint8_t* env = (uint8_t*)ext_mem_alloc_type_aligned(4096, MEMMAP_BOOTLOADER_RECLAIMABLE, 4096); + uint8_t *env = ext_mem_alloc_type_aligned(4096, MEMMAP_BOOTLOADER_RECLAIMABLE, 4096); uint64_t envoff = 0; do { - file_t conf = initrd_open_auto(bootboot_initrd_file, "sys/config"); - if (!conf.data) break; + struct initrd_file conf = initrd_open_auto(bootboot_initrd_file, "sys/config"); + if (!conf.data) { + break; + } uint8_t state = 0; uint8_t ipeq = 0; @@ -100,7 +94,7 @@ void bootboot_load(char *config) { // state 1: precomment // state 2: comment - for (uint64_t inoff = 0;inoff < conf.size;inoff++) { + for (uint64_t inoff = 0; inoff < conf.size; inoff++) { if (conf.data[inoff] == ' ' && !(state == 0 && ipeq == 2)) continue; if (conf.data[inoff] != ' ' && state == 0 && ipeq == 1) { ipeq = 2; } if (conf.data[inoff] == '/' && state == 1) { state = 2; continue; } @@ -114,94 +108,111 @@ void bootboot_load(char *config) { } } while (false); _emitenv(0); - print("env: ---------\n%s\n--------\n", env); + + printv("env: ---------\n%s\n--------\n", env); /// Kernel loading code /// - uint8_t* kernel; + uint8_t *kernel; if (kernel_path) { print("bootboot: Loading kernel `%s`...\n", kernel_path); - struct file_handle* kernel_file; + struct file_handle *kernel_file; if ((kernel_file = uri_open(kernel_path)) == NULL) - panic("bootboot: Failed to open kernel with path `%s`. Is the path correct?\n", kernel_path); + panic("bootboot: Failed to open kernel with path `%s`. Is the path correct?", kernel_path); kernel = freadall(kernel_file, MEMMAP_KERNEL_AND_MODULES); + + fclose(kernel_file); } else { - const char* corefile = config_get_value((char*)env, 0, "kernel"); - if (!corefile) corefile = "sys/core"; - file_t file = initrd_open_auto(bootboot_initrd_file, corefile); + const char *corefile = config_get_value((char *)env, 0, "kernel"); + if (!corefile) { + corefile = "sys/core"; + } + struct initrd_file file = initrd_open_auto(bootboot_initrd_file, corefile); kernel = file.data; - if (!file.size) panic("bootboot: cannot find the kernel!"); + if (!file.size) { + panic("bootboot: cannot find the kernel!"); + } } /// Memory mappings /// pagemap_t pmap = new_pagemap(4); /// Load kernel /// - uint64_t entry, top, slide, rangecount, physbase, virtbase = 0; - struct elf_range* ranges; + uint64_t entry, top, physbase, virtbase; { if (elf64_load( - kernel, &entry, &top, &slide, MEMMAP_KERNEL_AND_MODULES, - false, false, &ranges, &rangecount, true, &physbase, &virtbase)) { + kernel, &entry, &top, NULL, MEMMAP_KERNEL_AND_MODULES, + false, false, NULL, NULL, true, &physbase, &virtbase)) { panic("bootboot: elf64 load failed"); } - for (uint64_t mapvirt = virtbase, mapphys = physbase; mapphys < top;mapvirt += 0x1000, mapphys += 0x1000) { + for (uint64_t mapvirt = virtbase, mapphys = physbase; mapphys < top; mapvirt += 0x1000, mapphys += 0x1000) { map_page(pmap, mapvirt, mapphys, VMM_FLAG_PRESENT | VMM_FLAG_WRITE, false); } } - - /// Funky macros /// -#define KOFFSET(type, off) (type)&kernel[(off)] -#define ESECTION(idx) KOFFSET(struct elf64_shdr*, elf_header->shoff + elf_header->shdr_size * (idx)) /// Bootboot symbols /// - struct elf64_hdr* elf_header = (struct elf64_hdr*)kernel; - struct elf64_shdr* section_header_strings_section = ESECTION(elf_header->shstrndx); - char* section_header_strings = KOFFSET(char*, section_header_strings_section->sh_offset); - struct elf64_shdr* symbol_table = NULL; - struct elf64_shdr* string_table = NULL; - for(uint32_t i = 0; i < elf_header->sh_num; i++){ - struct elf64_shdr* section_header = ESECTION(i); - char* secname = §ion_header_strings[section_header->sh_name]; - if(!strcmp(secname, ".symtab")) symbol_table = section_header; - if(!strcmp(secname, ".strtab")) string_table = section_header; - } - if (!symbol_table || !string_table) { - print("bootboot: warning: no symbol/string tables in the ELF!\n"); - } else { - struct elf64_sym* symbols = KOFFSET(struct elf64_sym*, symbol_table->sh_offset); - char* symbol_strings = KOFFSET(char*, string_table->sh_offset); - for (uint32_t i = 0, symcount = symbol_table->sh_size / sizeof(struct elf64_sym);i < symcount;i++) { - char* elf_sym = &symbol_strings[symbols[i].st_name]; - uint64_t symaddr = symbols[i].st_value; + struct elf64_hdr *elf_header = (struct elf64_hdr *)kernel; + struct elf64_shdr *section_header_strings_section = ESECTION(elf_header->shstrndx); + char *section_header_strings = KOFFSET(char *, section_header_strings_section->sh_offset); - if(!strcmp(elf_sym, "bootboot")) struct_vaddr = symaddr; - if(!strcmp(elf_sym, "environment")) env_vaddr = symaddr; - if(!strcmp(elf_sym, "fb")) fb_vaddr = symaddr; - if(!strcmp(elf_sym, "initstack")) init_stack_size = symaddr; + struct elf64_shdr *symbol_table = NULL; + struct elf64_shdr *string_table = NULL; + for (uint32_t i = 0; i < elf_header->sh_num; i++){ + struct elf64_shdr *section_header = ESECTION(i); + char *secname = §ion_header_strings[section_header->sh_name]; + if (!strcmp(secname, ".symtab")) { + symbol_table = section_header; + } + if (!strcmp(secname, ".strtab")) { + string_table = section_header; } } - if (init_stack_size == ~0UL) { + if (!symbol_table || !string_table) { + print("bootboot: warning: no symbol/string tables in the ELF!\n"); + } else { + struct elf64_sym *symbols = KOFFSET(struct elf64_sym *, symbol_table->sh_offset); + char *symbol_strings = KOFFSET(char *, string_table->sh_offset); + for (uint32_t i = 0, symcount = symbol_table->sh_size / sizeof(struct elf64_sym); i < symcount; i++) { + char *elf_sym = &symbol_strings[symbols[i].st_name]; + uint64_t symaddr = symbols[i].st_value; + + if (!strcmp(elf_sym, "bootboot")) { + struct_vaddr = symaddr; + } + if (!strcmp(elf_sym, "environment")) { + env_vaddr = symaddr; + } + if (!strcmp(elf_sym, "fb")) { + fb_vaddr = symaddr; + } + if (!strcmp(elf_sym, "initstack")) { + init_stack_size = symaddr; + } + } + } + + if (init_stack_size == (uint64_t)-1) { print("bootboot: warning: no init stack size entered, assuming 1024\n"); print("1024 is really small, specify more using initstack=size ini initrd;\n"); init_stack_size = 1024; delay(1000000); } + printv("bootboot: mapping struct to %X\n", struct_vaddr); printv("bootboot: mapping environemnt to %X\n", env_vaddr); printv("bootboot: mapping framebuffer to %X\n", fb_vaddr); printv("bootboot: the init stack is %X bytes\n", init_stack_size);; /// Bootboot structure /// - BOOTBOOT* bootboot = (BOOTBOOT*)ext_mem_alloc_type_aligned(4096, MEMMAP_BOOTLOADER_RECLAIMABLE, 4096); - map_page(pmap, struct_vaddr, (uint64_t)(size_t)bootboot, VMM_FLAG_PRESENT | VMM_FLAG_WRITE, false); + BOOTBOOT *bootboot = ext_mem_alloc_type_aligned(4096, MEMMAP_BOOTLOADER_RECLAIMABLE, 4096); + map_page(pmap, struct_vaddr, (uintptr_t)bootboot, VMM_FLAG_PRESENT | VMM_FLAG_WRITE, false); /// Environment /// { - map_page(pmap, env_vaddr, (uint64_t)(size_t)env, VMM_FLAG_PRESENT | VMM_FLAG_WRITE, false); + map_page(pmap, env_vaddr, (uintptr_t)env, VMM_FLAG_PRESENT | VMM_FLAG_WRITE, false); uint32_t index = 0, offset = 0; - char* cfgent = NULL; + char *cfgent = NULL; do { cfgent = config_get_value(config, index++, "BOOTBOOT_ENV"); if (cfgent) { @@ -226,19 +237,21 @@ void bootboot_load(char *config) { size_t fbwidth = 0, fbheight = 0, fbbpp = 32; struct fb_info fbi; char *resolution = config_get_value(config, 0, "RESOLUTION"); - if (resolution != NULL) + if (resolution != NULL) { parse_resolution(&fbwidth, &fbheight, &fbbpp, resolution); - + } + term_deinit(); fb_init(&fbi, fbwidth, fbheight, fbbpp); uint64_t fb_size = fbi.framebuffer_height * fbi.framebuffer_pitch; - for (uint64_t current = 0;current < fb_size;current += 0x1000) { + for (uint64_t current = 0; current < fb_size; current += 0x1000) { map_page(pmap, fb_vaddr + current, fbi.framebuffer_addr + current, VMM_FLAG_PRESENT | VMM_FLAG_WRITE, false); } /// Header info /// memcpy(bootboot->magic, "BOOT", 4); + #if bios bootboot->protocol = 2 | (0 << 2); #elif uefi @@ -248,11 +261,11 @@ void bootboot_load(char *config) { /// SMP info /// size_t numcores; uint32_t bsplapic; - volatile struct smp_information* cores; - init_smp(0, (void**)&cores, &numcores, &bsplapic, true, false, pmap, false, false); + volatile struct smp_information *cores; + init_smp(0, (void **)&cores, &numcores, &bsplapic, true, false, pmap, false, false); bootboot->numcores = numcores; bootboot->bspid = bsplapic; - for (size_t i = 0;i < numcores;i++) { + for (size_t i = 0; i < numcores; i++) { cores[i].stack_addr = ((uint64_t)(size_t)ext_mem_alloc(init_stack_size)) + init_stack_size; } @@ -269,7 +282,6 @@ void bootboot_load(char *config) { bootboot->datetime[6] = int_to_bcd(second); bootboot->datetime[7] = 0; - /// Ramdisk /// bootboot->initrd_ptr = initrd_start; bootboot->initrd_size = initrd_size; @@ -286,25 +298,39 @@ void bootboot_load(char *config) { uint64_t smbios_entry_32 = 0, smbios_entry_64 = 0; acpi_get_smbios((void **)&smbios_entry_32, (void **)&smbios_entry_64); - bootboot->arch.x86_64.acpi_ptr = (uint64_t)(size_t)acpi_get_rsdp(); - if (smbios_entry_64) bootboot->arch.x86_64.smbi_ptr = smbios_entry_64; - else if (smbios_entry_32) bootboot->arch.x86_64.smbi_ptr = smbios_entry_32; - else bootboot->arch.x86_64.smbi_ptr = 0; - bootboot->arch.x86_64.efi_ptr = (uint64_t)(size_t)efi_system_table; + bootboot->arch.x86_64.acpi_ptr = (uintptr_t)acpi_get_rsdp(); + + if (smbios_entry_64) { + bootboot->arch.x86_64.smbi_ptr = smbios_entry_64; + } else if (smbios_entry_32) { + bootboot->arch.x86_64.smbi_ptr = smbios_entry_32; + } else { + bootboot->arch.x86_64.smbi_ptr = 0; + } + +#if uefi == 1 + bootboot->arch.x86_64.efi_ptr = (uintptr_t)gST; +#elif bios == 1 + bootboot->arch.x86_64.efi_ptr = 0; +#endif + bootboot->arch.x86_64.mp_ptr = 0; - + /// Memory map /// { size_t mmapent; struct e820_entry_t* e820e = get_memmap(&mmapent); if (mmapent > 248) { - panic("Too much memory entries! our god bzt decided that %d entries is too much, max is 248", mmapent); + panic("Too many memory map entries"); } - for (uint32_t i = 0;i < mmapent;i++) { - uint32_t btype = 0; - if (e820e[i].type == 1) btype = 1; - if (e820e[i].type == 3) btype = 2; - if (e820e[i].type == 4) btype = 2; + for (size_t i = 0; i < mmapent; i++) { + uint32_t btype; + + switch (e820e[i].type) { + case 1: btype = 1; break; + case 3: case 4: btype = 2; break; + default: btype = 0; break; + } bootboot->mmap[i].size = (e820e[i].length & ~0xF) | btype; bootboot->mmap[i].ptr = e820e[i].base; @@ -328,7 +354,7 @@ void bootboot_load(char *config) { irq_flush_type = IRQ_PIC_APIC_FLUSH; - for (size_t i = 0;i < numcores;i++) { + for (size_t i = 0; i < numcores; i++) { cores[i].extra_argument = 0; cores[i].goto_address = entry; } @@ -337,5 +363,4 @@ void bootboot_load(char *config) { (uint32_t)(uintptr_t)pmap.top_level, (uint32_t)entry, (uint32_t)(entry >> 32), (uint32_t)cores[0].stack_addr, (uint32_t)(cores[0].stack_addr >> 32)); - } diff --git a/stage23/protos/bootboot/cpio.c b/stage23/protos/bootboot/cpio.c index bc78d21b..c3fad181 100644 --- a/stage23/protos/bootboot/cpio.c +++ b/stage23/protos/bootboot/cpio.c @@ -1,75 +1,83 @@ -#include "lib/print.h" +#include +#include +#include #include #include -#include +#include +#include #define HPODC_MAGIC "070707" +#define _offset(cnt) do { offset += (cnt); if (offset > file.size) return (struct initrd_file){0}; } while (false); +#define _atoffset() (&file.data[offset]) +#define _must(n) do { if ((offset + (n)) > file.size) return (struct initrd_file){0}; } while (false); + /** * cpio archive */ INITRD_HANDLER(cpio) { - /// Some macros/// -#define _offset(cnt) do { offset += (cnt); if (offset > file.size) return (file_t){ 0, NULL }; } while (false); -#define _atoffset() (&file.data[offset]) -#define _must(n) do { if ((offset + (n)) > file.size) return (file_t){ 0, NULL }; } while (false); uint64_t offset = 0; - if (file.size < 6) return (file_t){ 0, NULL }; + if (file.size < 6) { + return (struct initrd_file){0}; + } /// Check magic /// // this may be a bit unclear, but this checks if the file even **has** a cpio header - if (memcmp(file.data,"070701",6) && memcmp(file.data, "070702", 6) && memcmp(file.data, "070707", 6)) - return (file_t){ 0, NULL }; - + if (memcmp(file.data, "070701", 6) && memcmp(file.data, "070702", 6) && memcmp(file.data, "070707", 6)) { + return (struct initrd_file){0}; + } + /// Some variables /// - uint64_t path_name_size = strlen(path); + size_t path_name_size = strlen(path); /// hpodc archive /// while (!memcmp(_atoffset(), HPODC_MAGIC, 6)) { _must(22); - uint32_t name_size = oct2bin(_atoffset()+ 8 * 6 + 11, 6); - uint32_t file_size = oct2bin(_atoffset()+ 8 * 6 + 11 + 6, 11); + uint32_t name_size = oct2bin(_atoffset() + 8 * 6 + 11, 6); + uint32_t file_size = oct2bin(_atoffset() + 8 * 6 + 11 + 6, 11); _must(9 * 6 + 2 * 11 + name_size); - uint8_t* target_path = _atoffset() + 9 * 6 + 2 * 11; + uint8_t *target_path = _atoffset() + 9 * 6 + 2 * 11; if (name_size > 2 && target_path[0] == '.' && target_path[1] == '/') { target_path += 2; } if (!memcmp(target_path, path, path_name_size + 1)) { - return (file_t){ + return (struct initrd_file){ file_size, _atoffset() + 9 * 6 + 2 * 11 + name_size, }; } + _offset(76 + name_size + file_size); } + offset = 0; + // newc and crc archive - while(!memcmp(_atoffset(), "07070", 5)){ + while (!memcmp(_atoffset(), "07070", 5)) { uint32_t file_size = hex2bin(_atoffset() + 8 * 6 + 6, 8); uint32_t name_size = hex2bin(_atoffset() + 8 * 11 + 6, 8); - uint8_t* target_path = _atoffset() + 110; + uint8_t *target_path = _atoffset() + 110; if (name_size > 2 && target_path[0] == '.' && target_path[1] == '/') { target_path += 2; } - + if (!memcmp(target_path, path, path_name_size + 1)) { uint8_t buf[9]; memcpy(buf, _atoffset() + 8 * 11 + 6, 8); buf[8] = 0; - return (file_t){ + return (struct initrd_file){ file_size, (_atoffset() + ((110 + name_size + 3) / 4) * 4), }; } + _offset(((110 + name_size + 3) / 4) * 4 + ((file_size + 3) / 4) * 4); } - char buf[9]; - memcpy(buf, _atoffset(), 8); - buf[8] = 0; - return (file_t){ 0, NULL }; -} \ No newline at end of file + + return (struct initrd_file){0}; +} diff --git a/stage23/protos/bootboot/initrd.c b/stage23/protos/bootboot/initrd.c index 859ad815..39657f3e 100644 --- a/stage23/protos/bootboot/initrd.c +++ b/stage23/protos/bootboot/initrd.c @@ -1,72 +1,63 @@ +#include +#include #include #include #include #include - INITRD_HANDLER(jamesm); INITRD_HANDLER(ustar); INITRD_HANDLER(cpio); -INITRD_HANDLER(auto) { #define DETECT_FAILED panic("bootboot: cannot read file `%s`: cannot detect initrd type (only ustar, cpio and jamesm is supported).", path) - if (file.size < 4) DETECT_FAILED; - if (!memcmp(file.data, "\x7f""ELF", 4)) { + +INITRD_HANDLER(auto) { + if (file.size < 4) { + DETECT_FAILED; + } + + if (!memcmp(file.data, "\177ELF", 4)) { if (strcmp("sys/core", path) == 0) { printv("bootboot: using ELF as initrd to open sys/core\n"); return file; } - return (file_t){0, NULL}; + return (struct initrd_file){0}; } - if (file.size < 5) DETECT_FAILED; + + if (file.size < 5) { + DETECT_FAILED; + } + if (file.data[4] == 0xBF) { - file_t jamesm_attempt = initrd_open_jamesm(file, path); + struct initrd_file jamesm_attempt = initrd_open_jamesm(file, path); if (jamesm_attempt.data) { printv("bootboot: jamesm matched when reading file `%s`\n", path); return jamesm_attempt; } panic("bootboot: cannot read file `%s`: no such file or directory", path); } + if (!memcmp("07070", file.data, 5)) { - file_t cpio_attempt = initrd_open_cpio(file, path); + struct initrd_file cpio_attempt = initrd_open_cpio(file, path); if (cpio_attempt.data) { printv("bootboot: cpio matched when reading file `%s`\n", path); return cpio_attempt; } panic("bootboot: cannot read file `%s`: no such file or directory", path); } - if (file.size < 262) DETECT_FAILED; + + if (file.size < 262) { + DETECT_FAILED; + } + if (!memcmp("ustar", file.data + 257, 5)) { - file_t ustar_attempt = initrd_open_ustar(file, path); + struct initrd_file ustar_attempt = initrd_open_ustar(file, path); if (ustar_attempt.data) { printv("bootboot: ustar matched when reading file `%s`\n", path); return ustar_attempt; } panic("bootboot: cannot read file `%s`: no such file or directory", path); } + DETECT_FAILED; } - -/// Utilities /// -uint32_t oct2bin(uint8_t* str, uint32_t max) { - uint32_t value = 0; - while(max-- > 0) { - value <<= 3; - value += *str++ - '0'; - } - return value; -} -uint32_t hex2bin(uint8_t* str, uint32_t size) { - uint32_t value = 0; - while(size-- > 0){ - value <<= 4; - if (*str >= '0' && *str <= '9') - value += (uint32_t)((*str) - '0'); - else if (*str >= 'A' && *str <= 'F') - value += (uint32_t)((*str) - 'A' + 10); - else if (*str >= 'a' && *str <= 'f') - value += (uint32_t)((*str) - 'a' + 10); - str++; - } - return value; -} \ No newline at end of file diff --git a/stage23/protos/bootboot/initrd.h b/stage23/protos/bootboot/initrd.h index 2ec76d60..752faff4 100644 --- a/stage23/protos/bootboot/initrd.h +++ b/stage23/protos/bootboot/initrd.h @@ -1,19 +1,15 @@ -#ifndef __PROTOS__BOOTBOOT_FS_H__ -#define __PROTOS__BOOTBOOT_FS_H__ +#ifndef __PROTOS__BOOTBOOT__INITRD_H__ +#define __PROTOS__BOOTBOOT__INITRD_H__ #include -#include -typedef struct file { +struct initrd_file { uint64_t size; - uint8_t* data; -} file_t; + uint8_t *data; +}; -#define INITRD_HANDLER(name) file_t initrd_open_##name(file_t file, const char* path) +#define INITRD_HANDLER(name) struct initrd_file initrd_open_##name(struct initrd_file file, const char *path) INITRD_HANDLER(auto); -uint32_t oct2bin(uint8_t* str, uint32_t max); -uint32_t hex2bin(uint8_t* str, uint32_t size); - #endif diff --git a/stage23/protos/bootboot/jamesm.c b/stage23/protos/bootboot/jamesm.c index d5ed8265..2db460b2 100644 --- a/stage23/protos/bootboot/jamesm.c +++ b/stage23/protos/bootboot/jamesm.c @@ -1,32 +1,41 @@ +#include +#include #include #include -#include // This looks really sketchy, but that's what the official """spec""" says... -typedef struct initrd_header { - unsigned char magic; // The magic number is there to check for consistency. +struct initrd_entry { + uint8_t magic; // The magic number is there to check for consistency. char name[64]; - unsigned int offset; // Offset in the initrd the file starts. - unsigned int length; // Length of the file. -} initrd_entry_t; + uint32_t offset; // Offset in the initrd the file starts. + uint32_t length; // Length of the file. +}; INITRD_HANDLER(jamesm) { - if (file.size < 5) return (file_t){}; + if (file.size < 5) { + return (struct initrd_file){0}; + } - uint32_t file_count = *((uint32_t*)(file.data)); - uint32_t path_len = strlen(path); + uint32_t file_count = *((uint32_t *)(file.data)); + size_t path_len = strlen(path); - initrd_entry_t* data = (initrd_entry_t*)(file.data + 4); - if (data[0].magic != 0xBF) return (file_t){}; + struct initrd_entry *data = (void *)(file.data + 4); + if (data->magic != 0xbf) { + return (struct initrd_file){0}; + } - for(uint32_t i = 0;i < file_count;i++) { - if (data[i].magic != 0xBF) return (file_t){}; - if(!memcmp(data[i].name, path, path_len + 1)){ - return (file_t){ + for (uint32_t i = 0; i < file_count; i++) { + if (data[i].magic != 0xbf) { + return (struct initrd_file){0}; + } + + if (!memcmp(data[i].name, path, path_len + 1)) { + return (struct initrd_file){ data[i].length, file.data + data[i].offset }; } } - return (file_t){}; -} \ No newline at end of file + + return (struct initrd_file){0}; +} diff --git a/stage23/protos/bootboot/ustar.c b/stage23/protos/bootboot/ustar.c index 4d6053c9..ad7a94aa 100644 --- a/stage23/protos/bootboot/ustar.c +++ b/stage23/protos/bootboot/ustar.c @@ -1,27 +1,34 @@ +#include +#include #include #include -#include +#include + +#define PTR (file.data + offset) INITRD_HANDLER(ustar) { -#define PTR (file.data + offset) - if (file.size < 262) return (file_t){}; + if (file.size < 262) { + return (struct initrd_file){0}; + } - if(memcmp(file.data + 257, "ustar", 5)) - return (file_t){}; - - uint32_t path_size = strlen(path); + if (memcmp(file.data + 257, "ustar", 5)) { + return (struct initrd_file){0}; + } + + size_t path_size = strlen(path); uint32_t offset = 0; - while(!memcmp(PTR + 257,"ustar",5)){ - uint32_t file_size = oct2bin(PTR + 0x7c,11); - if(!memcmp(PTR, path, path_size + 1) - || (PTR[0] == '.' && PTR[1] == '/' && !memcmp(PTR + 2, path, path_size + 1))) { - return (file_t){ + while (!memcmp(PTR + 257, "ustar", 5)) { + uint32_t file_size = oct2bin(PTR + 0x7c, 11); + if (!memcmp(PTR, path, path_size + 1) + || (PTR[0] == '.' && PTR[1] == '/' && !memcmp(PTR + 2, path, path_size + 1))) { + return (struct initrd_file){ file_size, - PTR+512, + PTR + 512, }; } offset += (((file_size + 511) / 512) + 1) * 512; } - return (file_t){}; -} \ No newline at end of file + + return (struct initrd_file){0}; +}