Skip site navigation (1)Skip section navigation (2)
Date:      Tue, 15 Dec 2009 21:48:55 GMT
From:      Rafal Jaworowski <raj@FreeBSD.org>
To:        Perforce Change Reviews <perforce@freebsd.org>
Subject:   PERFORCE change 171811 for review
Message-ID:  <200912152148.nBFLmtDC068472@repoman.freebsd.org>

next in thread | raw e-mail | index | archive | help
http://p4web.freebsd.org/chv.cgi?CH=171811

Change 171811 by raj@raj_fdt on 2009/12/15 21:48:17

	Improve DT blob fixup handling in loader(8).
	
	- Handle 'bus-frequency' prop fixup according to ePAPR.
	
	- Provide fixup for dynamic /memory node adjustments.
	
	- Initial support for 'stdout' property in the /chosen node.

Affected files ...

.. //depot/projects/fdt/sys/boot/uboot/lib/fdt.c#2 edit

Differences ...

==== //depot/projects/fdt/sys/boot/uboot/lib/fdt.c#2 (text+ko) ====

@@ -54,6 +54,8 @@
 #define STR(number) #number
 #define STRINGIFY(number) STR(number)
 
+#define MIN(num1, num2)	(((num1) < (num2)) ? (num1):(num2))
+
 static struct fdt_header *fdtp = NULL;
 
 static int fdt_cmd_nyi(int argc, char *argv[]);
@@ -88,11 +90,6 @@
 	{ NULL, NULL }
 };
 
-/* List of possible bus node names (used to fixup bus(clock)-frequency) */
-static const char *possible_buses[] = {
-	"soc8555", "soc8572", "immr", NULL
-};
-
 static char cwd[FDT_CWD_LEN] = "/";
 static unsigned char fdt_fixup_applied = 0;
 
@@ -130,8 +127,17 @@
 	return (CMD_OK);
 }
 
+
+#define fdt_strtovect(str, cellbuf, lim, cellsize) _fdt_strtovect((str), \
+    (cellbuf), (lim), (cellsize), 0);
+
+/* Force using base 16 */
+#define fdt_strtovectx(str, cellbuf, lim, cellsize) _fdt_strtovect((str), \
+    (cellbuf), (lim), (cellsize), 16);
+
 static int
