From 763f939d662fcdddb30bd6d64753a7b8c8ebba9d Mon Sep 17 00:00:00 2001 From: David Garske Date: Wed, 6 Nov 2024 14:53:49 -0800 Subject: [PATCH] Finished support for Flattened uImage Tree (FIT) image (FDT format). --- IDE/XilinxSDK/README.md | 16 ++++- hal/zynq.c | 4 +- include/fdt.h | 8 ++- src/fdt.c | 128 +++++++++++++++++++++++++++++++--- src/update_ram.c | 78 ++++++++++++++------- tools/fdt-parser/README.md | 22 ++++++ tools/fdt-parser/fdt-parser.c | 84 +++++++--------------- 7 files changed, 239 insertions(+), 101 deletions(-) diff --git a/IDE/XilinxSDK/README.md b/IDE/XilinxSDK/README.md index adf2dd262..6d0723f8c 100644 --- a/IDE/XilinxSDK/README.md +++ b/IDE/XilinxSDK/README.md @@ -71,11 +71,24 @@ WOLFBOOT_ORIGIN=0x0 WOLFBOOT_SHA_BLOCK_SIZE=4096 WOLFBOOT_SIGN_RSA4096 WOLFBOOT_UBOOT_LEGACY +``` + +Note: If not using Position Independent Code (PIC) the linker script `ldscript.ld` must have the start address offset to match the `WOLFBOOT_LOAD_ADDRESS`. + + +## Zynq UltraScale+ ARMv8 Crypto Extensions + +To enable ARM assembly speedups for SHA: + +1) Add these build symbols: + +``` WOLFSSL_ARMASM WOLFSSL_ARMASM_INLINE ``` -Note: If not using Position Independent Code (PIC) the linker script `ldscript.ld` must have the start address offset to match the `WOLFBOOT_LOAD_ADDRESS`. +2) Add these compiler misc flags: `-mcpu=generic+crypto -mstrict-align -DWOLFSSL_AARCH64_NO_SQRMLSH` + ## Generate signing key @@ -339,3 +352,4 @@ Output image(s) successfully created. ### References: * [ZAPP1319](https://www.xilinx.com/support/documentation/application_notes/xapp1319-zynq-usp-prog-nvm.pdf): Programming BBRAM and eFUSEs * [UG1283](https://www.xilinx.com/support/documentation/sw_manuals/xilinx2018_2/ug1283-bootgen-user-guide.pdf): Bootgen User Guide +* [Using Cryptography in Zynq UltraScale MPSoC](https://xilinx-wiki.atlassian.net/wiki/spaces/A/pages/18842541/Using+Cryptography+in+Zynq+UltraScale+MPSoC) diff --git a/hal/zynq.c b/hal/zynq.c index d6ebdfbf4..62d0fcd63 100644 --- a/hal/zynq.c +++ b/hal/zynq.c @@ -532,7 +532,7 @@ static int qspi_flash_read_id(QspiDev_t* dev, uint8_t* id, uint32_t idSz) { int ret; uint8_t cmd[20]; /* size multiple of uint32_t */ - uint8_t status; + uint8_t status = 0; memset(cmd, 0, sizeof(cmd)); cmd[0] = MULTI_IO_READ_ID_CMD; @@ -562,7 +562,7 @@ static int qspi_write_enable(QspiDev_t* dev) { int ret; uint8_t cmd[4]; /* size multiple of uint32_t */ - uint8_t status; + uint8_t status = 0; memset(cmd, 0, sizeof(cmd)); cmd[0] = WRITE_ENABLE_CMD; diff --git a/include/fdt.h b/include/fdt.h index aac9baf4b..e963b9658 100644 --- a/include/fdt.h +++ b/include/fdt.h @@ -139,7 +139,9 @@ const char* fdt_get_string(const void *fdt, int stroffset, int *lenp); const void *fdt_getprop(const void *fdt, int nodeoffset, const char *name, int *lenp); int fdt_setprop(void *fdt, int nodeoffset, const char *name, const void *val, int len); -int fdt_find_node_offset(void* fdt, int startoff, const char* node); +void* fdt_getprop_address(const void *fdt, int nodeoffset, const char *name); + +int fdt_find_node_offset(void* fdt, int startoff, const char* nodename); int fdt_find_prop_offset(void* fdt, int startoff, const char* propname, const char* propval); int fdt_find_devtype(void* fdt, int startoff, const char* node); @@ -155,6 +157,10 @@ int fdt_fixup_val64(void* fdt, int off, const char* node, const char* name, uint int fdt_shrink(void* fdt); +/* FIT */ +const char* fit_find_images(void* fdt, const char** pkernel, const char** pflat_dt); +void* fit_load_image(void* fdt, const char* image, int* lenp); + #ifdef __cplusplus } #endif diff --git a/src/fdt.c b/src/fdt.c index 2cfd3699b..97c199fdf 100644 --- a/src/fdt.c +++ b/src/fdt.c @@ -510,7 +510,7 @@ const char* fdt_get_name(const void *fdt, int nodeoffset, int *len) err = fdt_check_node_offset_(fdt, nodeoffset); if (err >= 0) { name = nh->name; - namelen = strlen(nh->name); + namelen = (int)strlen(nh->name); } } if (err < 0) @@ -524,7 +524,7 @@ const char* fdt_get_string(const void *fdt, int stroffset, int *lenp) { const char *s = (const char*)fdt + fdt_off_dt_strings(fdt) + stroffset; if (lenp) { - *lenp = strlen(s); + *lenp = (int)strlen(s); } return s; } @@ -560,7 +560,7 @@ int fdt_setprop(void *fdt, int nodeoffset, const char *name, const void *val, return err; } -const void *fdt_getprop(const void *fdt, int nodeoffset, const char *name, +const void* fdt_getprop(const void *fdt, int nodeoffset, const char *name, int *lenp) { int poffset; @@ -577,19 +577,39 @@ const void *fdt_getprop(const void *fdt, int nodeoffset, const char *name, return NULL; } -int fdt_find_node_offset(void* fdt, int startoff, const char* node) +void* fdt_getprop_address(const void *fdt, int nodeoffset, const char *name) { - int off; - int nodelen = strlen(node); - int nlen; + void* ret = NULL; + int len = 0; + void* val = (void*)fdt_getprop(fdt, nodeoffset, name, &len); + if (val != NULL && len > 0) { + if (len == 8) { + uint64_t* val64 = (uint64_t*)val; + ret = (void*)((uintptr_t)fdt64_to_cpu(*val64)); + } + else if (len == 4) { + uint32_t* val32 = (uint32_t*)val; + ret = (void*)((uintptr_t)fdt32_to_cpu(*val32)); + } + } + return ret; +} + +int fdt_find_node_offset(void* fdt, int startoff, const char* nodename) +{ + int off, nlen, fnlen; const char* nstr = NULL; + if (nodename == NULL) + return -1; + + fnlen = (int)strlen(nodename); for (off = fdt_next_node(fdt, startoff, NULL); off >= 0; off = fdt_next_node(fdt, off, NULL)) { nstr = fdt_get_name(fdt, off, &nlen); - if ((nlen == nodelen) && (memcmp(nstr, node, nodelen) == 0)) { + if ((nlen == fnlen) && (memcmp(nstr, nodename, fnlen) == 0)) { break; } } @@ -599,16 +619,19 @@ int fdt_find_node_offset(void* fdt, int startoff, const char* node) int fdt_find_prop_offset(void* fdt, int startoff, const char* propname, const char* propval) { - int len, off; + int len, off, pvallen; const void* val; - int nodelen = strlen(propval)+1; + if (propname == NULL || propval == NULL) + return -1; + + pvallen = (int)strlen(propval)+1; for (off = fdt_next_node(fdt, startoff, NULL); off >= 0; off = fdt_next_node(fdt, off, NULL)) { val = fdt_getprop(fdt, off, propname, &len); - if (val && (len == nodelen) && (memcmp(val, propval, len) == 0)) { + if (val && (len == pvallen) && (memcmp(val, propval, len) == 0)) { break; } } @@ -745,4 +768,87 @@ int fdt_fixup_val64(void* fdt, int off, const char* node, const char* name, return fdt_setprop(fdt, off, name, &val, sizeof(val)); } + +/* FIT Specific */ +const char* fit_find_images(void* fdt, const char** pkernel, const char** pflat_dt) +{ + const void* val; + const char *conf = NULL, *kernel = NULL, *flat_dt = NULL; + int off, len = 0; + + /* Find the default configuration (optional) */ + off = fdt_find_node_offset(fdt, -1, "configurations"); + if (off > 0) { + val = fdt_getprop(fdt, off, "default", &len); + if (val != NULL && len > 0) { + conf = (const char*)val; + } + } + if (conf != NULL) { + off = fdt_find_node_offset(fdt, -1, conf); + if (off > 0) { + kernel = fdt_getprop(fdt, off, "kernel", &len); + flat_dt = fdt_getprop(fdt, off, "fdt", &len); + } + } + if (kernel == NULL) { + /* find node with "type" == kernel */ + off = fdt_find_prop_offset(fdt, -1, "type", "kernel"); + if (off > 0) { + val = fdt_get_name(fdt, off, &len); + if (val != NULL && len > 0) { + kernel = (const char*)val; + } + } + } + if (flat_dt == NULL) { + /* find node with "type" == flat_dt */ + off = fdt_find_prop_offset(fdt, -1, "type", "flat_dt"); + if (off > 0) { + val = fdt_get_name(fdt, off, &len); + if (val != NULL && len > 0) { + flat_dt = (const char*)val; + } + } + } + + if (pkernel) + *pkernel = kernel; + if (pflat_dt) + *pflat_dt = flat_dt; + + return conf; +} + +void* fit_load_image(void* fdt, const char* image, int* lenp) +{ + void *load, *entry, *data = NULL; + int off, len = 0; + + off = fdt_find_node_offset(fdt, -1, image); + if (off > 0) { + /* get load and entry */ + data = (void*)fdt_getprop(fdt, off, "data", &len); + load = fdt_getprop_address(fdt, off, "load"); + entry = fdt_getprop_address(fdt, off, "entry"); + if (data != NULL && load != NULL && data != load) { + wolfBoot_printf("Loading Image %s: %p -> %p (%d bytes)\n", + image, data, load, len); + memcpy(load, data, len); + + /* load should always have entry, but if not use load adress */ + data = (entry != NULL) ? entry : load; + } + wolfBoot_printf("Image %s: %p (%d bytes)\n", image, data, len); + } + else { + wolfBoot_printf("Image %s: Not found!\n", image); + } + if (lenp != NULL) { + *lenp = len; + } + return data; + +} + #endif /* MMU && !BUILD_LOADER_STAGE1 */ diff --git a/src/update_ram.c b/src/update_ram.c index 9856d6ede..60f16819a 100644 --- a/src/update_ram.c +++ b/src/update_ram.c @@ -290,36 +290,62 @@ void RAMFUNCTION wolfBoot_start(void) #endif #ifdef MMU + /* Is this a Flattened uImage Tree (FIT) image (FDT format) */ + if (wolfBoot_get_dts_size(load_address) > 0) { + void* fit = (void*)load_address; + const char *kernel = NULL, *flat_dt = NULL; + + wolfBoot_printf("Flattened uImage Tree: Version %d, Size %d\n", + fdt_version(fit), fdt_totalsize(fit)); + + (void)fit_find_images(fit, &kernel, &flat_dt); + if (kernel != NULL) { + load_address = fit_load_image(fit, kernel, NULL); + } + if (flat_dt != NULL) { + dts_addr = fit_load_image(fit, flat_dt, NULL); + if (dts_addr != NULL) { + /* check DTS */ + ret = wolfBoot_get_dts_size(dts_addr); + if (ret < 0) { + wolfBoot_printf("FIT FDT parsing failed!\n"); + /* Allow failure, continue booting */ + } + } + } + } + else { /* Load DTS to RAM */ #ifdef EXT_FLASH - if (PART_IS_EXT(&os_image) && - wolfBoot_open_image(&os_image, PART_DTS_BOOT) >= 0) { - dts_addr = (uint8_t*)WOLFBOOT_LOAD_DTS_ADDRESS; - dts_size = (uint32_t)os_image.fw_size; - - wolfBoot_printf("Loading DTS (size %lu) to RAM at %08lx\n", - dts_size, dts_addr); - ext_flash_check_read((uintptr_t)os_image.fw_base, - (uint8_t*)dts_addr, dts_size); - } - else + if (PART_IS_EXT(&os_image) && + wolfBoot_open_image(&os_image, PART_DTS_BOOT) >= 0) { + dts_addr = (uint8_t*)WOLFBOOT_LOAD_DTS_ADDRESS; + dts_size = (uint32_t)os_image.fw_size; + + wolfBoot_printf("Loading DTS (size %lu) to RAM at %08lx\n", + dts_size, dts_addr); + ext_flash_check_read((uintptr_t)os_image.fw_base, + (uint8_t*)dts_addr, dts_size); + } + else #endif /* EXT_FLASH */ - { - dts_addr = hal_get_dts_address(); - if (dts_addr) { - ret = wolfBoot_get_dts_size(dts_addr); - if (ret < 0) { - wolfBoot_printf("Failed parsing DTB to load\n"); - /* Allow failure, continue booting */ - } - else { - /* relocate DTS to RAM */ - uint8_t* dts_dst = (uint8_t*)WOLFBOOT_LOAD_DTS_ADDRESS; - dts_size = (uint32_t)ret; - wolfBoot_printf("Loading DTB (size %d) from %p to RAM at %p\n", + { + dts_addr = hal_get_dts_address(); + if (dts_addr) { + ret = wolfBoot_get_dts_size(dts_addr); + if (ret < 0) { + wolfBoot_printf("Failed parsing DTB to load\n"); + /* Allow failure, continue booting */ + } + else { + /* relocate DTS to RAM */ + uint8_t* dts_dst = (uint8_t*)WOLFBOOT_LOAD_DTS_ADDRESS; + dts_size = (uint32_t)ret; + wolfBoot_printf("Loading DTB (size %d) from %p to RAM at %p\n", dts_size, dts_addr, WOLFBOOT_LOAD_DTS_ADDRESS); - memcpy(dts_dst, dts_addr, dts_size); - dts_addr = dts_dst; + memcpy(dts_dst, dts_addr, dts_size); + dts_addr = dts_dst; + } } } } diff --git a/tools/fdt-parser/README.md b/tools/fdt-parser/README.md index 5855b02b7..9011b8dc6 100644 --- a/tools/fdt-parser/README.md +++ b/tools/fdt-parser/README.md @@ -36,4 +36,26 @@ root (node offset 0, depth 1, len 0): ## Example FIT Output ```sh +% ./tools/fdt-parser/fdt-parser -i ./tools/fdt-parser/lynx-test-arm.srp +FDT Parser (./tools/fdt-parser/lynx-test-arm.srp): +FDT Version 17, Size 164232633 +FIT: Found 'conf@1' configuration + description (len 46): LynxSecure 2024.06.0-96ce6f31a0 SRP (aarch64) +Kernel Image: kernel@1 + description (len 46): LynxSecure 2024.06.0-96ce6f31a0 SRP (aarch64) + type (len 7): kernel + os (len 6): linux + arch (len 6): arm64 + compression (len 5): none + load (len 4): + entry (len 4): + data (len 164186944): not rendering +FDT Image: fdt@1 + description (len 77): Flattened Device Tree blob for LynxSecure 2024.06.0-96ce6f31a0 SRP (aarch64) + type (len 8): flat_dt + arch (len 6): arm64 + compression (len 5): none + padding (len 8): + data (len 44770): not rendering +Return 0 ``` diff --git a/tools/fdt-parser/fdt-parser.c b/tools/fdt-parser/fdt-parser.c index 0cf3143b3..317951021 100644 --- a/tools/fdt-parser/fdt-parser.c +++ b/tools/fdt-parser/fdt-parser.c @@ -320,23 +320,33 @@ static int load_file(const char* filename, uint8_t** buf, size_t* bufLen) return ret; } -static void dts_fit_image_item(void* fit, uint32_t off, const char* prop) +static void* dts_fit_image_addr(void* fit, uint32_t off, const char* prop) +{ + void* val = fdt_getprop_address(fit, off, prop); + printf("\t%s: %p\n", prop, val); + return val; +} + +static const void* dts_fit_image_item(void* fit, uint32_t off, const char* prop) { - const void* val; int len = 0; - val = fdt_getprop(fit, off, prop, &len); + const void* val = fdt_getprop(fit, off, prop, &len); if (val != NULL && len > 0) { if (len < 256) printf("\t%s (len %d): %s\n", prop, len, (const char*)val); else printf("\t%s (len %d): not rendering\n", prop, len); } + return val; } -void dts_parse_fit_image(void* fit, const char* image) + +void dts_parse_fit_image(void* fit, const char* image, const char* desc) { - uint32_t off; + int off; - printf("Image: %s\n", image); + if (fit != NULL) { + printf("%s Image: %s\n", desc, image); + } off = fdt_find_node_offset(fit, -1, image); if (off > 0) { @@ -345,8 +355,8 @@ void dts_parse_fit_image(void* fit, const char* image) dts_fit_image_item(fit, off, "os"); dts_fit_image_item(fit, off, "arch"); dts_fit_image_item(fit, off, "compression"); - dts_fit_image_item(fit, off, "load"); - dts_fit_image_item(fit, off, "entry"); + dts_fit_image_addr(fit, off, "load"); + dts_fit_image_addr(fit, off, "entry"); dts_fit_image_item(fit, off, "padding"); dts_fit_image_item(fit, off, "data"); } @@ -354,64 +364,18 @@ void dts_parse_fit_image(void* fit, const char* image) int dts_parse_fit(void* image) { - void* fit = (void*)image; - const void* val; const char *conf = NULL, *kernel = NULL, *flat_dt = NULL; - uint32_t off; - int len = 0; - /* Find the default configuration */ - off = fdt_find_node_offset(fit, -1, "configurations"); - if (off > 0) { - val = fdt_getprop(fit, off, "default", &len); - if (val != NULL && len > 0) { - conf = (const char*)val; - printf("Found '%s' configuration\n", conf); - } - } + conf = fit_find_images(image, &kernel, &flat_dt); if (conf != NULL) { - off = fdt_find_node_offset(fit, -1, conf); - if (off > 0) { - /* get "kernel" */ - val = fdt_getprop(fit, off, "kernel", &len); - if (val != NULL && len > 0) { - kernel = (const char*)val; - printf("Default Kernel: %s\n", kernel); - } - /* get "fdt" */ - val = fdt_getprop(fit, off, "fdt", &len); - if (val != NULL && len > 0) { - flat_dt = (const char*)val; - printf("Default FDT: %s\n", flat_dt); - } - } - } - if (kernel == NULL) { - /* find node with "type" == kernel */ - off = fdt_find_prop_offset(fit, -1, "type", "kernel"); - if (off > 0) { - val = fdt_get_name(fit, off, &len); - if (val != NULL && len > 0) { - kernel = (const char*)val; - printf("Found Kernel: %s\n", kernel); - } - } - } - if (flat_dt == NULL) { - /* find node with "type" == flat_dt */ - off = fdt_find_prop_offset(fit, -1, "type", "flat_dt"); - if (off > 0) { - val = fdt_get_name(fit, off, &len); - if (val != NULL && len > 0) { - flat_dt = (const char*)val; - printf("Found FDT: %s\n", flat_dt); - } - } + printf("FIT: Found '%s' configuration\n", conf); + dts_fit_image_item(image, fdt_find_node_offset(image, -1, conf), + "description"); } /* dump image information */ - dts_parse_fit_image(fit, kernel); - dts_parse_fit_image(fit, flat_dt); + dts_parse_fit_image(image, kernel, "Kernel"); + dts_parse_fit_image(image, flat_dt, "FDT"); return 0; }