Skip to content

Commit

Permalink
Finished support for Flattened uImage Tree (FIT) image (FDT format).
Browse files Browse the repository at this point in the history
  • Loading branch information
dgarske committed Nov 6, 2024
1 parent 5e9a28f commit 21dbad1
Show file tree
Hide file tree
Showing 7 changed files with 240 additions and 102 deletions.
16 changes: 15 additions & 1 deletion IDE/XilinxSDK/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -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

Expand Down Expand Up @@ -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)
4 changes: 2 additions & 2 deletions hal/zynq.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -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;
Expand Down
8 changes: 7 additions & 1 deletion include/fdt.h
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand All @@ -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
Expand Down
130 changes: 118 additions & 12 deletions src/fdt.c
Original file line number Diff line number Diff line change
Expand Up @@ -502,15 +502,15 @@ const char* fdt_get_name(const void *fdt, int nodeoffset, int *len)
{
int err;
const struct fdt_node_header *nh = fdt_offset_ptr_(fdt, nodeoffset);
int namelen = 0;
size_t namelen = 0;
const char* name = NULL;

err = fdt_check_header(fdt);
if (err == 0) {
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)
Expand All @@ -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;
}
Expand Down Expand Up @@ -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;
Expand All @@ -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;
}
}
Expand All @@ -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;
}
}
Expand Down Expand Up @@ -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 */
78 changes: 52 additions & 26 deletions src/update_ram.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;
}
}
}
}
Expand Down
22 changes: 22 additions & 0 deletions tools/fdt-parser/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -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
```
Loading

0 comments on commit 21dbad1

Please sign in to comment.