-fdt_strtovect(char *str, void *cellbuf, int lim, unsigned char cellsize)
+_fdt_strtovect(char *str, void *cellbuf, int lim, unsigned char cellsize,
+    uint8_t base)
 {
 	char *buf = str;
 	char *end = str + strlen(str) - 2;
@@ -148,14 +154,16 @@
 		return (0);
 
 	while (buf < end) {
-		/* Skip white space(s) */
-		while (!isdigit(*buf) && buf < end)
+
+		/* Skip white whitespace(s)/separators */
+		while (!isxdigit(*buf) && buf < end)
 			buf++;
 
 		if (u32buf != NULL)
-			u32buf[cnt] = (uint32_t)strtol(buf, NULL, 0);
+			u32buf[cnt] = (uint32_t)strtol(buf, NULL, base);
+
 		else
-			u8buf[cnt] = (uint8_t)strtol(buf, NULL, 0);
+			u8buf[cnt] = (uint8_t)strtol(buf, NULL, base);
 
 		if (cnt + 1 <= lim - 1)
 			cnt++;
@@ -163,7 +171,7 @@
 			break;
 		buf++;
 		/* Find another number */
-		while (isdigit(*buf) && buf < end)
+		while ((isxdigit(*buf) || *buf == 'x') && buf < end)
 			buf++;
 	}
 	return (cnt);
@@ -192,12 +200,11 @@
 	str = ub_env_get(env);
 
 	/* Convert macaddr string into a vector of uints */
-	fdt_strtovect(str, &tmp_addr, 6, sizeof(uint8_t));
+	fdt_strtovectx(str, &tmp_addr, 6, sizeof(uint8_t));
 	if (n != 0) {
 		i = strlen(env) - 7;
 		strncpy(ethstr + 8, env + 3, i);
 	}
-
 	/* Set actual property to a value from vect */
 	fdt_setprop(fdtp, fdt_path_offset(fdtp, ethstr),
 	    "local-mac-address", &tmp_addr, 6 * sizeof(uint8_t));
@@ -212,69 +219,158 @@
 void
 fixup_cpubusfreqs(unsigned long cpufreq, unsigned long busfreq)
 {
-	int i, o = 0;
-	char *curbus;
+	int lo, o = 0, o2, maxo = 0, depth;
 	const uint32_t zero = 0;
 
+	/* We want to modify every subnode of /cpus */
 	o = fdt_path_offset(fdtp, "/cpus");
 
+	/* maxo should contain offset of node next to /cpus */
+	depth = 0;
+	maxo = o;
+	while (depth != -1)
+		maxo = fdt_next_node(fdtp, maxo, &depth);
+
 	/* Find CPU frequency properties */
 	o = fdt_node_offset_by_prop_value(fdtp, o, "clock-frequency",
 	    &zero, sizeof(uint32_t));
 
-	while (o != -FDT_ERR_NOTFOUND) {
+	o2 = fdt_node_offset_by_prop_value(fdtp, o, "bus-frequency", &zero,
+	    sizeof(uint32_t));
+
+	lo = MIN(o, o2);
+
+	while (o != -FDT_ERR_NOTFOUND && o2 != -FDT_ERR_NOTFOUND) {
+
+		o = fdt_node_offset_by_prop_value(fdtp, lo,
+		    "clock-frequency", &zero, sizeof(uint32_t));
 
-		o = fdt_node_offset_by_prop_value(fdtp, o, "clock-frequency",
+		o2 = fdt_node_offset_by_prop_value(fdtp, lo, "bus-frequency",
 		    &zero, sizeof(uint32_t));
 
-		fdt_setprop_inplace_cell(fdtp, o, "clock-frequency",
+		/* We're only interested in /cpus subnode(s) */
+		if (lo > maxo)
+			break;
+
+		fdt_setprop_inplace_cell(fdtp, lo, "clock-frequency",
 		    (uint32_t)cpufreq);
+
+		fdt_setprop_inplace_cell(fdtp, lo, "bus-frequency",
+		    (uint32_t)busfreq);
+
+		lo = MIN(o, o2);
 	}
 
-	/* Find "bus" node appropriate for the board */
-	i = 0;
-	o = -1;
-	while ((curbus = (char *)possible_buses[i]) && o < 0) {
-		o = fdt_subnode_offset_namelen(fdtp, 0, curbus,
-		    strlen(curbus));
-		if (o > 0)
-			break;
-		else
-			i++;
-	}
+}
+
+void
+fixup_memory(struct sys_info *si)
+{
+	uint8_t *buf, *sb, sizesz, startsz;
+	int i, len, no, err, realmrno = 0;
+	struct mem_region *curmr;
+	const uint32_t *addrcell, *sizecell;
+
+	no = fdt_path_offset(fdtp, "/memory");
+	if (no < 0)
+		no = fdt_add_subnode(fdtp, 0, "memory");
+
+	err = fdt_setprop(fdtp, no, "device_type", "memory",
+	    sizeof("memory"));
+
+	if (err < 0)
+		return;
+
+	addrcell = fdt_getprop(fdtp, 0, "#address-cells", NULL);
+	sizecell = fdt_getprop(fdtp, 0, "#size-cells", NULL);
+
+	sizesz = (sizecell && (*sizecell == 2)) ? 8 : 4;
+	startsz = (addrcell && (*addrcell == 2)) ? 8 : 4;
+
+	/* Do not alloc memory for mr's with size and start == 0 */
+	realmrno = si->mr_no;
+	for (i = 0; i < si->mr_no; i++)
+		if (si->mr[i].start == 0 && si->mr[i].size == 0)
+			realmrno--;
+
+	len = (sizesz + startsz) * realmrno;
+	sb = buf = (uint8_t *)malloc(len);
+
+	if(!buf)
+		return;
 
-	/* Change bus-frequency/clock-frequency */
-	while (o != -FDT_ERR_NOTFOUND) {
+	bzero(buf, len);
 
-		o = fdt_node_offset_by_prop_value(fdtp, o, "clock-frequency",
-		    &zero, sizeof(uint32_t));
+	for (i = 0; i < si->mr_no; i++) {
+		curmr = &si->mr[i];
+		if (curmr->size != 0) {
+			/* Ensure endianess, and put cells into a buffer */
+			if (*addrcell == 2)
+				*((uint64_t *)buf) =
+				    cpu_to_fdt64(curmr->start);
+			else
+				*((uint32_t *)buf) =
+				    cpu_to_fdt32(curmr->start);
 
-		if (o > 0)
-			fdt_setprop_inplace_cell(fdtp, o, "clock-frequency",
-			    (uint32_t)busfreq);
-		else {
-			/*
-			 * According to ePAPR document:
-			 * The recommended practice is to represent the
-			 * frequency of a bus on the bus node using a
-			 * clock-frequency property. However, most
-			 * current DTS-es seem to be using bus-frequency
-			 * property instead of clock-frequency. Because of
-			 * that, we do the following:
-			 */
-			o = fdt_node_offset_by_prop_value(fdtp, o,
-			    "bus-frequency", &zero, sizeof(uint32_t));
+			buf += startsz;
+			if (*sizecell == 2)
+				*((uint64_t *)buf) =
+				    cpu_to_fdt64(curmr->size);
+			else
+				*((uint32_t *)buf) =
+				    cpu_to_fdt32(curmr->size);
 
-			if (o > 0)
-				fdt_setprop_inplace_cell(fdtp, o,
-				    "bus-frequency", (uint32_t)busfreq);
+			buf += sizesz;
 		}
 	}
+
+	/* Set property */
+	fdt_setprop(fdtp, no, "reg", sb, len);
 }
 
 void
-fixup_busfreq(unsigned long freq)
+fixup_stdout(const char *env)
 {
+	const char *str = ub_env_get(env);
+	char *ptr;
+	int serialno;
+	int len, no, sero;
+	const struct fdt_property *prop;
+	char *tmp[10];
+
+	ptr = (char *)str + strlen(str) - 1;
+	while (ptr > str && isdigit(*(str - 1)))
+		str--;
+
+	if (ptr == str)
+		return;
+
+	serialno = (int)strtol(ptr, NULL, 0);
+	no = fdt_path_offset(fdtp, "/chosen");
+	if (no < 0)
+		return;
+
+	prop = fdt_get_property(fdtp, no, "stdout", &len);
+	if (prop == NULL || (prop != NULL && len == 0)) {
+
+		bzero(tmp, 10 * sizeof(char));
+		strcpy((char *)&tmp, "serial");
+		if (strlen(ptr) > 3)
+			/* Serial number too long */
+			return;
+
+		strncpy((char *)tmp + 6, ptr, 3);
+		sero = fdt_path_offset(fdtp, (const char *)tmp);
+		if (sero < 0)
+			/*
+			 * If serial device we're trying to assign
+			 * stdout to doesn't exist in DT -- return.
+			 */
+			return;
+
+		fdt_setprop(fdtp, no, "stdout", &tmp,
+		    strlen((char *)&tmp) + 1);
+	}
 }
 
 int
@@ -300,6 +396,13 @@
 		}
 	}
 
+	/* Create /chosen node (if not exists) */
+	if (fdt_subnode_offset(fdtp, 0, "chosen") == -FDT_ERR_NOTFOUND)
+		fdt_add_subnode(fdtp, 0, "chosen");
+
+	/* Acquire sys_info */
+	si = ub_get_sys_info();
+
 	while ((env = ub_env_enum(env)) != NULL) {
 		if (strncmp(env, "eth", 3) == 0 &&
 		    strncmp(env + (strlen(env) - 4), "addr", 4) == 0) {
@@ -326,16 +429,16 @@
 
 			/* Modify blob */
 			fixup_ethernet(env, ethstr, &eth_no, len);
-		}
+
+		} else if (strcmp(env, "consoledev") == 0)
+			fixup_stdout(env);
 	}
 
-	si = ub_get_sys_info();
-
 	/* Modify cpu(s) and bus clock frequenties in /cpus node [Hz] */
 	fixup_cpubusfreqs(si->clk_cpu, si->clk_bus);
 
-	/* Modify other bus clock frequencies [Hz] */
-	fixup_busfreq(si->clk_bus);
+	/* Fixup memory regions */
+	fixup_memory(si);
 
 	fdt_fixup_applied = 1;
 
@@ -806,7 +909,6 @@
 		return (CMD_ERROR);
 	}
 	len = strlen(value);
-
 	rv = 0;
 	buf = (char *)value;
 
@@ -819,7 +921,7 @@
 		len = fdt_strtovect(buf, (void *)&cells, 100,
 		    sizeof(uint32_t));
 
-		fdt_setprop(fdtp, nodeoff, propname, &cells,
+		rv = fdt_setprop(fdtp, nodeoff, propname, &cells,
 		    len * sizeof(uint32_t));
 		break;
 	case '[':
@@ -827,7 +929,7 @@
 		len = fdt_strtovect(buf, (void *)&cells, 100,
 		    sizeof(uint8_t));
 
-		fdt_setprop(fdtp, nodeoff, propname, &cells,
+		rv = fdt_setprop(fdtp, nodeoff, propname, &cells,
 		    len * sizeof(uint8_t));
 		break;
 	case '"':



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?200912152148.nBFLmtDC068472>