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, ð_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>