summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMark Kettenis <kettenis@cvs.openbsd.org>2023-02-13 16:16:04 +0000
committerMark Kettenis <kettenis@cvs.openbsd.org>2023-02-13 16:16:04 +0000
commit02c5932ab2970cf4c2a11e6111f33f578372d76d (patch)
tree4081d639ec43995e15c0b647d183e34cf03787f1
parentf645ca647f98fec6f7f642e4bb9dfa319f17f212 (diff)
Support device trees with NOPs in them (like the kernel version already
does). tested by jca@ (riscv64) ok patrick@
-rw-r--r--sys/arch/arm64/stand/efiboot/fdt.c35
-rw-r--r--sys/arch/armv7/stand/efiboot/fdt.c35
-rw-r--r--sys/arch/riscv64/stand/efiboot/fdt.c35
3 files changed, 75 insertions, 30 deletions
diff --git a/sys/arch/arm64/stand/efiboot/fdt.c b/sys/arch/arm64/stand/efiboot/fdt.c
index b1e3d6ebb14..5c0cfedce0c 100644
--- a/sys/arch/arm64/stand/efiboot/fdt.c
+++ b/sys/arch/arm64/stand/efiboot/fdt.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: fdt.c,v 1.7 2022/11/05 18:56:09 patrick Exp $ */
+/* $OpenBSD: fdt.c,v 1.8 2023/02/13 16:16:03 kettenis Exp $ */
/*
* Copyright (c) 2009 Dariusz Swiderski <sfires@sfires.net>
@@ -30,6 +30,7 @@ void *skip_property(uint32_t *);
void *skip_props(uint32_t *);
void *skip_node_name(uint32_t *);
void *skip_node(void *);
+void *skip_nops(uint32_t *);
void *fdt_parent_node_recurse(void *, void *);
static int tree_inited = 0;
@@ -39,7 +40,7 @@ unsigned int
fdt_check_head(void *fdt)
{
struct fdt_head *fh;
- uint32_t *ptr;
+ uint32_t *ptr, *tok;
fh = fdt;
ptr = (uint32_t *)fdt;
@@ -50,8 +51,8 @@ fdt_check_head(void *fdt)
if (betoh32(fh->fh_version) > FDT_CODE_VERSION)
return 0;
- if (betoh32(*(ptr + (betoh32(fh->fh_struct_off) / 4))) !=
- FDT_NODE_BEGIN)
+ tok = skip_nops(ptr + (betoh32(fh->fh_struct_off) / 4));
+ if (betoh32(*tok) != FDT_NODE_BEGIN)
return 0;
/* check for end signature on version 17 blob */
@@ -154,6 +155,16 @@ fdt_add_str(char *name)
/*
* Utility functions for skipping parts of tree.
*/
+
+void *
+skip_nops(uint32_t *ptr)
+{
+ while (betoh32(*ptr) == FDT_NOP)
+ ptr++;
+
+ return ptr;
+}
+
void *
skip_property(uint32_t *ptr)
{
@@ -163,7 +174,7 @@ skip_property(uint32_t *ptr)
/* move forward by magic + size + nameid + rounded up property size */
ptr += 3 + roundup(size, sizeof(uint32_t)) / sizeof(uint32_t);
- return ptr;
+ return skip_nops(ptr);
}
void *
@@ -179,8 +190,10 @@ void *
skip_node_name(uint32_t *ptr)
{
/* skip name, aligned to 4 bytes, this is NULL term., so must add 1 */
- return ptr + roundup(strlen((char *)ptr) + 1,
+ ptr += roundup(strlen((char *)ptr) + 1,
sizeof(uint32_t)) / sizeof(uint32_t);
+
+ return skip_nops(ptr);
}
/*
@@ -346,7 +359,7 @@ skip_node(void *node)
while (betoh32(*ptr) == FDT_NODE_BEGIN)
ptr = skip_node(ptr);
- return (ptr + 1);
+ return skip_nops(ptr + 1);
}
/*
@@ -365,7 +378,7 @@ fdt_next_node(void *node)
ptr = node;
if (node == NULL) {
- ptr = (uint32_t *)tree.tree;
+ ptr = skip_nops((uint32_t *)tree.tree);
return (betoh32(*ptr) == FDT_NODE_BEGIN) ? ptr : NULL;
}
@@ -384,10 +397,12 @@ fdt_next_node(void *node)
if (betoh32(*ptr) != FDT_NODE_END)
return NULL;
- if (betoh32(*(ptr + 1)) != FDT_NODE_BEGIN)
+ ptr = skip_nops(ptr + 1);
+
+ if (betoh32(*ptr) != FDT_NODE_BEGIN)
return NULL;
- return (ptr + 1);
+ return ptr;
}
/*
diff --git a/sys/arch/armv7/stand/efiboot/fdt.c b/sys/arch/armv7/stand/efiboot/fdt.c
index 9c49b840a28..ccc524755d1 100644
--- a/sys/arch/armv7/stand/efiboot/fdt.c
+++ b/sys/arch/armv7/stand/efiboot/fdt.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: fdt.c,v 1.9 2022/11/05 18:56:09 patrick Exp $ */
+/* $OpenBSD: fdt.c,v 1.10 2023/02/13 16:16:03 kettenis Exp $ */
/*
* Copyright (c) 2009 Dariusz Swiderski <sfires@sfires.net>
@@ -30,6 +30,7 @@ void *skip_property(uint32_t *);
void *skip_props(uint32_t *);
void *skip_node_name(uint32_t *);
void *skip_node(void *);
+void *skip_nops(uint32_t *);
void *fdt_parent_node_recurse(void *, void *);
static int tree_inited = 0;
@@ -39,7 +40,7 @@ unsigned int
fdt_check_head(void *fdt)
{
struct fdt_head *fh;
- uint32_t *ptr;
+ uint32_t *ptr, *tok;
fh = fdt;
ptr = (uint32_t *)fdt;
@@ -50,8 +51,8 @@ fdt_check_head(void *fdt)
if (betoh32(fh->fh_version) > FDT_CODE_VERSION)
return 0;
- if (betoh32(*(ptr + (betoh32(fh->fh_struct_off) / 4))) !=
- FDT_NODE_BEGIN)
+ tok = skip_nops(ptr + (betoh32(fh->fh_struct_off) / 4));
+ if (betoh32(*tok) != FDT_NODE_BEGIN)
return 0;
/* check for end signature on version 17 blob */
@@ -154,6 +155,16 @@ fdt_add_str(char *name)
/*
* Utility functions for skipping parts of tree.
*/
+
+void *
+skip_nops(uint32_t *ptr)
+{
+ while (betoh32(*ptr) == FDT_NOP)
+ ptr++;
+
+ return ptr;
+}
+
void *
skip_property(uint32_t *ptr)
{
@@ -163,7 +174,7 @@ skip_property(uint32_t *ptr)
/* move forward by magic + size + nameid + rounded up property size */
ptr += 3 + roundup(size, sizeof(uint32_t)) / sizeof(uint32_t);
- return ptr;
+ return skip_nops(ptr);
}
void *
@@ -179,8 +190,10 @@ void *
skip_node_name(uint32_t *ptr)
{
/* skip name, aligned to 4 bytes, this is NULL term., so must add 1 */
- return ptr + roundup(strlen((char *)ptr) + 1,
+ ptr += roundup(strlen((char *)ptr) + 1,
sizeof(uint32_t)) / sizeof(uint32_t);
+
+ return skip_nops(ptr);
}
/*
@@ -346,7 +359,7 @@ skip_node(void *node)
while (betoh32(*ptr) == FDT_NODE_BEGIN)
ptr = skip_node(ptr);
- return (ptr + 1);
+ return skip_nops(ptr + 1);
}
/*
@@ -365,7 +378,7 @@ fdt_next_node(void *node)
ptr = node;
if (node == NULL) {
- ptr = (uint32_t *)tree.tree;
+ ptr = skip_nops((uint32_t *)tree.tree);
return (betoh32(*ptr) == FDT_NODE_BEGIN) ? ptr : NULL;
}
@@ -384,10 +397,12 @@ fdt_next_node(void *node)
if (betoh32(*ptr) != FDT_NODE_END)
return NULL;
- if (betoh32(*(ptr + 1)) != FDT_NODE_BEGIN)
+ ptr = skip_nops(ptr + 1);
+
+ if (betoh32(*ptr) != FDT_NODE_BEGIN)
return NULL;
- return (ptr + 1);
+ return ptr;
}
/*
diff --git a/sys/arch/riscv64/stand/efiboot/fdt.c b/sys/arch/riscv64/stand/efiboot/fdt.c
index 7fbc0a8e4b8..fa603c1001a 100644
--- a/sys/arch/riscv64/stand/efiboot/fdt.c
+++ b/sys/arch/riscv64/stand/efiboot/fdt.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: fdt.c,v 1.3 2022/11/05 18:56:09 patrick Exp $ */
+/* $OpenBSD: fdt.c,v 1.4 2023/02/13 16:16:03 kettenis Exp $ */
/*
* Copyright (c) 2009 Dariusz Swiderski <sfires@sfires.net>
@@ -30,6 +30,7 @@ void *skip_property(uint32_t *);
void *skip_props(uint32_t *);
void *skip_node_name(uint32_t *);
void *skip_node(void *);
+void *skip_nops(uint32_t *);
void *fdt_parent_node_recurse(void *, void *);
static int tree_inited = 0;
@@ -39,7 +40,7 @@ unsigned int
fdt_check_head(void *fdt)
{
struct fdt_head *fh;
- uint32_t *ptr;
+ uint32_t *ptr, *tok;
fh = fdt;
ptr = (uint32_t *)fdt;
@@ -50,8 +51,8 @@ fdt_check_head(void *fdt)
if (betoh32(fh->fh_version) > FDT_CODE_VERSION)
return 0;
- if (betoh32(*(ptr + (betoh32(fh->fh_struct_off) / 4))) !=
- FDT_NODE_BEGIN)
+ tok = skip_nops(ptr + (betoh32(fh->fh_struct_off) / 4));
+ if (betoh32(*tok) != FDT_NODE_BEGIN)
return 0;
/* check for end signature on version 17 blob */
@@ -154,6 +155,16 @@ fdt_add_str(char *name)
/*
* Utility functions for skipping parts of tree.
*/
+
+void *
+skip_nops(uint32_t *ptr)
+{
+ while (betoh32(*ptr) == FDT_NOP)
+ ptr++;
+
+ return ptr;
+}
+
void *
skip_property(uint32_t *ptr)
{
@@ -163,7 +174,7 @@ skip_property(uint32_t *ptr)
/* move forward by magic + size + nameid + rounded up property size */
ptr += 3 + roundup(size, sizeof(uint32_t)) / sizeof(uint32_t);
- return ptr;
+ return skip_nops(ptr);
}
void *
@@ -179,8 +190,10 @@ void *
skip_node_name(uint32_t *ptr)
{
/* skip name, aligned to 4 bytes, this is NULL term., so must add 1 */
- return ptr + roundup(strlen((char *)ptr) + 1,
+ ptr += roundup(strlen((char *)ptr) + 1,
sizeof(uint32_t)) / sizeof(uint32_t);
+
+ return skip_nops(ptr);
}
/*
@@ -346,7 +359,7 @@ skip_node(void *node)
while (betoh32(*ptr) == FDT_NODE_BEGIN)
ptr = skip_node(ptr);
- return (ptr + 1);
+ return skip_nops(ptr + 1);
}
/*
@@ -365,7 +378,7 @@ fdt_next_node(void *node)
ptr = node;
if (node == NULL) {
- ptr = (uint32_t *)tree.tree;
+ ptr = skip_nops((uint32_t *)tree.tree);
return (betoh32(*ptr) == FDT_NODE_BEGIN) ? ptr : NULL;
}
@@ -384,10 +397,12 @@ fdt_next_node(void *node)
if (betoh32(*ptr) != FDT_NODE_END)
return NULL;
- if (betoh32(*(ptr + 1)) != FDT_NODE_BEGIN)
+ ptr = skip_nops(ptr + 1);
+
+ if (betoh32(*ptr) != FDT_NODE_BEGIN)
return NULL;
- return (ptr + 1);
+ return ptr;
}
/*