PERFORCE change 171811 for review
Rafal Jaworowski
raj at FreeBSD.org
Tue Dec 15 13:48:56 PST 2009
http://p4web.freebsd.org/chv.cgi?CH=171811
Change 171811 by raj at 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, ð_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 '"':
More information about the p4-projects
mailing list