Index: /usr/src/stand/powerpc/ofw/ofwfdt.c =================================================================== --- /usr/src/stand/powerpc/ofw/ofwfdt.c (revision 345758) +++ /usr/src/stand/powerpc/ofw/ofwfdt.c (working copy) @@ -42,22 +42,54 @@ } static void -add_node_to_fdt(void *buffer, phandle_t node, int fdt_offset) +add_node_to_fdt(void *buffer, phandle_t parent_node, int fdt_offset) { int i, child_offset, error; - char name[255], *lastprop, *subname; + char name[255+1], *lastprop, *subname; // +1 added for always having a trailing '\0' position. void *propbuf; ssize_t proplen; - lastprop = NULL; - while (OF_nextprop(node, lastprop, name) > 0) { - proplen = OF_getproplen(node, name); + // WARNING: fdt_setprop adds to the beginning of the property sequence. So, + // to avoid reversing the sequence, use it last to first for the originals. + int prop_cnt= 0; + lastprop= NULL; + while (0 1024) + } + if (proplen > 1024) { + printf("proplen was large: %jd while adding property %s to " + "parent_node %d\n", (intmax_t)proplen, name, fdt_offset); +#if 0 +// WARNING: Some Macintoshes end up with video-card driver code as properties. +// An example PowerMac7,2 configuration had 2 such properties, each +// being 96306 bytes in size. If these were ever used in a truncated +// from things would be messed up. So do not force truncations. There +// are a few other, smaller properties that bigger than 1 KBytes. I +// checked: fdt_platform_load_dtb's 409600 buflen is more than +// sufficient for the example context. + proplen = 1024; +#endif + } propbuf = malloc(proplen); if (propbuf == NULL) { @@ -64,31 +96,99 @@ printf("Cannot allocate memory for prop %s\n", name); return; } - OF_getprop(node, name, propbuf, proplen); + OF_getprop(parent_node, name, propbuf, proplen); error = fdt_setprop(buffer, fdt_offset, name, propbuf, proplen); free(propbuf); - lastprop = name; if (error) printf("Error %d adding property %s to " - "node %d\n", error, name, fdt_offset); + "parent_node %d\n", error, name, fdt_offset); } - if (!OF_hasprop(node, "phandle") && !OF_hasprop(node, "linux,phandle") - && !OF_hasprop(node, "ibm,phandle")) - fdt_setprop(buffer, fdt_offset, "phandle", &node, sizeof(node)); + if (!OF_hasprop(parent_node, "phandle") && !OF_hasprop(parent_node, "linux,phandle") + && !OF_hasprop(parent_node, "ibm,phandle")) + fdt_setprop(buffer, fdt_offset, "phandle", &parent_node, sizeof(parent_node)); - for (node = OF_child(node); node > 0; node = OF_peer(node)) { - OF_package_to_path(node, name, sizeof(name)); - subname = strrchr(name, '/'); + // WARNING: fdt_add_subnode adds to the beginning of the node sequence (after + // the properties). So, to avoid reversing the sequence, use it last to first + // for the originals. + + // WARNING: openfirmware's package-to-path(nd,nm,len) does not place a trailing '\0' + // character in nm when it returns a full_str_len with len<=full_str_len . + // For full_str_len 0) fdt_delprop(fdtp, offset, "available"); +#endif } @@ -182,19 +297,40 @@ int fdt_platform_load_dtb(void) { - void *buffer; - size_t buflen = 409600; + void *buffer; + size_t buflen = 409600; + int ret; - buffer = malloc(buflen); - fdt_create_empty_tree(buffer, buflen); - add_node_to_fdt(buffer, OF_peer(0), fdt_path_offset(buffer, "/")); - ofwfdt_fixups(buffer); - fdt_pack(buffer); + buffer = malloc(buflen); + if (NULL==buffer) { + printf("fdt_platform_load_dtb: Large buffer malloc failed.\n"); + return 1; // Give up. + } - fdt_load_dtb_addr(buffer); - free(buffer); + ret= fdt_create_empty_tree(buffer, buflen); + if (ret) { + printf("fdt_platform_load_dtb: fdt_create_empty_tree failed\n"); + goto cleanup_and_return; + } - return (0); + add_node_to_fdt(buffer, OF_peer(0), fdt_path_offset(buffer, "/")); + ofwfdt_fixups(buffer); + + ret= fdt_pack(buffer); + if (ret) { + printf("fdt_platform_load_dtb: fdt_pack failed\n"); + goto cleanup_and_return; + } + + ret= fdt_load_dtb_addr(buffer); + if (ret) { + printf("fdt_platform_load_dtb: fdt_load_dtb_addr failed\n"); + goto cleanup_and_return; + } + +cleanup_and_return: + free(buffer); + return ret; } void Index: /usr/src/sys/contrib/libfdt/fdt_rw.c =================================================================== --- /usr/src/sys/contrib/libfdt/fdt_rw.c (revision 345758) +++ /usr/src/sys/contrib/libfdt/fdt_rw.c (working copy) @@ -358,7 +358,14 @@ offset = fdt_subnode_offset_namelen(fdt, parentoffset, name, namelen); if (offset >= 0) +#if 0 +// Some Macintoshes have identical package-to-pathname results for +// multiple nodes of the same type and unit under the parent node. +// Avoid blocking this for fdt. return -FDT_ERR_EXISTS; +#else + ; +#endif else if (offset != -FDT_ERR_NOTFOUND) return offset;