提交 308e2b3a 编写于 作者: W Wolfgang Denk

Merge with /home/wd/git/u-boot/custodian/u-boot-fdt

......@@ -45,8 +45,8 @@
DECLARE_GLOBAL_DATA_PTR;
/*cmd_boot.c*/
extern int do_reset (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[]);
/*cmd_boot.c*/
extern int do_reset (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[]);
#if defined(CONFIG_TIMESTAMP) || defined(CONFIG_CMD_DATE)
#include <rtc.h>
......@@ -362,7 +362,6 @@ int do_bootm (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[])
if (i != BZ_OK) {
printf ("BUNZIP2 ERROR %d - must RESET board to recover\n", i);
show_boot_progress (-6);
udelay(100000);
do_reset (cmdtp, flag, argc, argv);
}
break;
......@@ -741,59 +740,65 @@ do_bootm_linux (cmd_tbl_t *cmdtp, int flag,
if(argc > 3) {
of_flat_tree = (char *) simple_strtoul(argv[3], NULL, 16);
hdr = (image_header_t *)of_flat_tree;
#if defined(CONFIG_OF_LIBFDT)
if (fdt_check_header(of_flat_tree) == 0) {
#if defined(CONFIG_OF_FLAT_TREE)
if (*((ulong *)(of_flat_tree + sizeof(image_header_t))) != OF_DT_HEADER) {
#else
if (*(ulong *)of_flat_tree == OF_DT_HEADER) {
if (fdt_check_header(of_flat_tree + sizeof(image_header_t)) != 0) {
#endif
#ifndef CFG_NO_FLASH
if (addr2info((ulong)of_flat_tree) != NULL)
of_data = (ulong)of_flat_tree;
#endif
} else if (ntohl(hdr->ih_magic) == IH_MAGIC) {
printf("## Flat Device Tree Image at %08lX\n", hdr);
printf("## Flat Device Tree at %08lX\n", hdr);
print_image_hdr(hdr);
if ((ntohl(hdr->ih_load) < ((unsigned long)hdr + ntohl(hdr->ih_size) + sizeof(hdr))) &&
((ntohl(hdr->ih_load) + ntohl(hdr->ih_size)) > (unsigned long)hdr)) {
printf ("ERROR: Load address overwrites Flat Device Tree uImage\n");
return;
puts ("ERROR: fdt overwritten - "
"must RESET the board to recover.\n");
do_reset (cmdtp, flag, argc, argv);
}
printf(" Verifying Checksum ... ");
puts (" Verifying Checksum ... ");
memmove (&header, (char *)hdr, sizeof(image_header_t));
checksum = ntohl(header.ih_hcrc);
header.ih_hcrc = 0;
if(checksum != crc32(0, (uchar *)&header, sizeof(image_header_t))) {
printf("ERROR: Flat Device Tree header checksum is invalid\n");
return;
puts ("ERROR: fdt header checksum invalid - "
"must RESET the board to recover.\n");
do_reset (cmdtp, flag, argc, argv);
}
checksum = ntohl(hdr->ih_dcrc);
addr = (ulong)((uchar *)(hdr) + sizeof(image_header_t));
if(checksum != crc32(0, (uchar *)addr, ntohl(hdr->ih_size))) {
printf("ERROR: Flat Device Tree checksum is invalid\n");
return;
puts ("ERROR: fdt checksum invalid - "
"must RESET the board to recover.\n");
do_reset (cmdtp, flag, argc, argv);
}
printf("OK\n");
puts ("OK\n");
if (ntohl(hdr->ih_type) != IH_TYPE_FLATDT) {
printf ("ERROR: uImage not Flat Device Tree type\n");
return;
puts ("ERROR: uImage is not a fdt - "
"must RESET the board to recover.\n");
do_reset (cmdtp, flag, argc, argv);
}
if (ntohl(hdr->ih_comp) != IH_COMP_NONE) {
printf("ERROR: uImage is not uncompressed\n");
return;
puts ("ERROR: uImage is compressed - "
"must RESET the board to recover.\n");
do_reset (cmdtp, flag, argc, argv);
}
#if defined(CONFIG_OF_LIBFDT)
if (fdt_check_header(of_flat_tree + sizeof(image_header_t)) == 0) {
#else
#if defined(CONFIG_OF_FLAT_TREE)
if (*((ulong *)(of_flat_tree + sizeof(image_header_t))) != OF_DT_HEADER) {
#else
if (fdt_check_header(of_flat_tree + sizeof(image_header_t)) != 0) {
#endif
printf ("ERROR: uImage data is not a flat device tree\n");
return;
puts ("ERROR: uImage data is not a fdt - "
"must RESET the board to recover.\n");
do_reset (cmdtp, flag, argc, argv);
}
memmove((void *)ntohl(hdr->ih_load),
......@@ -801,10 +806,11 @@ do_bootm_linux (cmd_tbl_t *cmdtp, int flag,
ntohl(hdr->ih_size));
of_flat_tree = (char *)ntohl(hdr->ih_load);
} else {
printf ("Did not find a flat flat device tree at address %08lX\n", of_flat_tree);
return;
puts ("Did not find a flat Flat Device Tree.\n"
"Must RESET the board to recover.\n");
do_reset (cmdtp, flag, argc, argv);
}
printf (" Booting using flat device tree at 0x%x\n",
printf (" Booting using the fdt at 0x%x\n",
of_flat_tree);
} else if ((hdr->ih_type==IH_TYPE_MULTI) && (len_ptr[1]) && (len_ptr[2])) {
u_long tail = ntohl(len_ptr[0]) % 4;
......@@ -828,22 +834,24 @@ do_bootm_linux (cmd_tbl_t *cmdtp, int flag,
of_data += 4 - tail;
}
#if defined(CONFIG_OF_LIBFDT)
if (fdt_check_header((void *)of_data) != 0) {
#if defined(CONFIG_OF_FLAT_TREE)
if (*((ulong *)(of_flat_tree + sizeof(image_header_t))) != OF_DT_HEADER) {
#else
if (((struct boot_param_header *)of_data)->magic != OF_DT_HEADER) {
if (fdt_check_header(of_flat_tree + sizeof(image_header_t)) != 0) {
#endif
printf ("ERROR: image is not a flat device tree\n");
return;
puts ("ERROR: image is not a fdt - "
"must RESET the board to recover.\n");
do_reset (cmdtp, flag, argc, argv);
}
#if defined(CONFIG_OF_LIBFDT)
if (be32_to_cpu(fdt_totalsize(of_data)) != ntohl(len_ptr[2])) {
#else
#if defined(CONFIG_OF_FLAT_TREE)
if (((struct boot_param_header *)of_data)->totalsize != ntohl(len_ptr[2])) {
#else
if (be32_to_cpu(fdt_totalsize(of_data)) != ntohl(len_ptr[2])) {
#endif
printf ("ERROR: flat device tree size does not agree with image\n");
return;
puts ("ERROR: fdt size != image size - "
"must RESET the board to recover.\n");
do_reset (cmdtp, flag, argc, argv);
}
}
#endif
......@@ -916,15 +924,6 @@ do_bootm_linux (cmd_tbl_t *cmdtp, int flag,
initrd_end = 0;
}
debug ("## Transferring control to Linux (at address %08lx) ...\n",
(ulong)kernel);
show_boot_progress (15);
#if defined(CFG_INIT_RAM_LOCK) && !defined(CONFIG_E500)
unlock_ram_in_cache();
#endif
#if defined(CONFIG_OF_LIBFDT)
/* move of_flat_tree if needed */
if (of_data) {
......@@ -944,32 +943,41 @@ do_bootm_linux (cmd_tbl_t *cmdtp, int flag,
of_flat_tree = (char *)of_start;
printf (" Loading Device Tree to %08lx, end %08lx ... ",
of_start, of_start + of_len - 1);
err = fdt_open_into((void *)of_start, (void *)of_data, of_len);
err = fdt_open_into((void *)of_data, (void *)of_start, of_len);
if (err != 0) {
printf ("libfdt: %s " __FILE__ " %d\n", fdt_strerror(err), __LINE__);
}
/*
* Add the chosen node if it doesn't exist, add the env and bd_t
* if the user wants it (the logic is in the subroutines).
*/
if (fdt_chosen(of_flat_tree, initrd_start, initrd_end, 0) < 0) {
printf("Failed creating the /chosen node (0x%08X), aborting.\n", of_flat_tree);
return;
puts ("ERROR: fdt move failed - "
"must RESET the board to recover.\n");
do_reset (cmdtp, flag, argc, argv);
}
}
/*
* Add the chosen node if it doesn't exist, add the env and bd_t
* if the user wants it (the logic is in the subroutines).
*/
if (fdt_chosen(of_flat_tree, initrd_start, initrd_end, 0) < 0) {
puts ("ERROR: /chosen node create failed - "
"must RESET the board to recover.\n");
do_reset (cmdtp, flag, argc, argv);
}
#ifdef CONFIG_OF_HAS_UBOOT_ENV
if (fdt_env(of_flat_tree) < 0) {
printf("Failed creating the /u-boot-env node, aborting.\n");
return;
}
if (fdt_env(of_flat_tree) < 0) {
puts ("ERROR: /u-boot-env node create failed - "
"must RESET the board to recover.\n");
do_reset (cmdtp, flag, argc, argv);
}
#endif
#ifdef CONFIG_OF_HAS_BD_T
if (fdt_bd_t(of_flat_tree) < 0) {
printf("Failed creating the /bd_t node, aborting.\n");
return;
}
#endif
if (fdt_bd_t(of_flat_tree) < 0) {
puts ("ERROR: /bd_t node create failed - "
"must RESET the board to recover.\n");
do_reset (cmdtp, flag, argc, argv);
}
#endif
#ifdef CONFIG_OF_BOARD_SETUP
/* Call the board-specific fixup routine */
ft_board_setup(of_flat_tree, gd->bd);
#endif
#endif /* CONFIG_OF_LIBFDT */
#if defined(CONFIG_OF_FLAT_TREE)
/* move of_flat_tree if needed */
if (of_data) {
......@@ -989,8 +997,36 @@ do_bootm_linux (cmd_tbl_t *cmdtp, int flag,
of_start, of_start + of_len - 1);
memmove ((void *)of_start, (void *)of_data, of_len);
}
/*
* Create the /chosen node and modify the blob with board specific
* values as needed.
*/
ft_setup(of_flat_tree, kbd, initrd_start, initrd_end);
/* ft_dump_blob(of_flat_tree); */
#endif
debug ("## Transferring control to Linux (at address %08lx) ...\n",
(ulong)kernel);
show_boot_progress (15);
#if defined(CFG_INIT_RAM_LOCK) && !defined(CONFIG_E500)
unlock_ram_in_cache();
#endif
#if defined(CONFIG_OF_FLAT_TREE) || defined(CONFIG_OF_LIBFDT)
if (of_flat_tree) { /* device tree; boot new style */
/*
* Linux Kernel Parameters (passing device tree):
* r3: pointer to the fdt, followed by the board info data
* r4: physical pointer to the kernel itself
* r5: NULL
* r6: NULL
* r7: NULL
*/
(*kernel) ((bd_t *)of_flat_tree, (ulong)kernel, 0, 0, 0);
/* does not return */
}
#endif
/*
* Linux Kernel Parameters (passing board info data):
* r3: ptr to board info data
......@@ -999,46 +1035,8 @@ do_bootm_linux (cmd_tbl_t *cmdtp, int flag,
* r6: Start of command line string
* r7: End of command line string
*/
#if defined(CONFIG_OF_FLAT_TREE) || defined(CONFIG_OF_LIBFDT)
if (!of_flat_tree) /* no device tree; boot old style */
#endif
(*kernel) (kbd, initrd_start, initrd_end, cmd_start, cmd_end);
/* does not return */
#if defined(CONFIG_OF_FLAT_TREE) || defined(CONFIG_OF_LIBFDT)
/*
* Linux Kernel Parameters (passing device tree):
* r3: ptr to OF flat tree, followed by the board info data
* r4: physical pointer to the kernel itself
* r5: NULL
* r6: NULL
* r7: NULL
*/
#if defined(CONFIG_OF_FLAT_TREE)
ft_setup(of_flat_tree, kbd, initrd_start, initrd_end);
/* ft_dump_blob(of_flat_tree); */
#endif
#if defined(CONFIG_OF_LIBFDT)
if (fdt_chosen(of_flat_tree, initrd_start, initrd_end, 0) < 0) {
printf("Failed creating the /chosen node (0x%08X), aborting.\n", of_flat_tree);
return;
}
#ifdef CONFIG_OF_HAS_UBOOT_ENV
if (fdt_env(of_flat_tree) < 0) {
printf("Failed creating the /u-boot-env node, aborting.\n");
return;
}
#endif
#ifdef CONFIG_OF_HAS_BD_T
if (fdt_bd_t(of_flat_tree) < 0) {
printf("Failed creating the /bd_t node, aborting.\n");
return;
}
#endif
#endif /* if defined(CONFIG_OF_LIBFDT) */
(*kernel) ((bd_t *)of_flat_tree, (ulong)kernel, 0, 0, 0);
#endif
(*kernel) (kbd, initrd_start, initrd_end, cmd_start, cmd_end);
/* does not return */
}
#endif /* CONFIG_PPC */
......
此差异已折叠。
......@@ -37,6 +37,10 @@
*/
DECLARE_GLOBAL_DATA_PTR;
/*
* fdt points to our working device tree.
*/
struct fdt_header *fdt;
/********************************************************************/
......@@ -45,13 +49,12 @@ int fdt_chosen(void *fdt, ulong initrd_start, ulong initrd_end, int force)
bd_t *bd = gd->bd;
int nodeoffset;
int err;
u32 tmp; /* used to set 32 bit integer properties */
char *str; /* used to set string properties */
ulong clock;
u32 tmp; /* used to set 32 bit integer properties */
char *str; /* used to set string properties */
err = fdt_check_header(fdt);
if (err < 0) {
printf("libfdt: %s\n", fdt_strerror(err));
printf("fdt_chosen: %s\n", fdt_strerror(err));
return err;
}
......@@ -63,11 +66,12 @@ int fdt_chosen(void *fdt, ulong initrd_start, ulong initrd_end, int force)
err = fdt_num_reservemap(fdt, &used, &total);
if (err < 0) {
printf("libfdt: %s\n", fdt_strerror(err));
printf("fdt_chosen: %s\n", fdt_strerror(err));
return err;
}
if (used >= total) {
printf("fdt_chosen: no room in the reserved map (%d of %d)\n",
printf("WARNING: "
"no room in the reserved map (%d of %d)\n",
used, total);
return -1;
}
......@@ -84,7 +88,7 @@ int fdt_chosen(void *fdt, ulong initrd_start, ulong initrd_end, int force)
err = fdt_replace_reservemap_entry(fdt, j,
initrd_start, initrd_end - initrd_start + 1);
if (err < 0) {
printf("libfdt: %s\n", fdt_strerror(err));
printf("fdt_chosen: %s\n", fdt_strerror(err));
return err;
}
}
......@@ -92,7 +96,7 @@ int fdt_chosen(void *fdt, ulong initrd_start, ulong initrd_end, int force)
/*
* Find the "chosen" node.
*/
nodeoffset = fdt_path_offset (fdt, "/chosen");
nodeoffset = fdt_find_node_by_path (fdt, "/chosen");
/*
* If we have a "chosen" node already the "force the writing"
......@@ -110,7 +114,8 @@ int fdt_chosen(void *fdt, ulong initrd_start, ulong initrd_end, int force)
*/
nodeoffset = fdt_add_subnode(fdt, 0, "chosen");
if (nodeoffset < 0) {
printf("libfdt: %s\n", fdt_strerror(nodeoffset));
printf("WARNING: could not create /chosen %s.\n",
fdt_strerror(nodeoffset));
return nodeoffset;
}
}
......@@ -120,42 +125,35 @@ int fdt_chosen(void *fdt, ulong initrd_start, ulong initrd_end, int force)
*/
str = getenv("bootargs");
if (str != NULL) {
err = fdt_setprop(fdt, nodeoffset, "bootargs", str, strlen(str)+1);
err = fdt_setprop(fdt, nodeoffset,
"bootargs", str, strlen(str)+1);
if (err < 0)
printf("libfdt: %s\n", fdt_strerror(err));
printf("WARNING: could not set bootargs %s.\n",
fdt_strerror(err));
}
if (initrd_start && initrd_end) {
tmp = __cpu_to_be32(initrd_start);
err = fdt_setprop(fdt, nodeoffset, "linux,initrd-start", &tmp, sizeof(tmp));
err = fdt_setprop(fdt, nodeoffset,
"linux,initrd-start", &tmp, sizeof(tmp));
if (err < 0)
printf("libfdt: %s\n", fdt_strerror(err));
printf("WARNING: "
"could not set linux,initrd-start %s.\n",
fdt_strerror(err));
tmp = __cpu_to_be32(initrd_end);
err = fdt_setprop(fdt, nodeoffset, "linux,initrd-end", &tmp, sizeof(tmp));
err = fdt_setprop(fdt, nodeoffset,
"linux,initrd-end", &tmp, sizeof(tmp));
if (err < 0)
printf("libfdt: %s\n", fdt_strerror(err));
printf("WARNING: could not set linux,initrd-end %s.\n",
fdt_strerror(err));
}
#ifdef OF_STDOUT_PATH
err = fdt_setprop(fdt, nodeoffset, "linux,stdout-path", OF_STDOUT_PATH, strlen(OF_STDOUT_PATH)+1);
err = fdt_setprop(fdt, nodeoffset,
"linux,stdout-path", OF_STDOUT_PATH, strlen(OF_STDOUT_PATH)+1);
if (err < 0)
printf("libfdt: %s\n", fdt_strerror(err));
printf("WARNING: could not set linux,stdout-path %s.\n",
fdt_strerror(err));
#endif
nodeoffset = fdt_path_offset (fdt, "/cpus");
if (nodeoffset >= 0) {
clock = cpu_to_be32(bd->bi_intfreq);
err = fdt_setprop(fdt, nodeoffset, "clock-frequency", &clock, 4);
if (err < 0)
printf("libfdt: %s\n", fdt_strerror(err));
}
#ifdef OF_TBCLK
nodeoffset = fdt_path_offset (fdt, "/cpus/" OF_CPU "/timebase-frequency");
if (nodeoffset >= 0) {
clock = cpu_to_be32(OF_TBCLK);
err = fdt_setprop(fdt, nodeoffset, "clock-frequency", &clock, 4);
if (err < 0)
printf("libfdt: %s\n", fdt_strerror(err));
}
#endif
return err;
}
......@@ -177,7 +175,7 @@ int fdt_env(void *fdt)
err = fdt_check_header(fdt);
if (err < 0) {
printf("libfdt: %s\n", fdt_strerror(err));
printf("fdt_env: %s\n", fdt_strerror(err));
return err;
}
......@@ -185,11 +183,11 @@ int fdt_env(void *fdt)
* See if we already have a "u-boot-env" node, delete it if so.
* Then create a new empty node.
*/
nodeoffset = fdt_path_offset (fdt, "/u-boot-env");
nodeoffset = fdt_find_node_by_path (fdt, "/u-boot-env");
if (nodeoffset >= 0) {
err = fdt_del_node(fdt, nodeoffset);
if (err < 0) {
printf("libfdt: %s\n", fdt_strerror(err));
printf("fdt_env: %s\n", fdt_strerror(err));
return err;
}
}
......@@ -198,7 +196,8 @@ int fdt_env(void *fdt)
*/
nodeoffset = fdt_add_subnode(fdt, 0, "u-boot-env");
if (nodeoffset < 0) {
printf("libfdt: %s\n", fdt_strerror(nodeoffset));
printf("WARNING: could not create /u-boot-env %s.\n",
fdt_strerror(nodeoffset));
return nodeoffset;
}
......@@ -226,7 +225,8 @@ int fdt_env(void *fdt)
continue;
err = fdt_setprop(fdt, nodeoffset, lval, rval, strlen(rval)+1);
if (err < 0) {
printf("libfdt: %s\n", fdt_strerror(err));
printf("WARNING: could not set %s %s.\n",
lval, fdt_strerror(err));
return err;
}
}
......@@ -292,12 +292,12 @@ int fdt_bd_t(void *fdt)
bd_t *bd = gd->bd;
int nodeoffset;
int err;
u32 tmp; /* used to set 32 bit integer properties */
u32 tmp; /* used to set 32 bit integer properties */
int i;
err = fdt_check_header(fdt);
if (err < 0) {
printf("libfdt: %s\n", fdt_strerror(err));
printf("fdt_bd_t: %s\n", fdt_strerror(err));
return err;
}
......@@ -305,11 +305,11 @@ int fdt_bd_t(void *fdt)
* See if we already have a "bd_t" node, delete it if so.
* Then create a new empty node.
*/
nodeoffset = fdt_path_offset (fdt, "/bd_t");
nodeoffset = fdt_find_node_by_path (fdt, "/bd_t");
if (nodeoffset >= 0) {
err = fdt_del_node(fdt, nodeoffset);
if (err < 0) {
printf("libfdt: %s\n", fdt_strerror(err));
printf("fdt_bd_t: %s\n", fdt_strerror(err));
return err;
}
}
......@@ -318,7 +318,9 @@ int fdt_bd_t(void *fdt)
*/
nodeoffset = fdt_add_subnode(fdt, 0, "bd_t");
if (nodeoffset < 0) {
printf("libfdt: %s\n", fdt_strerror(nodeoffset));
printf("WARNING: could not create /bd_t %s.\n",
fdt_strerror(nodeoffset));
printf("fdt_bd_t: %s\n", fdt_strerror(nodeoffset));
return nodeoffset;
}
/*
......@@ -326,20 +328,23 @@ int fdt_bd_t(void *fdt)
*/
for (i = 0; i < sizeof(bd_map)/sizeof(bd_map[0]); i++) {
tmp = cpu_to_be32(getenv("bootargs"));
err = fdt_setprop(fdt, nodeoffset, bd_map[i].name, &tmp, sizeof(tmp));
err = fdt_setprop(fdt, nodeoffset,
bd_map[i].name, &tmp, sizeof(tmp));
if (err < 0)
printf("libfdt: %s\n", fdt_strerror(err));
printf("WARNING: could not set %s %s.\n",
bd_map[i].name, fdt_strerror(err));
}
/*
* Add a couple of oddball entries...
*/
err = fdt_setprop(fdt, nodeoffset, "enetaddr", &bd->bi_enetaddr, 6);
if (err < 0)
printf("libfdt: %s\n", fdt_strerror(err));
printf("WARNING: could not set enetaddr %s.\n",
fdt_strerror(err));
err = fdt_setprop(fdt, nodeoffset, "ethspeed", &bd->bi_ethspeed, 4);
if (err < 0)
printf("libfdt: %s\n", fdt_strerror(err));
printf("WARNING: could not set ethspeed %s.\n",
fdt_strerror(err));
return 0;
}
#endif /* ifdef CONFIG_OF_HAS_BD_T */
......
......@@ -38,5 +38,11 @@ int fdt_env(void *fdt);
int fdt_bd_t(void *fdt);
#endif
#ifdef CONFIG_OF_BOARD_SETUP
void ft_board_setup(void *blob, bd_t *bd);
void ft_cpu_setup(void *blob, bd_t *bd);
void ft_pci_setup(void *blob, bd_t *bd);
#endif
#endif /* ifdef CONFIG_OF_LIBFDT */
#endif /* ifndef __FDT_SUPPORT_H */
......@@ -77,7 +77,13 @@ int fdt_subnode_offset_namelen(const void *fdt, int parentoffset,
const char *name, int namelen);
int fdt_subnode_offset(const void *fdt, int parentoffset, const char *name);
int fdt_path_offset(const void *fdt, const char *path);
int fdt_find_node_by_path(const void *fdt, const char *path);
int fdt_find_node_by_type(const void *fdt, int nodeoffset, const char *type);
int fdt_node_is_compatible(const void *fdt, int nodeoffset,
const char *compat);
int fdt_find_compatible_node(const void *fdt, int nodeoffset,
const char *type, const char *compat);
struct fdt_property *fdt_get_property(const void *fdt, int nodeoffset,
const char *name, int *lenp);
......
......@@ -26,7 +26,7 @@
#include <asm/byteorder.h>
#include <linux/string.h>
struct fdt_header *fdt; /* Pointer to the working fdt */
extern struct fdt_header *fdt; /* Pointer to the working fdt */
#define fdt32_to_cpu(x) __be32_to_cpu(x)
#define cpu_to_fdt32(x) __cpu_to_be32(x)
......
......@@ -16,6 +16,9 @@
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
#include "config.h"
#if CONFIG_OF_LIBFDT
#include "libfdt_env.h"
#include <fdt.h>
......@@ -83,3 +86,5 @@ int fdt_move(const void *fdt, void *buf, int bufsize)
memmove(buf, fdt, fdt_totalsize(fdt));
return 0;
}
#endif /* CONFIG_OF_LIBFDT */
......@@ -16,6 +16,9 @@
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
#include "config.h"
#if CONFIG_OF_LIBFDT
#include "libfdt_env.h"
#include <fdt.h>
......@@ -47,6 +50,33 @@ static int offset_streq(const void *fdt, int offset,
return 1;
}
/*
* Checks if the property name matches.
*/
static int prop_name_eq(const void *fdt, int offset, const char *name,
struct fdt_property **prop, int *lenp)
{
int namestroff, len;
*prop = fdt_offset_ptr_typed(fdt, offset, *prop);
if (! *prop)
return -FDT_ERR_BADSTRUCTURE;
namestroff = fdt32_to_cpu((*prop)->nameoff);
if (streq(fdt_string(fdt, namestroff), name)) {
len = fdt32_to_cpu((*prop)->len);
*prop = fdt_offset_ptr(fdt, offset,
sizeof(**prop) + len);
if (*prop) {
if (lenp)
*lenp = len;
return 1;
} else
return -FDT_ERR_BADSTRUCTURE;
}
return 0;
}
/*
* Return a pointer to the string at the given string offset.
*/
......@@ -55,6 +85,118 @@ char *fdt_string(const void *fdt, int stroffset)
return (char *)fdt + fdt_off_dt_strings(fdt) + stroffset;
}
/*
* Check if the specified node is compatible by comparing the tokens
* in its "compatible" property with the specified string:
*
* nodeoffset - starting place of the node
* compat - the string to match to one of the tokens in the
* "compatible" list.
*/
int fdt_node_is_compatible(const void *fdt, int nodeoffset,
const char *compat)
{
const char* cp;
int cplen, len;
cp = fdt_getprop(fdt, nodeoffset, "compatible", &cplen);
if (cp == NULL)
return 0;
while (cplen > 0) {
if (strncmp(cp, compat, strlen(compat)) == 0)
return 1;
len = strlen(cp) + 1;
cp += len;
cplen -= len;
}
return 0;
}
/*
* Find a node by its device type property. On success, the offset of that
* node is returned or an error code otherwise:
*
* nodeoffset - the node to start searching from or 0, the node you pass
* will not be searched, only the next one will; typically,
* you pass 0 to start the search and then what the previous
* call returned.
* type - the device type string to match against.
*/
int fdt_find_node_by_type(const void *fdt, int nodeoffset, const char *type)
{
int offset, nextoffset;
struct fdt_property *prop;
uint32_t tag;
int len, ret;
CHECK_HEADER(fdt);
tag = fdt_next_tag(fdt, nodeoffset, &nextoffset, NULL);
if (tag != FDT_BEGIN_NODE)
return -FDT_ERR_BADOFFSET;
if (nodeoffset)
nodeoffset = 0; /* start searching with next node */
while (1) {
offset = nextoffset;
tag = fdt_next_tag(fdt, offset, &nextoffset, NULL);
switch (tag) {
case FDT_BEGIN_NODE:
nodeoffset = offset;
break;
case FDT_PROP:
if (nodeoffset == 0)
break;
ret = prop_name_eq(fdt, offset, "device_type",
&prop, &len);
if (ret < 0)
return ret;
else if (ret > 0 &&
strncmp(prop->data, type, len - 1) == 0)
return nodeoffset;
break;
case FDT_END_NODE:
case FDT_NOP:
break;
case FDT_END:
return -FDT_ERR_NOTFOUND;
default:
return -FDT_ERR_BADSTRUCTURE;
}
}
}
/*
* Find a node based on its device type and one of the tokens in its its
* "compatible" property. On success, the offset of that node is returned
* or an error code otherwise:
*
* nodeoffset - the node to start searching from or 0, the node you pass
* will not be searched, only the next one will; typically,
* you pass 0 to start the search and then what the previous
* call returned.
* type - the device type string to match against.
* compat - the string to match to one of the tokens in the
* "compatible" list.
*/
int fdt_find_compatible_node(const void *fdt, int nodeoffset,
const char *type, const char *compat)
{
int offset;
offset = fdt_find_node_by_type(fdt, nodeoffset, type);
if (offset < 0 || fdt_node_is_compatible(fdt, offset, compat))
return offset;
return -FDT_ERR_NOTFOUND;
}
/*
* Return the node offset of the node specified by:
* parentoffset - starting place (0 to start at the root)
......@@ -129,7 +271,7 @@ int fdt_subnode_offset(const void *fdt, int parentoffset,
* Searches for the node corresponding to the given path and returns the
* offset of that node.
*/
int fdt_path_offset(const void *fdt, const char *path)
int fdt_find_node_by_path(const void *fdt, const char *path)
{
const char *end = path + strlen(path);
const char *p = path;
......@@ -141,6 +283,10 @@ int fdt_path_offset(const void *fdt, const char *path)
if (*path != '/')
return -FDT_ERR_BADPATH;
/* Handle the root path: root offset is 0 */
if (strcmp(path, "/") == 0)
return 0;
while (*p) {
const char *q;
......@@ -184,7 +330,6 @@ struct fdt_property *fdt_get_property(const void *fdt,
int level = 0;
uint32_t tag;
struct fdt_property *prop;
int namestroff;
int offset, nextoffset;
int err;
......@@ -224,24 +369,11 @@ struct fdt_property *fdt_get_property(const void *fdt,
if (level != 0)
continue;
err = -FDT_ERR_BADSTRUCTURE;
prop = fdt_offset_ptr_typed(fdt, offset, prop);
if (! prop)
goto fail;
namestroff = fdt32_to_cpu(prop->nameoff);
if (streq(fdt_string(fdt, namestroff), name)) {
/* Found it! */
int len = fdt32_to_cpu(prop->len);
prop = fdt_offset_ptr(fdt, offset,
sizeof(*prop)+len);
if (! prop)
goto fail;
if (lenp)
*lenp = len;
err = prop_name_eq(fdt, offset, name, &prop, lenp);
if (err > 0)
return prop;
}
else if (err < 0)
goto fail;
break;
case FDT_NOP:
......@@ -400,3 +532,6 @@ int fdt_get_reservemap(void *fdt, int n, struct fdt_reserve_entry *re)
}
return 0;
}
#endif /* CONFIG_OF_LIBFDT */
......@@ -16,6 +16,9 @@
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
#include "config.h"
#if CONFIG_OF_LIBFDT
#include "libfdt_env.h"
#include <fdt.h>
......@@ -291,3 +294,5 @@ int fdt_pack(void *fdt)
fdt_set_header(fdt, totalsize, _blob_data_size(fdt));
return 0;
}
#endif /* CONFIG_OF_LIBFDT */
......@@ -16,6 +16,9 @@
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
#include "config.h"
#if CONFIG_OF_LIBFDT
#include "libfdt_env.h"
#include <fdt.h>
......@@ -62,3 +65,5 @@ const char *fdt_strerror(int errval)
return "<unknown error>";
}
#endif /* CONFIG_OF_LIBFDT */
......@@ -16,6 +16,9 @@
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
#include "config.h"
#if CONFIG_OF_LIBFDT
#include "libfdt_env.h"
#include <fdt.h>
......@@ -224,3 +227,5 @@ int fdt_finish(void *fdt)
fdt_set_header(fdt, magic, FDT_MAGIC);
return 0;
}
#endif /* CONFIG_OF_LIBFDT */
......@@ -16,6 +16,9 @@
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
#include "config.h"
#if CONFIG_OF_LIBFDT
#include "libfdt_env.h"
#include <fdt.h>
......@@ -135,3 +138,5 @@ int fdt_replace_reservemap_entry(void *fdt, int n, uint64_t addr, uint64_t size)
return 0;
}
#endif /* CONFIG_OF_LIBFDT */
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册