bootboot: General cleanup

This commit is contained in:
mintsuki 2021-11-07 12:29:58 +01:00
parent 99be5e2df5
commit 93cd5b1de3
8 changed files with 259 additions and 196 deletions

View File

@ -140,6 +140,30 @@ uint32_t get_crc32(void *_stream, size_t len) {
return ret; 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 #if uefi == 1
bool efi_boot_services_exited = false; bool efi_boot_services_exited = false;

View File

@ -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 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); uint64_t sqrt(uint64_t a_nInput);
size_t get_trailing_zeros(uint64_t val); size_t get_trailing_zeros(uint64_t val);

View File

@ -25,16 +25,15 @@
#include <mm/pmm.h> #include <mm/pmm.h>
#include <drivers/vga_textmode.h> #include <drivers/vga_textmode.h>
__attribute__((noreturn)) void bootboot_spinup( #define _emitenv(e) do { \
pagemap_t *pagemap, if (envoff >= 4095) { \
uint64_t entry_point, uint64_t stack, panic("bootboot: too much env data!"); \
size_t numcores, struct smp_information* cores); } \
env[envoff++] = e; \
#define BOOTBOOT_FB 0xfffffffffc000000 } while (false);
#define BOOTBOOT_INFO 0xffffffffffe00000
#define BOOTBOOT_ENV 0xffffffffffe01000
#define BOOTBOOT_CORE 0xffffffffffe02000
#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( __attribute__((noreturn)) void bootboot_spinup_32(
uint32_t pagemap_top_lv, uint32_t pagemap_top_lv,
@ -42,37 +41,34 @@ __attribute__((noreturn)) void bootboot_spinup_32(
uint32_t stack_lo, uint32_t stack_hi); uint32_t stack_lo, uint32_t stack_hi);
void bootboot_load(char *config) { 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 fb_vaddr = BOOTBOOT_FB;
uint64_t struct_vaddr = BOOTBOOT_INFO; uint64_t struct_vaddr = BOOTBOOT_INFO;
uint64_t env_vaddr = BOOTBOOT_ENV; uint64_t env_vaddr = BOOTBOOT_ENV;
uint64_t init_stack_size = ~0; uint64_t init_stack_size = (uint64_t)-1;
/// Config /// /// Config ///
char *kernel_path = config_get_value(config, 0, "KERNEL_PATH"); char *kernel_path = config_get_value(config, 0, "KERNEL_PATH");
char *initrd = config_get_value(config, 0, "INITRD_PATH"); char *initrd = config_get_value(config, 0, "INITRD_PATH");
if (initrd == NULL) { if (initrd == NULL) {
initrd = kernel_path; initrd = kernel_path;
kernel_path = NULL; kernel_path = NULL;
} }
if (kernel_path == NULL && initrd == NULL) if (kernel_path == NULL && initrd == NULL) {
panic("bootboot: no KERNEL_PATH or INITRD_PATH specified!"); panic("bootboot: no KERNEL_PATH or INITRD_PATH specified!");
}
/// Initrd loading /// /// Initrd loading ///
file_t bootboot_initrd_file; struct initrd_file bootboot_initrd_file;
uint64_t initrd_start = 0, initrd_size = 0; uint64_t initrd_start = 0, initrd_size = 0;
if (initrd) { if (initrd) {
struct file_handle* initrd_file; struct file_handle *initrd_file;
if ((initrd_file = uri_open(initrd)) == NULL) if ((initrd_file = uri_open(initrd)) == NULL) {
panic("bootboot: Failed to open initrd with path `%s`. Is the path correct?\n", initrd); 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_size = initrd_file->size;
initrd_start = (uint64_t)(size_t)initrd_data; initrd_start = (uint64_t)(size_t)initrd_data;
fclose(initrd_file); fclose(initrd_file);
@ -83,15 +79,13 @@ void bootboot_load(char *config) {
} }
/// Load bootboot config /// /// Load bootboot config ///
#define _emitenv(e) do { \ uint8_t *env = ext_mem_alloc_type_aligned(4096, MEMMAP_BOOTLOADER_RECLAIMABLE, 4096);
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);
uint64_t envoff = 0; uint64_t envoff = 0;
do { do {
file_t conf = initrd_open_auto(bootboot_initrd_file, "sys/config"); struct initrd_file conf = initrd_open_auto(bootboot_initrd_file, "sys/config");
if (!conf.data) break; if (!conf.data) {
break;
}
uint8_t state = 0; uint8_t state = 0;
uint8_t ipeq = 0; uint8_t ipeq = 0;
@ -100,7 +94,7 @@ void bootboot_load(char *config) {
// state 1: precomment // state 1: precomment
// state 2: comment // 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 == 2)) continue;
if (conf.data[inoff] != ' ' && state == 0 && ipeq == 1) { ipeq = 2; } if (conf.data[inoff] != ' ' && state == 0 && ipeq == 1) { ipeq = 2; }
if (conf.data[inoff] == '/' && state == 1) { state = 2; continue; } if (conf.data[inoff] == '/' && state == 1) { state = 2; continue; }
@ -114,94 +108,111 @@ void bootboot_load(char *config) {
} }
} while (false); } while (false);
_emitenv(0); _emitenv(0);
print("env: ---------\n%s\n--------\n", env);
printv("env: ---------\n%s\n--------\n", env);
/// Kernel loading code /// /// Kernel loading code ///
uint8_t* kernel; uint8_t *kernel;
if (kernel_path) { if (kernel_path) {
print("bootboot: Loading kernel `%s`...\n", 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) 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); kernel = freadall(kernel_file, MEMMAP_KERNEL_AND_MODULES);
fclose(kernel_file);
} else { } else {
const char* corefile = config_get_value((char*)env, 0, "kernel"); const char *corefile = config_get_value((char *)env, 0, "kernel");
if (!corefile) corefile = "sys/core"; if (!corefile) {
file_t file = initrd_open_auto(bootboot_initrd_file, corefile); corefile = "sys/core";
}
struct initrd_file file = initrd_open_auto(bootboot_initrd_file, corefile);
kernel = file.data; kernel = file.data;
if (!file.size) panic("bootboot: cannot find the kernel!"); if (!file.size) {
panic("bootboot: cannot find the kernel!");
}
} }
/// Memory mappings /// /// Memory mappings ///
pagemap_t pmap = new_pagemap(4); pagemap_t pmap = new_pagemap(4);
/// Load kernel /// /// Load kernel ///
uint64_t entry, top, slide, rangecount, physbase, virtbase = 0; uint64_t entry, top, physbase, virtbase;
struct elf_range* ranges;
{ {
if (elf64_load( if (elf64_load(
kernel, &entry, &top, &slide, MEMMAP_KERNEL_AND_MODULES, kernel, &entry, &top, NULL, MEMMAP_KERNEL_AND_MODULES,
false, false, &ranges, &rangecount, true, &physbase, &virtbase)) { false, false, NULL, NULL, true, &physbase, &virtbase)) {
panic("bootboot: elf64 load failed"); 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); 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 /// /// Bootboot symbols ///
struct elf64_hdr* elf_header = (struct elf64_hdr*)kernel; struct elf64_hdr *elf_header = (struct elf64_hdr *)kernel;
struct elf64_shdr* section_header_strings_section = ESECTION(elf_header->shstrndx); struct elf64_shdr *section_header_strings_section = ESECTION(elf_header->shstrndx);
char* section_header_strings = KOFFSET(char*, section_header_strings_section->sh_offset); 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 = &section_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;
if(!strcmp(elf_sym, "bootboot")) struct_vaddr = symaddr; struct elf64_shdr *symbol_table = NULL;
if(!strcmp(elf_sym, "environment")) env_vaddr = symaddr; struct elf64_shdr *string_table = NULL;
if(!strcmp(elf_sym, "fb")) fb_vaddr = symaddr; for (uint32_t i = 0; i < elf_header->sh_num; i++){
if(!strcmp(elf_sym, "initstack")) init_stack_size = symaddr; struct elf64_shdr *section_header = ESECTION(i);
char *secname = &section_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("bootboot: warning: no init stack size entered, assuming 1024\n");
print("1024 is really small, specify more using initstack=size ini initrd;\n"); print("1024 is really small, specify more using initstack=size ini initrd;\n");
init_stack_size = 1024; init_stack_size = 1024;
delay(1000000); delay(1000000);
} }
printv("bootboot: mapping struct to %X\n", struct_vaddr); printv("bootboot: mapping struct to %X\n", struct_vaddr);
printv("bootboot: mapping environemnt to %X\n", env_vaddr); printv("bootboot: mapping environemnt to %X\n", env_vaddr);
printv("bootboot: mapping framebuffer to %X\n", fb_vaddr); printv("bootboot: mapping framebuffer to %X\n", fb_vaddr);
printv("bootboot: the init stack is %X bytes\n", init_stack_size);; printv("bootboot: the init stack is %X bytes\n", init_stack_size);;
/// Bootboot structure /// /// Bootboot structure ///
BOOTBOOT* bootboot = (BOOTBOOT*)ext_mem_alloc_type_aligned(4096, MEMMAP_BOOTLOADER_RECLAIMABLE, 4096); 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); map_page(pmap, struct_vaddr, (uintptr_t)bootboot, VMM_FLAG_PRESENT | VMM_FLAG_WRITE, false);
/// Environment /// /// 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; uint32_t index = 0, offset = 0;
char* cfgent = NULL; char *cfgent = NULL;
do { do {
cfgent = config_get_value(config, index++, "BOOTBOOT_ENV"); cfgent = config_get_value(config, index++, "BOOTBOOT_ENV");
if (cfgent) { if (cfgent) {
@ -226,19 +237,21 @@ void bootboot_load(char *config) {
size_t fbwidth = 0, fbheight = 0, fbbpp = 32; size_t fbwidth = 0, fbheight = 0, fbbpp = 32;
struct fb_info fbi; struct fb_info fbi;
char *resolution = config_get_value(config, 0, "RESOLUTION"); char *resolution = config_get_value(config, 0, "RESOLUTION");
if (resolution != NULL) if (resolution != NULL) {
parse_resolution(&fbwidth, &fbheight, &fbbpp, resolution); parse_resolution(&fbwidth, &fbheight, &fbbpp, resolution);
}
term_deinit(); term_deinit();
fb_init(&fbi, fbwidth, fbheight, fbbpp); fb_init(&fbi, fbwidth, fbheight, fbbpp);
uint64_t fb_size = fbi.framebuffer_height * fbi.framebuffer_pitch; 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); map_page(pmap, fb_vaddr + current, fbi.framebuffer_addr + current, VMM_FLAG_PRESENT | VMM_FLAG_WRITE, false);
} }
/// Header info /// /// Header info ///
memcpy(bootboot->magic, "BOOT", 4); memcpy(bootboot->magic, "BOOT", 4);
#if bios #if bios
bootboot->protocol = 2 | (0 << 2); bootboot->protocol = 2 | (0 << 2);
#elif uefi #elif uefi
@ -248,11 +261,11 @@ void bootboot_load(char *config) {
/// SMP info /// /// SMP info ///
size_t numcores; size_t numcores;
uint32_t bsplapic; uint32_t bsplapic;
volatile struct smp_information* cores; volatile struct smp_information *cores;
init_smp(0, (void**)&cores, &numcores, &bsplapic, true, false, pmap, false, false); init_smp(0, (void **)&cores, &numcores, &bsplapic, true, false, pmap, false, false);
bootboot->numcores = numcores; bootboot->numcores = numcores;
bootboot->bspid = bsplapic; 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; 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[6] = int_to_bcd(second);
bootboot->datetime[7] = 0; bootboot->datetime[7] = 0;
/// Ramdisk /// /// Ramdisk ///
bootboot->initrd_ptr = initrd_start; bootboot->initrd_ptr = initrd_start;
bootboot->initrd_size = initrd_size; bootboot->initrd_size = initrd_size;
@ -286,25 +298,39 @@ void bootboot_load(char *config) {
uint64_t smbios_entry_32 = 0, smbios_entry_64 = 0; uint64_t smbios_entry_32 = 0, smbios_entry_64 = 0;
acpi_get_smbios((void **)&smbios_entry_32, (void **)&smbios_entry_64); acpi_get_smbios((void **)&smbios_entry_32, (void **)&smbios_entry_64);
bootboot->arch.x86_64.acpi_ptr = (uint64_t)(size_t)acpi_get_rsdp(); 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; if (smbios_entry_64) {
else bootboot->arch.x86_64.smbi_ptr = 0; bootboot->arch.x86_64.smbi_ptr = smbios_entry_64;
bootboot->arch.x86_64.efi_ptr = (uint64_t)(size_t)efi_system_table; } 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; bootboot->arch.x86_64.mp_ptr = 0;
/// Memory map /// /// Memory map ///
{ {
size_t mmapent; size_t mmapent;
struct e820_entry_t* e820e = get_memmap(&mmapent); struct e820_entry_t* e820e = get_memmap(&mmapent);
if (mmapent > 248) { 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++) { for (size_t i = 0; i < mmapent; i++) {
uint32_t btype = 0; uint32_t btype;
if (e820e[i].type == 1) btype = 1;
if (e820e[i].type == 3) btype = 2; switch (e820e[i].type) {
if (e820e[i].type == 4) btype = 2; 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].size = (e820e[i].length & ~0xF) | btype;
bootboot->mmap[i].ptr = e820e[i].base; bootboot->mmap[i].ptr = e820e[i].base;
@ -328,7 +354,7 @@ void bootboot_load(char *config) {
irq_flush_type = IRQ_PIC_APIC_FLUSH; 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].extra_argument = 0;
cores[i].goto_address = entry; cores[i].goto_address = entry;
} }
@ -337,5 +363,4 @@ void bootboot_load(char *config) {
(uint32_t)(uintptr_t)pmap.top_level, (uint32_t)(uintptr_t)pmap.top_level,
(uint32_t)entry, (uint32_t)(entry >> 32), (uint32_t)entry, (uint32_t)(entry >> 32),
(uint32_t)cores[0].stack_addr, (uint32_t)(cores[0].stack_addr >> 32)); (uint32_t)cores[0].stack_addr, (uint32_t)(cores[0].stack_addr >> 32));
} }

View File

@ -1,75 +1,83 @@
#include "lib/print.h" #include <stdint.h>
#include <stddef.h>
#include <stdbool.h>
#include <protos/bootboot/initrd.h> #include <protos/bootboot/initrd.h>
#include <lib/libc.h> #include <lib/libc.h>
#include <stdint.h> #include <lib/blib.h>
#include <lib/print.h>
#define HPODC_MAGIC "070707" #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 * cpio archive
*/ */
INITRD_HANDLER(cpio) { 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; uint64_t offset = 0;
if (file.size < 6) return (file_t){ 0, NULL }; if (file.size < 6) {
return (struct initrd_file){0};
}
/// Check magic /// /// Check magic ///
// this may be a bit unclear, but this checks if the file even **has** a cpio header // 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)) if (memcmp(file.data, "070701", 6) && memcmp(file.data, "070702", 6) && memcmp(file.data, "070707", 6)) {
return (file_t){ 0, NULL }; return (struct initrd_file){0};
}
/// Some variables /// /// Some variables ///
uint64_t path_name_size = strlen(path); size_t path_name_size = strlen(path);
/// hpodc archive /// /// hpodc archive ///
while (!memcmp(_atoffset(), HPODC_MAGIC, 6)) { while (!memcmp(_atoffset(), HPODC_MAGIC, 6)) {
_must(22); _must(22);
uint32_t name_size = oct2bin(_atoffset()+ 8 * 6 + 11, 6); uint32_t name_size = oct2bin(_atoffset() + 8 * 6 + 11, 6);
uint32_t file_size = oct2bin(_atoffset()+ 8 * 6 + 11 + 6, 11); uint32_t file_size = oct2bin(_atoffset() + 8 * 6 + 11 + 6, 11);
_must(9 * 6 + 2 * 11 + name_size); _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] == '/') { if (name_size > 2 && target_path[0] == '.' && target_path[1] == '/') {
target_path += 2; target_path += 2;
} }
if (!memcmp(target_path, path, path_name_size + 1)) { if (!memcmp(target_path, path, path_name_size + 1)) {
return (file_t){ return (struct initrd_file){
file_size, file_size,
_atoffset() + 9 * 6 + 2 * 11 + name_size, _atoffset() + 9 * 6 + 2 * 11 + name_size,
}; };
} }
_offset(76 + name_size + file_size); _offset(76 + name_size + file_size);
} }
offset = 0; offset = 0;
// newc and crc archive // 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 file_size = hex2bin(_atoffset() + 8 * 6 + 6, 8);
uint32_t name_size = hex2bin(_atoffset() + 8 * 11 + 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] == '/') { if (name_size > 2 && target_path[0] == '.' && target_path[1] == '/') {
target_path += 2; target_path += 2;
} }
if (!memcmp(target_path, path, path_name_size + 1)) { if (!memcmp(target_path, path, path_name_size + 1)) {
uint8_t buf[9]; uint8_t buf[9];
memcpy(buf, _atoffset() + 8 * 11 + 6, 8); memcpy(buf, _atoffset() + 8 * 11 + 6, 8);
buf[8] = 0; buf[8] = 0;
return (file_t){ return (struct initrd_file){
file_size, file_size,
(_atoffset() + ((110 + name_size + 3) / 4) * 4), (_atoffset() + ((110 + name_size + 3) / 4) * 4),
}; };
} }
_offset(((110 + name_size + 3) / 4) * 4 + ((file_size + 3) / 4) * 4); _offset(((110 + name_size + 3) / 4) * 4 + ((file_size + 3) / 4) * 4);
} }
char buf[9];
memcpy(buf, _atoffset(), 8); return (struct initrd_file){0};
buf[8] = 0; }
return (file_t){ 0, NULL };
}

