From 02c5932ab2970cf4c2a11e6111f33f578372d76d Mon Sep 17 00:00:00 2001 From: Mark Kettenis Date: Mon, 13 Feb 2023 16:16:04 +0000 Subject: Support device trees with NOPs in them (like the kernel version already does). tested by jca@ (riscv64) ok patrick@ --- sys/arch/arm64/stand/efiboot/fdt.c | 35 +++++++++++++++++++++++++---------- sys/arch/armv7/stand/efiboot/fdt.c | 35 +++++++++++++++++++++++++---------- sys/arch/riscv64/stand/efiboot/fdt.c | 35 +++++++++++++++++++++++++---------- 3 files changed, 75 insertions(+), 30 deletions(-) (limited to 'sys/arch') 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 @@ -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 @@ -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 @@ -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; } /* -- cgit v1.2.3