diff options
author | Mark Kettenis <kettenis@cvs.openbsd.org> | 2023-02-13 16:16:04 +0000 |
---|---|---|
committer | Mark Kettenis <kettenis@cvs.openbsd.org> | 2023-02-13 16:16:04 +0000 |
commit | 02c5932ab2970cf4c2a11e6111f33f578372d76d (patch) | |
tree | 4081d639ec43995e15c0b647d183e34cf03787f1 | |
parent | f645ca647f98fec6f7f642e4bb9dfa319f17f212 (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.c | 35 | ||||
-rw-r--r-- | sys/arch/armv7/stand/efiboot/fdt.c | 35 | ||||
-rw-r--r-- | sys/arch/riscv64/stand/efiboot/fdt.c | 35 |
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; } /* |