Merge branch 'master' of /home/wd/git/u-boot/master/

This commit is contained in:
Wolfgang Denk 2008-03-25 00:12:54 +01:00
commit b38d7fc2f1
10 changed files with 389 additions and 229 deletions

5
README
View file

@ -1946,6 +1946,11 @@ Configuration Settings:
is useful, if some of the configured banks are only is useful, if some of the configured banks are only
optionally available. optionally available.
- CONFIG_FLASH_SHOW_PROGRESS
If defined (must be an integer), print out countdown
digits and dots. Recommended value: 45 (9..1) for 80
column displays, 15 (3..1) for 40 column displays.
- CFG_RX_ETH_BUFFER: - CFG_RX_ETH_BUFFER:
Defines the number of ethernet receive buffers. On some Defines the number of ethernet receive buffers. On some
ethernet controllers it is recommended to set this value ethernet controllers it is recommended to set this value

View file

@ -260,7 +260,7 @@ int do_fdt (cmd_tbl_t * cmdtp, int flag, int argc, char *argv[])
/******************************************************************** /********************************************************************
* Remove a property/node * Remove a property/node
********************************************************************/ ********************************************************************/
} else if (argv[1][0] == 'r') { } else if ((argv[1][0] == 'r') && (argv[1][1] == 'm')) {
int nodeoffset; /* node offset from libfdt */ int nodeoffset; /* node offset from libfdt */
int err; int err;
@ -296,6 +296,111 @@ int do_fdt (cmd_tbl_t * cmdtp, int flag, int argc, char *argv[])
return err; return err;
} }
} }
/********************************************************************
* Display header info
********************************************************************/
} else if (argv[1][0] == 'h') {
u32 version = fdt_version(fdt);
printf("magic:\t\t\t0x%x\n", fdt_magic(fdt));
printf("totalsize:\t\t0x%x (%d)\n", fdt_totalsize(fdt), fdt_totalsize(fdt));
printf("off_dt_struct:\t\t0x%x\n", fdt_off_dt_struct(fdt));
printf("off_dt_strings:\t\t0x%x\n", fdt_off_dt_strings(fdt));
printf("off_mem_rsvmap:\t\t0x%x\n", fdt_off_mem_rsvmap(fdt));
printf("version:\t\t%d\n", version);
printf("last_comp_version:\t%d\n", fdt_last_comp_version(fdt));
if (version >= 2)
printf("boot_cpuid_phys:\t0x%x\n",
fdt_boot_cpuid_phys(fdt));
if (version >= 3)
printf("size_dt_strings:\t0x%x\n",
fdt_size_dt_strings(fdt));
if (version >= 17)
printf("size_dt_struct:\t\t0x%x\n",
fdt_size_dt_struct(fdt));
printf("number mem_rsv:\t\t0x%x\n", fdt_num_mem_rsv(fdt));
printf("\n");
/********************************************************************
* Set boot cpu id
********************************************************************/
} else if ((argv[1][0] == 'b') && (argv[1][1] == 'o') &&
(argv[1][2] == 'o')) {
unsigned long tmp = simple_strtoul(argv[2], NULL, 16);
fdt_set_boot_cpuid_phys(fdt, tmp);
/********************************************************************
* memory command
********************************************************************/
} else if ((argv[1][0] == 'm') && (argv[1][1] == 'e')) {
uint64_t addr, size;
int err;
#ifdef CFG_64BIT_STRTOUL
addr = simple_strtoull(argv[2], NULL, 16);
size = simple_strtoull(argv[3], NULL, 16);
#else
addr = simple_strtoul(argv[2], NULL, 16);
size = simple_strtoul(argv[3], NULL, 16);
#endif
err = fdt_fixup_memory(fdt, addr, size);
if (err < 0)
return err;
/********************************************************************
* mem reserve commands
********************************************************************/
} else if ((argv[1][0] == 'r') && (argv[1][1] == 's')) {
if (argv[2][0] == 'p') {
uint64_t addr, size;
int total = fdt_num_mem_rsv(fdt);
int j, err;
printf("index\t\t start\t\t size\n");
printf("-------------------------------"
"-----------------\n");
for (j = 0; j < total; j++) {
err = fdt_get_mem_rsv(fdt, j, &addr, &size);
if (err < 0) {
printf("libfdt fdt_get_mem_rsv(): %s\n",
fdt_strerror(err));
return err;
}
printf(" %x\t%08x%08x\t%08x%08x\n", j,
(u32)(addr >> 32),
(u32)(addr & 0xffffffff),
(u32)(size >> 32),
(u32)(size & 0xffffffff));
}
} else if (argv[2][0] == 'a') {
uint64_t addr, size;
int err;
#ifdef CFG_64BIT_STRTOUL
addr = simple_strtoull(argv[3], NULL, 16);
size = simple_strtoull(argv[4], NULL, 16);
#else
addr = simple_strtoul(argv[3], NULL, 16);
size = simple_strtoul(argv[4], NULL, 16);
#endif
err = fdt_add_mem_rsv(fdt, addr, size);
if (err < 0) {
printf("libfdt fdt_add_mem_rsv(): %s\n",
fdt_strerror(err));
return err;
}
} else if (argv[2][0] == 'd') {
unsigned long idx = simple_strtoul(argv[3], NULL, 16);
int err = fdt_del_mem_rsv(fdt, idx);
if (err < 0) {
printf("libfdt fdt_del_mem_rsv(): %s\n",
fdt_strerror(err));
return err;
}
} else {
/* Unrecognized command */
printf ("Usage:\n%s\n", cmdtp->usage);
return 1;
}
} }
#ifdef CONFIG_OF_BOARD_SETUP #ifdef CONFIG_OF_BOARD_SETUP
/* Call the board-specific fixup routine */ /* Call the board-specific fixup routine */
@ -689,6 +794,12 @@ U_BOOT_CMD(
"fdt set <path> <prop> [<val>] - Set <property> [to <val>]\n" "fdt set <path> <prop> [<val>] - Set <property> [to <val>]\n"
"fdt mknode <path> <node> - Create a new node after <path>\n" "fdt mknode <path> <node> - Create a new node after <path>\n"
"fdt rm <path> [<prop>] - Delete the node or <property>\n" "fdt rm <path> [<prop>] - Delete the node or <property>\n"
"fdt header - Display header info\n"
"fdt bootcpu <id> - Set boot cpuid\n"
"fdt memory <addr> <size> - Add/Update memory node\n"
"fdt rsvmem print - Show current mem reserves\n"
"fdt rsvmem add <addr> <size> - Add a mem reserve\n"
"fdt rsvmem delete <index> - Delete a mem reserves\n"
"fdt chosen - Add/update the /chosen branch in the tree\n" "fdt chosen - Add/update the /chosen branch in the tree\n"
#ifdef CONFIG_OF_HAS_UBOOT_ENV #ifdef CONFIG_OF_HAS_UBOOT_ENV
"fdt env - Add/replace the /u-boot-env branch in the tree\n" "fdt env - Add/replace the /u-boot-env branch in the tree\n"

View file

@ -1179,6 +1179,27 @@ void flash_print_info (flash_info_t * info)
return; return;
} }
/*-----------------------------------------------------------------------
* This is used in a few places in write_buf() to show programming
* progress. Making it a function is nasty because it needs to do side
* effect updates to digit and dots. Repeated code is nasty too, so
* we define it once here.
*/
#ifdef CONFIG_FLASH_SHOW_PROGRESS
#define FLASH_SHOW_PROGRESS(scale, dots, digit, dots_sub) \
dots -= dots_sub; \
if ((scale > 0) && (dots <= 0)) { \
if ((digit % 5) == 0) \
printf ("%d", digit / 5); \
else \
putc ('.'); \
digit--; \
dots += scale; \
}
#else
#define FLASH_SHOW_PROGRESS(scale, dots, digit, dots_sub)
#endif
/*----------------------------------------------------------------------- /*-----------------------------------------------------------------------
* Copy memory to flash, returns: * Copy memory to flash, returns:
* 0 - OK * 0 - OK
@ -1192,10 +1213,23 @@ int write_buff (flash_info_t * info, uchar * src, ulong addr, ulong cnt)
int aln; int aln;
cfiword_t cword; cfiword_t cword;
int i, rc; int i, rc;
#ifdef CFG_FLASH_USE_BUFFER_WRITE #ifdef CFG_FLASH_USE_BUFFER_WRITE
int buffered_size; int buffered_size;
#endif #endif
#ifdef CONFIG_FLASH_SHOW_PROGRESS
int digit = CONFIG_FLASH_SHOW_PROGRESS;
int scale = 0;
int dots = 0;
/*
* Suppress if there are fewer than CONFIG_FLASH_SHOW_PROGRESS writes.
*/
if (cnt >= CONFIG_FLASH_SHOW_PROGRESS) {
scale = (int)((cnt + CONFIG_FLASH_SHOW_PROGRESS - 1) /
CONFIG_FLASH_SHOW_PROGRESS);
}
#endif
/* get lower aligned address */ /* get lower aligned address */
wp = (addr & ~(info->portwidth - 1)); wp = (addr & ~(info->portwidth - 1));
@ -1219,6 +1253,7 @@ int write_buff (flash_info_t * info, uchar * src, ulong addr, ulong cnt)
return rc; return rc;
wp += i; wp += i;
FLASH_SHOW_PROGRESS(scale, dots, digit, i);
} }
/* handle the aligned part */ /* handle the aligned part */
@ -1248,6 +1283,7 @@ int write_buff (flash_info_t * info, uchar * src, ulong addr, ulong cnt)
wp += i; wp += i;
src += i; src += i;
cnt -= i; cnt -= i;
FLASH_SHOW_PROGRESS(scale, dots, digit, i);
} }
#else #else
while (cnt >= info->portwidth) { while (cnt >= info->portwidth) {
@ -1259,8 +1295,10 @@ int write_buff (flash_info_t * info, uchar * src, ulong addr, ulong cnt)
return rc; return rc;
wp += info->portwidth; wp += info->portwidth;
cnt -= info->portwidth; cnt -= info->portwidth;
FLASH_SHOW_PROGRESS(scale, dots, digit, info->portwidth);
} }
#endif /* CFG_FLASH_USE_BUFFER_WRITE */ #endif /* CFG_FLASH_USE_BUFFER_WRITE */
if (cnt == 0) { if (cnt == 0) {
return (0); return (0);
} }

