From 98255910aa82c27d04ba79704086eca2310b3075 Mon Sep 17 00:00:00 2001 From: Kimplul Date: Sun, 19 Dec 2021 19:13:41 +0200 Subject: Add cpio newc format reader + Still need to actually add in an initrd that uses the format :D --- TODO.txt | 2 + arch/riscv/kernel/main.c | 27 ++----------- common/initrd.c | 99 ++++++++++++++++++++++++++++++++++++++++++++++++ include/apos/initrd.h | 6 ++- include/apos/utils.h | 27 +++++++++++++ 5 files changed, 136 insertions(+), 25 deletions(-) diff --git a/TODO.txt b/TODO.txt index 149fcfc..bbe214d 100644 --- a/TODO.txt +++ b/TODO.txt @@ -4,3 +4,5 @@ + Create sensible thread handling + Add in init process loading + Make sure vmap is in 4K increments or whatever ++ Remove/converge convnum and debugging __atoi ++ Create actual init program diff --git a/arch/riscv/kernel/main.c b/arch/riscv/kernel/main.c index c7a1290..40f0eb6 100644 --- a/arch/riscv/kernel/main.c +++ b/arch/riscv/kernel/main.c @@ -66,28 +66,6 @@ static pm_t get_kerneltop() return (pm_t)&__kernel_end; } -static pm_t get_initrdtop(void *fdt) -{ - int chosen_offset = fdt_path_offset(fdt, "/chosen"); - struct cell_info_t ci = get_cellinfo(fdt, chosen_offset); - - void *initrd_end_ptr = (void *)fdt_getprop(fdt, chosen_offset, - "linux,initrd-end", NULL); - - return (pm_t)fdt_load_int_ptr(ci.addr_cells, initrd_end_ptr); -} - -static pm_t get_initrdbase(void *fdt) -{ - int chosen_offset = fdt_path_offset(fdt, "/chosen"); - struct cell_info_t ci = get_cellinfo(fdt, chosen_offset); - - void *initrd_base_ptr = (void *)fdt_getprop(fdt, chosen_offset, - "linux,initrd-start", NULL); - - return (pm_t)fdt_load_int_ptr(ci.addr_cells, initrd_base_ptr); -} - static pm_t get_fdttop(void *fdt) { const char *b = (const char *)fdt; @@ -290,15 +268,16 @@ static void init_proc(void *fdt, struct vm_branch_t *b) t->stack = alloc_uvmem(t, SZ_2M, VM_V | VM_R | VM_W); /* if it needs heap, it'll ask for it */ - move_init(fdt, (void *)t->bin, sz); + move_init(fdt, (void *)t->bin); jump_to_userspace(t, 0, 0); } void __main main(void *fdt) { init_dbg(fdt); - struct vm_branch_t *b = init_vmem(fdt); + dbg_fdt(fdt); + struct vm_branch_t *b = init_vmem(fdt); init_mem_blocks(); init_irq(fdt); init_proc(fdt, b); diff --git a/common/initrd.c b/common/initrd.c index e69de29..f625209 100644 --- a/common/initrd.c +++ b/common/initrd.c @@ -0,0 +1,99 @@ +#include +#include +#include +#include +#include + +/* GNU cpio, use POSIX 'newc' format */ +__packed struct cpio_header { + char c_magic[6]; + char c_ino[8]; + char c_mode[8]; + char c_uid[8]; + char c_gid[8]; + char c_nlink[8]; + char c_mtime[8]; + char c_filesize[8]; + char c_devmajor[8]; + char c_devminor[8]; + char c_rdevmajor[8]; + char c_rdevminor[8]; + char c_namesize[8]; + char c_check[8]; +}; + +static struct cpio_header *next_entry(struct cpio_header *cp) +{ + size_t blen = align_up(sizeof(struct cpio_header) + convnum(cp->c_namesize, 8, 16), 4); + size_t tlen = align_up(convnum(cp->c_filesize, 8, 16), 4); + + return (struct cpio_header *)(((char *)cp) + blen + tlen); +} + +static struct cpio_header *find_file(char *c, char* fname, size_t fname_len) +{ + struct cpio_header *cp = (struct cpio_header *)c; + for(; cp; cp = next_entry(cp)){ + size_t namelen = convnum(cp->c_namesize, 8, 16); + if(namelen == 0) + return 0; + + if(namelen < fname_len) + continue; + + char *name = (char *)(cp + 1); + if(fname[0] != '/') + name += namelen - (fname_len + 1); /* match ending */ + + if(strncmp(name, fname, fname_len) == 0) + return cp; + } + + return 0; +} + +pm_t get_initrdtop(void *fdt) +{ + int chosen_offset = fdt_path_offset(fdt, "/chosen"); + struct cell_info_t ci = get_cellinfo(fdt, chosen_offset); + + void *initrd_end_ptr = (void *)fdt_getprop(fdt, chosen_offset, + "linux,initrd-end", NULL); + + return (pm_t)fdt_load_int_ptr(ci.addr_cells, initrd_end_ptr); +} + +pm_t get_initrdbase(void *fdt) +{ + int chosen_offset = fdt_path_offset(fdt, "/chosen"); + struct cell_info_t ci = get_cellinfo(fdt, chosen_offset); + + void *initrd_base_ptr = (void *)fdt_getprop(fdt, chosen_offset, + "linux,initrd-start", NULL); + + return (pm_t)fdt_load_int_ptr(ci.addr_cells, initrd_base_ptr); +} + +static char init_n[] = "init"; +static size_t init_nlen = ARRAY_SIZE(init_n); + +size_t get_init_size(void *fdt) +{ + char *c = (char *)get_initrdbase(fdt); + struct cpio_header *cp = find_file(c, init_n, init_nlen); + return convnum(cp->c_filesize, 8, 16); +} + +void move_init(void *fdt, void *target) +{ + char *c = (char *)get_initrdbase(fdt); + + struct cpio_header *cp = find_file(c, init_n, init_nlen); + size_t name_len = convnum(cp->c_namesize, 8, 16); + size_t file_len = convnum(cp->c_filesize, 8, 16); + + char *fp = (char *)cp; + fp += align_up(sizeof(struct cpio_header) + name_len, 4); + + memmove(target, fp, file_len); +} diff --git a/include/apos/initrd.h b/include/apos/initrd.h index 942875f..1e1129c 100644 --- a/include/apos/initrd.h +++ b/include/apos/initrd.h @@ -2,8 +2,12 @@ #define APOS_INITRD_H #include +#include size_t get_init_size(void *fdt); -void move_init(void *fdt, void *target, size_t sz); +void move_init(void *fdt, void *target); + +pm_t get_initrdtop(void *fdt); +pm_t get_initrdbase(void *fdt); #endif /* APOS_INITRD_H */ diff --git a/include/apos/utils.h b/include/apos/utils.h index 881cd8f..d0b41ce 100644 --- a/include/apos/utils.h +++ b/include/apos/utils.h @@ -25,6 +25,8 @@ #define container_of(ptr, type, member) \ ((type *)((char *)(ptr) - offsetof(type, member))) +#define ARRAY_SIZE(x) (sizeof(x) / sizeof((x)[0])) + #include static inline size_t align_up(size_t val, size_t a) @@ -48,4 +50,29 @@ static inline size_t align_down(size_t val, size_t a) return val - (val % a); } +static inline size_t asciinum(char c) +{ + if(c >= '0' && c <= '9') + return c - '0'; + else if(c >= 'A' && c <= 'F') + return c - 'A' + 10; + else if(c >= 'a' && c <= 'f') + return c - 'a' + 10; + else + return 0; +} + +static inline size_t convnum(const char *c, size_t len, size_t base) +{ + size_t multiplier = 1; + size_t sum = 0; + for(size_t i = 0; i < len; ++i){ + sum += asciinum(c[len - 1 - i]) * multiplier; + multiplier *= base; + } + + return sum; +} + + #endif /* APOS_UTILS_H */ -- cgit v1.3