View File

@ -1,72 +1,63 @@
#include <stdint.h>
#include <stddef.h>
#include <protos/bootboot/initrd.h> #include <protos/bootboot/initrd.h>
#include <lib/print.h> #include <lib/print.h>
#include <lib/libc.h> #include <lib/libc.h>
#include <lib/blib.h> #include <lib/blib.h>
INITRD_HANDLER(jamesm); INITRD_HANDLER(jamesm);
INITRD_HANDLER(ustar); INITRD_HANDLER(ustar);
INITRD_HANDLER(cpio); 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) #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) { if (strcmp("sys/core", path) == 0) {
printv("bootboot: using ELF as initrd to open sys/core\n"); printv("bootboot: using ELF as initrd to open sys/core\n");
return file; 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) { 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) { if (jamesm_attempt.data) {
printv("bootboot: jamesm matched when reading file `%s`\n", path); printv("bootboot: jamesm matched when reading file `%s`\n", path);
return jamesm_attempt; return jamesm_attempt;
} }
panic("bootboot: cannot read file `%s`: no such file or directory", path); panic("bootboot: cannot read file `%s`: no such file or directory", path);
} }
if (!memcmp("07070", file.data, 5)) { 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) { if (cpio_attempt.data) {
printv("bootboot: cpio matched when reading file `%s`\n", path); printv("bootboot: cpio matched when reading file `%s`\n", path);
return cpio_attempt; return cpio_attempt;
} }
panic("bootboot: cannot read file `%s`: no such file or directory", path); 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)) { 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) { if (ustar_attempt.data) {
printv("bootboot: ustar matched when reading file `%s`\n", path); printv("bootboot: ustar matched when reading file `%s`\n", path);
return ustar_attempt; return ustar_attempt;
} }
panic("bootboot: cannot read file `%s`: no such file or directory", path); panic("bootboot: cannot read file `%s`: no such file or directory", path);
} }
DETECT_FAILED; 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;
}