View file

@ -252,12 +252,22 @@
"setup=tftp 200000 cam5200/setup.img; autoscr 200000\0" "setup=tftp 200000 cam5200/setup.img; autoscr 200000\0"
#endif #endif
#if defined(CONFIG_TQM5200_B)
#define ENV_FLASH_LAYOUT \
"fdt_addr=FC100000\0" \
"kernel_addr=FC140000\0" \
"ramdisk_addr=FC600000\0"
#else /* !CONFIG_TQM5200_B */
#define ENV_FLASH_LAYOUT \
"fdt_addr=FC0A0000\0" \
"kernel_addr=FC0C0000\0" \
"ramdisk_addr=FC300000\0"
#endif
#define CONFIG_EXTRA_ENV_SETTINGS \ #define CONFIG_EXTRA_ENV_SETTINGS \
"netdev=eth0\0" \ "netdev=eth0\0" \
"console=ttyPSC0\0" \ "console=ttyPSC0\0" \
"fdt_addr=FC0A0000\0" \ ENV_FLASH_LAYOUT \
"kernel_addr=FC0C0000\0" \
"ramdisk_addr=FC300000\0" \
"kernel_addr_r=400000\0" \ "kernel_addr_r=400000\0" \
"fdt_addr_r=600000\0" \ "fdt_addr_r=600000\0" \
"rootpath=/opt/eldk/ppc_6xx\0" \ "rootpath=/opt/eldk/ppc_6xx\0" \
@ -400,8 +410,9 @@
# if defined(CONFIG_TQM5200_B) # if defined(CONFIG_TQM5200_B)
# if defined(CFG_LOWBOOT) # if defined(CFG_LOWBOOT)
# define MTDPARTS_DEFAULT "mtdparts=TQM5200-0:1m(firmware)," \ # define MTDPARTS_DEFAULT "mtdparts=TQM5200-0:1m(firmware)," \
"1536k(kernel)," \ "256k(dtb)," \
"3584k(small-fs)," \ "2304k(kernel)," \
"2560k(small-fs)," \
"2m(initrd)," \ "2m(initrd)," \
"8m(misc)," \ "8m(misc)," \
"16m(big-fs)" "16m(big-fs)"

