aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorKimplul <kimi.h.kuparinen@gmail.com>2021-09-20 14:17:18 +0300
committerKimplul <kimi.h.kuparinen@gmail.com>2021-09-20 14:17:18 +0300
commit68fcd6d027b88581992b4fb10ee1edc301e30678 (patch)
treec75ce91b2db43e562447b88958cff6eebaa96c98
parent64405594929502951624942e2a9ca53077aba2ae (diff)
downloadkmi-68fcd6d027b88581992b4fb10ee1edc301e30678.tar.gz
kmi-68fcd6d027b88581992b4fb10ee1edc301e30678.zip
Some slight robustness improvements and obo errors
-rw-r--r--TODO.txt1
-rw-r--r--arch/riscv/init/init.c36
-rw-r--r--common/string.c20
-rw-r--r--include/apos/utils.h17
-rw-r--r--include/libfdt.h4
5 files changed, 55 insertions, 23 deletions
diff --git a/TODO.txt b/TODO.txt
index 1d84441..012fba9 100644
--- a/TODO.txt
+++ b/TODO.txt
@@ -11,3 +11,4 @@
+ Mark fdt, reserved mem, kernel, init and initrd in vmem. Remember to remove
init from vmem when jumping to vmem
+ Figure out best way to tell the init how large out kernel is
++ Make code more robust, error checking etc
diff --git a/arch/riscv/init/init.c b/arch/riscv/init/init.c
index c389e3b..5612d0b 100644
--- a/arch/riscv/init/init.c
+++ b/arch/riscv/init/init.c
@@ -31,26 +31,40 @@ static struct cell_info get_cellinfo(void *fdt, int offset)
}
-static struct pmem_layout get_memlayout(void *fdt)
+/* How "reg" is interpreted depends on the parent node */
+static struct cell_info get_reginfo(void *fdt, const char *path)
{
- struct cell_info ci = get_cellinfo(fdt, 0);
+ const char *i = strrchr(path, '/');
+ if(!i)
+ return (struct cell_info){0, 0};
+
+ size_t baselen = i - path;
+ if(i == 0)
+ /* root node */
+ baselen = 1;
+
+ return get_cellinfo(fdt, fdt_path_offset_namelen(fdt, path, baselen));
+}
+static struct pmem_layout get_memlayout(void *fdt)
+{
+ struct cell_info ci = get_reginfo(fdt, "/memory");
int mem_offset = fdt_path_offset(fdt, "/memory");
uint8_t *mem_reg =
(uint8_t *) fdt_getprop(fdt, mem_offset, "reg", NULL);
/* if riscv128 comes around we will probably see addr_cells == 4, but
* I'm not too concerned about it at the moment */
- pm_t base = fdt_load_int_ptr(pm_t, ci.addr_cells, mem_reg);
+ pm_t base = (pm_t)fdt_load_int_ptr(ci.addr_cells, mem_reg);
if(ci.addr_cells == 2)
mem_reg += sizeof(fdt64_t);
else
mem_reg += sizeof(fdt32_t);
- pm_t top = fdt_load_int_ptr(pm_t, ci.size_cells, mem_reg) + base;
- struct pmem_layout ret = { base, top };
- return ret;
+ /* -1 because base is a legitimate memory address */
+ pm_t top = (pm_t)fdt_load_int_ptr(ci.size_cells, mem_reg) + base - 1;
+ return (struct pmem_layout){base, top};
}
#ifdef DEBUG
@@ -80,11 +94,11 @@ static void init_debug(void *fdt)
enum serial_dev_t dev = serial_dev_enum(dev_name);
/* get serial device address */
- struct cell_info ci = get_cellinfo(fdt, stdout_offset);
+ struct cell_info ci = get_reginfo(fdt, stdout);
void *reg_ptr = (void *)fdt_getprop(fdt, stdout_offset, "reg", NULL);
void *uart_ptr = 0;
- uart_ptr = (void *)fdt_load_int_ptr(pm_t, ci.addr_cells, reg_ptr);
+ uart_ptr = (void *)(pm_t)fdt_load_int_ptr(ci.addr_cells, reg_ptr);
dbg_init(uart_ptr, dev);
}
@@ -110,7 +124,7 @@ static pm_t get_initrdtop(void *fdt)
void *initrd_end_ptr = (void *)fdt_getprop(fdt, chosen_offset,
"linux,initrd-end", NULL);
- return fdt_load_int_ptr(pm_t, ci.addr_cells, initrd_end_ptr);
+ return (pm_t)fdt_load_int_ptr(ci.addr_cells, initrd_end_ptr);
}
static pm_t get_fdttop(void *fdt)
@@ -132,7 +146,9 @@ static void setup_pmem(void *fdt)
dbg("kernel_top:\t%#lx\n", kernel_top);
dbg("fdt_top:\t%#lx\n", fdt_top);
- populate_pmap(pmem.base, pmem.top - pmem.base, top + 1);
+ /* riscv handles two byte boundaries better than one byte, so align
+ * upwards */
+ populate_pmap(pmem.base, pmem.top - pmem.base, align_up(top + 1, 2));
/* TODO: mark used pages */
}
diff --git a/common/string.c b/common/string.c
index af9c54a..0870b78 100644
--- a/common/string.c
+++ b/common/string.c
@@ -93,12 +93,11 @@ __weak int strncmp(const char *str1, const char *str2, size_t num)
__weak char *strchr(const char *str, int chr)
{
const char *s1 = str;
- size_t num = strlen(s1);
+ ssize_t num = strlen(s1);
while (num-- && *(s1--) != chr) ;
- num++;
- if (!num)
+ if (num < 0)
return 0;
return (char *)(s1 + 1);
@@ -162,16 +161,15 @@ __weak char *strstr(const char *str1, const char *str2)
#undef strrchr
__weak char *strrchr(const char *str, int chr)
{
- size_t num = strlen(str);
- const char *s1 = str + num;
+ ssize_t num = strlen(str);
+ const char *s1 = (str + num) - 1;
while (num-- && *(s1--) != chr) ;
- num++;
- if (!num)
+ if (num < 0)
return 0;
- return (char *)s1;
+ return (char *)(s1 + 1);
}
#undef strpbrk
@@ -262,12 +260,12 @@ __weak void *memset(void *ptr, int value, size_t num)
__weak void *memchr(const void *ptr, int val, size_t num)
{
const char *p1 = (char *)ptr;
+ ssize_t n = num;
char c = (char)val;
- while (num-- && *(p1++) != c) ;
+ while (n-- && *(p1++) != c) ;
- num++;
- if (!num)
+ if (n < 0)
return 0;
return (void *)(p1 - 1);
diff --git a/include/apos/utils.h b/include/apos/utils.h
index 45e7194..3855a37 100644
--- a/include/apos/utils.h
+++ b/include/apos/utils.h
@@ -11,4 +11,21 @@
#define MIN4(a, b, c, d) (MIN3(a, b, c) <= MIN3(b, c, d) ? MIN3(a, b, c) : MIN3(b, c, d))
/* etc... */
+#include <apos/types.h>
+
+static inline size_t align_up(size_t val, size_t a)
+{
+ size_t rem = val % a;
+
+ if (rem == 0)
+ return val;
+
+ return val + a - rem;
+}
+
+static inline size_t align_down(size_t val, size_t a)
+{
+ return val - (val % a);
+}
+
#endif /* APOS_UTILS_H */
diff --git a/include/libfdt.h b/include/libfdt.h
index 7425aef..406b6d7 100644
--- a/include/libfdt.h
+++ b/include/libfdt.h
@@ -9,7 +9,7 @@ void __dbg_fdt(void *fdt, int node_offset, int depth);
#define dbg_fdt(...)
#endif
-#define fdt_load_int_ptr(t, c, p)\
- ((c) == 2 ? (t)fdt64_to_cpu(*(fdt64_t *)(p)) : (t)fdt32_to_cpu(*(fdt32_t *)(p)))
+#define fdt_load_int_ptr(c, p)\
+ ((c) == 2 ? fdt64_to_cpu(*(fdt64_t *)(p)) : fdt32_to_cpu(*(fdt32_t *)(p)))
#endif