[coreboot-gerrit] Patch set updated for coreboot: riscv: bring in the configstring parsing functions from UCB

Ronald G. Minnich (rminnich@gmail.com) gerrit at coreboot.org
Mon Nov 7 16:52:36 CET 2016


Ronald G. Minnich (rminnich at gmail.com) just uploaded a new patch set to gerrit, which you can find at https://review.coreboot.org/17255

-gerrit

commit cf30fad5069648e8bb7f7e5b313b98f39c9d5956
Author: Ronald G. Minnich <rminnich at gmail.com>
Date:   Sun Nov 6 20:51:18 2016 -0800

    riscv: bring in the configstring parsing functions from UCB
    
    I've tested this with commits to come later.
    
    This is from the lowrisc bbl distribution, 87588c4,
    with fixes so it builds.
    
    Change-Id: I87893638872259c94d6972e1971578b633155e7e
    Signed-off-by: Ronald G. Minnich <rminnich at gmail.com>
---
 src/commonlib/configstring.c                   |  54 +++++++
 src/commonlib/include/commonlib/configstring.h | 209 +++++++++++++++++++++++++
 2 files changed, 263 insertions(+)

diff --git a/src/commonlib/configstring.c b/src/commonlib/configstring.c
new file mode 100644
index 0000000..40beb16
--- /dev/null
+++ b/src/commonlib/configstring.c
@@ -0,0 +1,54 @@
+/*
+ * Copyright (c) 2013-2016, The Regents of the University of California
+ *(Regents).
+ * All Rights Reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the Regents nor the
+ *    names of its contributors may be used to endorse or promote products
+ *    derived from this software without specific prior written permission.
+ *
+ * IN NO EVENT SHALL REGENTS BE LIABLE TO ANY PARTY FOR DIRECT, INDIRECT,
+ * SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES, INCLUDING LOST PROFITS,
+ * ARISING
+ * OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF REGENTS HAS
+ * BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * REGENTS SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE. THE SOFTWARE AND ACCOMPANYING DOCUMENTATION, IF ANY, PROVIDED
+ * HEREUNDER IS PROVIDED "AS IS". REGENTS HAS NO OBLIGATION TO PROVIDE
+ * MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
+ */
+
+#include <config.h>
+#include <assert.h>
+#include <string.h>
+#include <commonlib/configstring.h>
+
+void query_mem(const char *config_string, uintptr_t *base, size_t *size)
+{
+	query_result res = query_config_string(config_string, "ram{0{addr");
+	*base = get_uint(res);
+	res = query_config_string(config_string, "ram{0{size");
+	*size = get_uint(res);
+}
+
+/* query_rtc returns the physical address of the rtc. */
+void query_rtc(const char *config_string, uintptr_t *mtime)
+{
+	query_result res = query_config_string(config_string, "rtc{addr");
+	*mtime = (uintptr_t)get_uint(res);
+}
+
+const char *configstring(void)
+{
+	uint32_t addr = *(uint32_t *)CONFIG_ARCH_CONFIGSTRING_RISCV;
+	return (const char *)(uintptr_t)addr;
+}
diff --git a/src/commonlib/include/commonlib/configstring.h b/src/commonlib/include/commonlib/configstring.h
new file mode 100644
index 0000000..8aacbda
--- /dev/null
+++ b/src/commonlib/include/commonlib/configstring.h
@@ -0,0 +1,209 @@
+/*
+ * Copyright (c) 2013-2016, The Regents of the University of California
+ *(Regents).
+ * All Rights Reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the Regents nor the
+ *    names of its contributors may be used to endorse or promote products
+ *    derived from this software without specific prior written permission.
+ *
+ * IN NO EVENT SHALL REGENTS BE LIABLE TO ANY PARTY FOR DIRECT, INDIRECT,
+ * SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES, INCLUDING LOST PROFITS,
+ * ARISING
+ * OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF REGENTS HAS
+ * BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * REGENTS SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE. THE SOFTWARE AND ACCOMPANYING DOCUMENTATION, IF ANY, PROVIDED
+ * HEREUNDER IS PROVIDED "AS IS". REGENTS HAS NO OBLIGATION TO PROVIDE
+ * MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
+ */
+
+#ifndef RISCV_CONFIG_STRING_H
+#define RISCV_CONFIG_STRING_H
+
+#include <stddef.h>
+#include <stdint.h>
+
+static const char *skip_whitespace(const char *str)
+{
+	while (*str && *str <= ' ')
+		str++;
+	return str;
+}
+
+static const char *skip_string(const char *str)
+{
+	while (*str && *str++ != '"')
+		;
+	return str;
+}
+
+static int is_hex(char ch)
+{
+	return (ch >= '0' && ch <= '9') || (ch >= 'a' && ch <= 'f') ||
+	       (ch >= 'A' && ch <= 'F');
+}
+
+static int parse_hex(char ch)
+{
+	return (ch >= '0' && ch <= '9') ? ch - '0' : (ch >= 'a' && ch <= 'f')
+							 ? ch - 'a' + 10
+							 : ch - 'A' + 10;
+}
+
+static const char *skip_key(const char *str)
+{
+	while (*str >= 35 && *str <= 122 && *str != ';')
+		str++;
+	return str;
+}
+
+typedef struct {
+	const char *start;
+	const char *end;
+} query_result;
+
+static inline query_result query_config_string(const char *str, const char *k)
+{
+	size_t ksize = 0;
+	while (k[ksize] && k[ksize] != '{')
+		ksize++;
+	int last = !k[ksize];
+
+	query_result res = {0, 0};
+	while (1) {
+		const char *key_start = str = skip_whitespace(str);
+		const char *key_end = str = skip_key(str);
+		int match = (size_t)(key_end - key_start) == ksize;
+		if (match)
+			for (size_t i = 0; i < ksize; i++)
+				if (key_start[i] != k[i])
+					match = 0;
+		const char *value_start = str = skip_whitespace(str);
+		while (*str != ';') {
+			if (!*str) {
+				return res;
+			} else if (*str == '"') {
+				str = skip_string(str + 1);
+			} else if (*str == '{') {
+				const char *search_key =
+				    match && !last ? k + ksize + 1 : "";
+				query_result inner_res =
+				    query_config_string(str + 1, search_key);
+				if (inner_res.start)
+					return inner_res;
+				str = inner_res.end + 1;
+			} else {
+				str = skip_key(str);
+			}
+			str = skip_whitespace(str);
+		}
+		res.end = str;
+		if (match && last) {
+			res.start = value_start;
+			return res;
+		}
+		str = skip_whitespace(str + 1);
+		if (*str == '}') {
+			res.end = str;
+			return res;
+		}
+	}
+}
+
+static void parse_string(query_result r, char *buf)
+{
+	if (r.start < r.end) {
+		if (*r.start == '"') {
+			for (const char *p = r.start + 1;
+			     p < r.end && *p != '"'; p++) {
+				char ch = p[0];
+				if (ch == '\\' && p[1] == 'x' && is_hex(p[2])) {
+					ch = parse_hex(p[2]);
+					if (is_hex(p[3])) {
+						ch =
+						    (ch << 4) + parse_hex(p[3]);
+						p++;
+					}
+					p += 2;
+				}
+				*buf++ = ch;
+			}
+		} else {
+			for (const char *p = r.start; p < r.end && *p > ' ';
+			     p++)
+				*buf++ = *p;
+		}
+	}
+	*buf = 0;
+}
+
+static uint64_t __get_uint_hex(const char *s)
+{
+	uint64_t res = 0;
+	while (*s) {
+		if (is_hex(*s))
+			res = (res << 4) + parse_hex(*s);
+		else if (*s != '_')
+			break;
+		s++;
+	}
+	return res;
+}
+
+static uint64_t __get_uint_dec(const char *s)
+{
+	uint64_t res = 0;
+	while (*s) {
+		if (*s >= '0' && *s <= '9')
+			res = res * 10 + (*s - '0');
+		else
+			break;
+		s++;
+	}
+	return res;
+}
+
+static uint64_t __get_uint(const char *s)
+{
+	if (s[0] == '0' && s[1] == 'x')
+		return __get_uint_hex(s + 2);
+	return __get_uint_dec(s);
+}
+
+// This is nasty. But the original code used a much nastier thing,
+// an array declared as an automatic, which triggered gcc warnings
+// as it was sized by the res.end - res.start. We'll need a better
+// solution, long term. Malloc is probably not it.
+static char name[1024];
+static inline uint64_t get_uint(query_result res)
+{
+	uint64_t v;
+	parse_string(res, name);
+	v = __get_uint(name);
+	return v;
+}
+
+static inline int64_t get_sint(query_result res)
+{
+	int64_t v;
+	parse_string(res, name);
+	if (name[0] == '-')
+		return -__get_uint(name + 1);
+	v = __get_uint(name);
+	return v;
+}
+
+const char *configstring(void);
+void query_mem(const char *config_string, uintptr_t *base, size_t *size);
+void query_rtc(const char *config_string, uintptr_t *mtime);
+#endif



More information about the coreboot-gerrit mailing list