summaryrefslogtreecommitdiffstats
path: root/arch/powerpc/boot/devtree.c
diff options
context:
space:
mode:
authorScott Wood <scottwood@freescale.com>2007-08-21 03:39:48 +1000
committerPaul Mackerras <paulus@samba.org>2007-08-22 15:21:48 +1000
commita73ac50c4787b1b28d5c94bb18c60352f5dd7d6f (patch)
tree8c78ad293d3ee4bb43543e25df348b729832a02c /arch/powerpc/boot/devtree.c
parent0602801c22ea1767cd0298b11da140bd5cb764d2 (diff)
[POWERPC] bootwrapper: Add dt_is_compatible()
This can be used rather than doing a simple strcmp, which will fail to handle multiple compatible entries. Signed-off-by: Scott Wood <scottwood@freescale.com> Acked-by: David Gibson <david@gibson.dropbear.id.au> Signed-off-by: Paul Mackerras <paulus@samba.org>
Diffstat (limited to 'arch/powerpc/boot/devtree.c')
-rw-r--r--arch/powerpc/boot/devtree.c48
1 files changed, 33 insertions, 15 deletions
diff --git a/arch/powerpc/boot/devtree.c b/arch/powerpc/boot/devtree.c
index 129e6d9b8d4..3a18bfe0fdf 100644
--- a/arch/powerpc/boot/devtree.c
+++ b/arch/powerpc/boot/devtree.c
@@ -113,7 +113,6 @@ void __dt_fixup_mac_addresses(u32 startindex, ...)
}
#define MAX_ADDR_CELLS 4
-#define MAX_RANGES 8
static void get_reg_format(void *node, u32 *naddr, u32 *nsize)
{
@@ -209,7 +208,7 @@ static int find_range(u32 *reg, u32 *ranges, int nregaddr,
* In particular, PCI is not supported. Also, only the beginning of the
* reg block is tracked; size is ignored except in ranges.
*/
-static u32 dt_xlate_buf[MAX_ADDR_CELLS * MAX_RANGES * 3];
+static u32 prop_buf[MAX_PROP_LEN / 4];
static int dt_xlate(void *node, int res, int reglen, unsigned long *addr,
unsigned long *size)
@@ -233,15 +232,15 @@ static int dt_xlate(void *node, int res, int reglen, unsigned long *addr,
offset = (naddr + nsize) * res;
if (reglen < offset + naddr + nsize ||
- sizeof(dt_xlate_buf) < (offset + naddr + nsize) * 4)
+ MAX_PROP_LEN < (offset + naddr + nsize) * 4)
return 0;
- copy_val(last_addr, dt_xlate_buf + offset, naddr);
+ copy_val(last_addr, prop_buf + offset, naddr);
- ret_size = dt_xlate_buf[offset + naddr];
+ ret_size = prop_buf[offset + naddr];
if (nsize == 2) {
ret_size <<= 32;
- ret_size |= dt_xlate_buf[offset + naddr + 1];
+ ret_size |= prop_buf[offset + naddr + 1];
}
for (;;) {
@@ -255,25 +254,25 @@ static int dt_xlate(void *node, int res, int reglen, unsigned long *addr,
get_reg_format(parent, &naddr, &nsize);
- buflen = getprop(node, "ranges", dt_xlate_buf,
- sizeof(dt_xlate_buf));
+ buflen = getprop(node, "ranges", prop_buf,
+ sizeof(prop_buf));
if (buflen == 0)
continue;
- if (buflen < 0 || buflen > sizeof(dt_xlate_buf))
+ if (buflen < 0 || buflen > sizeof(prop_buf))
return 0;
- offset = find_range(last_addr, dt_xlate_buf, prev_naddr,
+ offset = find_range(last_addr, prop_buf, prev_naddr,
naddr, prev_nsize, buflen / 4);
if (offset < 0)
return 0;
- copy_val(this_addr, dt_xlate_buf + offset, prev_naddr);
+ copy_val(this_addr, prop_buf + offset, prev_naddr);
if (!sub_reg(last_addr, this_addr))
return 0;
- copy_val(this_addr, dt_xlate_buf + offset + prev_naddr, naddr);
+ copy_val(this_addr, prop_buf + offset + prev_naddr, naddr);
if (!add_reg(last_addr, this_addr, naddr))
return 0;
@@ -300,16 +299,35 @@ int dt_xlate_reg(void *node, int res, unsigned long *addr, unsigned long *size)
{
int reglen;
- reglen = getprop(node, "reg", dt_xlate_buf, sizeof(dt_xlate_buf)) / 4;
+ reglen = getprop(node, "reg", prop_buf, sizeof(prop_buf)) / 4;
return dt_xlate(node, res, reglen, addr, size);
}
int dt_xlate_addr(void *node, u32 *buf, int buflen, unsigned long *xlated_addr)
{
- if (buflen > sizeof(dt_xlate_buf))
+ if (buflen > sizeof(prop_buf))
return 0;
- memcpy(dt_xlate_buf, buf, buflen);
+ memcpy(prop_buf, buf, buflen);
return dt_xlate(node, 0, buflen / 4, xlated_addr, NULL);
}
+
+int dt_is_compatible(void *node, const char *compat)
+{
+ char *buf = (char *)prop_buf;
+ int len, pos;
+
+ len = getprop(node, "compatible", buf, MAX_PROP_LEN);
+ if (len < 0)
+ return 0;
+
+ for (pos = 0; pos < len; pos++) {
+ if (!strcmp(buf + pos, compat))
+ return 1;
+
+ pos += strnlen(&buf[pos], len - pos);
+ }
+
+ return 0;
+}