diff options
-rw-r--r-- | common/cmd_fdt.c | 186 | ||||
-rw-r--r-- | common/image.c | 46 | ||||
-rw-r--r-- | include/image.h | 4 | ||||
-rw-r--r-- | include/libfdt.h | 275 | ||||
-rw-r--r-- | lib/libfdt/Makefile | 2 | ||||
-rw-r--r-- | lib/libfdt/fdt_empty_tree.c | 84 | ||||
-rw-r--r-- | lib/libfdt/fdt_rw.c | 27 |
7 files changed, 592 insertions, 32 deletions
diff --git a/common/cmd_fdt.c b/common/cmd_fdt.c index e2225c4..a5e2cfc 100644 --- a/common/cmd_fdt.c +++ b/common/cmd_fdt.c @@ -35,6 +35,9 @@ #define MAX_LEVEL 32 /* how deeply nested we will go */ #define SCRATCHPAD 1024 /* bytes of scratchpad memory */ +#ifndef CONFIG_CMD_FDT_MAX_DUMP +#define CONFIG_CMD_FDT_MAX_DUMP 64 +#endif /* * Global data (for the gd->bd) @@ -44,6 +47,7 @@ DECLARE_GLOBAL_DATA_PTR; static int fdt_valid(void); static int fdt_parse_prop(char *const*newval, int count, char *data, int *len); static int fdt_print(const char *pathp, char *prop, int depth); +static int is_printable_string(const void *data, int len); /* * The working_fdt points to our working flattened device tree. @@ -61,6 +65,34 @@ void set_working_fdt_addr(void *addr) } /* + * Get a value from the fdt and format it to be set in the environment + */ +static int fdt_value_setenv(const void *nodep, int len, const char *var) +{ + if (is_printable_string(nodep, len)) + setenv(var, (void *)nodep); + else if (len == 4) { + char buf[11]; + + sprintf(buf, "0x%08X", *(uint32_t *)nodep); + setenv(var, buf); + } else if (len%4 == 0 && len <= 20) { + /* Needed to print things like sha1 hashes. */ + char buf[41]; + int i; + + for (i = 0; i < len; i += sizeof(unsigned int)) + sprintf(buf + (i * 2), "%08x", + *(unsigned int *)(nodep + i)); + setenv(var, buf); + } else { + printf("error: unprintable value\n"); + return 1; + } + return 0; +} + +/* * Flattened Device Tree command, see the help for parameter definitions. */ int do_fdt (cmd_tbl_t * cmdtp, int flag, int argc, char * const argv[]) @@ -250,6 +282,117 @@ int do_fdt (cmd_tbl_t * cmdtp, int flag, int argc, char * const argv[]) return 1; } + /******************************************************************** + * Get the value of a property in the working_fdt. + ********************************************************************/ + } else if (argv[1][0] == 'g') { + char *subcmd; /* sub-command */ + char *pathp; /* path */ + char *prop; /* property */ + char *var; /* variable to store result */ + int nodeoffset; /* node offset from libfdt */ + const void *nodep; /* property node pointer */ + int len = 0; /* new length of the property */ + + /* + * Parameters: Node path, property, optional value. + */ + if (argc < 5) + return CMD_RET_USAGE; + + subcmd = argv[2]; + + if (argc < 6 && subcmd[0] != 's') + return CMD_RET_USAGE; + + var = argv[3]; + pathp = argv[4]; + prop = argv[5]; + + nodeoffset = fdt_path_offset(working_fdt, pathp); + if (nodeoffset < 0) { + /* + * Not found or something else bad happened. + */ + printf("libfdt fdt_path_offset() returned %s\n", + fdt_strerror(nodeoffset)); + return 1; + } + + if (subcmd[0] == 'n' || (subcmd[0] == 's' && argc == 5)) { + int reqIndex = -1; + int startDepth = fdt_node_depth( + working_fdt, nodeoffset); + int curDepth = startDepth; + int curIndex = -1; + int nextNodeOffset = fdt_next_node( + working_fdt, nodeoffset, &curDepth); + + if (subcmd[0] == 'n') + reqIndex = simple_strtoul(argv[5], NULL, 16); + + while (curDepth > startDepth) { + if (curDepth == startDepth + 1) + curIndex++; + if (subcmd[0] == 'n' && curIndex == reqIndex) { + const char *nodeName = fdt_get_name( + working_fdt, nextNodeOffset, NULL); + + setenv(var, (char *)nodeName); + return 0; + } + nextNodeOffset = fdt_next_node( + working_fdt, nextNodeOffset, &curDepth); + if (nextNodeOffset < 0) + break; + } + if (subcmd[0] == 's') { + /* get the num nodes at this level */ + char buf[11]; + + sprintf(buf, "%d", curIndex + 1); + setenv(var, buf); + } else { + /* node index not found */ + printf("libfdt node not found\n"); + return 1; + } + } else { + nodep = fdt_getprop( + working_fdt, nodeoffset, prop, &len); + if (len == 0) { + /* no property value */ + setenv(var, ""); + return 0; + } else if (len > 0) { + if (subcmd[0] == 'v') { + int ret; + + ret = fdt_value_setenv(nodep, len, var); + if (ret != 0) + return ret; + } else if (subcmd[0] == 'a') { + /* Get address */ + char buf[11]; + + sprintf(buf, "0x%08X", (uint32_t)nodep); + setenv(var, buf); + } else if (subcmd[0] == 's') { + /* Get size */ + char buf[11]; + + sprintf(buf, "0x%08X", len); + setenv(var, buf); + } else + return CMD_RET_USAGE; + return 0; + } else { + printf("libfdt fdt_getprop(): %s\n", + fdt_strerror(len)); + return 1; + } + } + /* * Print (recursive) / List (single level) */ @@ -611,12 +754,12 @@ static int is_printable_string(const void *data, int len) if (len == 0) return 0; - /* must terminate with zero */ - if (s[len - 1] != '\0') + /* must terminate with zero or '\n' */ + if (s[len - 1] != '\0' && s[len - 1] != '\n') return 0; /* printable or a null byte (concatenated strings) */ - while (((*s == '\0') || isprint(*s)) && (len > 0)) { + while (((*s == '\0') || isprint(*s) || isspace(*s)) && (len > 0)) { /* * If we see a null, there are three possibilities: * 1) If len == 1, it is the end of the string, printable @@ -672,19 +815,28 @@ static void print_data(const void *data, int len) } if ((len %4) == 0) { - const u32 *p; - - printf("<"); - for (j = 0, p = data; j < len/4; j ++) - printf("0x%x%s", fdt32_to_cpu(p[j]), j < (len/4 - 1) ? " " : ""); - printf(">"); + if (len > CONFIG_CMD_FDT_MAX_DUMP) + printf("* 0x%08x [0x%08x]", (unsigned int)data, len); + else { + const u32 *p; + + printf("<"); + for (j = 0, p = data; j < len/4; j++) + printf("0x%08x%s", fdt32_to_cpu(p[j]), + j < (len/4 - 1) ? " " : ""); + printf(">"); + } } else { /* anything else... hexdump */ - const u8 *s; - - printf("["); - for (j = 0, s = data; j < len; j++) - printf("%02x%s", s[j], j < len - 1 ? " " : ""); - printf("]"); + if (len > CONFIG_CMD_FDT_MAX_DUMP) + printf("* 0x%08x [0x%08x]", (unsigned int)data, len); + else { + const u8 *s; + + printf("["); + for (j = 0, s = data; j < len; j++) + printf("%02x%s", s[j], j < len - 1 ? " " : ""); + printf("]"); + } } } @@ -824,6 +976,10 @@ U_BOOT_CMD( "fdt resize - Resize fdt to size + padding to 4k addr\n" "fdt print <path> [<prop>] - Recursive print starting at <path>\n" "fdt list <path> [<prop>] - Print one level starting at <path>\n" + "fdt get value <var> <path> <prop> - Get <property> and store in <var>\n" + "fdt get name <var> <path> <index> - Get name of node <index> and store in <var>\n" + "fdt get addr <var> <path> <prop> - Get start address of <property> and store in <var>\n" + "fdt get size <var> <path> [<prop>] - Get size of [<property>] or num nodes and store in <var>\n" "fdt set <path> <prop> [<val>] - Set <property> [to <val>]\n" "fdt mknode <path> <node> - Create a new node after <path>\n" "fdt rm <path> [<prop>] - Delete the node or <property>\n" diff --git a/common/image.c b/common/image.c index f084d2b..750a98b 100644 --- a/common/image.c +++ b/common/image.c @@ -2496,6 +2496,36 @@ int fit_image_hash_get_value(const void *fit, int noffset, uint8_t **value, return 0; } +#ifndef USE_HOSTCC +/** + * fit_image_hash_get_ignore - get hash ignore flag + * @fit: pointer to the FIT format image header + * @noffset: hash node offset + * @ignore: pointer to an int, will hold hash ignore flag + * + * fit_image_hash_get_ignore() finds hash ignore property in a given hash node. + * If the property is found and non-zero, the hash algorithm is not verified by + * u-boot automatically. + * + * returns: + * 0, on ignore not found + * value, on ignore found + */ +int fit_image_hash_get_ignore(const void *fit, int noffset, int *ignore) +{ + int len; + int *value; + + value = (int *)fdt_getprop(fit, noffset, FIT_IGNORE_PROP, &len); + if (value == NULL || len != sizeof(int)) + *ignore = 0; + else + *ignore = *value; + + return 0; +} +#endif + /** * fit_set_timestamp - set node timestamp property * @fit: pointer to the FIT format image header @@ -2759,6 +2789,9 @@ int fit_image_check_hashes(const void *fit, int image_noffset) char *algo; uint8_t *fit_value; int fit_value_len; +#ifndef USE_HOSTCC + int ignore; +#endif uint8_t value[FIT_MAX_HASH_LEN]; int value_len; int noffset; @@ -2795,6 +2828,14 @@ int fit_image_check_hashes(const void *fit, int image_noffset) } printf("%s", algo); +#ifndef USE_HOSTCC + fit_image_hash_get_ignore(fit, noffset, &ignore); + if (ignore) { + printf("-skipped "); + continue; + } +#endif + if (fit_image_hash_get_value(fit, noffset, &fit_value, &fit_value_len)) { err_msg = " error!\nCan't get hash value " @@ -2820,6 +2861,11 @@ int fit_image_check_hashes(const void *fit, int image_noffset) } } + if (noffset == -FDT_ERR_TRUNCATED || noffset == -FDT_ERR_BADSTRUCTURE) { + err_msg = " error!\nCorrupted or truncated tree"; + goto error; + } + return 1; error: diff --git a/include/image.h b/include/image.h index e5f6649..4e5863f 100644 --- a/include/image.h +++ b/include/image.h @@ -511,6 +511,7 @@ static inline int image_check_target_arch(const image_header_t *hdr) #define FIT_HASH_NODENAME "hash" #define FIT_ALGO_PROP "algo" #define FIT_VALUE_PROP "value" +#define FIT_IGNORE_PROP "uboot-ignore" /* image node */ #define FIT_DATA_PROP "data" @@ -595,6 +596,9 @@ int fit_image_get_data(const void *fit, int noffset, int fit_image_hash_get_algo(const void *fit, int noffset, char **algo); int fit_image_hash_get_value(const void *fit, int noffset, uint8_t **value, int *value_len); +#ifndef USE_HOSTCC +int fit_image_hash_get_ignore(const void *fit, int noffset, int *ignore); +#endif int fit_set_timestamp(void *fit, int noffset, time_t timestamp); int fit_set_hashes(void *fit); diff --git a/include/libfdt.h b/include/libfdt.h index de82ed5..c93ae28 100644 --- a/include/libfdt.h +++ b/include/libfdt.h @@ -852,17 +852,17 @@ int fdt_setprop_inplace(void *fdt, int nodeoffset, const char *name, const void *val, int len); /** - * fdt_setprop_inplace_cell - change the value of a single-cell property + * fdt_setprop_inplace_u32 - change the value of a 32-bit integer property * @fdt: pointer to the device tree blob * @nodeoffset: offset of the node whose property to change * @name: name of the property to change - * @val: cell (32-bit integer) value to replace the property with + * @val: 32-bit integer value to replace the property with * - * fdt_setprop_inplace_cell() replaces the value of a given property - * with the 32-bit integer cell value in val, converting val to - * big-endian if necessary. This function cannot change the size of a - * property, and so will only work if the property already exists and - * has length 4. + * fdt_setprop_inplace_u32() replaces the value of a given property + * with the 32-bit integer value in val, converting val to big-endian + * if necessary. This function cannot change the size of a property, + * and so will only work if the property already exists and has length + * 4. * * This function will alter only the bytes in the blob which contain * the given property value, and will not alter or move any other part @@ -871,7 +871,7 @@ int fdt_setprop_inplace(void *fdt, int nodeoffset, const char *name, * returns: * 0, on success * -FDT_ERR_NOSPACE, if the property's length is not equal to 4 - * -FDT_ERR_NOTFOUND, node does not have the named property + * -FDT_ERR_NOTFOUND, node does not have the named property * -FDT_ERR_BADOFFSET, nodeoffset did not point to FDT_BEGIN_NODE tag * -FDT_ERR_BADMAGIC, * -FDT_ERR_BADVERSION, @@ -879,14 +879,60 @@ int fdt_setprop_inplace(void *fdt, int nodeoffset, const char *name, * -FDT_ERR_BADSTRUCTURE, * -FDT_ERR_TRUNCATED, standard meanings */ -static inline int fdt_setprop_inplace_cell(void *fdt, int nodeoffset, - const char *name, uint32_t val) +static inline int fdt_setprop_inplace_u32(void *fdt, int nodeoffset, + const char *name, uint32_t val) { val = cpu_to_fdt32(val); return fdt_setprop_inplace(fdt, nodeoffset, name, &val, sizeof(val)); } /** + * fdt_setprop_inplace_u64 - change the value of a 64-bit integer property + * @fdt: pointer to the device tree blob + * @nodeoffset: offset of the node whose property to change + * @name: name of the property to change + * @val: 64-bit integer value to replace the property with + * + * fdt_setprop_inplace_u64() replaces the value of a given property + * with the 64-bit integer value in val, converting val to big-endian + * if necessary. This function cannot change the size of a property, + * and so will only work if the property already exists and has length + * 8. + * + * This function will alter only the bytes in the blob which contain + * the given property value, and will not alter or move any other part + * of the tree. + * + * returns: + * 0, on success + * -FDT_ERR_NOSPACE, if the property's length is not equal to 8 + * -FDT_ERR_NOTFOUND, node does not have the named property + * -FDT_ERR_BADOFFSET, nodeoffset did not point to FDT_BEGIN_NODE tag + * -FDT_ERR_BADMAGIC, + * -FDT_ERR_BADVERSION, + * -FDT_ERR_BADSTATE, + * -FDT_ERR_BADSTRUCTURE, + * -FDT_ERR_TRUNCATED, standard meanings + */ +static inline int fdt_setprop_inplace_u64(void *fdt, int nodeoffset, + const char *name, uint64_t val) +{ + val = cpu_to_fdt64(val); + return fdt_setprop_inplace(fdt, nodeoffset, name, &val, sizeof(val)); +} + +/** + * fdt_setprop_inplace_cell - change the value of a single-cell property + * + * This is an alternative name for fdt_setprop_inplace_u32() + */ +static inline int fdt_setprop_inplace_cell(void *fdt, int nodeoffset, + const char *name, uint32_t val) +{ + return fdt_setprop_inplace_u32(fdt, nodeoffset, name, val); +} + +/** * fdt_nop_property - replace a property with nop tags * @fdt: pointer to the device tree blob * @nodeoffset: offset of the node whose property to nop @@ -945,11 +991,20 @@ int fdt_add_reservemap_entry(void *fdt, uint64_t addr, uint64_t size); int fdt_finish_reservemap(void *fdt); int fdt_begin_node(void *fdt, const char *name); int fdt_property(void *fdt, const char *name, const void *val, int len); -static inline int fdt_property_cell(void *fdt, const char *name, uint32_t val) +static inline int fdt_property_u32(void *fdt, const char *name, uint32_t val) { val = cpu_to_fdt32(val); return fdt_property(fdt, name, &val, sizeof(val)); } +static inline int fdt_property_u64(void *fdt, const char *name, uint64_t val) +{ + val = cpu_to_fdt64(val); + return fdt_property(fdt, name, &val, sizeof(val)); +} +static inline int fdt_property_cell(void *fdt, const char *name, uint32_t val) +{ + return fdt_property_u32(fdt, name, val); +} #define fdt_property_string(fdt, name, str) \ fdt_property(fdt, name, str, strlen(str)+1) int fdt_end_node(void *fdt); @@ -959,6 +1014,7 @@ int fdt_finish(void *fdt); /* Read-write functions */ /**********************************************************************/ +int fdt_create_empty_tree(void *buf, int bufsize); int fdt_open_into(const void *fdt, void *buf, int bufsize); int fdt_pack(void *fdt); @@ -1068,14 +1124,14 @@ int fdt_setprop(void *fdt, int nodeoffset, const char *name, const void *val, int len); /** - * fdt_setprop_cell - set a property to a single cell value + * fdt_setprop_u32 - set a property to a 32-bit integer * @fdt: pointer to the device tree blob * @nodeoffset: offset of the node whose property to change * @name: name of the property to change * @val: 32-bit integer value for the property (native endian) * - * fdt_setprop_cell() sets the value of the named property in the - * given node to the given cell value (converting to big-endian if + * fdt_setprop_u32() sets the value of the named property in the given + * node to the given 32-bit integer value (converting to big-endian if * necessary), or creates a new property with that value if it does * not already exist. * @@ -1095,14 +1151,60 @@ int fdt_setprop(void *fdt, int nodeoffset, const char *name, * -FDT_ERR_BADLAYOUT, * -FDT_ERR_TRUNCATED, standard meanings */ -static inline int fdt_setprop_cell(void *fdt, int nodeoffset, const char *name, - uint32_t val) +static inline int fdt_setprop_u32(void *fdt, int nodeoffset, const char *name, + uint32_t val) { val = cpu_to_fdt32(val); return fdt_setprop(fdt, nodeoffset, name, &val, sizeof(val)); } /** + * fdt_setprop_u64 - set a property to a 64-bit integer + * @fdt: pointer to the device tree blob + * @nodeoffset: offset of the node whose property to change + * @name: name of the property to change + * @val: 64-bit integer value for the property (native endian) + * + * fdt_setprop_u64() sets the value of the named property in the given + * node to the given 64-bit integer value (converting to big-endian if + * necessary), or creates a new property with that value if it does + * not already exist. + * + * This function may insert or delete data from the blob, and will + * therefore change the offsets of some existing nodes. + * + * returns: + * 0, on success + * -FDT_ERR_NOSPACE, there is insufficient free space in the blob to + * contain the new property value + * -FDT_ERR_BADOFFSET, nodeoffset did not point to FDT_BEGIN_NODE tag + * -FDT_ERR_BADLAYOUT, + * -FDT_ERR_BADMAGIC, + * -FDT_ERR_BADVERSION, + * -FDT_ERR_BADSTATE, + * -FDT_ERR_BADSTRUCTURE, + * -FDT_ERR_BADLAYOUT, + * -FDT_ERR_TRUNCATED, standard meanings + */ +static inline int fdt_setprop_u64(void *fdt, int nodeoffset, const char *name, + uint64_t val) +{ + val = cpu_to_fdt64(val); + return fdt_setprop(fdt, nodeoffset, name, &val, sizeof(val)); +} + +/** + * fdt_setprop_cell - set a property to a single cell value + * + * This is an alternative name for fdt_setprop_u32() + */ +static inline int fdt_setprop_cell(void *fdt, int nodeoffset, const char *name, + uint32_t val) +{ + return fdt_setprop_u32(fdt, nodeoffset, name, val); +} + +/** * fdt_setprop_string - set a property to a string value * @fdt: pointer to the device tree blob * @nodeoffset: offset of the node whose property to change @@ -1134,6 +1236,147 @@ static inline int fdt_setprop_cell(void *fdt, int nodeoffset, const char *name, fdt_setprop((fdt), (nodeoffset), (name), (str), strlen(str)+1) /** + * fdt_appendprop - append to or create a property + * @fdt: pointer to the device tree blob + * @nodeoffset: offset of the node whose property to change + * @name: name of the property to append to + * @val: pointer to data to append to the property value + * @len: length of the data to append to the property value + * + * fdt_appendprop() appends the value to the named property in the + * given node, creating the property if it does not already exist. + * + * This function may insert data into the blob, and will therefore + * change the offsets of some existing nodes. + * + * returns: + * 0, on success + * -FDT_ERR_NOSPACE, there is insufficient free space in the blob to + * contain the new property value + * -FDT_ERR_BADOFFSET, nodeoffset did not point to FDT_BEGIN_NODE tag + * -FDT_ERR_BADLAYOUT, + * -FDT_ERR_BADMAGIC, + * -FDT_ERR_BADVERSION, + * -FDT_ERR_BADSTATE, + * -FDT_ERR_BADSTRUCTURE, + * -FDT_ERR_BADLAYOUT, + * -FDT_ERR_TRUNCATED, standard meanings + */ +int fdt_appendprop(void *fdt, int nodeoffset, const char *name, + const void *val, int len); + +/** + * fdt_appendprop_u32 - append a 32-bit integer value to a property + * @fdt: pointer to the device tree blob + * @nodeoffset: offset of the node whose property to change + * @name: name of the property to change + * @val: 32-bit integer value to append to the property (native endian) + * + * fdt_appendprop_u32() appends the given 32-bit integer value + * (converting to big-endian if necessary) to the value of the named + * property in the given node, or creates a new property with that + * value if it does not already exist. + * + * This function may insert data into the blob, and will therefore + * change the offsets of some existing nodes. + * + * returns: + * 0, on success + * -FDT_ERR_NOSPACE, there is insufficient free space in the blob to + * contain the new property value + * -FDT_ERR_BADOFFSET, nodeoffset did not point to FDT_BEGIN_NODE tag + * -FDT_ERR_BADLAYOUT, + * -FDT_ERR_BADMAGIC, + * -FDT_ERR_BADVERSION, + * -FDT_ERR_BADSTATE, + * -FDT_ERR_BADSTRUCTURE, + * -FDT_ERR_BADLAYOUT, + * -FDT_ERR_TRUNCATED, standard meanings + */ +static inline int fdt_appendprop_u32(void *fdt, int nodeoffset, + const char *name, uint32_t val) +{ + val = cpu_to_fdt32(val); + return fdt_appendprop(fdt, nodeoffset, name, &val, sizeof(val)); +} + +/** + * fdt_appendprop_u64 - append a 64-bit integer value to a property + * @fdt: pointer to the device tree blob + * @nodeoffset: offset of the node whose property to change + * @name: name of the property to change + * @val: 64-bit integer value to append to the property (native endian) + * + * fdt_appendprop_u64() appends the given 64-bit integer value + * (converting to big-endian if necessary) to the value of the named + * property in the given node, or creates a new property with that + * value if it does not already exist. + * + * This function may insert data into the blob, and will therefore + * change the offsets of some existing nodes. + * + * returns: + * 0, on success + * -FDT_ERR_NOSPACE, there is insufficient free space in the blob to + * contain the new property value + * -FDT_ERR_BADOFFSET, nodeoffset did not point to FDT_BEGIN_NODE tag + * -FDT_ERR_BADLAYOUT, + * -FDT_ERR_BADMAGIC, + * -FDT_ERR_BADVERSION, + * -FDT_ERR_BADSTATE, + * -FDT_ERR_BADSTRUCTURE, + * -FDT_ERR_BADLAYOUT, + * -FDT_ERR_TRUNCATED, standard meanings + */ +static inline int fdt_appendprop_u64(void *fdt, int nodeoffset, + const char *name, uint64_t val) +{ + val = cpu_to_fdt64(val); + return fdt_appendprop(fdt, nodeoffset, name, &val, sizeof(val)); +} + +/** + * fdt_appendprop_cell - append a single cell value to a property + * + * This is an alternative name for fdt_appendprop_u32() + */ +static inline int fdt_appendprop_cell(void *fdt, int nodeoffset, + const char *name, uint32_t val) +{ + return fdt_appendprop_u32(fdt, nodeoffset, name, val); +} + +/** + * fdt_appendprop_string - append a string to a property + * @fdt: pointer to the device tree blob + * @nodeoffset: offset of the node whose property to change + * @name: name of the property to change + * @str: string value to append to the property + * + * fdt_appendprop_string() appends the given string to the value of + * the named property in the given node, or creates a new property + * with that value if it does not already exist. + * + * This function may insert data into the blob, and will therefore + * change the offsets of some existing nodes. + * + * returns: + * 0, on success + * -FDT_ERR_NOSPACE, there is insufficient free space in the blob to + * contain the new property value + * -FDT_ERR_BADOFFSET, nodeoffset did not point to FDT_BEGIN_NODE tag + * -FDT_ERR_BADLAYOUT, + * -FDT_ERR_BADMAGIC, + * -FDT_ERR_BADVERSION, + * -FDT_ERR_BADSTATE, + * -FDT_ERR_BADSTRUCTURE, + * -FDT_ERR_BADLAYOUT, + * -FDT_ERR_TRUNCATED, standard meanings + */ +#define fdt_appendprop_string(fdt, nodeoffset, name, str) \ + fdt_appendprop((fdt), (nodeoffset), (name), (str), strlen(str)+1) + +/** * fdt_delprop - delete a property * @fdt: pointer to the device tree blob * @nodeoffset: offset of the node whose property to nop diff --git a/lib/libfdt/Makefile b/lib/libfdt/Makefile index c965577..0693d4b 100644 --- a/lib/libfdt/Makefile +++ b/lib/libfdt/Makefile @@ -27,7 +27,7 @@ LIB = $(obj)libfdt.o SOBJS = -COBJS-libfdt += fdt.o fdt_ro.o fdt_rw.o fdt_strerror.o fdt_sw.o fdt_wip.o +COBJS-libfdt += fdt.o fdt_ro.o fdt_rw.o fdt_strerror.o fdt_sw.o fdt_wip.o fdt_empty_tree.o COBJS-$(CONFIG_OF_LIBFDT) += $(COBJS-libfdt) COBJS-$(CONFIG_FIT) += $(COBJS-libfdt) diff --git a/lib/libfdt/fdt_empty_tree.c b/lib/libfdt/fdt_empty_tree.c new file mode 100644 index 0000000..f72d13b --- /dev/null +++ b/lib/libfdt/fdt_empty_tree.c @@ -0,0 +1,84 @@ +/* + * libfdt - Flat Device Tree manipulation + * Copyright (C) 2012 David Gibson, IBM Corporation. + * + * libfdt is dual licensed: you can use it either under the terms of + * the GPL, or the BSD license, at your option. + * + * a) This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of the + * License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public + * License along with this library; if not, write to the Free + * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, + * MA 02110-1301 USA + * + * Alternatively, + * + * b) 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. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND + * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, + * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, + * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +#include "libfdt_env.h" + +#include <fdt.h> +#include <libfdt.h> + +#include "libfdt_internal.h" + +int fdt_create_empty_tree(void *buf, int bufsize) +{ + int err; + + err = fdt_create(buf, bufsize); + if (err) + return err; + + err = fdt_finish_reservemap(buf); + if (err) + return err; + + err = fdt_begin_node(buf, ""); + if (err) + return err; + + err = fdt_end_node(buf); + if (err) + return err; + + err = fdt_finish(buf); + if (err) + return err; + + return fdt_open_into(buf, buf, bufsize); +} + diff --git a/lib/libfdt/fdt_rw.c b/lib/libfdt/fdt_rw.c index 5c27a67..5ed23d6 100644 --- a/lib/libfdt/fdt_rw.c +++ b/lib/libfdt/fdt_rw.c @@ -293,6 +293,33 @@ int fdt_setprop(void *fdt, int nodeoffset, const char *name, return 0; } +int fdt_appendprop(void *fdt, int nodeoffset, const char *name, + const void *val, int len) +{ + struct fdt_property *prop; + int err, oldlen, newlen; + + FDT_RW_CHECK_HEADER(fdt); + + prop = fdt_get_property_w(fdt, nodeoffset, name, &oldlen); + if (prop) { + newlen = len + oldlen; + err = _fdt_splice_struct(fdt, prop->data, + FDT_TAGALIGN(oldlen), + FDT_TAGALIGN(newlen)); + if (err) + return err; + prop->len = cpu_to_fdt32(newlen); + memcpy(prop->data + oldlen, val, len); + } else { + err = _fdt_add_property(fdt, nodeoffset, name, len, &prop); + if (err) + return err; + memcpy(prop->data, val, len); + } + return 0; +} + int fdt_delprop(void *fdt, int nodeoffset, const char *name) { struct fdt_property *prop; |