diff options
| -rw-r--r-- | Makefile | 6 | ||||
| -rw-r--r-- | TODO.txt | 4 | ||||
| -rw-r--r-- | arch/riscv/conf/apos.its | 17 | ||||
| -rw-r--r-- | arch/riscv/conf/boot.cmd | 2 | ||||
| -rw-r--r-- | arch/riscv/conf/initrd.txt | 1 | ||||
| -rw-r--r-- | arch/riscv/init/init.c | 68 | ||||
| -rw-r--r-- | common/debug.c | 9 | ||||
| -rw-r--r-- | include/apos/utils.h | 14 | ||||
| -rw-r--r-- | include/fdt.h | 3 | ||||
| -rw-r--r-- | include/libfdt.h | 11 | ||||
| -rw-r--r-- | lib/fdt_dbg.c | 121 |
11 files changed, 221 insertions, 35 deletions
@@ -1,7 +1,7 @@ DO != echo > deps.mk # this could be done better -DEBUGFLAGS != [ $(DEBUG) ] && echo "-Og -ggdb3 -DDEBUG" || echo "-flto -O2" +DEBUGFLAGS != [ $(DEBUG) ] && echo "-O0 -ggdb3 -DDEBUG" || echo "-flto -O2" CFLAGS = -fno-pie -ffreestanding -nostdlib -std=c11 -Wall -Wextra DEPFLAGS = -MT $@ -MMD -MP -MF $@.d @@ -60,5 +60,7 @@ init.elf: $(INIT_OBJECTS) $(INIT_LD) $(GENELF) -T $(INIT_LD) $(INIT_OBJECTS) -o $@ clean: - $(CLEANUP_CMD) $(RM) -r $(CLEANUP) + +clean_run: clean + $(CLEANUP_CMD) @@ -6,3 +6,7 @@ + Test string.c + Write the kernel lol + Test libfdt and see if it can be used to read memory geometry etc. + ++ Jump to vmem ++ Mark fdt, reserved mem, kernel, init and initrd in vmem. Remember to remove +init from vmem when jumping to vmem diff --git a/arch/riscv/conf/apos.its b/arch/riscv/conf/apos.its index c3611dd..7c05044 100644 --- a/arch/riscv/conf/apos.its +++ b/arch/riscv/conf/apos.its @@ -18,6 +18,19 @@ algo = "sha1"; }; }; + + initrd { + description = "Gargabbio initrd"; + data = /incbin/("initrd.txt"); + type = "ramdisk"; + arch = "riscv"; + os = "apos"; + compression = "none"; + load = <0x88300000>; + hash-1 { + algo = "sha1"; + }; + }; }; configurations { @@ -26,6 +39,10 @@ config { description = "Default configuration"; kernel = "kernel"; + ramdisk = "initrd"; + hash-1 { + algo = "sha1"; + }; }; }; }; diff --git a/arch/riscv/conf/boot.cmd b/arch/riscv/conf/boot.cmd index 782c1e8..a7517fd 100644 --- a/arch/riscv/conf/boot.cmd +++ b/arch/riscv/conf/boot.cmd @@ -1,4 +1,4 @@ fdt move ${fdt_addr} ${fdt_addr_r} fdt addr ${fdt_addr_r} load ${devtype} ${devnum} ${kernel_addr_r} apos.itb -bootm ${kernel_addr_r} - ${fdt_addr_r} +bootm ${kernel_addr_r} ${kernel_addr_r} ${fdt_addr_r} diff --git a/arch/riscv/conf/initrd.txt b/arch/riscv/conf/initrd.txt new file mode 100644 index 0000000..e965047 --- /dev/null +++ b/arch/riscv/conf/initrd.txt @@ -0,0 +1 @@ +Hello diff --git a/arch/riscv/init/init.c b/arch/riscv/init/init.c index e12c351..105a23d 100644 --- a/arch/riscv/init/init.c +++ b/arch/riscv/init/init.c @@ -4,6 +4,7 @@ #include <apos/string.h> #include <apos/debug.h> #include <apos/pmem.h> +#include <apos/utils.h> #include <libfdt.h> #include <pages.h> #include <csr.h> @@ -19,37 +20,17 @@ struct cell_info { uint32_t addr_cells; }; -struct cell_info get_cellinfo(void *fdt, int offset) +static struct cell_info get_cellinfo(void *fdt, int offset) { - - fdt32_t *size_ptr = 0; - fdt32_t *addr_ptr = 0; - - while (offset) { - size_ptr = (fdt32_t *) fdt_getprop(fdt, offset, - "#size-cells", NULL); - - addr_ptr = (fdt32_t *) fdt_getprop(fdt, offset, - "#address-cells", NULL); - - if (size_ptr && addr_ptr) - break; - - /* dtc warns that this function is slow, but I don't care */ - offset = fdt_parent_offset(fdt, offset); - } - - struct cell_info ret = {0}; - - if (size_ptr && addr_ptr){ - ret.size_cells = fdt32_to_cpu(*size_ptr); - ret.addr_cells = fdt32_to_cpu(*addr_ptr); - } + struct cell_info ret = { + fdt_size_cells(fdt, offset), + fdt_address_cells(fdt, offset) + }; return ret; } -struct mem_layout get_memlayout(void *fdt) +static struct mem_layout get_memlayout(void *fdt) { struct cell_info ci = get_cellinfo(fdt, 0); @@ -82,7 +63,7 @@ struct mem_layout get_memlayout(void *fdt) /* this should probably be improved in the future, possibly also moved * somewhere? */ -enum serial_dev_t serial_dev_enum(const char *dev_name) +static enum serial_dev_t serial_dev_enum(const char *dev_name) { if (strncmp("ns16550", dev_name, 7) == 0) return NS16550A; @@ -90,7 +71,7 @@ enum serial_dev_t serial_dev_enum(const char *dev_name) return -1; } -void init_debug(void *fdt) +static void init_debug(void *fdt) { int offset = fdt_path_offset(fdt, "/soc/uart"); @@ -114,14 +95,41 @@ void init_debug(void *fdt) } #else - #define init_debug(...) - #endif +/* TODO: these */ +static pm_t get_kerneltop(void *fdt) +{ + return 0; +} + +static pm_t get_initrdtop(void *fdt) +{ + return 0; +} + +static pm_t get_fdttop(void *fdt) +{ + return 0; +} + +static void setup_pmem(void *fdt) +{ + struct mem_layout pmem = get_memlayout(fdt); + + pm_t kernel_top = get_kerneltop(fdt); + pm_t initrd_top = get_initrdtop(fdt); + pm_t fdt_top = get_fdttop(fdt); + + pm_t top = MAX3(kernel_top, initrd_top, fdt_top); +} + void __noreturn init(void *fdt) { init_debug(fdt); + dbg_fdt(fdt); + setup_pmem(fdt); /* basic memory layout info */ struct mem_layout pmem = get_memlayout(fdt); diff --git a/common/debug.c b/common/debug.c index 9925bd6..c82377c 100644 --- a/common/debug.c +++ b/common/debug.c @@ -154,7 +154,7 @@ static size_t __integral_val(ssize_t value, size_t base, size_t flags, bool prin #undef handle_type if(base == 16) - c += c >= 9 ? 'a' - 10 : '0'; + c += c > 9 ? 'a' - 10 : '0'; else c += '0'; @@ -430,6 +430,7 @@ void dbg(const char *fmt, ...) /* read actual specifier */ size_t base = 10; size_t value = 0; + int i = -1; const char *s = 0; void *p = 0; int *n = 0; @@ -486,7 +487,11 @@ void dbg(const char *fmt, ...) case 's': s = va_arg(vl, const char *); - for(; *s ;){ + + if(__is_set(flags, PRECS_FLAG)) + i = precision; + + for(; *s && i--;){ __putchar(*s++); chars_written++; } diff --git a/include/apos/utils.h b/include/apos/utils.h new file mode 100644 index 0000000..45e7194 --- /dev/null +++ b/include/apos/utils.h @@ -0,0 +1,14 @@ +#ifndef APOS_UTILS_H +#define APOS_UTILS_H + +#define MAX(a, b) ((a) >= (b) ? (a) : (b)) +#define MAX3(a, b, c) (MAX(a, b) >= MAX(b, c) ? MAX(a, b) : MAX(b, c)) +#define MAX4(a, b, c, d) (MAX3(a, b, c) >= MAX3(b, c, d) ? MAX3(a, b, c) : MAX3(b, c, d)) +/* etc... */ + +#define MIN(a, b) ((a) <= (b) ? (a) : (b)) +#define MIN3(a, b, c) (MIN(a, b) <= MIN(b, c) ? MIN(a, b) : MIN(b, c)) +#define MIN4(a, b, c, d) (MIN3(a, b, c) <= MIN3(b, c, d) ? MIN3(a, b, c) : MIN3(b, c, d)) +/* etc... */ + +#endif /* APOS_UTILS_H */ diff --git a/include/fdt.h b/include/fdt.h index 9236a45..f0b85e8 100644 --- a/include/fdt.h +++ b/include/fdt.h @@ -1 +1,4 @@ +#ifndef APOS_FDT_H +#define APOS_FDT_H #include "../dtc/libfdt/fdt.h" +#endif diff --git a/include/libfdt.h b/include/libfdt.h index 65b3ca6..d734715 100644 --- a/include/libfdt.h +++ b/include/libfdt.h @@ -1 +1,12 @@ +#ifndef APOS_LIBFDT_H +#define APOS_LIBFDT_H #include "../dtc/libfdt/libfdt.h" + +#if defined(DEBUG) +void __dbg_fdt(void *fdt, int node_offset, int depth); +#define dbg_fdt(fdt) __dbg_fdt(fdt, 0, 0) +#else +#define dbg_fdt(...) +#endif + +#endif diff --git a/lib/fdt_dbg.c b/lib/fdt_dbg.c new file mode 100644 index 0000000..1dd8007 --- /dev/null +++ b/lib/fdt_dbg.c @@ -0,0 +1,121 @@ +#include <apos/debug.h> +#include <libfdt.h> + +#if defined(DEBUG) +static void __print_char(char c, int depth) +{ + /* lol, ugly but good enough for now */ + for(int i = 0; i < depth; ++i) + dbg("%c", c); +} + +static int __printable(char c) +{ + return (c >= 32) && (c <= 126); +} + +static int __is_string(const void *data, int len) +{ + const char *s = data; + + /* zero length is not */ + if (len == 0) + return 0; + + /* must terminate with zero or '\n' */ + if (s[len - 1] != '\0' && s[len - 1] != '\n') + return 0; + + /* printable or a null byte (concatenated strings) */ + while (((*s == '\0') || __printable(*s)) && (len > 0)) { + /* + * If we see a null, there are three possibilities: + * 1) If len == 1, it is the end of the string, printable + * 2) Next character also a null, not printable. + * 3) Next character not a null, continue to check. + */ + if (s[0] == '\0') { + if (len == 1) + return 1; + if (s[1] == '\0') + return 0; + } + s++; + len--; + } + + /* Not the null termination, or not done yet: not printable */ + if (*s != '\0' || (len != 0)) + return 0; + + return 1; +} + +static void __print_prop_value(const void *data, int len) +{ + if(len == 0) + return; + + dbg(" = "); + + /* heavily inspired by u-boot's fdt print */ + if(__is_string(data, len)){ + dbg("\""); + int i = 0; + while(i < len){ + if(i > 0) + dbg("\", \""); + + dbg("%s", (const char *)data); + i += strlen(data) + 1; + data += strlen(data) + 1; + } + dbg("\""); + + } else if ((len % 4) == 0) { + const int32_t *p = (const int32_t *)data; + dbg("<"); + for(int i = 0; i < len / 4; ++i) + dbg("%#08x%s", fdt32_to_cpu(p[i]), i < (len / 4 - 1) ? " " : ""); + + dbg(">"); + } else { + const int32_t *p = (const int32_t *)data; + dbg("["); + for(int i = 0; i < len / 4; ++i) + dbg("%#02x%s", fdt32_to_cpu(p[i]), i < (len / 4 - 1) ? " " : ""); + + dbg("]"); + } +} + +void __dbg_fdt(void *fdt, int node_offset, int depth) +{ + int node = 0; + fdt_for_each_subnode(node, fdt, node_offset){ + __print_char('\t', depth); + dbg("%s: {\n", fdt_get_name(fdt, node, 0)); + + int property = 0; + fdt_for_each_property_offset(property, fdt, node){ + + int len; + const char *name; + const void *data = fdt_getprop_by_offset(fdt, property, + &name, &len); + + __print_char('\t', depth + 1); + dbg("%s", name); + + __print_prop_value(data, len); + dbg(";\n"); + } + + + __dbg_fdt(fdt, node, depth + 1); + + __print_char('\t', depth); + dbg("};\n\n"); + } +} +#endif |