View File

@ -1,19 +1,15 @@
#ifndef __PROTOS__BOOTBOOT_FS_H__ #ifndef __PROTOS__BOOTBOOT__INITRD_H__
#define __PROTOS__BOOTBOOT_FS_H__ #define __PROTOS__BOOTBOOT__INITRD_H__
#include <stdint.h> #include <stdint.h>
#include <stdbool.h>
typedef struct file { struct initrd_file {
uint64_t size; uint64_t size;
uint8_t* data; uint8_t *data;
} file_t; };
#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); INITRD_HANDLER(auto);
uint32_t oct2bin(uint8_t* str, uint32_t max);
uint32_t hex2bin(uint8_t* str, uint32_t size);
#endif #endif

View File

@ -1,32 +1,41 @@
#include <stdint.h>
#include <stddef.h>
#include <protos/bootboot/initrd.h> #include <protos/bootboot/initrd.h>
#include <lib/libc.h> #include <lib/libc.h>
#include <stdint.h>
// This looks really sketchy, but that's what the official """spec""" says... // This looks really sketchy, but that's what the official """spec""" says...
typedef struct initrd_header { struct initrd_entry {
unsigned char magic; // The magic number is there to check for consistency. uint8_t magic; // The magic number is there to check for consistency.
char name[64]; char name[64];
unsigned int offset; // Offset in the initrd the file starts. uint32_t offset; // Offset in the initrd the file starts.
unsigned int length; // Length of the file. uint32_t length; // Length of the file.
} initrd_entry_t; };
INITRD_HANDLER(jamesm) { 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 file_count = *((uint32_t *)(file.data));
uint32_t path_len = strlen(path); size_t path_len = strlen(path);
initrd_entry_t* data = (initrd_entry_t*)(file.data + 4); struct initrd_entry *data = (void *)(file.data + 4);
if (data[0].magic != 0xBF) return (file_t){}; if (data->magic != 0xbf) {
return (struct initrd_file){0};
}
for(uint32_t i = 0;i < file_count;i++) { for (uint32_t i = 0; i < file_count; i++) {
if (data[i].magic != 0xBF) return (file_t){}; if (data[i].magic != 0xbf) {
if(!memcmp(data[i].name, path, path_len + 1)){ return (struct initrd_file){0};
return (file_t){ }
if (!memcmp(data[i].name, path, path_len + 1)) {
return (struct initrd_file){
data[i].length, data[i].length,
file.data + data[i].offset file.data + data[i].offset
}; };
} }
} }
return (file_t){};
} return (struct initrd_file){0};
}

