diff options
| -rw-r--r-- | Makefile | 7 | ||||
| -rw-r--r-- | arch/riscv/init/init.c | 104 | ||||
| -rw-r--r-- | arch/riscv/source.mk | 2 | ||||
| -rw-r--r-- | common/debug.c | 77 | ||||
| -rw-r--r-- | include/apos/attrs.h | 4 | ||||
| -rw-r--r-- | include/apos/debug.h | 22 |
6 files changed, 198 insertions, 18 deletions
@@ -1,6 +1,7 @@ DO != echo > deps.mk -CFLAGS = -fno-pie -ggdb3 -ffreestanding -nostdlib -std=c11 -Wall -Wextra -mcmodel=medany +DEBUGFLAGS != [ $(DEBUG) ] && echo "-g3 -DDEBUG" || echo "-O2" +CFLAGS = -fno-pie -ffreestanding -nostdlib -std=c11 -Wall -Wextra DEPFLAGS = -MT $@ -MMD -MP -MF $@.d all: apos.bin @@ -26,8 +27,8 @@ include arch/$(ARCH)/source.mk INCLUDE_FLAGS := -I include -I arch/$(ARCH)/include\ -include config.h -include arch/$(ARCH)/config.h -COMPILE = $(CROSS_COMPILE)$(CC) $(CFLAGS) $(DEPFLAGS) $(INCLUDE_FLAGS) -GENELF = $(CROSS_COMPILE)$(CC) $(CFLAGS) $(INCLUDE_FLAGS) +COMPILE = $(CROSS_COMPILE)$(CC) $(DEBUGFLAGS) $(CFLAGS) $(ARCH_FLAGS) $(DEPFLAGS) $(INCLUDE_FLAGS) +GENELF = $(CROSS_COMPILE)$(CC) $(DEBUGFLAGS) $(CFLAGS) $(ARCH_FLAGS) $(INCLUDE_FLAGS) GENLINK = $(CROSS_COMPILE)$(CPP) $(DEPFLAGS) $(INCLUDE_FLAGS) STRIPLINK = sed -n '/^[^\#]/p' diff --git a/arch/riscv/init/init.c b/arch/riscv/init/init.c index bb16876..6bb6bc3 100644 --- a/arch/riscv/init/init.c +++ b/arch/riscv/init/init.c @@ -1,6 +1,8 @@ #include <apos/init.h> #include <apos/sizes.h> #include <apos/types.h> +#include <apos/string.h> +#include <apos/debug.h> #include <libfdt.h> #include <pages.h> #include <csr.h> @@ -11,40 +13,116 @@ struct mem_layout { pm_t top; }; -struct mem_layout get_memlayout(void *fdt) +struct cell_info { + uint32_t size_cells; + uint32_t addr_cells; +}; + +struct cell_info get_cellinfo(void *fdt, int offset) { - fdt32_t *size_ptr = (fdt32_t *)fdt_getprop(fdt, 0, "#size-cells", NULL); - fdt32_t *addr_ptr = (fdt32_t *)fdt_getprop(fdt, 0, "#address-cells", NULL); - uint32_t size_cells = fdt32_to_cpu(*size_ptr); - uint32_t addr_cells = fdt32_to_cpu(*addr_ptr); + 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); + } + + return ret; +} + +struct mem_layout get_memlayout(void *fdt) +{ + struct cell_info ci = get_cellinfo(fdt, 0); int mem_offset = fdt_path_offset(fdt, "/memory"); - uint8_t *mem_reg = (uint8_t *)fdt_getprop(fdt, mem_offset, "reg", NULL); + uint8_t *mem_reg = + (uint8_t *) fdt_getprop(fdt, mem_offset, "reg", NULL); pm_t base; /* if riscv128 comes around we will probably see addr_cells == 4, but * I'm not too concerned about it at the moment */ - if (addr_cells == 2) { - base = fdt64_to_cpu(*(fdt64_t *)mem_reg); + if (ci.addr_cells == 2) { + base = fdt64_to_cpu(*(fdt64_t *) mem_reg); mem_reg += sizeof(fdt64_t); } else { - base = fdt32_to_cpu(*(fdt32_t *)mem_reg); + base = fdt32_to_cpu(*(fdt32_t *) mem_reg); mem_reg += sizeof(fdt32_t); } pm_t top; - if (size_cells == 2) - top = fdt64_to_cpu(*(fdt64_t *)mem_reg) + base; + if (ci.size_cells == 2) + top = fdt64_to_cpu(*(fdt64_t *) mem_reg) + base; else - top = fdt32_to_cpu(*(fdt64_t *)mem_reg) + base; + top = fdt32_to_cpu(*(fdt64_t *) mem_reg) + base; - struct mem_layout ret = {base, top}; + struct mem_layout ret = { base, top }; return ret; } +#ifdef DEBUG + +/* this should probably be improved in the future, possibly also moved + * somewhere? */ +enum serial_dev_t serial_dev_enum(const char *dev_name) +{ + if (strncmp("ns16550", dev_name, 7) == 0) + return NS16550A; + + return -1; +} + +void init_debug(void *fdt) +{ + int offset = fdt_path_offset(fdt, "/soc/uart"); + + /* get serial device type */ + const char *dev_name = (const char *)fdt_getprop(fdt, offset, + "compatible", NULL); + + enum serial_dev_t dev = serial_dev_enum(dev_name); + + /* get serial device address */ + struct cell_info ci = get_cellinfo(fdt, offset); + void *reg_ptr = (void *)fdt_getprop(fdt, offset, "reg", NULL); + + void *uart_ptr = 0; + if (ci.addr_cells == 2) + uart_ptr = (void *)(pm_t)fdt64_to_cpu(*(fdt64_t *) reg_ptr); + else + uart_ptr = (void *)(pm_t)fdt32_to_cpu(*(fdt32_t *) reg_ptr); + + dbg_init(uart_ptr, dev); +} + +#else + +#define init_debug(...) + +#endif + void init(void *fdt) { + init_debug(fdt); + dbg("hello\n"); + struct mem_layout pmem = get_memlayout(fdt); /* struct mm_ptinfo ptbl = create_pagetable(pmem); */ } diff --git a/arch/riscv/source.mk b/arch/riscv/source.mk index cf8edd7..50e0f5f 100644 --- a/arch/riscv/source.mk +++ b/arch/riscv/source.mk @@ -7,7 +7,7 @@ INIT_SOURCES += $(INIT_LOCAL) $(INIT_FDT) CLEANUP_CMD := ./arch/riscv/conf/rmimage.sh -USE_FDT := y +ARCH_FLAGS := -mcmodel=medany run: ./arch/riscv/conf/mkimage.sh diff --git a/common/debug.c b/common/debug.c new file mode 100644 index 0000000..be71cd2 --- /dev/null +++ b/common/debug.c @@ -0,0 +1,77 @@ +#include <apos/types.h> +#include <apos/debug.h> + +#ifdef DEBUG + +/* if there arises a need for more supported serial drivers, I should probably + * try to implement some kind of basic driver subsystem, but this is good enough + * for now. */ + +struct __packed ns16550a { + union { + struct { + uint8_t data; + uint8_t irq; + }; + + struct { + uint8_t lsbr; + uint8_t msbr; + }; + }; + + uint8_t irq_id; + uint8_t lcr; + uint8_t mcr; + uint8_t lsr; + uint8_t msr; + uint8_t scr; +}; + +#define LSR_DR (1 << 0) +#define LSR_OE (1 << 1) +#define LSR_PE (1 << 2) +#define LSR_FE (1 << 3) +#define LSR_BI (1 << 4) +#define LSR_THRE (1 << 5) +#define LSR_TEMT (1 << 6) +#define LSR_ERR (1 << 7) + +static struct ns16550a *port = 0; + +int __serial_tx_empty() +{ + return port->lsr & LSR_THRE; +} + +void __serial_putchar(char c) +{ + if (!port) + return; + + while(__serial_tx_empty() == 0); + + port->data = c; +} + +void dbg_init(void *pt, enum serial_dev_t dev) +{ + switch (dev) { + case NS16550A: + port = pt; + break; + } + + /* in the future possibly configure the serial connection, though the + * defaults (set by U-boot) seem to work alright */ +} + +void dbg(const char *fmt, ...) +{ + /* do a proper implementation later, for now just dump stuff */ + while(*fmt){ + __serial_putchar(*fmt++); + } +} + +#endif /* DEBUG */ diff --git a/include/apos/attrs.h b/include/apos/attrs.h index 00dcf82..e088ec9 100644 --- a/include/apos/attrs.h +++ b/include/apos/attrs.h @@ -1,7 +1,9 @@ #ifndef APOS_COMPILER_ATTRIBUTES_H #define __section(section) __attribute__((__section__(section))) +#define __fmt(x, y) __attribute__((format (__printf__, x, y))) #define __noinline __attribute__((noinline)) -#define __weak __attribute((weak)) +#define __weak __attribute__((weak)) +#define __packed __attribute__((packed)) #endif /* APOS_COMPILER_ATTRIBUTES_H */ diff --git a/include/apos/debug.h b/include/apos/debug.h new file mode 100644 index 0000000..021612d --- /dev/null +++ b/include/apos/debug.h @@ -0,0 +1,22 @@ +#ifndef APOS_DEBUG_H +#define APOS_DEBUG_H + +#include <apos/attrs.h> + +#ifdef DEBUG +enum serial_dev_t { + /* only the NS16550A and compatible at the moment */ + NS16550A, +}; + +void __fmt(1, 2) dbg(const char *fmt, ...); +void dbg_init(void *pt, enum serial_dev_t dev); + +#else + +#define dbg(...) +#define dbg_init(...) + +#endif /* DEBUG */ + +#endif /* APOS_DEBUG_H */ |
