diff options
| author | Kimplul <kimi.h.kuparinen@gmail.com> | 2023-05-29 21:31:09 +0300 |
|---|---|---|
| committer | Kimplul <kimi.h.kuparinen@gmail.com> | 2023-05-29 21:31:09 +0300 |
| commit | 3ace1ddd76b9c04f3ed23883de6279b4485612e8 (patch) | |
| tree | 2f4af69d70967c2455cb83d8c18a5416c8d1b54d /common | |
| parent | b7f53b9a9001708dea5303faf52f1b508eefb712 (diff) | |
| download | kmi-3ace1ddd76b9c04f3ed23883de6279b4485612e8.tar.gz kmi-3ace1ddd76b9c04f3ed23883de6279b4485612e8.zip | |
start trying to boot on visionfive 2
+ Not bootable quite yet. Among other things, I couldn't
get the current starfive u-boot fork to boot, so
try adding support for booting with precompiled u-boot
via the `go` command. Initial testing with qemu shows that
this should be possible, and if it works, might be useful
in the (far) future with other slightly janky SBCs.
Also, NS16550 is 8250-based, and I'm really only using the base
8250, so rename and add visionfive 2 uart to list of compatibles.
Visionfive 2 is still completely untested.
Diffstat (limited to 'common')
| -rw-r--r-- | common/debug.c | 25 | ||||
| -rw-r--r-- | common/pmem.c | 2 | ||||
| -rw-r--r-- | common/string.c | 136 |
3 files changed, 155 insertions, 8 deletions
diff --git a/common/debug.c b/common/debug.c index 1bc87f7..2cd4570 100644 --- a/common/debug.c +++ b/common/debug.c @@ -59,8 +59,8 @@ vm_t map_io_dbg(struct vmem *b) * try to implement some kind of basic driver subsystem, but this is good enough * for now. */ -/** NS16550A and compatible serial drivers. */ -struct __packed ns16550a { +/** 8250 and compatible serial drivers. */ +struct __packed uart_8250 { /** Receiver buffer/transmitter holding register. */ uint8_t data; @@ -111,10 +111,10 @@ struct __packed ns16550a { #define LSR_ERR (1 << 7) /** - * Address of ns16550a port. If other serial drivers are added, this should - * maybe be made a void *. + * Address of generic 8250 port. If other serial drivers are added, this should + * maybe be made a void *. No support for quirks at the moment. */ -static struct ns16550a *port = 0; +static struct uart_8250 *port = 0; /** * Serial transmitter empty. @@ -150,8 +150,17 @@ static void __putchar(char c) */ static enum serial_dev __serial_dev_enum(const char *dev_name) { + /* qemu, for example */ if (strncmp("ns16550", dev_name, 7) == 0) - return NS16550A; + return UART_8250; + + /* mentioned in dtc documentation as an example */ + if (strncmp("ns8250", dev_name, 7) == 0) + return UART_8250; + + /* starfive visionfive 2, for example (hopefully works) */ + if (strncmp("snps,dw-apb-uart", dev_name, 16) == 0) + return UART_8250; return -1; } @@ -194,8 +203,8 @@ static struct dbg_info __dbg_from_fdt(const void *fdt) void __setup_dbg(vm_t pt, enum serial_dev dev) { switch (dev) { - case NS16550A: - port = (struct ns16550a *)pt; + case UART_8250: + port = (struct uart_8250 *)pt; break; } diff --git a/common/pmem.c b/common/pmem.c index 22a1493..c817c5a 100644 --- a/common/pmem.c +++ b/common/pmem.c @@ -612,6 +612,8 @@ void init_pmem(void *fdt) pm_t ram_size = __get_ramtop(fdt) - get_ram_base(); pm_t ram_base = (pm_t)__va(get_ram_base()); + /** @todo could probably improve error messages on failing to get fdt + * values */ pm_t initrd_top = get_initrdtop(fdt); pm_t fdt_top = __get_fdttop(fdt); diff --git a/common/string.c b/common/string.c index 6685c08..a76c875 100644 --- a/common/string.c +++ b/common/string.c @@ -324,3 +324,139 @@ __weak int memcmp(const void *ptr1, const void *ptr2, size_t num) return (int)(p1[-1] - p2[-1]); } + +/** + * Convert ASCII hex character to integer. + * Allows both upper- and lowercase letters. + * + * @param c Character to convert. + * @return Corresponding integer value. That is, '1' => 1, '2' => 2, etc. + * \c -1 if conversion failed. + */ +static int __hexval(char c) +{ + if (c >= '0' && c <= '9') + return c - '0'; + + if (c >= 'a' && c <= 'f') + return c - 'a'; + + if (c >= 'A' && c <= 'F') + return c - 'A'; + + return -1; +} + +/** + * Convert string assumed to represent hex + * value to corresponding pointer. + * + * @param s String to convert to value. + * @return Corresponding pointer value. + */ +static uintptr_t __hexuintptr(const char *s) +{ + uintptr_t res = 0; + int val = 0; + while ((val = __hexval(*(s++))) != -1) { + res *= 16; + res += val; + } + + return res; +} + +/** + * Convert ASCII decimal character to integer. + * + * @param c Character to convert. + * @return Corresponding integer value. That is, '1' => 1, '2' => 2, etc. + * \c -1 if conversion failed. + */ +static int __decval(char c) +{ + if (c >= '0' && c <= '9') + return c - '0'; + + return -1; +} + +/** + * Convert string assumed to represent decimal + * value to corresponding pointer. + * + * @param s String to convert to value. + * @return Corresponding pointer value. + */ +static uintptr_t __decuintptr(const char *s) +{ + uintptr_t res = 0; + int val = 0; + while ((val = __decval(*(s++))) != -1) { + res *= 10; + res += val; + } + + return res; +} + +/** + * Convert ASCII octal character to integer. + * + * @param c Character to convert. + * @return Corresponding integer value. That is, '1' => 1, '2' => 2, etc. + * \c -1 if conversion failed. + */ +static int __octval(char c) +{ + if (c >= '0' && c <= '7') + return c - '0'; + + return -1; +} + +/** + * Convert string assumed to represent octal + * value to corresponding pointer. + * + * @param s String to convert to value. + * @return Corresponding pointer value. + */ +static uintptr_t __octuintptr(const char *s) +{ + uintptr_t res = 0; + int val = 0; + while ((val = __octval(*(s++))) != -1) { + res *= 8; + res += val; + } + + return res; +} + +uintptr_t strtouintptr(const char *s) +{ + if (!s) + return 0; + + if (s[0] == 0) + return 0; + + if (s[0] == '0') { + if (s[1] == 0) + return 0; + + if (s[1] == 'x' || s[1] == 'X') + return __hexuintptr(s + 2); + + return __octuintptr(s + 1); + } + + if (s[0] == '-') + return -__decuintptr(s + 1); + + if (s[0] == '+') + return __decuintptr(s + 1); + + return __decuintptr(s); +} |