View File

@ -1,27 +1,34 @@
#include <stdint.h>
#include <stddef.h>
#include <protos/bootboot/initrd.h> #include <protos/bootboot/initrd.h>
#include <lib/libc.h> #include <lib/libc.h>
#include <stdint.h> #include <lib/blib.h>
#define PTR (file.data + offset)
INITRD_HANDLER(ustar) { INITRD_HANDLER(ustar) {
#define PTR (file.data + offset) if (file.size < 262) {
if (file.size < 262) return (file_t){}; return (struct initrd_file){0};
}
if(memcmp(file.data + 257, "ustar", 5)) if (memcmp(file.data + 257, "ustar", 5)) {
return (file_t){}; return (struct initrd_file){0};
}
uint32_t path_size = strlen(path);
size_t path_size = strlen(path);
uint32_t offset = 0; uint32_t offset = 0;
while(!memcmp(PTR + 257,"ustar",5)){ while (!memcmp(PTR + 257, "ustar", 5)) {
uint32_t file_size = oct2bin(PTR + 0x7c,11); uint32_t file_size = oct2bin(PTR + 0x7c, 11);
if(!memcmp(PTR, path, path_size + 1) if (!memcmp(PTR, path, path_size + 1)
|| (PTR[0] == '.' && PTR[1] == '/' && !memcmp(PTR + 2, path, path_size + 1))) { || (PTR[0] == '.' && PTR[1] == '/' && !memcmp(PTR + 2, path, path_size + 1))) {
return (file_t){ return (struct initrd_file){
file_size, file_size,
PTR+512, PTR + 512,
}; };
} }
offset += (((file_size + 511) / 512) + 1) * 512; offset += (((file_size + 511) / 512) + 1) * 512;
} }
return (file_t){};
} return (struct initrd_file){0};
}