aboutsummaryrefslogtreecommitdiff
path: root/common
diff options
context:
space:
mode:
Diffstat (limited to 'common')
-rw-r--r--common/debug.c25
-rw-r--r--common/pmem.c2
-rw-r--r--common/string.c136
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);
+}