View file

@ -130,6 +130,12 @@ static inline void *fdt_offset_ptr_w(void *fdt, int offset, int checklen)
uint32_t fdt_next_tag(const void *fdt, int offset, int *nextoffset); uint32_t fdt_next_tag(const void *fdt, int offset, int *nextoffset);
/**********************************************************************/
/* Traversal functions */
/**********************************************************************/
int fdt_next_node(const void *fdt, int offset, int *depth);
/**********************************************************************/ /**********************************************************************/
/* General functions */ /* General functions */
/**********************************************************************/ /**********************************************************************/
@ -845,6 +851,32 @@ int fdt_add_mem_rsv(void *fdt, uint64_t address, uint64_t size);
*/ */
int fdt_del_mem_rsv(void *fdt, int n); int fdt_del_mem_rsv(void *fdt, int n);
/**
* fdt_set_name - change the name of a given node
* @fdt: pointer to the device tree blob
* @nodeoffset: structure block offset of a node
* @name: name to give the node
*
* fdt_set_name() replaces the name (including unit address, if any)
* of the given node with the given string. NOTE: this function can't
* efficiently check if the new name is unique amongst the given
* node's siblings; results are undefined if this function is invoked
* with a name equal to one of the given node's siblings.
*
* 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 name
* -FDT_ERR_BADOFFSET, nodeoffset did not point to FDT_BEGIN_NODE tag
* -FDT_ERR_BADMAGIC,
* -FDT_ERR_BADVERSION,
* -FDT_ERR_BADSTATE, standard meanings
*/
int fdt_set_name(void *fdt, int nodeoffset, const char *name);
/** /**
* fdt_setprop - create or change a property * fdt_setprop - create or change a property
* @fdt: pointer to the device tree blob * @fdt: pointer to the device tree blob

View file

@ -129,6 +129,47 @@ uint32_t fdt_next_tag(const void *fdt, int offset, int *nextoffset)
return tag; return tag;
} }
int fdt_next_node(const void *fdt, int offset, int *depth)
{
int nextoffset = 0;
uint32_t tag;
if (offset >= 0) {
tag = fdt_next_tag(fdt, offset, &nextoffset);
if (tag != FDT_BEGIN_NODE)
return -FDT_ERR_BADOFFSET;
}
do {
offset = nextoffset;
tag = fdt_next_tag(fdt, offset, &nextoffset);
switch (tag) {
case FDT_PROP:
case FDT_NOP:
break;
case FDT_BEGIN_NODE:
if (depth)
(*depth)++;
break;
case FDT_END_NODE:
if (depth)
(*depth)--;
break;
case FDT_END:
return -FDT_ERR_NOTFOUND;
default:
return -FDT_ERR_BADSTRUCTURE;
}
} while (tag != FDT_BEGIN_NODE);
return offset;
}
const char *_fdt_find_string(const char *strtab, int tabsize, const char *s) const char *_fdt_find_string(const char *strtab, int tabsize, const char *s)
{ {
int len = strlen(s) + 1; int len = strlen(s) + 1;
@ -143,10 +184,7 @@ const char *_fdt_find_string(const char *strtab, int tabsize, const char *s)
int fdt_move(const void *fdt, void *buf, int bufsize) int fdt_move(const void *fdt, void *buf, int bufsize)
{ {
int err = fdt_check_header(fdt); CHECK_HEADER(fdt);
if (err)
return err;
if (fdt_totalsize(fdt) > bufsize) if (fdt_totalsize(fdt) > bufsize)
return -FDT_ERR_NOSPACE; return -FDT_ERR_NOSPACE;

View file

@ -55,17 +55,10 @@
#include "libfdt_internal.h" #include "libfdt_internal.h"
#define CHECK_HEADER(fdt) \
{ \
int err; \
if ((err = fdt_check_header(fdt)) != 0) \
return err; \
}
static int nodename_eq(const void *fdt, int offset, static int nodename_eq(const void *fdt, int offset,
const char *s, int len) const char *s, int len)
{ {
const char *p = fdt_offset_ptr(fdt, offset, len+1); const char *p = fdt_offset_ptr(fdt, offset + FDT_TAGSIZE, len+1);
if (! p) if (! p)
/* short match */ /* short match */
@ -104,50 +97,24 @@ int fdt_num_mem_rsv(const void *fdt)
return i; return i;
} }
int fdt_subnode_offset_namelen(const void *fdt, int parentoffset, int fdt_subnode_offset_namelen(const void *fdt, int offset,
const char *name, int namelen) const char *name, int namelen)
{ {
int level = 0; int depth;
uint32_t tag;
int offset, nextoffset;
CHECK_HEADER(fdt); CHECK_HEADER(fdt);
tag = fdt_next_tag(fdt, parentoffset, &nextoffset); for (depth = 0;
if (tag != FDT_BEGIN_NODE) offset >= 0;
return -FDT_ERR_BADOFFSET; offset = fdt_next_node(fdt, offset, &depth)) {
if (depth < 0)
do {
offset = nextoffset;
tag = fdt_next_tag(fdt, offset, &nextoffset);
switch (tag) {
case FDT_END:
return -FDT_ERR_TRUNCATED;
case FDT_BEGIN_NODE:
level++;
if (level != 1)
continue;
if (nodename_eq(fdt, offset+FDT_TAGSIZE, name, namelen))
/* Found it! */
return offset;
break;
case FDT_END_NODE:
level--;
break;
case FDT_PROP:
case FDT_NOP:
break;
default:
return -FDT_ERR_BADSTRUCTURE;
}
} while (level >= 0);
return -FDT_ERR_NOTFOUND; return -FDT_ERR_NOTFOUND;
else if ((depth == 1)
&& nodename_eq(fdt, offset, name, namelen))
return offset;
}
return offset; /* error */
} }
int fdt_subnode_offset(const void *fdt, int parentoffset, int fdt_subnode_offset(const void *fdt, int parentoffset,
@ -307,76 +274,61 @@ uint32_t fdt_get_phandle(const void *fdt, int nodeoffset)
int fdt_get_path(const void *fdt, int nodeoffset, char *buf, int buflen) int fdt_get_path(const void *fdt, int nodeoffset, char *buf, int buflen)
{ {
uint32_t tag; int pdepth = 0, p = 0;
int p = 0, overflow = 0; int offset, depth, namelen;
int offset, nextoffset, namelen;
const char *name; const char *name;
CHECK_HEADER(fdt); CHECK_HEADER(fdt);
tag = fdt_next_tag(fdt, 0, &nextoffset);
if (tag != FDT_BEGIN_NODE)
return -FDT_ERR_BADSTRUCTURE;
if (buflen < 2) if (buflen < 2)
return -FDT_ERR_NOSPACE; return -FDT_ERR_NOSPACE;
buf[0] = '/';
p = 1;
while (nextoffset <= nodeoffset) { for (offset = 0, depth = 0;
offset = nextoffset; (offset >= 0) && (offset <= nodeoffset);
tag = fdt_next_tag(fdt, offset, &nextoffset); offset = fdt_next_node(fdt, offset, &depth)) {
switch (tag) { if (pdepth < depth)
case FDT_END: continue; /* overflowed buffer */
return -FDT_ERR_BADOFFSET;
case FDT_BEGIN_NODE: while (pdepth > depth) {
name = fdt_get_name(fdt, offset, &namelen);
if (!name)
return namelen;
if (overflow || ((p + namelen + 1) > buflen)) {
overflow++;
break;
}
memcpy(buf + p, name, namelen);
p += namelen;
buf[p++] = '/';
break;
case FDT_END_NODE:
if (overflow) {
overflow--;
break;
}
do { do {
p--; p--;
} while (buf[p-1] != '/'); } while (buf[p-1] != '/');
break; pdepth--;
case FDT_PROP:
case FDT_NOP:
break;
default:
return -FDT_ERR_BADSTRUCTURE;
}
} }
if (overflow) name = fdt_get_name(fdt, offset, &namelen);
if (!name)
return namelen;
if ((p + namelen + 1) <= buflen) {
memcpy(buf + p, name, namelen);
p += namelen;
buf[p++] = '/';
pdepth++;
}
if (offset == nodeoffset) {
if (pdepth < (depth + 1))
return -FDT_ERR_NOSPACE; return -FDT_ERR_NOSPACE;
if (p > 1) /* special case so that root path is "/", not "" */ if (p > 1) /* special case so that root path is "/", not "" */
p--; p--;
buf[p] = '\0'; buf[p] = '\0';
return p; return p;
}
}
if ((offset == -FDT_ERR_NOTFOUND) || (offset >= 0))
return -FDT_ERR_BADOFFSET;
else if (offset == -FDT_ERR_BADOFFSET)
return -FDT_ERR_BADSTRUCTURE;
return offset; /* error from fdt_next_node() */
} }
int fdt_supernode_atdepth_offset(const void *fdt, int nodeoffset, int fdt_supernode_atdepth_offset(const void *fdt, int nodeoffset,
int supernodedepth, int *nodedepth) int supernodedepth, int *nodedepth)
{ {
int level = -1; int offset, depth;
uint32_t tag;
int offset, nextoffset = 0;
int supernodeoffset = -FDT_ERR_INTERNAL; int supernodeoffset = -FDT_ERR_INTERNAL;
CHECK_HEADER(fdt); CHECK_HEADER(fdt);
@ -384,38 +336,29 @@ int fdt_supernode_atdepth_offset(const void *fdt, int nodeoffset,
if (supernodedepth < 0) if (supernodedepth < 0)
return -FDT_ERR_NOTFOUND; return -FDT_ERR_NOTFOUND;
do { for (offset = 0, depth = 0;
offset = nextoffset; (offset >= 0) && (offset <= nodeoffset);
tag = fdt_next_tag(fdt, offset, &nextoffset); offset = fdt_next_node(fdt, offset, &depth)) {
switch (tag) { if (depth == supernodedepth)
case FDT_END:
return -FDT_ERR_BADOFFSET;
case FDT_BEGIN_NODE:
level++;
if (level == supernodedepth)
supernodeoffset = offset; supernodeoffset = offset;
break;
case FDT_END_NODE:
level--;
break;
case FDT_PROP:
case FDT_NOP:
break;
default:
return -FDT_ERR_BADSTRUCTURE;
}
} while (offset < nodeoffset);
if (offset == nodeoffset) {
if (nodedepth) if (nodedepth)
*nodedepth = level; *nodedepth = depth;
if (supernodedepth > level) if (supernodedepth > depth)
return -FDT_ERR_NOTFOUND; return -FDT_ERR_NOTFOUND;
else
return supernodeoffset; return supernodeoffset;
}
}
if ((offset == -FDT_ERR_NOTFOUND) || (offset >= 0))
return -FDT_ERR_BADOFFSET;
else if (offset == -FDT_ERR_BADOFFSET)
return -FDT_ERR_BADSTRUCTURE;
return offset; /* error from fdt_next_node() */
} }
int fdt_node_depth(const void *fdt, int nodeoffset) int fdt_node_depth(const void *fdt, int nodeoffset)
@ -443,51 +386,27 @@ int fdt_node_offset_by_prop_value(const void *fdt, int startoffset,
const char *propname, const char *propname,
const void *propval, int proplen) const void *propval, int proplen)
{ {
uint32_t tag; int offset;
int offset, nextoffset;
const void *val; const void *val;
int len; int len;
CHECK_HEADER(fdt); CHECK_HEADER(fdt);
if (startoffset >= 0) {
tag = fdt_next_tag(fdt, startoffset, &nextoffset);
if (tag != FDT_BEGIN_NODE)
return -FDT_ERR_BADOFFSET;
} else {
nextoffset = 0;
}
/* FIXME: The algorithm here is pretty horrible: we scan each /* FIXME: The algorithm here is pretty horrible: we scan each
* property of a node in fdt_getprop(), then if that didn't * property of a node in fdt_getprop(), then if that didn't
* find what we want, we scan over them again making our way * find what we want, we scan over them again making our way
* to the next node. Still it's the easiest to implement * to the next node. Still it's the easiest to implement
* approach; performance can come later. */ * approach; performance can come later. */
do { for (offset = fdt_next_node(fdt, startoffset, NULL);
offset = nextoffset; offset >= 0;
tag = fdt_next_tag(fdt, offset, &nextoffset); offset = fdt_next_node(fdt, offset, NULL)) {
switch (tag) {
case FDT_BEGIN_NODE:
val = fdt_getprop(fdt, offset, propname, &len); val = fdt_getprop(fdt, offset, propname, &len);
if (val if (val && (len == proplen)
&& (len == proplen)
&& (memcmp(val, propval, len) == 0)) && (memcmp(val, propval, len) == 0))
return offset; return offset;
break;
case FDT_PROP:
case FDT_END:
case FDT_END_NODE:
case FDT_NOP:
break;
default:
return -FDT_ERR_BADSTRUCTURE;
} }
} while (tag != FDT_END);
return -FDT_ERR_NOTFOUND; return offset; /* error from fdt_next_node() */
} }
int fdt_node_offset_by_phandle(const void *fdt, uint32_t phandle) int fdt_node_offset_by_phandle(const void *fdt, uint32_t phandle)
@ -534,50 +453,24 @@ int fdt_node_check_compatible(const void *fdt, int nodeoffset,
int fdt_node_offset_by_compatible(const void *fdt, int startoffset, int fdt_node_offset_by_compatible(const void *fdt, int startoffset,
const char *compatible) const char *compatible)
{ {
uint32_t tag; int offset, err;
int offset, nextoffset;
int err;
CHECK_HEADER(fdt); CHECK_HEADER(fdt);
if (startoffset >= 0) {
tag = fdt_next_tag(fdt, startoffset, &nextoffset);
if (tag != FDT_BEGIN_NODE)
return -FDT_ERR_BADOFFSET;
} else {
nextoffset = 0;
}
/* FIXME: The algorithm here is pretty horrible: we scan each /* FIXME: The algorithm here is pretty horrible: we scan each
* property of a node in fdt_node_check_compatible(), then if * property of a node in fdt_node_check_compatible(), then if
* that didn't find what we want, we scan over them again * that didn't find what we want, we scan over them again
* making our way to the next node. Still it's the easiest to * making our way to the next node. Still it's the easiest to
* implement approach; performance can come later. */ * implement approach; performance can come later. */
do { for (offset = fdt_next_node(fdt, startoffset, NULL);
offset = nextoffset; offset >= 0;
tag = fdt_next_tag(fdt, offset, &nextoffset); offset = fdt_next_node(fdt, offset, NULL)) {
err = fdt_node_check_compatible(fdt, offset, compatible);
switch (tag) { if ((err < 0) && (err != -FDT_ERR_NOTFOUND))
case FDT_BEGIN_NODE:
err = fdt_node_check_compatible(fdt, offset,
compatible);
if ((err < 0)
&& (err != -FDT_ERR_NOTFOUND))
return err; return err;
else if (err == 0) else if (err == 0)
return offset; return offset;
break;
case FDT_PROP:
case FDT_END:
case FDT_END_NODE:
case FDT_NOP:
break;
default:
return -FDT_ERR_BADSTRUCTURE;
} }
} while (tag != FDT_END);
return -FDT_ERR_NOTFOUND; return offset; /* error from fdt_next_node() */
} }

View file

@ -69,10 +69,8 @@ static int _blocks_misordered(const void *fdt,
static int rw_check_header(void *fdt) static int rw_check_header(void *fdt)
{ {
int err; CHECK_HEADER(fdt);
if ((err = fdt_check_header(fdt)))
return err;
if (fdt_version(fdt) < 17) if (fdt_version(fdt) < 17)
return -FDT_ERR_BADVERSION; return -FDT_ERR_BADVERSION;
if (_blocks_misordered(fdt, sizeof(struct fdt_reserve_entry), if (_blocks_misordered(fdt, sizeof(struct fdt_reserve_entry),
@ -252,6 +250,30 @@ static int _add_property(void *fdt, int nodeoffset, const char *name, int len,
return 0; return 0;
} }
int fdt_set_name(void *fdt, int nodeoffset, const char *name)
{
char *namep;
int oldlen, newlen;
int err;
if ((err = rw_check_header(fdt)))
return err;
namep = (char *)fdt_get_name(fdt, nodeoffset, &oldlen);
if (!namep)
return oldlen;
newlen = strlen(name);
err = _blob_splice_struct(fdt, namep, ALIGN(oldlen+1, FDT_TAGSIZE),
ALIGN(newlen+1, FDT_TAGSIZE));
if (err)
return err;
memcpy(namep, name, newlen+1);
return 0;
}
int fdt_setprop(void *fdt, int nodeoffset, const char *name, int fdt_setprop(void *fdt, int nodeoffset, const char *name,
const void *val, int len) const void *val, int len)
{ {
@ -309,7 +331,7 @@ int fdt_add_subnode_namelen(void *fdt, int parentoffset,
do { do {
offset = nextoffset; offset = nextoffset;
tag = fdt_next_tag(fdt, offset, &nextoffset); tag = fdt_next_tag(fdt, offset, &nextoffset);
} while (tag == FDT_PROP); } while ((tag == FDT_PROP) || (tag == FDT_NOP));
nh = _fdt_offset_ptr_w(fdt, offset); nh = _fdt_offset_ptr_w(fdt, offset);
nodelen = sizeof(*nh) + ALIGN(namelen+1, FDT_TAGSIZE) + FDT_TAGSIZE; nodelen = sizeof(*nh) + ALIGN(namelen+1, FDT_TAGSIZE) + FDT_TAGSIZE;
@ -375,9 +397,7 @@ int fdt_open_into(const void *fdt, void *buf, int bufsize)
int newsize; int newsize;
void *tmp; void *tmp;
err = fdt_check_header(fdt); CHECK_HEADER(fdt);
if (err)
return err;
mem_rsv_size = (fdt_num_mem_rsv(fdt)+1) mem_rsv_size = (fdt_num_mem_rsv(fdt)+1)
* sizeof(struct fdt_reserve_entry); * sizeof(struct fdt_reserve_entry);

View file

@ -58,6 +58,13 @@
#define memeq(p, q, n) (memcmp((p), (q), (n)) == 0) #define memeq(p, q, n) (memcmp((p), (q), (n)) == 0)
#define streq(p, q) (strcmp((p), (q)) == 0) #define streq(p, q) (strcmp((p), (q)) == 0)
#define CHECK_HEADER(fdt) \
{ \
int err; \
if ((err = fdt_check_header(fdt)) != 0) \
return err; \
}
uint32_t _fdt_next_tag(const void *fdt, int startoffset, int *nextoffset); uint32_t _fdt_next_tag(const void *fdt, int startoffset, int *nextoffset);
const char *_fdt_find_string(const char *strtab, int tabsize, const char *s); const char *_fdt_find_string(const char *strtab, int tabsize, const char *s);
int _fdt_node_end_offset(void *fdt, int nodeoffset); int _fdt_node_end_offset(void *fdt, int nodeoffset);

View file

@ -24,7 +24,8 @@
#include <common.h> #include <common.h>
/* This test verifies if the reason of last reset was an abnormal voltage /*
* This test verifies if the reason of last reset was an abnormal voltage
* condition, than it performs watchdog test, measuing time required to * condition, than it performs watchdog test, measuing time required to
* trigger watchdog reset. * trigger watchdog reset.
*/ */
@ -55,7 +56,8 @@ static void watchdog_magic_write(uint value)
int sysmon1_post_test(int flags) int sysmon1_post_test(int flags)
{ {
if (gpio_read_in_bit(CFG_GPIO_SYSMON_STATUS)) { if (gpio_read_in_bit(CFG_GPIO_SYSMON_STATUS)) {
/* 3.1. GPIO62 is low /*
* 3.1. GPIO62 is low
* Assuming system voltage failure. * Assuming system voltage failure.
*/ */
post_log("Abnormal voltage detected (GPIO62)\n"); post_log("Abnormal voltage detected (GPIO62)\n");
@ -67,11 +69,14 @@ int sysmon1_post_test(int flags)
int lwmon5_watchdog_post_test(int flags) int lwmon5_watchdog_post_test(int flags)
{ {
ulong time;
/* On each reset scratch register 1 should be tested, /* On each reset scratch register 1 should be tested,
* but first test GPIO62: * but first test GPIO62:
*/ */
if (!(flags & POST_MANUAL) && sysmon1_post_test(flags)) { if (!(flags & POST_MANUAL) && sysmon1_post_test(flags)) {
/* 3.1. GPIO62 is low /*
* 3.1. GPIO62 is low
* Assuming system voltage failure. * Assuming system voltage failure.
*/ */
/* 3.1.1. Set scratch register 1 to 0x0000xxxx */ /* 3.1.1. Set scratch register 1 to 0x0000xxxx */
@ -81,12 +86,12 @@ int lwmon5_watchdog_post_test(int flags)
} }
if (watchdog_magic_read() != CFG_WATCHDOG_MAGIC) { if (watchdog_magic_read() != CFG_WATCHDOG_MAGIC) {
/* 3.2. Scratch register 1 differs from magic value 0x1248xxxx /*
* 3.2. Scratch register 1 differs from magic value 0x1248xxxx
* Assuming PowerOn * Assuming PowerOn
*/ */
int ints; int ints;
ulong base; ulong base;
ulong time;
/* 3.2.1. Set magic value to scratch register */ /* 3.2.1. Set magic value to scratch register */
watchdog_magic_write(CFG_WATCHDOG_MAGIC); watchdog_magic_write(CFG_WATCHDOG_MAGIC);
@ -104,28 +109,28 @@ int lwmon5_watchdog_post_test(int flags)
if (ints) if (ints)
enable_interrupts (); enable_interrupts ();
/* 3.2.5. Reset didn't happen. - Set 0x0000xxxx /*
* 3.2.5. Reset didn't happen. - Set 0x0000xxxx
* into scratch register 1 * into scratch register 1
*/ */
watchdog_magic_write(0); watchdog_magic_write(0);
/* 3.2.6. Mark test as failed. */ /* 3.2.6. Mark test as failed. */
post_log("hw watchdog time : %u ms, failed ", time); post_log("hw watchdog time : %u ms, failed ", time);
return 2; return 2;
} else { }
/* 3.3. Scratch register matches magic value 0x1248xxxx
/*
* 3.3. Scratch register matches magic value 0x1248xxxx
* Assume this is watchdog-initiated reset * Assume this is watchdog-initiated reset
*/ */
ulong time;
/* 3.3.1. So, the test succeed, save measured time to syslog. */ /* 3.3.1. So, the test succeed, save measured time to syslog. */
time = in_be32((void *)CFG_WATCHDOG_TIME_ADDR); time = in_be32((void *)CFG_WATCHDOG_TIME_ADDR);
post_log("hw watchdog time : %u ms, passed ", time); post_log("hw watchdog time : %u ms, passed ", time);
/* 3.3.2. Set scratch register 1 to 0x0000xxxx */ /* 3.3.2. Set scratch register 1 to 0x0000xxxx */
watchdog_magic_write(0); watchdog_magic_write(0);
return 0;
}
return -1;
}
return 0;
}
#endif /* CONFIG_POST & CFG_POST_WATCHDOG */ #endif /* CONFIG_POST & CFG_POST_WATCHDOG */
#endif /* CONFIG_POST */ #endif /* CONFIG_POST */