Fixes for Xilinx Zynq UltraScale+ MPSoC:

* Fixes to support wolfBoot native make and gcc-arm cross compiler. ZD 18159
* Adjust wolfBoot linker script to not use 0 base, instead use end of DDR - 1MB.
* Fixed QSPI bare-metal driver for multi-sector and read return code.
* Fixed issue with Xilinx XMSS IMAGE_HEADER_SIZE in documentation. It should be 5000 bytes.
* Performance optimizations for QSPI:
  - Allow configuration of SPI clock.
  - Improve GSPI FIFO TX/RX fill.
* Added support for FAST_MEMCPY that supports an aligned 32-bit.
* Added Flattened uImage Tree (FIT) image (FDT format).
* Added Aarch64 support for FDT fixups.
* Added Aarch64 startup to support EL2 with cache/MMU.
* Added documentation about exception levels
* Moved zynqmp registers to header.
* Fix printf uart_writenum "buf" len.
* Updated fdt-parser to support saving off larger data images.
pull/532/head
David Garske 2024-12-09 17:33:14 -08:00 committed by Daniele Lacamera
parent a04f234b85
commit acb9d832eb
20 changed files with 2109 additions and 886 deletions

View File

@ -131,7 +131,7 @@
</toolChain>
</folderInfo>
<sourceEntries>
<entry excluding="src/qspi_flash.c|IDE/AURIX|IDE/CCS|IDE/MPLAB|IDE/Renesas|.git|IDE/IAR|test-app|tools|lib/wolfPKCS11|lib/wolfTPM|lib/wolfssl/linuxkm|lib/wolfssl/wolfcrypt/src/port/arm/armv8-32-aes-asm.S|lib/wolfssl/wolfcrypt/src/port/arm/armv8-32-curve25519.S|lib/wolfssl/wolfcrypt/src/port/arm/armv8-32-sha256-asm.S|lib/wolfssl/wolfcrypt/src/port/arm/armv8-32-sha3-asm.S|lib/wolfssl/wolfcrypt/src/port/arm/armv8-32-sha512-asm.S|lib/wolfssl/wolfcrypt/src/port/arm/armv8-curve25519.S|lib/wolfssl/wolfcrypt/src/port/arm/armv8-sha3-asm.S|lib/wolfssl/wolfcrypt/src/port/arm/armv8-sha512-asm.S|lib/wolfssl/wolfcrypt/src/port/arm/thumb2-aes-asm.S|lib/wolfssl/wolfcrypt/src/port/arm/thumb2-curve25519.S|lib/wolfssl/wolfcrypt/src/port/arm/thumb2-sha256-asm.S|lib/wolfssl/wolfcrypt/src/port/arm/thumb2-sha3-asm.S|lib/wolfssl/wolfcrypt/src/port/arm/thumb2-sha512-asm.S|lib/wolfssl/wolfcrypt/src/port/autosar|lib/wolfssl/wrapper|lib/wolfssl/zephyr|src/boot_x86_fsp.c|src/boot_x86_fsp_start.S|src/boot_x86_fsp_payload.c|src/boot_x86_64.c|src/boot_renesas.c|src/boot_renesas_start.S|src/boot_ppc_start.S|src/boot_ppc_mp.S|src/boot_ppc.c|src/x86|lib/wolfTPM/examples|lib/wolfTPM/tests|lib/wolfTPM/IDE|lib/wolfssl/tests|lib/wolfssl/tirtos|lib/wolfssl/swig|lib/wolfssl/mqx|lib/wolfssl/mplabx|lib/wolfssl/IPP|lib/wolfssl/mcapi|lib/wolfssl/testsuite|lib/wolfssl/examples|lib/wolfssl/IDE|lib/wolfssl/wolfcrypt/user-crypto|lib/wolfssl/wolfcrypt/src/aes_asm.S|lib/wolfssl/wolfcrypt/src/aes_gcm_asm.S|lib/wolfssl/wolfcrypt/src/aes_gcm_x86_asm.S|lib/wolfssl/wolfcrypt/src/aes_xts_asm.S|lib/wolfssl/wolfcrypt/src/chacha_asm.S|lib/wolfssl/wolfcrypt/src/fe_x25519_asm.S|lib/wolfssl/wolfcrypt/src/poly1305_asm.S|lib/wolfssl/wolfcrypt/src/sha256_asm.S|lib/wolfssl/wolfcrypt/src/sha3_asm.S|lib/wolfssl/wolfcrypt/src/sha512_asm.S|lib/wolfssl/wolfcrypt/src/sm3_asm.S|lib/wolfssl/wolfcrypt/src/sp_sm2_x86_64_asm.S|lib/wolfssl/wolfcrypt/src/sp_x86_64_asm.S|lib/wolfssl/wolfcrypt/src/wc_kyber_asm.S|src/vector_riscv.S|src/update_flash_hwswap.c|src/update_flash.c|src/boot_riscv.c|src/boot_arm.c|hal/aurix_tc3xx.c|hal/cc26x2.c|hal/hifive1.c|hal/imx_rt.c|hal/kinetis.c|hal/kontron_vx3060_s2.c|hal/kontron_vx3060_s2_loader.c|hal/library.c|hal/lpc.c|hal/mcxa.c|hal/nrf52.c|hal/nxp_p1021.c|hal/nxp_ppc.c|hal/nxp_t1024.c|hal/nxp_t2080.c|hal/psoc6.c|hal/raspi3.c|hal/renesas-ra.c|hal/renesas-rx.c|hal/renesas-rz.c|hal/rx65n.c|hal/rx72n.c|hal/same51.c|hal/samr21.c|hal/sim.c|hal/skeleton.c|hal/stm32c0.c|hal/stm32f4.c|hal/stm32f7.c|hal/stm32g0.c|hal/stm32h5.c|hal/stm32h7.c|hal/stm32l0.c|hal/stm32l4.c|hal/stm32l5.c|hal/stm32_tz.c|hal/stm32u5.c|hal/stm32wb.c|hal/ti_hercules.c|hal/x86_64_efi.c|hal/x86_fsp_qemu.c|hal/x86_fsp_qemu_loader.c|hal/x86_fsp_tgl.c|hal/x86_uart.c" flags="VALUE_WORKSPACE_PATH|RESOLVED" kind="sourcePath" name=""/>
<entry excluding="lib/wolfssl/wolfcrypt/src/port/arm/thumb2-poly1305-asm.S|lib/wolfssl/wolfcrypt/src/port/arm/thumb2-kyber-asm.S|lib/wolfssl/wolfcrypt/src/port/arm/thumb2-chacha-asm.S|lib/wolfssl/wolfcrypt/src/port/arm/armv8-kyber-asm.S|lib/wolfssl/wolfcrypt/src/port/arm/armv8-32-poly1305-asm.S|lib/wolfssl/wolfcrypt/src/port/arm/armv8-32-kyber-asm.S|lib/wolfssl/wolfcrypt/src/port/arm/armv8-32-chacha-asm.S|src/qspi_flash.c|IDE/AURIX|IDE/CCS|IDE/MPLAB|IDE/Renesas|.git|IDE/IAR|test-app|tools|lib/wolfPKCS11|lib/wolfTPM|lib/wolfssl/linuxkm|lib/wolfssl/wolfcrypt/src/port/arm/armv8-32-aes-asm.S|lib/wolfssl/wolfcrypt/src/port/arm/armv8-32-curve25519.S|lib/wolfssl/wolfcrypt/src/port/arm/armv8-32-sha256-asm.S|lib/wolfssl/wolfcrypt/src/port/arm/armv8-32-sha3-asm.S|lib/wolfssl/wolfcrypt/src/port/arm/armv8-32-sha512-asm.S|lib/wolfssl/wolfcrypt/src/port/arm/armv8-curve25519.S|lib/wolfssl/wolfcrypt/src/port/arm/armv8-sha3-asm.S|lib/wolfssl/wolfcrypt/src/port/arm/armv8-sha512-asm.S|lib/wolfssl/wolfcrypt/src/port/arm/thumb2-aes-asm.S|lib/wolfssl/wolfcrypt/src/port/arm/thumb2-curve25519.S|lib/wolfssl/wolfcrypt/src/port/arm/thumb2-sha256-asm.S|lib/wolfssl/wolfcrypt/src/port/arm/thumb2-sha3-asm.S|lib/wolfssl/wolfcrypt/src/port/arm/thumb2-sha512-asm.S|lib/wolfssl/wolfcrypt/src/port/autosar|lib/wolfssl/wrapper|lib/wolfssl/zephyr|src/boot_x86_fsp.c|src/boot_x86_fsp_start.S|src/boot_x86_fsp_payload.c|src/boot_x86_64.c|src/boot_renesas.c|src/boot_renesas_start.S|src/boot_ppc_start.S|src/boot_ppc_mp.S|src/boot_ppc.c|src/x86|lib/wolfTPM/examples|lib/wolfTPM/tests|lib/wolfTPM/IDE|lib/wolfssl/tests|lib/wolfssl/tirtos|lib/wolfssl/swig|lib/wolfssl/mqx|lib/wolfssl/mplabx|lib/wolfssl/IPP|lib/wolfssl/mcapi|lib/wolfssl/testsuite|lib/wolfssl/examples|lib/wolfssl/IDE|lib/wolfssl/wolfcrypt/user-crypto|lib/wolfssl/wolfcrypt/src/aes_asm.S|lib/wolfssl/wolfcrypt/src/aes_gcm_asm.S|lib/wolfssl/wolfcrypt/src/aes_gcm_x86_asm.S|lib/wolfssl/wolfcrypt/src/aes_xts_asm.S|lib/wolfssl/wolfcrypt/src/chacha_asm.S|lib/wolfssl/wolfcrypt/src/fe_x25519_asm.S|lib/wolfssl/wolfcrypt/src/poly1305_asm.S|lib/wolfssl/wolfcrypt/src/sha256_asm.S|lib/wolfssl/wolfcrypt/src/sha3_asm.S|lib/wolfssl/wolfcrypt/src/sha512_asm.S|lib/wolfssl/wolfcrypt/src/sm3_asm.S|lib/wolfssl/wolfcrypt/src/sp_sm2_x86_64_asm.S|lib/wolfssl/wolfcrypt/src/sp_x86_64_asm.S|lib/wolfssl/wolfcrypt/src/wc_kyber_asm.S|src/vector_riscv.S|src/update_flash_hwswap.c|src/update_flash.c|src/boot_riscv.c|src/boot_arm.c|src/boot_arm32_start.S|src/boot_arm32.c|hal/aurix_tc3xx.c|hal/cc26x2.c|hal/hifive1.c|hal/imx_rt.c|hal/kinetis.c|hal/kontron_vx3060_s2.c|hal/kontron_vx3060_s2_loader.c|hal/library.c|hal/lpc.c|hal/mcxa.c|hal/nrf52.c|hal/nxp_p1021.c|hal/nxp_ppc.c|hal/nxp_t1024.c|hal/nxp_t2080.c|hal/psoc6.c|hal/raspi3.c|hal/renesas-ra.c|hal/renesas-rx.c|hal/renesas-rz.c|hal/rx65n.c|hal/rx72n.c|hal/same51.c|hal/sama5d3.c|hal/samr21.c|hal/sim.c|hal/skeleton.c|hal/stm32c0.c|hal/stm32f4.c|hal/stm32f7.c|hal/stm32g0.c|hal/stm32h5.c|hal/stm32h7.c|hal/stm32l0.c|hal/stm32l4.c|hal/stm32l5.c|hal/stm32_tz.c|hal/stm32u5.c|hal/stm32wb.c|hal/ti_hercules.c|hal/x86_64_efi.c|hal/x86_fsp_qemu.c|hal/x86_fsp_qemu_loader.c|hal/x86_fsp_tgl.c|hal/x86_uart.c" flags="VALUE_WORKSPACE_PATH|RESOLVED" kind="sourcePath" name=""/>
</sourceEntries>
</configuration>
</storageModule>
@ -267,7 +267,7 @@
</toolChain>
</folderInfo>
<sourceEntries>
<entry excluding="src/qspi_flash.c|IDE/AURIX|IDE/CCS|IDE/MPLAB|IDE/Renesas|.git|IDE/IAR|test-app|tools|lib/wolfPKCS11|lib/wolfTPM|lib/wolfssl/linuxkm|lib/wolfssl/wolfcrypt/src/port/arm/armv8-32-aes-asm.S|lib/wolfssl/wolfcrypt/src/port/arm/armv8-32-curve25519.S|lib/wolfssl/wolfcrypt/src/port/arm/armv8-32-sha256-asm.S|lib/wolfssl/wolfcrypt/src/port/arm/armv8-32-sha3-asm.S|lib/wolfssl/wolfcrypt/src/port/arm/armv8-32-sha512-asm.S|lib/wolfssl/wolfcrypt/src/port/arm/armv8-curve25519.S|lib/wolfssl/wolfcrypt/src/port/arm/armv8-sha3-asm.S|lib/wolfssl/wolfcrypt/src/port/arm/armv8-sha512-asm.S|lib/wolfssl/wolfcrypt/src/port/arm/thumb2-aes-asm.S|lib/wolfssl/wolfcrypt/src/port/arm/thumb2-curve25519.S|lib/wolfssl/wolfcrypt/src/port/arm/thumb2-sha256-asm.S|lib/wolfssl/wolfcrypt/src/port/arm/thumb2-sha3-asm.S|lib/wolfssl/wolfcrypt/src/port/arm/thumb2-sha512-asm.S|lib/wolfssl/wolfcrypt/src/port/autosar|lib/wolfssl/wrapper|lib/wolfssl/zephyr|src/boot_x86_fsp.c|src/boot_x86_fsp_start.S|src/boot_x86_fsp_payload.c|src/boot_x86_64.c|src/boot_renesas.c|src/boot_renesas_start.S|src/boot_ppc_start.S|src/boot_ppc_mp.S|src/boot_ppc.c|src/x86|lib/wolfTPM/examples|lib/wolfTPM/tests|lib/wolfTPM/IDE|lib/wolfssl/tests|lib/wolfssl/tirtos|lib/wolfssl/swig|lib/wolfssl/mqx|lib/wolfssl/mplabx|lib/wolfssl/IPP|lib/wolfssl/mcapi|lib/wolfssl/testsuite|lib/wolfssl/examples|lib/wolfssl/IDE|lib/wolfssl/wolfcrypt/user-crypto|lib/wolfssl/wolfcrypt/src/aes_asm.S|lib/wolfssl/wolfcrypt/src/aes_gcm_asm.S|lib/wolfssl/wolfcrypt/src/aes_gcm_x86_asm.S|lib/wolfssl/wolfcrypt/src/aes_xts_asm.S|lib/wolfssl/wolfcrypt/src/chacha_asm.S|lib/wolfssl/wolfcrypt/src/fe_x25519_asm.S|lib/wolfssl/wolfcrypt/src/poly1305_asm.S|lib/wolfssl/wolfcrypt/src/sha256_asm.S|lib/wolfssl/wolfcrypt/src/sha3_asm.S|lib/wolfssl/wolfcrypt/src/sha512_asm.S|lib/wolfssl/wolfcrypt/src/sm3_asm.S|lib/wolfssl/wolfcrypt/src/sp_sm2_x86_64_asm.S|lib/wolfssl/wolfcrypt/src/sp_x86_64_asm.S|lib/wolfssl/wolfcrypt/src/wc_kyber_asm.S|src/vector_riscv.S|src/update_flash_hwswap.c|src/update_flash.c|src/boot_riscv.c|src/boot_arm.c|hal/aurix_tc3xx.c|hal/cc26x2.c|hal/hifive1.c|hal/imx_rt.c|hal/kinetis.c|hal/kontron_vx3060_s2.c|hal/kontron_vx3060_s2_loader.c|hal/library.c|hal/lpc.c|hal/mcxa.c|hal/nrf52.c|hal/nxp_p1021.c|hal/nxp_ppc.c|hal/nxp_t1024.c|hal/nxp_t2080.c|hal/psoc6.c|hal/raspi3.c|hal/renesas-ra.c|hal/renesas-rx.c|hal/renesas-rz.c|hal/rx65n.c|hal/rx72n.c|hal/same51.c|hal/samr21.c|hal/sim.c|hal/skeleton.c|hal/stm32c0.c|hal/stm32f4.c|hal/stm32f7.c|hal/stm32g0.c|hal/stm32h5.c|hal/stm32h7.c|hal/stm32l0.c|hal/stm32l4.c|hal/stm32l5.c|hal/stm32_tz.c|hal/stm32u5.c|hal/stm32wb.c|hal/ti_hercules.c|hal/x86_64_efi.c|hal/x86_fsp_qemu.c|hal/x86_fsp_qemu_loader.c|hal/x86_fsp_tgl.c|hal/x86_uart.c" flags="VALUE_WORKSPACE_PATH|RESOLVED" kind="sourcePath" name=""/>
<entry excluding="lib/wolfssl/wolfcrypt/src/port/arm/thumb2-poly1305-asm.S|lib/wolfssl/wolfcrypt/src/port/arm/thumb2-kyber-asm.S|lib/wolfssl/wolfcrypt/src/port/arm/thumb2-chacha-asm.S|lib/wolfssl/wolfcrypt/src/port/arm/armv8-kyber-asm.S|lib/wolfssl/wolfcrypt/src/port/arm/armv8-32-poly1305-asm.S|lib/wolfssl/wolfcrypt/src/port/arm/armv8-32-kyber-asm.S|lib/wolfssl/wolfcrypt/src/port/arm/armv8-32-chacha-asm.S|src/qspi_flash.c|IDE/AURIX|IDE/CCS|IDE/MPLAB|IDE/Renesas|.git|IDE/IAR|test-app|tools|lib/wolfPKCS11|lib/wolfTPM|lib/wolfssl/linuxkm|lib/wolfssl/wolfcrypt/src/port/arm/armv8-32-aes-asm.S|lib/wolfssl/wolfcrypt/src/port/arm/armv8-32-curve25519.S|lib/wolfssl/wolfcrypt/src/port/arm/armv8-32-sha256-asm.S|lib/wolfssl/wolfcrypt/src/port/arm/armv8-32-sha3-asm.S|lib/wolfssl/wolfcrypt/src/port/arm/armv8-32-sha512-asm.S|lib/wolfssl/wolfcrypt/src/port/arm/armv8-curve25519.S|lib/wolfssl/wolfcrypt/src/port/arm/armv8-sha3-asm.S|lib/wolfssl/wolfcrypt/src/port/arm/armv8-sha512-asm.S|lib/wolfssl/wolfcrypt/src/port/arm/thumb2-aes-asm.S|lib/wolfssl/wolfcrypt/src/port/arm/thumb2-curve25519.S|lib/wolfssl/wolfcrypt/src/port/arm/thumb2-sha256-asm.S|lib/wolfssl/wolfcrypt/src/port/arm/thumb2-sha3-asm.S|lib/wolfssl/wolfcrypt/src/port/arm/thumb2-sha512-asm.S|lib/wolfssl/wolfcrypt/src/port/autosar|lib/wolfssl/wrapper|lib/wolfssl/zephyr|src/boot_x86_fsp.c|src/boot_x86_fsp_start.S|src/boot_x86_fsp_payload.c|src/boot_x86_64.c|src/boot_renesas.c|src/boot_renesas_start.S|src/boot_ppc_start.S|src/boot_ppc_mp.S|src/boot_ppc.c|src/x86|lib/wolfTPM/examples|lib/wolfTPM/tests|lib/wolfTPM/IDE|lib/wolfssl/tests|lib/wolfssl/tirtos|lib/wolfssl/swig|lib/wolfssl/mqx|lib/wolfssl/mplabx|lib/wolfssl/IPP|lib/wolfssl/mcapi|lib/wolfssl/testsuite|lib/wolfssl/examples|lib/wolfssl/IDE|lib/wolfssl/wolfcrypt/user-crypto|lib/wolfssl/wolfcrypt/src/aes_asm.S|lib/wolfssl/wolfcrypt/src/aes_gcm_asm.S|lib/wolfssl/wolfcrypt/src/aes_gcm_x86_asm.S|lib/wolfssl/wolfcrypt/src/aes_xts_asm.S|lib/wolfssl/wolfcrypt/src/chacha_asm.S|lib/wolfssl/wolfcrypt/src/fe_x25519_asm.S|lib/wolfssl/wolfcrypt/src/poly1305_asm.S|lib/wolfssl/wolfcrypt/src/sha256_asm.S|lib/wolfssl/wolfcrypt/src/sha3_asm.S|lib/wolfssl/wolfcrypt/src/sha512_asm.S|lib/wolfssl/wolfcrypt/src/sm3_asm.S|lib/wolfssl/wolfcrypt/src/sp_sm2_x86_64_asm.S|lib/wolfssl/wolfcrypt/src/sp_x86_64_asm.S|lib/wolfssl/wolfcrypt/src/wc_kyber_asm.S|src/vector_riscv.S|src/update_flash_hwswap.c|src/update_flash.c|src/boot_riscv.c|src/boot_arm.c|src/boot_arm32_start.S|src/boot_arm32.c|hal/aurix_tc3xx.c|hal/cc26x2.c|hal/hifive1.c|hal/imx_rt.c|hal/kinetis.c|hal/kontron_vx3060_s2.c|hal/kontron_vx3060_s2_loader.c|hal/library.c|hal/lpc.c|hal/mcxa.c|hal/nrf52.c|hal/nxp_p1021.c|hal/nxp_ppc.c|hal/nxp_t1024.c|hal/nxp_t2080.c|hal/psoc6.c|hal/raspi3.c|hal/renesas-ra.c|hal/renesas-rx.c|hal/renesas-rz.c|hal/rx65n.c|hal/rx72n.c|hal/same51.c|hal/sama5d3.c|hal/samr21.c|hal/sim.c|hal/skeleton.c|hal/stm32c0.c|hal/stm32f4.c|hal/stm32f7.c|hal/stm32g0.c|hal/stm32h5.c|hal/stm32h7.c|hal/stm32l0.c|hal/stm32l4.c|hal/stm32l5.c|hal/stm32_tz.c|hal/stm32u5.c|hal/stm32wb.c|hal/ti_hercules.c|hal/x86_64_efi.c|hal/x86_fsp_qemu.c|hal/x86_fsp_qemu_loader.c|hal/x86_fsp_tgl.c|hal/x86_uart.c" flags="VALUE_WORKSPACE_PATH|RESOLVED" kind="sourcePath" name=""/>
</sourceEntries>
</configuration>
</storageModule>

View File

@ -45,8 +45,51 @@ These template settings are also in this `.cproject` as preprocessor macros. The
#define WOLFBOOT_LOAD_DTS_ADDRESS 0x11800000
```
The default .cproject build symbols are:
```
ARCH_AARCH64
ARCH_FLASH_OFFSET=0x0
CORTEX_A53
DEBUG_ZYNQ=1
EXT_FLASH=1
FILL_BYTE=0xFF
IMAGE_HEADER_SIZE=1024
MMU
NO_QNX
NO_XIP
PART_BOOT_EXT=1
PART_SWAP_EXT=1
PART_UPDATE_EXT=1
TARGET_zynq
WC_HASH_DATA_ALIGNMENT=8
WOLFBOOT_ARCH_AARCH64
WOLFBOOT_DUALBOOT
WOLFBOOT_ELF
WOLFBOOT_HASH_SHA3_384
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
```
2) Add these compiler misc flags: `-mcpu=generic+crypto -mstrict-align -DWOLFSSL_AARCH64_NO_SQRMLSH`
## Generate signing key
The keygen tool creates an RSA 4096-bit private key (`wolfboot_signing_private_key.der`) and exports the public key to `src/keystore.c` for wolfBoot to use at compile-time as the default root-of-trust.
@ -91,9 +134,13 @@ Xilinx uses a `bootgen` tool for generating a boot binary image that has Xilinx
* Use "offset=" option to place the application into a specific location in flash.
* Use "load=" option to have FSBL load into specific location in RAM.
Generating a boot.bin (from boot.bif).
Run the Xilinx -> Vitis Shell and cd into the workspace root.
Default install locations for bootgen tools:
* Linux: `/tools/Xilinx/Vitis/2022.1/bin`
* Windows: `C:\Xilinx\Vitis\2022.1\bin`
Open the Vitis Shell from the IDE by using file menu "Xilinx" -> "Vitis Shell".
Generating a boot.bin (from boot.bif).
Example boot.bif in workspace root:
```
@ -102,11 +149,15 @@ Example boot.bif in workspace root:
the_ROM_image:
{
[bootloader, destination_cpu=a53-0] zcu102\zynqmp_fsbl\fsbl_a53.elf
[destination_cpu=a53-0, exception_level=el-1] wolfboot\Debug\wolfboot.elf
[destination_cpu=a53-0, exception_level=el-2] wolfboot\Debug\wolfboot.elf
[destination_cpu=a53-0, partition_owner=uboot, offset=0x800000] hello_world\Debug\hello_world_v1_signed.bin
}
```
You can also use exception level 3 or 1 depending on your needs.
From the workspace root:
```sh
bootgen -image boot.bif -arch zynqmp -w -o BOOT.bin
@ -184,10 +235,10 @@ Successfully ran Hello World application
```
6. Build “boot.bin” image:
* `bootgen.exe -image boot.bif -arch zynqmp -o i BOOT.BIN -w`
* `bootgen -image boot.bif -arch zynqmp -o i BOOT.BIN -w`
Note: To generate a report of a boot.bin use the `bootgen_utility`:
`bootgen_utility -arch zynqmp -bin boot.bin -out boot.bin.txt`
Note: To generate a report of a boot.bin use the `bootgen_utility` or after 2022.1 use `bootgen -read`:
`bootgen -arch zynqmp -read BOOT.BIN`
## Post Quantum
@ -207,7 +258,8 @@ WOLFSSL_XMSS_VERIFY_ONLY
WOLFSSL_XMSS_MAX_HEIGHT=32
WOLFBOOT_SHA_BLOCK_SIZE=4096
IMAGE_SIGNATURE_SIZE=2500
IMAGE_HEADER_SIZE=4096
XMSS_IMAGE_SIGNATURE_SIZE=2500
IMAGE_HEADER_SIZE=5000
```
2) Create and sign image:
@ -300,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)

27
arch.mk
View File

@ -37,7 +37,7 @@ WOLFCRYPT_OBJS+=./lib/wolfssl/wolfcrypt/src/sha256.o \
ifeq ($(ARCH),x86_64)
CFLAGS+=-DARCH_x86_64
CFLAGS+=-DARCH_x86_64 -DFAST_MEMCPY
ifeq ($(FORCE_32BIT),1)
NO_ASM=1
CFLAGS+=-DFORCE_32BIT
@ -65,9 +65,17 @@ endif
## ARM Cortex-A
ifeq ($(ARCH),AARCH64)
CROSS_COMPILE?=aarch64-none-elf-
CFLAGS+=-DARCH_AARCH64
CFLAGS+=-DARCH_AARCH64 -DFAST_MEMCPY
OBJS+=src/boot_aarch64.o src/boot_aarch64_start.o
ifeq ($(TARGET),zynq)
ARCH_FLAGS=-march=armv8-a+crypto
CFLAGS+=$(ARCH_FLAGS) -DCORTEX_A53
CFLAGS+=-DNO_QNX
# Support detection and skip of U-Boot legacy header */
CFLAGS+=-DWOLFBOOT_UBOOT_LEGACY
CFLAGS+=-DWOLFBOOT_DUALBOOT
else
ifeq ($(TARGET),nxp_ls1028a)
ARCH_FLAGS=-mcpu=cortex-a72+crypto -march=armv8-a+crypto -mtune=cortex-a72
CFLAGS+=$(ARCH_FLAGS) -DCORTEX_A72
@ -84,6 +92,7 @@ ifeq ($(ARCH),AARCH64)
# By default disable ARM ASM for other targets
NO_ARM_ASM?=1
endif
endif
ifeq ($(SPMATH),1)
MATH_OBJS += ./lib/wolfssl/wolfcrypt/src/sp_c32.o
@ -523,7 +532,7 @@ endif
ifeq ($(ARCH),PPC)
CROSS_COMPILE?=powerpc-linux-gnu-
LDFLAGS+=-Wl,--build-id=none
CFLAGS+=-DARCH_PPC
CFLAGS+=-DARCH_PPC -DFAST_MEMCPY
ifeq ($(DEBUG_UART),0)
CFLAGS+=-fno-builtin-printf
@ -789,12 +798,6 @@ ifeq ($(TARGET),nxp_p1021)
SPI_TARGET=nxp
endif
ifeq ($(TARGET),zynq)
# Support detection and skip of U-Boot legecy header */
CFLAGS+=-DWOLFBOOT_UBOOT_LEGACY
CFLAGS+=-DWOLFBOOT_DUALBOOT
endif
ifeq ($(TARGET),ti_hercules)
# HALCoGen Source and Include?
CORTEX_R5=1
@ -1087,12 +1090,12 @@ ifeq ($(ARCH),AARCH64)
CFLAGS+=-DMMU -DWOLFBOOT_DUALBOOT
OBJS+=src/fdt.o
UPDATE_OBJS:=src/update_ram.o
endif
ifeq ($(DUALBANK_SWAP),1)
else
ifeq ($(DUALBANK_SWAP),1)
CFLAGS+=-DWOLFBOOT_DUALBOOT
UPDATE_OBJS:=src/update_flash_hwswap.o
endif
endif
# Set default update object (if not library)
ifneq ($(TARGET),library)
ifeq ($(UPDATE_OBJS),)

View File

@ -31,6 +31,9 @@ WOLFBOOT_TPM_SEAL?=1
WOLFBOOT_TPM_SEAL_NV_BASE=0x01400300
#WOLFBOOT_TPM_SEAL_AUTH?=SealAuth
# Default image header size is larger to support room for policy
IMAGE_HEADER_SIZE?=512
# TPM Logging
#CFLAGS_EXTRA+=-DDEBUG_WOLFTPM
#CFLAGS_EXTRA+=-DWOLFTPM_DEBUG_VERBOSE

View File

@ -1,5 +1,8 @@
ARCH?=AARCH64
TARGET?=zynq
WOLFBOOT_VERSION?=0
# Default to ZCU102 as hardware platform (QSPI sizes)
CFLAGS_EXTRA+=-DZCU102
@ -28,15 +31,17 @@ IMAGE_HEADER_SIZE?=1024
#IMAGE_HEADER_SIZE?=5288
DEBUG?=0
DEBUG_SYMBOLS=1
DEBUG_UART=1
#DEBUG_ZYNQ=1
CFLAGS_EXTRA+=-DDEBUG_ZYNQ=1
#OPTIMIZATION_LEVEL=2
VTOR?=1
CORTEX_M0?=0
NO_ASM?=0
NO_ARM_ASM?=0
ALLOW_DOWNGRADE?=0
NVM_FLASH_WRITEONCE?=0
WOLFBOOT_VERSION?=0
V?=0
SPMATH?=1
RAM_CODE?=0
@ -48,6 +53,7 @@ SPI_FLASH?=0
NO_XIP=1
USE_GCC=1
ELF?=1
#DEBUG_ELF?=1
# Flash Sector Size
WOLFBOOT_SECTOR_SIZE=0x20000
@ -73,3 +79,6 @@ CROSS_COMPILE=aarch64-none-elf-
# Speed up reads from flash by using larger blocks
CFLAGS_EXTRA+=-DWOLFBOOT_SHA_BLOCK_SIZE=4096
# QSPI Clock at 0=150MHz, 1=75MHz, 2=37.5MHz (default)
#CFLAGS_EXTRA+=-DGQSPI_CLK_DIV=0

View File

@ -22,6 +22,27 @@
#ifndef NXP_LS1028A_H
#define NXP_LS1028A_H
/* By default expect EL3 at startup */
#ifndef EL3_SECURE
#define EL3_SECURE 1
#endif
#ifndef EL2_HYPERVISOR
#define EL2_HYPERVISOR 0
#endif
#ifndef EL1_NONSECURE
#define EL1_NONSECURE 0
#endif
#ifndef HYP_GUEST
/* ZEN Hypervisor guest format support */
#define HYP_GUEST 0
#endif
/* Floating Point Trap Enable */
#ifndef FPU_TRAP
#define FPU_TRAP 0
#endif
/* Expose AA64 defines */
#define AA64_TARGET_EL 2 /* Boot to EL2 hypervisor */
@ -32,7 +53,20 @@
#define AA64GICV3_GITS_BASE GITS_BASE
#define AA64GICV3_GITST_BASE GITST_BASE
/* ID_AA64PFR0_EL1 ARMv8 Processor Feature Register 0*/
#define ID_AA64PFRO_EL3_MASK (0xF<<12) /* EL3 is implemented: 0x0000 no */
/* 0x1000 AA64, 0x2000 AA64+AA32 */
#define ID_AA64PFRO_EL2_MASK (0xF<<8) /* EL2 is implemented: 0x000 no */
/* 0x100 AA64, 0x200 AA64+AA32 */
#define ID_AA64PFRO_EL1_MASK (0xF<<4) /* EL1 is implemented: */
/* 0x10 AA64, 0x20 AA64+AA32 */
#define ID_AA64PFRO_EL0_MASK (0xF<<0) /* EL0 is implemented: */
/* 0x1 AA64, 0x2 AA64+AA32 */
#define ID_AA64PFRO_FGT_MASK (0xFull<<56) /* Fine Grained Traps: */
/* 0x0 no, !0x0: yes */
#define TZPCDECPROT0_SET_BASE 0x02200804
#define TZPCDECPROT1_SET_BASE 0x02200810
#define OCRAM_TZPC_ADDR 0x02200000
/* LS1028A Reference Manual Rev 0 12/2019 */

View File

@ -23,6 +23,9 @@ SECTIONS
PROVIDE (_MEMORY_SIZE = LENGTH(OCRAM));
PROVIDE (_FLASH_SIZE = LENGTH(FLASH));
PROVIDE (_STACK_SIZE = 64K);
PROVIDE (_EL0_STACK_SIZE = DEFINED(_EL0_STACK_SIZE) ? _EL0_STACK_SIZE : 1024);
PROVIDE (_EL1_STACK_SIZE = DEFINED(_EL1_STACK_SIZE) ? _EL1_STACK_SIZE : 2048);
PROVIDE (_EL2_STACK_SIZE = DEFINED(_EL2_STACK_SIZE) ? _EL2_STACK_SIZE : 1024);
.boot :
{
@ -100,10 +103,26 @@ SECTIONS
} > OCRAM
. = ALIGN(16);
.stack :
{
.stack (NOLOAD) : {
. = ALIGN(64);
_start_stack = .;
. = . + _STACK_SIZE;
_el3_stack_end = .;
. += _STACK_SIZE;
__el3_stack = .;
_el2_stack_end = .;
. += _EL2_STACK_SIZE;
. = ALIGN(64);
__el2_stack = .;
_el1_stack_end = .;
. += _EL1_STACK_SIZE;
. = ALIGN(64);
__el1_stack = .;
_el0_stack_end = .;
. += _EL0_STACK_SIZE;
. = ALIGN(64);
__el0_stack = .;
_end_stack = .;
} > OCRAM

View File

@ -1,6 +1,6 @@
/* zynq.c
*
* Copyright (C) 2021 wolfSSL Inc.
* Copyright (C) 2024 wolfSSL Inc.
*
* This file is part of wolfBoot.
*
@ -19,8 +19,13 @@
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA
*/
#include <stdint.h>
#include <string.h>
#ifdef TARGET_zynq
#include "hal/zynq.h"
#ifndef ARCH_AARCH64
# error "wolfBoot zynq HAL: wrong architecture selected. Please compile with ARCH=AARCH64."
#endif
#if defined(__QNXNTO__) && !defined(NO_QNX)
#define USE_QNX
@ -31,15 +36,19 @@
#include <target.h>
#include "image.h"
#include "printf.h"
#ifndef ARCH_AARCH64
# error "wolfBoot zynq HAL: wrong architecture selected. Please compile with ARCH=AARCH64."
#endif
#include <stdint.h>
#include <string.h>
#ifdef USE_XQSPIPSU
/* Xilinx BSP Driver */
#include "xqspipsu.h"
#ifndef QSPI_DEVICE_ID
#define QSPI_DEVICE_ID XPAR_XQSPIPSU_0_DEVICE_ID
#endif
#ifndef QSPI_CLK_PRESACALE
#define QSPI_CLK_PRESACALE XQSPIPSU_CLK_PRESCALE_8
#endif
#elif defined(USE_QNX)
/* QNX QSPI driver */
#include <sys/siginfo.h>
@ -48,214 +57,6 @@
/* QSPI bare-metal */
#endif
/* QSPI bare-metal driver */
#define CORTEXA53_0_CPU_CLK_FREQ_HZ 1099989014
#define CORTEXA53_0_TIMESTAMP_CLK_FREQ 99998999
/* Generic Quad-SPI */
#define QSPI_BASE 0xFF0F0000UL
#define LQSPI_EN (*((volatile uint32_t*)(QSPI_BASE + 0x14))) /* SPI enable: 0: disable the SPI, 1: enable the SPI */
#define GQSPI_CFG (*((volatile uint32_t*)(QSPI_BASE + 0x100))) /* configuration register. */
#define GQSPI_ISR (*((volatile uint32_t*)(QSPI_BASE + 0x104))) /* interrupt status register. */
#define GQSPI_IER (*((volatile uint32_t*)(QSPI_BASE + 0x108))) /* interrupt enable register. */
#define GQSPI_IDR (*((volatile uint32_t*)(QSPI_BASE + 0x10C))) /* interrupt disable register. */
#define GQSPI_IMR (*((volatile uint32_t*)(QSPI_BASE + 0x110))) /* interrupt unmask register. */
#define GQSPI_EN (*((volatile uint32_t*)(QSPI_BASE + 0x114))) /* enable register. */
#define GQSPI_TXD (*((volatile uint32_t*)(QSPI_BASE + 0x11C))) /* TX data register. Keyhole addresses for the transmit data FIFO. */
#define GQSPI_RXD (*((volatile uint32_t*)(QSPI_BASE + 0x120))) /* RX data register. */
#define GQSPI_TX_THRESH (*((volatile uint32_t*)(QSPI_BASE + 0x128))) /* TXFIFO Threshold Level register: (bits 5:0) Defines the level at which the TX_FIFO_NOT_FULL interrupt is generated */
#define GQSPI_RX_THRESH (*((volatile uint32_t*)(QSPI_BASE + 0x12C))) /* RXFIFO threshold level register: (bits 5:0) Defines the level at which the RX_FIFO_NOT_EMPTY interrupt is generated */
#define GQSPI_GPIO (*((volatile uint32_t*)(QSPI_BASE + 0x130)))
#define GQSPI_LPBK_DLY_ADJ (*((volatile uint32_t*)(QSPI_BASE + 0x138))) /* adjusting the internal loopback clock delay for read data capturing */
#define GQSPI_GEN_FIFO (*((volatile uint32_t*)(QSPI_BASE + 0x140))) /* generic FIFO data register. Keyhole addresses for the generic FIFO. */
#define GQSPI_SEL (*((volatile uint32_t*)(QSPI_BASE + 0x144))) /* select register. */
#define GQSPI_FIFO_CTRL (*((volatile uint32_t*)(QSPI_BASE + 0x14C))) /* FIFO control register. */
#define GQSPI_GF_THRESH (*((volatile uint32_t*)(QSPI_BASE + 0x150))) /* generic FIFO threshold level register: (bits 4:0) Defines the level at which the GEN_FIFO_NOT_FULL interrupt is generated */
#define GQSPI_POLL_CFG (*((volatile uint32_t*)(QSPI_BASE + 0x154))) /* poll configuration register */
#define GQSPI_P_TIMEOUT (*((volatile uint32_t*)(QSPI_BASE + 0x158))) /* poll timeout register. */
#define GQSPI_XFER_STS (*((volatile uint32_t*)(QSPI_BASE + 0x15C))) /* transfer status register. */
#define QSPI_DATA_DLY_ADJ (*((volatile uint32_t*)(QSPI_BASE + 0x1F8))) /* adjusting the internal receive data delay for read data capturing */
#define GQSPI_MOD_ID (*((volatile uint32_t*)(QSPI_BASE + 0x1FC)))
#define QSPIDMA_DST_STS (*((volatile uint32_t*)(QSPI_BASE + 0x808)))
#define QSPIDMA_DST_CTRL (*((volatile uint32_t*)(QSPI_BASE + 0x80C)))
#define QSPIDMA_DST_I_STS (*((volatile uint32_t*)(QSPI_BASE + 0x814)))
#define QSPIDMA_DST_CTRL2 (*((volatile uint32_t*)(QSPI_BASE + 0x824)))
/* GQSPI Registers */
/* GQSPI_CFG: Configuration registers */
#define GQSPI_CFG_CLK_POL (1UL << 1) /* Clock polarity outside QSPI word: 0: QSPI clock is quiescent low, 1: QSPI clock is quiescent high */
#define GQSPI_CFG_CLK_PH (1UL << 2) /* Clock phase: 1: the QSPI clock is inactive outside the word, 0: the QSPI clock is active outside the word */
/* 000: divide by 2, 001: divide by 4, 010: divide by 8,
011: divide by 16, 100: divide by 32, 101: divide by 64,
110: divide by 128, 111: divide by 256 */
#define GQSPI_CFG_BAUD_RATE_DIV_MASK (7UL << 3)
#define GQSPI_CFG_BAUD_RATE_DIV(d) ((d << 3) & GQSPI_CFG_BAUD_RATE_DIV_MASK)
#define GQSPI_CFG_WP_HOLD (1UL << 19) /* If set, Holdb and WPn pins are actively driven by the qspi controller in 1-bit and 2-bit modes. */
#define GQSPI_CFG_EN_POLL_TIMEOUT (1UL << 20) /* Poll Timeout Enable: 0: disable, 1: enable */
#define GQSPI_CFG_ENDIAN (1UL << 26) /* Endian format transmit data register: 0: little endian, 1: big endian */
#define GQSPI_CFG_START_GEN_FIFO (1UL << 28) /* Trigger Generic FIFO Command Execution: 0:disable executing requests, 1: enable executing requests */
#define GQSPI_CFG_GEN_FIFO_START_MODE (1UL << 29) /* Start mode of Generic FIFO: 0: Auto Start Mode, 1: Manual Start Mode */
#define GQSPI_CFG_MODE_EN_MASK (3UL << 30) /* Flash memory interface mode control: 00: IO mode, 10: DMA mode */
#define GQSPI_CFG_MODE_EN(m) ((m << 30) & GQSPI_CFG_MODE_EN_MASK)
#define GQSPI_CFG_MODE_EN_IO GQSPI_CFG_MODE_EN(0)
#define GQSPI_CFG_MODE_EN_DMA GQSPI_CFG_MODE_EN(2)
/* GQSPI_ISR / GQSPI_IER / GQSPI_IDR / GQSPI_IMR: Interrupt registers */
#define GQSPI_IXR_RX_FIFO_EMPTY (1UL << 11)
#define GQSPI_IXR_GEN_FIFO_FULL (1UL << 10)
#define GQSPI_IXR_GEN_FIFO_NOT_FULL (1UL << 9)
#define GQSPI_IXR_TX_FIFO_EMPTY (1UL << 8)
#define GQSPI_IXR_GEN_FIFO_EMPTY (1UL << 7)
#define GQSPI_IXR_RX_FIFO_FULL (1UL << 5)
#define GQSPI_IXR_RX_FIFO_NOT_EMPTY (1UL << 4)
#define GQSPI_IXR_TX_FIFO_FULL (1UL << 3)
#define GQSPI_IXR_TX_FIFO_NOT_FULL (1UL << 2)
#define GQSPI_IXR_POLL_TIME_EXPIRE (1UL << 1)
#define GQSPI_IXR_ALL_MASK (GQSPI_IXR_POLL_TIME_EXPIRE | GQSPI_IXR_TX_FIFO_NOT_FULL | \
GQSPI_IXR_TX_FIFO_FULL | GQSPI_IXR_RX_FIFO_NOT_EMPTY | GQSPI_IXR_RX_FIFO_FULL | \
GQSPI_IXR_GEN_FIFO_EMPTY | GQSPI_IXR_TX_FIFO_EMPTY | GQSPI_IXR_GEN_FIFO_NOT_FULL | \
GQSPI_IXR_GEN_FIFO_FULL | GQSPI_IXR_RX_FIFO_EMPTY)
#define GQSPI_ISR_WR_TO_CLR_MASK 0x00000002U
/* GQSPI_GEN_FIFO: FIFO data register */
/* bits 0-7: Length in bytes (except when GQSPI_GEN_FIFO_EXP_MASK is set length as 255 chunks) */
#define GQSPI_GEN_FIFO_IMM_MASK (0xFFUL) /* Immediate Data Field */
#define GQSPI_GEN_FIFO_IMM(imm) (imm & GQSPI_GEN_FIFO_IMM_MASK)
#define GQSPI_GEN_FIFO_DATA_XFER (1UL << 8) /* Indicates IMM is size, otherwise byte is sent directly in IMM reg */
#define GQSPI_GEN_FIFO_EXP_MASK (1UL << 9) /* Length is Exponent (length / 255) */
#define GQSPI_GEN_FIFO_MODE_MASK (3UL << 10)
#define GQSPI_GEN_FIFO_MODE(m) ((m << 10) & GQSPI_GEN_FIFO_MODE_MASK)
#define GQSPI_GEN_FIFO_MODE_SPI GQSPI_GEN_FIFO_MODE(1)
#define GQSPI_GEN_FIFO_MODE_DSPI GQSPI_GEN_FIFO_MODE(2)
#define GQSPI_GEN_FIFO_MODE_QSPI GQSPI_GEN_FIFO_MODE(3)
#define GQSPI_GEN_FIFO_CS_MASK (3UL << 12)
#define GQSPI_GEN_FIFO_CS(c) ((c << 12) & GQSPI_GEN_FIFO_CS_MASK)
#define GQSPI_GEN_FIFO_CS_LOWER GQSPI_GEN_FIFO_CS(1)
#define GQSPI_GEN_FIFO_CS_UPPER GQSPI_GEN_FIFO_CS(2)
#define GQSPI_GEN_FIFO_CS_BOTH GQSPI_GEN_FIFO_CS(3)
#define GQSPI_GEN_FIFO_BUS_MASK (3UL << 14)
#define GQSPI_GEN_FIFO_BUS(b) ((b << 14) & GQSPI_GEN_FIFO_BUS_MASK)
#define GQSPI_GEN_FIFO_BUS_LOW GQSPI_GEN_FIFO_BUS(1)
#define GQSPI_GEN_FIFO_BUS_UP GQSPI_GEN_FIFO_BUS(2)
#define GQSPI_GEN_FIFO_BUS_BOTH GQSPI_GEN_FIFO_BUS(3)
#define GQSPI_GEN_FIFO_TX (1UL << 16)
#define GQSPI_GEN_FIFO_RX (1UL << 17)
#define GQSPI_GEN_FIFO_STRIPE (1UL << 18) /* Stripe data across the lower and upper data buses. */
#define GQSPI_GEN_FIFO_POLL (1UL << 19)
/* GQSPI_FIFO_CTRL */
#define GQSPI_FIFO_CTRL_RST_GEN_FIFO (1UL << 0)
#define GQSPI_FIFO_CTRL_RST_TX_FIFO (1UL << 1)
#define GQSPI_FIFO_CTRL_RST_RX_FIFO (1UL << 2)
/* QSPIDMA_DST_CTRL */
#define QSPIDMA_DST_CTRL_DEF 0x403FFA00UL
#define QSPIDMA_DST_CTRL2_DEF 0x081BFFF8UL
/* QSPIDMA_DST_STS */
#define QSPIDMA_DST_STS_WTC 0xE000U
/* QSPIDMA_DST_I_STS */
#define QSPIDMA_DST_I_STS_ALL_MASK 0xFEU
/* IOP System-level Control */
#define IOU_SLCR_BASSE 0xFF180000
#define IOU_TAPDLY_BYPASS (*((volatile uint32_t*)(IOU_SLCR_BASSE + 0x390)))
#define IOU_TAPDLY_BYPASS_LQSPI_RX (1UL << 2) /* LQSPI Tap Delay Enable on Rx Clock signal. 0: enable. 1: disable (bypass tap delay). */
/* Configuration used for bare-metal only */
#define GQSPI_CLK_FREQ_HZ 124987511
#define GQSPI_CLK_DIV 2 /* (CLK / (2 << val) = BUS) - DIV 2 = 37.5 MHz */
#define GQSPI_CS_ASSERT_CLOCKS 5 /* CS Setup Time (tCSS) - num of clock cycles foes in IMM */
#define GQSPI_FIFO_WORD_SZ 4
#define GQSPI_TIMEOUT_TRIES 100000
#define QSPI_FLASH_READY_TRIES 1000
/* QSPI Configuration */
#ifndef GQSPI_QSPI_MODE
#define GQSPI_QSPI_MODE GQSPI_GEN_FIFO_MODE_QSPI
#endif
#ifndef GQPI_USE_DUAL_PARALLEL
#define GQPI_USE_DUAL_PARALLEL 1 /* 0=no stripe, 1=stripe */
#endif
#ifndef GQPI_USE_4BYTE_ADDR
#define GQPI_USE_4BYTE_ADDR 1
#endif
#ifndef GQSPI_DUMMY_READ
#define GQSPI_DUMMY_READ (8*8) /* Number of dummy clock cycles for reads */
#endif
/* Flash Parameters:
* Micron Serial NOR Flash Memory 64KB Sector Erase MT25QU512ABB
* Stacked device (two 512Mb (64MB))
* Dual Parallel so total addressable size is double
*/
#ifndef FLASH_DEVICE_SIZE
#ifdef ZCU102
/* 64*2 (dual parallel) = 128MB */
#define FLASH_DEVICE_SIZE (2 * 64 * 1024 * 1024) /* MT25QU512ABB */
#else
/* 128*2 (dual parallel) = 256MB */
#define FLASH_DEVICE_SIZE (2 * 128 * 1024 * 1024) /* MT25QU01GBBB */
#endif
#endif
#ifndef FLASH_PAGE_SIZE
#ifdef ZCU102
#define FLASH_PAGE_SIZE 256 /* MT25QU512ABB */
#else
#define FLASH_PAGE_SIZE 512 /* MT25QU01GBBB */
#endif
#endif
#define FLASH_NUM_SECTORS (FLASH_DEVICE_SIZE/WOLFBOOT_SECTOR_SIZE)
/* Flash Commands */
#define WRITE_ENABLE_CMD 0x06U
#define READ_SR_CMD 0x05U
#define WRITE_DISABLE_CMD 0x04U
#define READ_ID_CMD 0x9FU
#define MULTI_IO_READ_ID_CMD 0xAFU
#define READ_FSR_CMD 0x70U
#define ENTER_QSPI_MODE_CMD 0x35U
#define EXIT_QSPI_MODE_CMD 0xF5U
#define ENTER_4B_ADDR_MODE_CMD 0xB7U
#define EXIT_4B_ADDR_MODE_CMD 0xE9U
#define FAST_READ_CMD 0x0BU
#define DUAL_READ_CMD 0x3BU
#define QUAD_READ_CMD 0x6BU
#define FAST_READ_4B_CMD 0x0CU
#define DUAL_READ_4B_CMD 0x3CU
#define QUAD_READ_4B_CMD 0x6CU
#define PAGE_PROG_CMD 0x02U
#define DUAL_PROG_CMD 0xA2U
#define QUAD_PROG_CMD 0x22U
#define PAGE_PROG_4B_CMD 0x12U
#define DUAL_PROG_4B_CMD 0x12U
#define QUAD_PROG_4B_CMD 0x34U
#define SEC_ERASE_CMD 0xD8U
#define SEC_4K_ERASE_CMD 0x20U
#define RESET_ENABLE_CMD 0x66U
#define RESET_MEMORY_CMD 0x99U
#define WRITE_EN_MASK 0x02 /* 0=Write Enabled, 1=Disabled Write */
#define FLASH_READY_MASK 0x80 /* 0=Busy, 1=Ready */
/* Return Codes */
#define GQSPI_CODE_SUCCESS 0
#define GQSPI_CODE_FAILED -100
#define GQSPI_CODE_TIMEOUT -101
/* QSPI Slave Device Information */
typedef struct QspiDev {
uint32_t mode; /* GQSPI_GEN_FIFO_MODE_SPI, GQSPI_GEN_FIFO_MODE_DSPI or GQSPI_GEN_FIFO_MODE_QSPI */
@ -279,84 +80,35 @@ static int qspi_wait_we(QspiDev_t* dev);
static int test_ext_flash(QspiDev_t* dev);
#endif
/* eFUSE support */
#define ZYNQMP_EFUSE_BASE 0xFFCC0000
#define ZYNQMP_EFUSE_STATUS (*((volatile uint32_t*)(ZYNQMP_EFUSE_BASE + 0x0008)))
#define ZYNQMP_EFUSE_SEC_CTRL (*((volatile uint32_t*)(ZYNQMP_EFUSE_BASE + 0x1058)))
#define ZYNQMP_EFUSE_PPK0_0 (*((volatile uint32_t*)(ZYNQMP_EFUSE_BASE + 0x10A0)))
#define ZYNQMP_EFUSE_PPK0_1 (*((volatile uint32_t*)(ZYNQMP_EFUSE_BASE + 0x10A4)))
#define ZYNQMP_EFUSE_PPK0_2 (*((volatile uint32_t*)(ZYNQMP_EFUSE_BASE + 0x10A8)))
#define ZYNQMP_EFUSE_PPK0_3 (*((volatile uint32_t*)(ZYNQMP_EFUSE_BASE + 0x10AC)))
#define ZYNQMP_EFUSE_PPK0_4 (*((volatile uint32_t*)(ZYNQMP_EFUSE_BASE + 0x10B0)))
#define ZYNQMP_EFUSE_PPK0_5 (*((volatile uint32_t*)(ZYNQMP_EFUSE_BASE + 0x10B4)))
#define ZYNQMP_EFUSE_PPK0_6 (*((volatile uint32_t*)(ZYNQMP_EFUSE_BASE + 0x10B8)))
#define ZYNQMP_EFUSE_PPK0_7 (*((volatile uint32_t*)(ZYNQMP_EFUSE_BASE + 0x10BC)))
#define ZYNQMP_EFUSE_PPK0_8 (*((volatile uint32_t*)(ZYNQMP_EFUSE_BASE + 0x10C0)))
#define ZYNQMP_EFUSE_PPK0_9 (*((volatile uint32_t*)(ZYNQMP_EFUSE_BASE + 0x10C4)))
#define ZYNQMP_EFUSE_PPK0_10 (*((volatile uint32_t*)(ZYNQMP_EFUSE_BASE + 0x10C8)))
#define ZYNQMP_EFUSE_PPK0_11 (*((volatile uint32_t*)(ZYNQMP_EFUSE_BASE + 0x10CC)))
/* eFUSE STATUS Registers */
#define ZYNQMP_EFUSE_STATUS_CACHE_DONE (1UL << 5)
#define ZYNQMP_EFUSE_STATUS_CACHE_LOAD (1UL << 4)
/* eFUSE SEC_CTRL Registers */
#define ZYNQMP_EFUSE_SEC_CTRL_PPK1_INVLD (3UL << 30) /* Revokes PPK1 */
#define ZYNQMP_EFUSE_SEC_CTRL_PPK1_WRLK (1UL << 29) /* Locks writing to PPK1 eFuses */
#define ZYNQMP_EFUSE_SEC_CTRL_PPK0_INVLD (3UL << 27) /* Revokes PPK0 */
#define ZYNQMP_EFUSE_SEC_CTRL_PPK0_WRLK (1UL << 26) /* Locks writing to PPK0 eFuses */
#define ZYNQMP_EFUSE_SEC_CTRL_RSA_EN (15UL << 11) /* Enables RSA Authentication during boot. All boots must be authenticated */
#define ZYNQMP_EFUSE_SEC_CTRL_SEC_LOCK (1UL << 10) /* Disables the reboot into JTAG mode when doing a secure lockdown. */
#define ZYNQMP_EFUSE_SEC_CTRL_JTAG_DIS (1UL << 5) /* Disables the JTAG controller. The only instructions available are BYPASS and IDCODE. */
#define ZYNQMP_EFUSE_SEC_CTRL_ENC_ONLY (1UL << 2) /* Requires all boots to be encrypted using the eFuse key. */
#define ZYNQMP_EFUSE_SEC_CTRL_AES_WRLK (1UL << 1) /* Locks writing to the AES key section of eFuse */
#define ZYNQMP_EFUSE_SEC_CTRL_AES_RDLK (1UL << 0) /* Locks the AES key CRC check function */
#ifdef DEBUG_UART
/* UART Support for Debugging */
#define ZYNQMP_UART0_BASE 0xFF000000
#define ZYNQMP_UART1_BASE 0xFF010000
#define ZYNQMP_UART_CR (*((volatile uint32_t*)(DEBUG_UART_BASE + 0x0)))
#define ZYNQMP_UART_MR (*((volatile uint32_t*)(DEBUG_UART_BASE + 0x4)))
#define ZYNQMP_UART_SR (*((volatile uint32_t*)(DEBUG_UART_BASE + 0x2C)))
#define ZYNQMP_UART_FIFO (*((volatile uint32_t*)(DEBUG_UART_BASE + 0x30)))
#define ZYNQMP_UART_BR_GEN (*((volatile uint32_t*)(DEBUG_UART_BASE + 0x18))) /* 2 - 65535: baud_sample */
#define ZYNQMP_UART_BR_DIV (*((volatile uint32_t*)(DEBUG_UART_BASE + 0x34))) /* 4 - 255: Baud rate */
/* UART Control Registers */
#define ZYNQMP_UART_CR_TX_EN 0x00000010 /* TX enabled */
#define ZYNQMP_UART_CR_RX_EN 0x00000004 /* RX enabled */
#define ZYNQMP_UART_CR_TXRST 0x00000002 /* TX logic reset */
#define ZYNQMP_UART_CR_RXRST 0x00000001 /* RX logic reset */
/* UART Mode Registers */
#define ZYNQMP_UART_MR_PARITY_NONE 0x00000020 /* No parity */
/* UART Channel Status Register (read only) */
#define ZYNQMP_UART_SR_TXFULL 0x00000010U /* TX FIFO full */
#define ZYNQMP_UART_SR_TXEMPTY 0x00000008U /* TX FIFO empty */
#define ZYNQMP_UART_SR_RXFULL 0x00000004U /* RX FIFO full */
#define ZYNQMP_UART_SR_RXEMPTY 0x00000002U /* RX FIFO empty */
/* UART Configuration */
#define UART_MASTER_CLOCK 100000000
#define DEBUG_UART_BASE ZYNQMP_UART1_BASE
#define DEBUG_UART_BAUD 115200
#define DEBUG_UART_DIV 4
void uart_init(void)
{
/* Enable TX/RX and Reset */
ZYNQMP_UART_CR = (ZYNQMP_UART_CR_TX_EN | ZYNQMP_UART_CR_RX_EN |
ZYNQMP_UART_CR_TXRST | ZYNQMP_UART_CR_RXRST);
/* Disable Interrupts */
ZYNQMP_UART_IDR = ZYNQMP_UART_ISR_MASK;
/* Disable TX/RX */
ZYNQMP_UART_CR = (ZYNQMP_UART_CR_TX_DIS | ZYNQMP_UART_CR_RX_DIS);
/* Clear ISR */
ZYNQMP_UART_ISR = ZYNQMP_UART_ISR_MASK;
/* 8-bits, no parity */
ZYNQMP_UART_MR = ZYNQMP_UART_MR_PARITY_NONE;
/* FIFO Trigger Level */
ZYNQMP_UART_RXWM = 32; /* half of 64 byte FIFO */
ZYNQMP_UART_TXWM = 32; /* half of 64 byte FIFO */
/* RX Timeout - disable */
ZYNQMP_UART_RXTOUT = 0;
/* baud (115200) = master clk / (BR_GEN * (BR_DIV + 1)) */
ZYNQMP_UART_BR_GEN = UART_MASTER_CLOCK / (DEBUG_UART_BAUD * (DEBUG_UART_DIV+1));
ZYNQMP_UART_BR_DIV = DEBUG_UART_DIV;
ZYNQMP_UART_BR_GEN = UART_MASTER_CLOCK / DEBUG_UART_BAUD / (DEBUG_UART_DIV+1);
/* Reset TX/RX */
ZYNQMP_UART_CR = (ZYNQMP_UART_CR_TXRST | ZYNQMP_UART_CR_RXRST);
/* Enable TX/RX */
ZYNQMP_UART_CR = (ZYNQMP_UART_CR_TX_EN | ZYNQMP_UART_CR_RX_EN);
}
void uart_write(const char* buf, uint32_t sz)
@ -366,10 +118,10 @@ void uart_write(const char* buf, uint32_t sz)
char c = buf[pos++];
if (c == '\n') { /* handle CRLF */
while (ZYNQMP_UART_SR & ZYNQMP_UART_SR_TXFULL);
ZYNQMP_UART_SR = '\r';
ZYNQMP_UART_FIFO = '\r';
}
while (ZYNQMP_UART_SR & ZYNQMP_UART_SR_TXFULL);
ZYNQMP_UART_SR = c;
ZYNQMP_UART_FIFO = c;
}
/* Wait till TX Fifo is empty */
while (!(ZYNQMP_UART_SR & ZYNQMP_UART_SR_TXEMPTY));
@ -558,9 +310,7 @@ static int qspi_gen_fifo_write(uint32_t reg_genfifo)
static int gspi_fifo_tx(const uint8_t* data, uint32_t sz)
{
uint32_t tmp32, txSz;
uint8_t* txData = (uint8_t*)&tmp32;
uint32_t tmp32;
while (sz > 0) {
/* Wait for TX FIFO not full */
if (qspi_isr_wait(GQSPI_IXR_TX_FIFO_FULL, GQSPI_IXR_TX_FIFO_FULL)) {
@ -568,57 +318,44 @@ static int gspi_fifo_tx(const uint8_t* data, uint32_t sz)
}
/* Write data */
txSz = sz;
if (txSz > GQSPI_FIFO_WORD_SZ)
txSz = GQSPI_FIFO_WORD_SZ;
if (sz >= 4) {
GQSPI_TXD = *(uint32_t*)data;
data += 4;
sz -= 4;
}
else {
tmp32 = 0;
memcpy(txData, data, txSz);
sz -= txSz;
data += txSz;
#if defined(DEBUG_ZYNQ) && DEBUG_ZYNQ >= 3
wolfBoot_printf("TXD=%08x\n", tmp32);
#endif
memcpy(&tmp32, data, sz);
GQSPI_TXD = tmp32;
sz = 0;
}
}
return GQSPI_CODE_SUCCESS;
}
static int gspi_fifo_rx(uint8_t* data, uint32_t sz, uint32_t discardSz)
{
uint32_t tmp32, rxSz;
uint8_t* rxData = (uint8_t*)&tmp32;
uint32_t tmp32;
while (sz > 0) {
/* Wait for RX FIFO not empty */
if (qspi_isr_wait(GQSPI_IXR_RX_FIFO_NOT_EMPTY, 0)) {
return GQSPI_CODE_TIMEOUT;
}
/* Read data */
tmp32 = GQSPI_RXD;
#if defined(DEBUG_ZYNQ) && DEBUG_ZYNQ >= 3
wolfBoot_printf("RXD=%08x\n", tmp32);
if (discardSz > 0)
wolfBoot_printf("Discard %d\n", discardSz);
#endif
if (discardSz >= GQSPI_FIFO_WORD_SZ) {
tmp32 = GQSPI_RXD; /* discard */
discardSz -= GQSPI_FIFO_WORD_SZ;
continue;
}
rxSz = sz;
if (rxSz > GQSPI_FIFO_WORD_SZ)
rxSz = GQSPI_FIFO_WORD_SZ;
if (rxSz > discardSz) {
rxSz -= discardSz;
sz -= discardSz;
if (sz >= 4) {
*(uint32_t*)data = GQSPI_RXD;
data += 4;
sz -= 4;
}
else {
tmp32 = GQSPI_RXD;
memcpy(data, &tmp32, sz);
sz = 0;
}
memcpy(data, rxData + discardSz, rxSz);
discardSz = 0;
sz -= rxSz;
data += rxSz;
}
return GQSPI_CODE_SUCCESS;
}
@ -778,14 +515,13 @@ static int qspi_transfer(QspiDev_t* pDev,
return ret;
}
#endif
#endif /* QSPI Implementation */
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;
@ -815,7 +551,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;
@ -990,7 +726,7 @@ static int qspi_exit_4byte_addr(QspiDev_t* dev)
void qspi_init(uint32_t cpu_clock, uint32_t flash_freq)
{
int ret;
uint32_t reg_cfg;
uint32_t reg_cfg, reg_isr;
uint8_t id_low[4];
#if GQPI_USE_DUAL_PARALLEL == 1
uint8_t id_hi[4];
@ -1037,9 +773,10 @@ void qspi_init(uint32_t cpu_clock, uint32_t flash_freq)
GQSPI_SEL = 1;
/* Clear and disable interrupts */
reg_cfg = GQSPI_ISR;
reg_isr = GQSPI_ISR;
GQSPI_ISR |= GQSPI_ISR_WR_TO_CLR_MASK; /* Clear poll timeout counter interrupt */
QSPIDMA_DST_I_STS = QSPIDMA_DST_I_STS; /* clear all active interrupts */
reg_cfg = QSPIDMA_DST_I_STS;
QSPIDMA_DST_I_STS = reg_cfg; /* clear all active interrupts */
QSPIDMA_DST_STS |= QSPIDMA_DST_STS_WTC; /* mark outstanding DMA's done */
GQSPI_IDR = GQSPI_IXR_ALL_MASK; /* disable interrupts */
QSPIDMA_DST_I_STS = QSPIDMA_DST_I_STS_ALL_MASK; /* disable interrupts */
@ -1047,7 +784,7 @@ void qspi_init(uint32_t cpu_clock, uint32_t flash_freq)
if (GQSPI_ISR & GQSPI_IXR_RX_FIFO_EMPTY) {
GQSPI_FIFO_CTRL |= (GQSPI_FIFO_CTRL_RST_TX_FIFO | GQSPI_FIFO_CTRL_RST_RX_FIFO);
}
if (reg_cfg & GQSPI_IXR_RX_FIFO_EMPTY) {
if (reg_isr & GQSPI_IXR_RX_FIFO_EMPTY) {
GQSPI_FIFO_CTRL |= GQSPI_FIFO_CTRL_RST_RX_FIFO;
}
@ -1061,10 +798,26 @@ void qspi_init(uint32_t cpu_clock, uint32_t flash_freq)
reg_cfg &= ~(GQSPI_CFG_CLK_POL | GQSPI_CFG_CLK_PH); /* Use POL=0,PH=0 */
GQSPI_CFG = reg_cfg;
/* use tap delay bypass < 40MHz SPI clock */
#if GQSPI_CLK_DIV >= 2 /* 300/8=37.5MHz */
/* At 40 MHz, the Quad-SPI controller should be in non-loopback mode with
* the clock and data tap delays bypassed. */
IOU_TAPDLY_BYPASS |= IOU_TAPDLY_BYPASS_LQSPI_RX;
GQSPI_LPBK_DLY_ADJ = 0;
QSPI_DATA_DLY_ADJ = 0;
#elif GQSPI_CLK_DIV >= 1 /* 300/4=75MHz */
/* At 100 MHz, the Quad-SPI controller should be in clock loopback mode
* with the clock tap delay bypassed, but the data tap delay enabled. */
IOU_TAPDLY_BYPASS |= IOU_TAPDLY_BYPASS_LQSPI_RX;
GQSPI_LPBK_DLY_ADJ = GQSPI_LPBK_DLY_ADJ_USE_LPBK;
QSPI_DATA_DLY_ADJ = QSPI_DATA_DLY_ADJ_USE_DATA_DLY | QSPI_DATA_DLY_ADJ_DATA_DLY_ADJ(2);
#else
/* At 150 MHz, only the generic controller can be used.
* The generic controller should be in clock loopback mode and the clock
* tap delay enabled, but the data tap delay disabled. */
IOU_TAPDLY_BYPASS = 0;
GQSPI_LPBK_DLY_ADJ = GQSPI_LPBK_DLY_ADJ_USE_LPBK;
QSPI_DATA_DLY_ADJ = 0;
#endif
/* Initialize hardware parameters for Threshold and Interrupts */
GQSPI_TX_THRESH = 1;
@ -1082,6 +835,7 @@ void qspi_init(uint32_t cpu_clock, uint32_t flash_freq)
GQSPI_EN = 1; /* Enable Device */
#endif /* USE_QNX */
(void)reg_cfg;
(void)reg_isr;
/* ------ Flash Read ID (retry) ------ */
timeout = 0;
@ -1138,34 +892,20 @@ void qspi_init(uint32_t cpu_clock, uint32_t flash_freq)
#endif
}
void zynq_init(uint32_t cpu_clock)
#if 0
uint64_t hal_timer_ms(void)
{
qspi_init(cpu_clock, 0);
uint64_t val;
unsigned long cntfrq;
unsigned long cntpct;
asm volatile("mrs %0, cntfrq_el0" : "=r" (cntfrq));
asm volatile("mrs %0, cntpct_el0" : "=r" (cntpct));
val = cntpct * 1000;
val /= cntfrq;
return val;
}
void zynq_exit(void)
{
int ret;
#if GQPI_USE_4BYTE_ADDR == 1
/* Exit 4-byte address mode */
ret = qspi_exit_4byte_addr(&mDev);
if (ret != GQSPI_CODE_SUCCESS)
return;
#endif
#ifdef USE_QNX
if (mDev.qnx) {
xzynq_qspi_close(mDev.qnx);
mDev.qnx = NULL;
}
#endif
(void)ret;
}
/* public HAL functions */
void hal_init(void)
{
@ -1177,17 +917,29 @@ void hal_init(void)
#endif
wolfBoot_printf(bootMsg);
#ifdef USE_BUILTIN_STARTUP /* Vitis is EL-3 */
#if 0
/* This is only allowed for EL-3 */
asm volatile("msr cntfrq_el0, %0" : : "r" (cpu_freq) : "memory");
#endif
zynq_init(cpu_freq);
qspi_init(cpu_freq, 0);
}
void hal_prepare_boot(void)
{
zynq_exit();
#if GQPI_USE_4BYTE_ADDR == 1
/* Exit 4-byte address mode */
int ret = qspi_exit_4byte_addr(&mDev);
if (ret != GQSPI_CODE_SUCCESS)
return;
#endif
#ifdef USE_QNX
if (mDev.qnx) {
xzynq_qspi_close(mDev.qnx);
mDev.qnx = NULL;
}
#endif
}
/* Flash functions must be relocated to RAM for execution */
@ -1216,14 +968,21 @@ int RAMFUNCTION ext_flash_write(uintptr_t address, const uint8_t *data, int len)
{
int ret = 0;
uint8_t cmd[8]; /* size multiple of uint32_t */
uint32_t xferSz, page, pages, idx = 0;
uint32_t xferSz, page, pages, idx;
uintptr_t addr;
#if defined(DEBUG_ZYNQ) && DEBUG_ZYNQ >= 2
wolfBoot_printf("Flash Write: Addr 0x%x, Ptr %p, Len %d\n",
address, data, len);
#endif
/* write by page */
pages = ((len + (FLASH_PAGE_SIZE-1)) / FLASH_PAGE_SIZE);
for (page = 0; page < pages; page++) {
ret = qspi_write_enable(&mDev);
if (ret == GQSPI_CODE_SUCCESS) {
if (ret != GQSPI_CODE_SUCCESS) {
break;
}
xferSz = len;
if (xferSz > FLASH_PAGE_SIZE)
xferSz = FLASH_PAGE_SIZE;
@ -1236,6 +995,7 @@ int RAMFUNCTION ext_flash_write(uintptr_t address, const uint8_t *data, int len)
/* ------ Write Flash (page at a time) ------ */
memset(cmd, 0, sizeof(cmd));
idx = 0;
cmd[idx++] = PAGE_PROG_CMD;
#if GQPI_USE_4BYTE_ADDR == 1
cmd[idx++] = ((addr >> 24) & 0xFF);
@ -1255,7 +1015,7 @@ int RAMFUNCTION ext_flash_write(uintptr_t address, const uint8_t *data, int len)
break;
}
qspi_write_disable(&mDev);
}
len -= xferSz;
}
return ret;
@ -1281,6 +1041,11 @@ int RAMFUNCTION ext_flash_read(uintptr_t address, uint8_t *data, int len)
uint8_t cmd[8]; /* size multiple of uint32_t */
uint32_t idx = 0;
#if defined(DEBUG_ZYNQ) && DEBUG_ZYNQ >= 2
wolfBoot_printf("Flash Read: Addr 0x%x, Ptr %p, Len %d\n",
address, data, len);
#endif
if (mDev.stripe) {
/* For dual parallel the address divide by 2 */
address /= 2;
@ -1312,6 +1077,10 @@ int RAMFUNCTION ext_flash_erase(uintptr_t address, int len)
uint32_t idx = 0;
uintptr_t qspiaddr;
#if defined(DEBUG_ZYNQ) && DEBUG_ZYNQ >= 2
wolfBoot_printf("Flash Erase: Addr 0x%x, Len %d\n", address, len);
#endif
while (len > 0) {
/* For dual parallel the address divide by 2 */
qspiaddr = (mDev.stripe) ? address / 2 : address;
@ -1358,6 +1127,13 @@ void* hal_get_dts_address(void)
{
return (void*)WOLFBOOT_DTS_BOOT_ADDRESS;
}
int hal_dts_fixup(void* dts_addr)
{
/* place FDT fixup specific to ZynqMP here */
//fdt_set_boot_cpuid_phys(buf, fdt_boot_cpuid_phys(fdt));
return 0;
}
#endif
@ -1369,7 +1145,7 @@ static int test_ext_flash(QspiDev_t* dev)
{
int ret;
uint32_t i;
uint8_t pageData[FLASH_PAGE_SIZE];
uint8_t pageData[FLASH_PAGE_SIZE*4];
#ifndef TEST_FLASH_READONLY
/* Erase sector */
@ -1403,3 +1179,5 @@ static int test_ext_flash(QspiDev_t* dev)
return ret;
}
#endif /* TEST_EXT_FLASH */
#endif /* TARGET_zynq */

363
hal/zynq.h 100644
View File

@ -0,0 +1,363 @@
/* zynq.h
*
* Copyright (C) 2024 wolfSSL Inc.
*
* This file is part of wolfBoot.
*
* wolfBoot is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 3 of the License, or
* (at your option) any later version.
*
* wolfBoot is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA
*/
#ifndef _ZYNQMP_H_
#define _ZYNQMP_H_
/* By default expect EL2 at startup */
#ifndef EL3_SECURE
#define EL3_SECURE 0
#endif
#ifndef EL2_HYPERVISOR
#define EL2_HYPERVISOR 1
#endif
#ifndef EL1_NONSECURE
#define EL1_NONSECURE 0
#endif
#ifndef HYP_GUEST
/* ZEN Hypervisor guest format support */
#define HYP_GUEST 0
#endif
/* Floating Point Trap Enable */
#ifndef FPU_TRAP
#define FPU_TRAP 0
#endif
/* Errata: 855873: An eviction might overtake a cache clean operation */
#define CONFIG_ARM_ERRATA_855873 1
#define XPAR_PSU_DDR_0_S_AXI_BASEADDR 0x00000000
#define XPAR_PSU_DDR_0_S_AXI_HIGHADDR 0x7FFFFFFF
#define XPAR_PSU_DDR_1_S_AXI_BASEADDR 0x800000000
#define XPAR_PSU_DDR_1_S_AXI_HIGHADDR 0x87FFFFFFF
/* Clocking */
#define CORTEXA53_0_CPU_CLK_FREQ_HZ 1199880127
#define CORTEXA53_0_TIMESTAMP_CLK_FREQ 99990005
#define UART_MASTER_CLOCK 99990005
#define GQSPI_CLK_FREQ_HZ 124987511
/* IOP System-level Control */
#define IOU_SLCR_BASSE 0xFF180000
#define IOU_TAPDLY_BYPASS (*((volatile uint32_t*)(IOU_SLCR_BASSE + 0x390)))
#define IOU_TAPDLY_BYPASS_LQSPI_RX (1UL << 2) /* LQSPI Tap Delay Enable on Rx Clock signal. 0: enable. 1: disable (bypass tap delay). */
/* QSPI bare-metal driver */
/* Generic Quad-SPI */
#define QSPI_BASE 0xFF0F0000UL
#define LQSPI_EN (*((volatile uint32_t*)(QSPI_BASE + 0x14))) /* SPI enable: 0: disable the SPI, 1: enable the SPI */
#define GQSPI_CFG (*((volatile uint32_t*)(QSPI_BASE + 0x100))) /* configuration register. */
#define GQSPI_ISR (*((volatile uint32_t*)(QSPI_BASE + 0x104))) /* interrupt status register. */
#define GQSPI_IER (*((volatile uint32_t*)(QSPI_BASE + 0x108))) /* interrupt enable register. */
#define GQSPI_IDR (*((volatile uint32_t*)(QSPI_BASE + 0x10C))) /* interrupt disable register. */
#define GQSPI_IMR (*((volatile uint32_t*)(QSPI_BASE + 0x110))) /* interrupt unmask register. */
#define GQSPI_EN (*((volatile uint32_t*)(QSPI_BASE + 0x114))) /* enable register. */
#define GQSPI_TXD (*((volatile uint32_t*)(QSPI_BASE + 0x11C))) /* TX data register. Keyhole addresses for the transmit data FIFO. */
#define GQSPI_RXD (*((volatile uint32_t*)(QSPI_BASE + 0x120))) /* RX data register. */
#define GQSPI_TX_THRESH (*((volatile uint32_t*)(QSPI_BASE + 0x128))) /* TXFIFO Threshold Level register: (bits 5:0) Defines the level at which the TX_FIFO_NOT_FULL interrupt is generated */
#define GQSPI_RX_THRESH (*((volatile uint32_t*)(QSPI_BASE + 0x12C))) /* RXFIFO threshold level register: (bits 5:0) Defines the level at which the RX_FIFO_NOT_EMPTY interrupt is generated */
#define GQSPI_GPIO (*((volatile uint32_t*)(QSPI_BASE + 0x130)))
#define GQSPI_LPBK_DLY_ADJ (*((volatile uint32_t*)(QSPI_BASE + 0x138))) /* adjusting the internal loopback clock delay for read data capturing */
#define GQSPI_GEN_FIFO (*((volatile uint32_t*)(QSPI_BASE + 0x140))) /* generic FIFO data register. Keyhole addresses for the generic FIFO. */
#define GQSPI_SEL (*((volatile uint32_t*)(QSPI_BASE + 0x144))) /* select register. */
#define GQSPI_FIFO_CTRL (*((volatile uint32_t*)(QSPI_BASE + 0x14C))) /* FIFO control register. */
#define GQSPI_GF_THRESH (*((volatile uint32_t*)(QSPI_BASE + 0x150))) /* generic FIFO threshold level register: (bits 4:0) Defines the level at which the GEN_FIFO_NOT_FULL interrupt is generated */
#define GQSPI_POLL_CFG (*((volatile uint32_t*)(QSPI_BASE + 0x154))) /* poll configuration register */
#define GQSPI_P_TIMEOUT (*((volatile uint32_t*)(QSPI_BASE + 0x158))) /* poll timeout register. */
#define GQSPI_XFER_STS (*((volatile uint32_t*)(QSPI_BASE + 0x15C))) /* transfer status register. */
#define QSPI_DATA_DLY_ADJ (*((volatile uint32_t*)(QSPI_BASE + 0x1F8))) /* adjusting the internal receive data delay for read data capturing */
#define GQSPI_MOD_ID (*((volatile uint32_t*)(QSPI_BASE + 0x1FC)))
#define QSPIDMA_DST_STS (*((volatile uint32_t*)(QSPI_BASE + 0x808)))
#define QSPIDMA_DST_CTRL (*((volatile uint32_t*)(QSPI_BASE + 0x80C)))
#define QSPIDMA_DST_I_STS (*((volatile uint32_t*)(QSPI_BASE + 0x814)))
#define QSPIDMA_DST_CTRL2 (*((volatile uint32_t*)(QSPI_BASE + 0x824)))
#define GQSPI_LPBK_DLY_ADJ_USE_LPBK (1UL << 5)
#define GQSPI_LPBK_DLY_ADJ_DIV0(x) (((x) & 0x7) << 0)
#define GQSPI_LPBK_DLY_ADJ_DLY1(x) (((x) & 0x3) << 3)
#define QSPI_DATA_DLY_ADJ_USE_DATA_DLY (1UL << 31)
#define QSPI_DATA_DLY_ADJ_DATA_DLY_ADJ(x) (((x) & 0x7) << 28)
/* GQSPI Registers */
/* GQSPI_CFG: Configuration registers */
#define GQSPI_CFG_CLK_POL (1UL << 1) /* Clock polarity outside QSPI word: 0: QSPI clock is quiescent low, 1: QSPI clock is quiescent high */
#define GQSPI_CFG_CLK_PH (1UL << 2) /* Clock phase: 1: the QSPI clock is inactive outside the word, 0: the QSPI clock is active outside the word */
/* 000: divide by 2, 001: divide by 4, 010: divide by 8,
011: divide by 16, 100: divide by 32, 101: divide by 64,
110: divide by 128, 111: divide by 256 */
#define GQSPI_CFG_BAUD_RATE_DIV_MASK (7UL << 3)
#define GQSPI_CFG_BAUD_RATE_DIV(d) ((d << 3) & GQSPI_CFG_BAUD_RATE_DIV_MASK)
#define GQSPI_CFG_WP_HOLD (1UL << 19) /* If set, Holdb and WPn pins are actively driven by the qspi controller in 1-bit and 2-bit modes. */
#define GQSPI_CFG_EN_POLL_TIMEOUT (1UL << 20) /* Poll Timeout Enable: 0: disable, 1: enable */
#define GQSPI_CFG_ENDIAN (1UL << 26) /* Endian format transmit data register: 0: little endian, 1: big endian */
#define GQSPI_CFG_START_GEN_FIFO (1UL << 28) /* Trigger Generic FIFO Command Execution: 0:disable executing requests, 1: enable executing requests */
#define GQSPI_CFG_GEN_FIFO_START_MODE (1UL << 29) /* Start mode of Generic FIFO: 0: Auto Start Mode, 1: Manual Start Mode */
#define GQSPI_CFG_MODE_EN_MASK (3UL << 30) /* Flash memory interface mode control: 00: IO mode, 10: DMA mode */
#define GQSPI_CFG_MODE_EN(m) ((m << 30) & GQSPI_CFG_MODE_EN_MASK)
#define GQSPI_CFG_MODE_EN_IO GQSPI_CFG_MODE_EN(0)
#define GQSPI_CFG_MODE_EN_DMA GQSPI_CFG_MODE_EN(2)
/* GQSPI_ISR / GQSPI_IER / GQSPI_IDR / GQSPI_IMR: Interrupt registers */
#define GQSPI_IXR_RX_FIFO_EMPTY (1UL << 11)
#define GQSPI_IXR_GEN_FIFO_FULL (1UL << 10)
#define GQSPI_IXR_GEN_FIFO_NOT_FULL (1UL << 9)
#define GQSPI_IXR_TX_FIFO_EMPTY (1UL << 8)
#define GQSPI_IXR_GEN_FIFO_EMPTY (1UL << 7)
#define GQSPI_IXR_RX_FIFO_FULL (1UL << 5)
#define GQSPI_IXR_RX_FIFO_NOT_EMPTY (1UL << 4)
#define GQSPI_IXR_TX_FIFO_FULL (1UL << 3)
#define GQSPI_IXR_TX_FIFO_NOT_FULL (1UL << 2)
#define GQSPI_IXR_POLL_TIME_EXPIRE (1UL << 1)
#define GQSPI_IXR_ALL_MASK (GQSPI_IXR_POLL_TIME_EXPIRE | GQSPI_IXR_TX_FIFO_NOT_FULL | \
GQSPI_IXR_TX_FIFO_FULL | GQSPI_IXR_RX_FIFO_NOT_EMPTY | GQSPI_IXR_RX_FIFO_FULL | \
GQSPI_IXR_GEN_FIFO_EMPTY | GQSPI_IXR_TX_FIFO_EMPTY | GQSPI_IXR_GEN_FIFO_NOT_FULL | \
GQSPI_IXR_GEN_FIFO_FULL | GQSPI_IXR_RX_FIFO_EMPTY)
#define GQSPI_ISR_WR_TO_CLR_MASK 0x00000002U
/* GQSPI_GEN_FIFO: FIFO data register */
/* bits 0-7: Length in bytes (except when GQSPI_GEN_FIFO_EXP_MASK is set length as 255 chunks) */
#define GQSPI_GEN_FIFO_IMM_MASK (0xFFUL) /* Immediate Data Field */
#define GQSPI_GEN_FIFO_IMM(imm) (imm & GQSPI_GEN_FIFO_IMM_MASK)
#define GQSPI_GEN_FIFO_DATA_XFER (1UL << 8) /* Indicates IMM is size, otherwise byte is sent directly in IMM reg */
#define GQSPI_GEN_FIFO_EXP_MASK (1UL << 9) /* Length is Exponent (length / 255) */
#define GQSPI_GEN_FIFO_MODE_MASK (3UL << 10)
#define GQSPI_GEN_FIFO_MODE(m) ((m << 10) & GQSPI_GEN_FIFO_MODE_MASK)
#define GQSPI_GEN_FIFO_MODE_SPI GQSPI_GEN_FIFO_MODE(1)
#define GQSPI_GEN_FIFO_MODE_DSPI GQSPI_GEN_FIFO_MODE(2)
#define GQSPI_GEN_FIFO_MODE_QSPI GQSPI_GEN_FIFO_MODE(3)
#define GQSPI_GEN_FIFO_CS_MASK (3UL << 12)
#define GQSPI_GEN_FIFO_CS(c) ((c << 12) & GQSPI_GEN_FIFO_CS_MASK)
#define GQSPI_GEN_FIFO_CS_LOWER GQSPI_GEN_FIFO_CS(1)
#define GQSPI_GEN_FIFO_CS_UPPER GQSPI_GEN_FIFO_CS(2)
#define GQSPI_GEN_FIFO_CS_BOTH GQSPI_GEN_FIFO_CS(3)
#define GQSPI_GEN_FIFO_BUS_MASK (3UL << 14)
#define GQSPI_GEN_FIFO_BUS(b) ((b << 14) & GQSPI_GEN_FIFO_BUS_MASK)
#define GQSPI_GEN_FIFO_BUS_LOW GQSPI_GEN_FIFO_BUS(1)
#define GQSPI_GEN_FIFO_BUS_UP GQSPI_GEN_FIFO_BUS(2)
#define GQSPI_GEN_FIFO_BUS_BOTH GQSPI_GEN_FIFO_BUS(3)
#define GQSPI_GEN_FIFO_TX (1UL << 16)
#define GQSPI_GEN_FIFO_RX (1UL << 17)
#define GQSPI_GEN_FIFO_STRIPE (1UL << 18) /* Stripe data across the lower and upper data buses. */
#define GQSPI_GEN_FIFO_POLL (1UL << 19)
/* GQSPI_FIFO_CTRL */
#define GQSPI_FIFO_CTRL_RST_GEN_FIFO (1UL << 0)
#define GQSPI_FIFO_CTRL_RST_TX_FIFO (1UL << 1)
#define GQSPI_FIFO_CTRL_RST_RX_FIFO (1UL << 2)
/* QSPIDMA_DST_CTRL */
#define QSPIDMA_DST_CTRL_DEF 0x403FFA00UL
#define QSPIDMA_DST_CTRL2_DEF 0x081BFFF8UL
/* QSPIDMA_DST_STS */
#define QSPIDMA_DST_STS_WTC 0xE000U
/* QSPIDMA_DST_I_STS */
#define QSPIDMA_DST_I_STS_ALL_MASK 0xFEU
/* QSPI Configuration (bare-metal only) */
#ifndef GQSPI_CLK_DIV
#define GQSPI_CLK_DIV 2 /* (CLK (300MHz) / (2 << DIV) = BUS): 0=DIV2, 1=DIV4, 2=DIV8 */
#endif
#define GQSPI_CS_ASSERT_CLOCKS 5 /* CS Setup Time (tCSS) - num of clock cycles foes in IMM */
#define GQSPI_FIFO_WORD_SZ 4
#define GQSPI_TIMEOUT_TRIES 100000
#define QSPI_FLASH_READY_TRIES 1000
/* QSPI Configuration */
#ifndef GQSPI_QSPI_MODE
#define GQSPI_QSPI_MODE GQSPI_GEN_FIFO_MODE_QSPI
#endif
#ifndef GQPI_USE_DUAL_PARALLEL
#define GQPI_USE_DUAL_PARALLEL 1 /* 0=no stripe, 1=stripe */
#endif
#ifndef GQPI_USE_4BYTE_ADDR
#define GQPI_USE_4BYTE_ADDR 1
#endif
#ifndef GQSPI_DUMMY_READ
#define GQSPI_DUMMY_READ (8*8) /* Number of dummy clock cycles for reads */
#endif
/* Flash Parameters:
* Micron Serial NOR Flash Memory 64KB Sector Erase MT25QU512ABB
* Stacked device (two 512Mb (64MB))
* Dual Parallel so total addressable size is double
*/
#ifndef FLASH_DEVICE_SIZE
#ifdef ZCU102
/* 64*2 (dual parallel) = 128MB */
#define FLASH_DEVICE_SIZE (2 * 64 * 1024 * 1024) /* MT25QU512ABB */
#else
/* 128*2 (dual parallel) = 256MB */
#define FLASH_DEVICE_SIZE (2 * 128 * 1024 * 1024) /* MT25QU01GBBB */
#endif
#endif
#ifndef FLASH_PAGE_SIZE
#ifdef ZCU102
/* MT25QU512ABB - Read FlashID: 20 BB 20 */
#define FLASH_PAGE_SIZE 256
#else
/* MT25QU01GBBB - Read FlashID: 20 BB 21 */
#define FLASH_PAGE_SIZE 512
#endif
#endif
#define FLASH_NUM_SECTORS (FLASH_DEVICE_SIZE/WOLFBOOT_SECTOR_SIZE)
/* Flash Commands */
#define WRITE_ENABLE_CMD 0x06U
#define READ_SR_CMD 0x05U
#define WRITE_DISABLE_CMD 0x04U
#define READ_ID_CMD 0x9FU
#define MULTI_IO_READ_ID_CMD 0xAFU
#define READ_FSR_CMD 0x70U
#define ENTER_QSPI_MODE_CMD 0x35U
#define EXIT_QSPI_MODE_CMD 0xF5U
#define ENTER_4B_ADDR_MODE_CMD 0xB7U
#define EXIT_4B_ADDR_MODE_CMD 0xE9U
#define FAST_READ_CMD 0x0BU
#define DUAL_READ_CMD 0x3BU
#define QUAD_READ_CMD 0x6BU
#define FAST_READ_4B_CMD 0x0CU
#define DUAL_READ_4B_CMD 0x3CU
#define QUAD_READ_4B_CMD 0x6CU
#define PAGE_PROG_CMD 0x02U
#define DUAL_PROG_CMD 0xA2U
#define QUAD_PROG_CMD 0x22U
#define PAGE_PROG_4B_CMD 0x12U
#define DUAL_PROG_4B_CMD 0x12U
#define QUAD_PROG_4B_CMD 0x34U
#define SEC_ERASE_CMD 0xD8U
#define SEC_4K_ERASE_CMD 0x20U
#define RESET_ENABLE_CMD 0x66U
#define RESET_MEMORY_CMD 0x99U
#define WRITE_EN_MASK 0x02 /* 0=Write Enabled, 1=Disabled Write */
#define FLASH_READY_MASK 0x80 /* 0=Busy, 1=Ready */
/* Return Codes */
#define GQSPI_CODE_SUCCESS 0
#define GQSPI_CODE_FAILED -100
#define GQSPI_CODE_TIMEOUT -101
/* eFUSE support */
#define ZYNQMP_EFUSE_BASE 0xFFCC0000
#define ZYNQMP_EFUSE_STATUS (*((volatile uint32_t*)(ZYNQMP_EFUSE_BASE + 0x0008)))
#define ZYNQMP_EFUSE_SEC_CTRL (*((volatile uint32_t*)(ZYNQMP_EFUSE_BASE + 0x1058)))
#define ZYNQMP_EFUSE_PPK0_0 (*((volatile uint32_t*)(ZYNQMP_EFUSE_BASE + 0x10A0)))
#define ZYNQMP_EFUSE_PPK0_1 (*((volatile uint32_t*)(ZYNQMP_EFUSE_BASE + 0x10A4)))
#define ZYNQMP_EFUSE_PPK0_2 (*((volatile uint32_t*)(ZYNQMP_EFUSE_BASE + 0x10A8)))
#define ZYNQMP_EFUSE_PPK0_3 (*((volatile uint32_t*)(ZYNQMP_EFUSE_BASE + 0x10AC)))
#define ZYNQMP_EFUSE_PPK0_4 (*((volatile uint32_t*)(ZYNQMP_EFUSE_BASE + 0x10B0)))
#define ZYNQMP_EFUSE_PPK0_5 (*((volatile uint32_t*)(ZYNQMP_EFUSE_BASE + 0x10B4)))
#define ZYNQMP_EFUSE_PPK0_6 (*((volatile uint32_t*)(ZYNQMP_EFUSE_BASE + 0x10B8)))
#define ZYNQMP_EFUSE_PPK0_7 (*((volatile uint32_t*)(ZYNQMP_EFUSE_BASE + 0x10BC)))
#define ZYNQMP_EFUSE_PPK0_8 (*((volatile uint32_t*)(ZYNQMP_EFUSE_BASE + 0x10C0)))
#define ZYNQMP_EFUSE_PPK0_9 (*((volatile uint32_t*)(ZYNQMP_EFUSE_BASE + 0x10C4)))
#define ZYNQMP_EFUSE_PPK0_10 (*((volatile uint32_t*)(ZYNQMP_EFUSE_BASE + 0x10C8)))
#define ZYNQMP_EFUSE_PPK0_11 (*((volatile uint32_t*)(ZYNQMP_EFUSE_BASE + 0x10CC)))
/* eFUSE STATUS Registers */
#define ZYNQMP_EFUSE_STATUS_CACHE_DONE (1UL << 5)
#define ZYNQMP_EFUSE_STATUS_CACHE_LOAD (1UL << 4)
/* eFUSE SEC_CTRL Registers */
#define ZYNQMP_EFUSE_SEC_CTRL_PPK1_INVLD (3UL << 30) /* Revokes PPK1 */
#define ZYNQMP_EFUSE_SEC_CTRL_PPK1_WRLK (1UL << 29) /* Locks writing to PPK1 eFuses */
#define ZYNQMP_EFUSE_SEC_CTRL_PPK0_INVLD (3UL << 27) /* Revokes PPK0 */
#define ZYNQMP_EFUSE_SEC_CTRL_PPK0_WRLK (1UL << 26) /* Locks writing to PPK0 eFuses */
#define ZYNQMP_EFUSE_SEC_CTRL_RSA_EN (15UL << 11) /* Enables RSA Authentication during boot. All boots must be authenticated */
#define ZYNQMP_EFUSE_SEC_CTRL_SEC_LOCK (1UL << 10) /* Disables the reboot into JTAG mode when doing a secure lockdown. */
#define ZYNQMP_EFUSE_SEC_CTRL_JTAG_DIS (1UL << 5) /* Disables the JTAG controller. The only instructions available are BYPASS and IDCODE. */
#define ZYNQMP_EFUSE_SEC_CTRL_ENC_ONLY (1UL << 2) /* Requires all boots to be encrypted using the eFuse key. */
#define ZYNQMP_EFUSE_SEC_CTRL_AES_WRLK (1UL << 1) /* Locks writing to the AES key section of eFuse */
#define ZYNQMP_EFUSE_SEC_CTRL_AES_RDLK (1UL << 0) /* Locks the AES key CRC check function */
/* UART Support */
#define ZYNQMP_UART0_BASE 0xFF000000
#define ZYNQMP_UART1_BASE 0xFF010000
#define ZYNQMP_UART_CR (*((volatile uint32_t*)(DEBUG_UART_BASE + 0x00)))
#define ZYNQMP_UART_MR (*((volatile uint32_t*)(DEBUG_UART_BASE + 0x04)))
#define ZYNQMP_UART_IDR (*((volatile uint32_t*)(DEBUG_UART_BASE + 0x0C))) /* Interrupt Disable Register */
#define ZYNQMP_UART_ISR (*((volatile uint32_t*)(DEBUG_UART_BASE + 0x14))) /* Interrupt Status Register */
#define ZYNQMP_UART_RXTOUT (*((volatile uint32_t*)(DEBUG_UART_BASE + 0x1C)))
#define ZYNQMP_UART_RXWM (*((volatile uint32_t*)(DEBUG_UART_BASE + 0x20)))
#define ZYNQMP_UART_TXWM (*((volatile uint32_t*)(DEBUG_UART_BASE + 0x44)))
#define ZYNQMP_UART_SR (*((volatile uint32_t*)(DEBUG_UART_BASE + 0x2C)))
#define ZYNQMP_UART_FIFO (*((volatile uint32_t*)(DEBUG_UART_BASE + 0x30)))
#define ZYNQMP_UART_BR_GEN (*((volatile uint32_t*)(DEBUG_UART_BASE + 0x18))) /* 2 - 65535: baud_sample */
#define ZYNQMP_UART_BR_DIV (*((volatile uint32_t*)(DEBUG_UART_BASE + 0x34))) /* 4 - 255: Baud rate */
/* UART Control Registers */
#define ZYNQMP_UART_CR_TX_DIS 0x00000020 /* TX disable */
#define ZYNQMP_UART_CR_TX_EN 0x00000010 /* TX enabled */
#define ZYNQMP_UART_CR_RX_DIS 0x00000008 /* RX disable */
#define ZYNQMP_UART_CR_RX_EN 0x00000004 /* RX enabled */
#define ZYNQMP_UART_CR_TXRST 0x00000002 /* TX logic reset */
#define ZYNQMP_UART_CR_RXRST 0x00000001 /* RX logic reset */
/* UART ISR Mask 0-13 bits */
#define ZYNQMP_UART_ISR_MASK 0x3FFF
/* UART Mode Registers */
#define ZYNQMP_UART_MR_PARITY_NONE 0x00000020 /* No parity */
/* UART Channel Status Register (read only) */
#define ZYNQMP_UART_SR_TXFULL 0x00000010U /* TX FIFO full */
#define ZYNQMP_UART_SR_TXEMPTY 0x00000008U /* TX FIFO empty */
#define ZYNQMP_UART_SR_RXFULL 0x00000004U /* RX FIFO full */
#define ZYNQMP_UART_SR_RXEMPTY 0x00000002U /* RX FIFO empty */
/* UART Configuration */
#if defined(DEBUG_UART_NUM) && DEBUG_UART_NUM == 0
#define DEBUG_UART_BASE ZYNQMP_UART0_BASE
#elif defined(DEBUG_UART_NUM) && DEBUG_UART_NUM == 1
#define DEBUG_UART_BASE ZYNQMP_UART1_BASE
#endif
#ifndef DEBUG_UART_BASE
/* default to UART0 */
#define DEBUG_UART_BASE ZYNQMP_UART0_BASE
#endif
#ifndef DEBUG_UART_BAUD
#define DEBUG_UART_BAUD 115200
#define DEBUG_UART_DIV 6
#endif
#define GICD_BASE 0xF9010000
#define GICC_BASE 0xF9020000
#endif /* _ZYNQMP_H_ */

View File

@ -11,12 +11,12 @@ _EL2_STACK_SIZE = DEFINED(_EL2_STACK_SIZE) ? _EL2_STACK_SIZE : 1024;
/* Define Memories in the system */
MEMORY
{
/* psu_ddr_0_MEM_0 : ORIGIN = 0x0, LENGTH = 0x7FF00000 */
psu_ddr_0_MEM_0 : ORIGIN = 0x40000000, LENGTH = 0x100000
/* psu_ddr_0_MEM_0 : ORIGIN = 0x0, LENGTH = 0x80000000 */
/* Use the end of DDR0 for wolfBoot (reserve 1MB) */
psu_ddr_0_MEM_0 : ORIGIN = 0x7FF00000, LENGTH = 0x100000
psu_ddr_1_MEM_0 : ORIGIN = 0x800000000, LENGTH = 0x80000000
psu_ocm_ram_0_MEM_0 : ORIGIN = 0xFFFC0000, LENGTH = 0x40000
psu_qspi_linear_0_MEM_0 : ORIGIN = 0xC0000000, LENGTH = 0x20000000
}
/* Specify the default entry point to the program */
@ -128,6 +128,10 @@ SECTIONS
*(.got2)
} > psu_ddr_0_MEM_0
.note.gnu.build-id : {
KEEP (*(.note.gnu.build-id))
} > psu_ddr_0_MEM_0
.ctors : {
. = ALIGN(64);
__CTOR_LIST__ = .;

View File

@ -139,6 +139,11 @@ 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);
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);
int fdt_node_check_compatible(const void *fdt, int nodeoffset, const char *compatible);
int fdt_node_offset_by_compatible(const void *fdt, int startoffset, const char *compatible);
@ -152,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

View File

@ -49,7 +49,7 @@
/* support for wolfBoot_printf logging */
#if defined(PRINTF_ENABLED) && !defined(WOLFBOOT_NO_PRINTF)
# include <stdio.h>
# if defined(DEBUG_ZYNQ) && !defined(USE_QNX)
# if defined(DEBUG_ZYNQ) && !defined(USE_QNX) && !defined(DEBUG_UART)
# include "xil_printf.h"
# define wolfBoot_printf(_f_, ...) xil_printf(_f_, ##__VA_ARGS__)
# elif defined(WOLFBOOT_DEBUG_EFI)

View File

@ -1,6 +1,6 @@
/* boot_aarch64.c
*
* Copyright (C) 2021 wolfSSL Inc.
* Copyright (C) 2024 wolfSSL Inc.
*
* This file is part of wolfBoot.
*
@ -67,6 +67,16 @@ void boot_entry_C(void)
main();
}
#ifdef MMU
int __attribute((weak)) hal_dts_fixup(void* dts_addr)
{
(void)dts_addr;
return 0;
}
#endif
/* This is the main loop for the bootloader.
*
* It performs the following actions:
@ -80,6 +90,10 @@ void RAMFUNCTION do_boot(const uint32_t *app_offset, const uint32_t* dts_offset)
void RAMFUNCTION do_boot(const uint32_t *app_offset)
#endif
{
#ifdef MMU
hal_dts_fixup((uint32_t*)dts_offset);
#endif
/* Set application address via x4 */
asm volatile("mov x4, %0" : : "r"(app_offset));
@ -122,3 +136,20 @@ void RAMFUNCTION arch_reboot(void)
}
#endif
void SynchronousInterrupt(void)
{
}
void IRQInterrupt(void)
{
}
void FIQInterrupt(void)
{
}
void SErrorInterrupt(void)
{
}

File diff suppressed because it is too large Load Diff

156
src/fdt.c
View File

@ -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;
}
@ -554,13 +554,13 @@ int fdt_setprop(void *fdt, int nodeoffset, const char *name, const void *val,
}
}
if (err != 0) {
wolfBoot_printf("FDT: Set prop failed! %d (name %d, off %d)\n",
wolfBoot_printf("FDT: Set prop failed! %d (name %s, off %d)\n",
err, name, nodeoffset);
}
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,23 +577,70 @@ const void *fdt_getprop(const void *fdt, int nodeoffset, const char *name,
return NULL;
}
int fdt_find_devtype(void* fdt, int startoff, const char* node)
void* fdt_getprop_address(const void *fdt, int nodeoffset, const char *name)
{
int len, off;
const void* val;
const char* propname = "device_type";
int nodelen = strlen(node)+1;
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 == fnlen) && (memcmp(nstr, nodename, fnlen) == 0)) {
break;
}
}
return off;
}
int fdt_find_prop_offset(void* fdt, int startoff, const char* propname,
const char* propval)
{
int len, off, pvallen;
const void* val;
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, node, len) == 0)) {
if (val && (len == pvallen) && (memcmp(val, propval, len) == 0)) {
break;
}
}
return off;
}
}
return off; /* return error from fdt_next_node() */
}
int fdt_find_devtype(void* fdt, int startoff, const char* node)
{
return fdt_find_prop_offset(fdt, startoff, "device_type", node);
}
int fdt_node_offset_by_compatible(const void *fdt, int startoffset,
@ -721,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 */

View File

@ -264,6 +264,19 @@ void RAMFUNCTION *memcpy(void *dst, const void *src, size_t n)
const char *s = (const char *)src;
char *d = (char *)dst;
#ifdef FAST_MEMCPY
/* is 32-bit aligned pointer */
if (((size_t)dst & (sizeof(unsigned long)-1)) == 0 &&
((size_t)src & (sizeof(unsigned long)-1)) == 0)
{
while (n >= sizeof(unsigned long)) {
*(unsigned long*)d = *(unsigned long*)s;
d += sizeof(unsigned long);
s += sizeof(unsigned long);
n -= sizeof(unsigned long);
}
}
#endif
for (i = 0; i < n; i++) {
d[i] = s[i];
}
@ -297,7 +310,7 @@ void *memmove(void *dst, const void *src, size_t n)
void uart_writenum(int num, int base, int zeropad, int maxdigits)
{
int i = 0;
char buf[sizeof(int)*2+1];
char buf[sizeof(unsigned long)*2+1];
const char* kDigitLut = "0123456789ABCDEF";
unsigned int val = (unsigned int)num;
int sz = 0;

View File

@ -49,19 +49,6 @@ extern uint32_t dts_load_addr;
#ifdef WOLFBOOT_USE_RAMBOOT
#if !(defined(EXT_FLASH) && defined(NO_XIP))
/* requires/assumes inputs and size to be 4-byte aligned */
static void memcpy32(void *dst, const void *src, size_t n)
{
size_t i;
const uint32_t *s = (const uint32_t*)src;
uint32_t *d = (uint32_t*)dst;
for (i = 0; i < n/4; i++) {
d[i] = s[i];
}
}
#endif
/* Function to load image from flash to ram */
int wolfBoot_ramboot(struct wolfBoot_image *img, uint8_t *src, uint8_t *dst)
{
@ -78,7 +65,7 @@ int wolfBoot_ramboot(struct wolfBoot_image *img, uint8_t *src, uint8_t *dst)
return -1;
}
#else
memcpy32(dst, src, IMAGE_HEADER_SIZE);
memcpy(dst, src, IMAGE_HEADER_SIZE);
#endif
/* check for valid header and version */
@ -102,7 +89,7 @@ int wolfBoot_ramboot(struct wolfBoot_image *img, uint8_t *src, uint8_t *dst)
return -1;
}
#else
memcpy32(dst + IMAGE_HEADER_SIZE, src + IMAGE_HEADER_SIZE, img_size);
memcpy(dst + IMAGE_HEADER_SIZE, src + IMAGE_HEADER_SIZE, img_size);
#endif
/* mark image as no longer external */
@ -290,6 +277,30 @@ backup_on_failure:
#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) {
uint8_t *dts_ptr = fit_load_image(fit, flat_dt, (int*)&dts_size);
if (dts_ptr != NULL && wolfBoot_get_dts_size(dts_ptr) >= 0) {
/* relocate to load DTS address */
dts_addr = (uint8_t*)WOLFBOOT_LOAD_DTS_ADDRESS;
wolfBoot_printf("Loading DTS: %p -> %p (%d bytes)\n",
dts_ptr, dts_addr, dts_size);
memcpy(dts_addr, dts_ptr, dts_size);
}
}
}
else {
/* Load DTS to RAM */
#ifdef EXT_FLASH
if (PART_IS_EXT(&os_image) &&
@ -323,6 +334,7 @@ backup_on_failure:
}
}
}
}
#endif /* MMU */
wolfBoot_printf("Booting at %p\n", load_address);

View File

@ -55,17 +55,6 @@
#endif
#endif
/* requires/assumes inputs and size to be 4-byte aligned */
static void memcpy32(void *dst, const void *src, size_t n)
{
size_t i;
const uint32_t *s = (const uint32_t*)src;
uint32_t *d = (uint32_t*)dst;
for (i = 0; i < n/4; i++) {
d[i] = s[i];
}
}
int main(void)
{
int ret = -1;
@ -84,7 +73,7 @@ int main(void)
#endif
/* relocate 4KB code to DST and jump */
memcpy32((void*)wolfboot_start, (void*)BOOT_ROM_ADDR, BOOT_ROM_SIZE);
memcpy((void*)wolfboot_start, (void*)BOOT_ROM_ADDR, BOOT_ROM_SIZE);
#ifdef WOLFBOOT_ARCH_PPC
/* TODO: Fix hack and consider moving to hal_prepare_boot */
@ -113,7 +102,7 @@ int main(void)
);
#else
/* copy from flash to ram */
memcpy32(
memcpy(
(uint8_t*)WOLFBOOT_STAGE1_LOAD_ADDR,/* ram destination */
(uint8_t*)WOLFBOOT_ORIGIN, /* flash offset */
BOOTLOADER_PARTITION_SIZE /* boot-loader partition (entire) */

View File

@ -1,6 +1,10 @@
# Flattened Device Tree (FDT) Parser
This tool uses our internal FDT (fdt.c) parsing code to dump the device tree. There is also a `-t` option that tests making several updates to the device tree.
This tool uses our internal FDT (fdt.c) parsing code to dump the device tree.
Use `-i` to parse a Flattened uImage Tree (FIT) image.
There is also a `-t` option that tests making several updates to the device tree (useful with the nxp_t1024.dtb).
## Building fdt-parser
@ -8,7 +12,7 @@ From root: `make fdt-parser`
OR
From `tools/fdt-parser` use `make clean && make`
## Example Output
## Example FDT Output
```sh
% ./tools/fdt-parser/fdt-parser ./tools/fdt-parser/nxp_t1024.dtb
@ -28,3 +32,30 @@ root (node offset 0, depth 1, len 0):
power-isa-cs (prop offset 180, len 0): NULL
...
```
## 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
```

View File

@ -31,6 +31,7 @@
#include <limits.h>
static int gEnableUnitTest = 0;
static int gParseFit = 0;
#define UNIT_TEST_GROW_SIZE 1024
/* Test case for "nxp_t1024.dtb" */
@ -113,7 +114,7 @@ static int fdt_test(void* fdt)
p += sizeof(uint64_t);
ret = fdt_setprop(fdt, off, "reg", ranges, (int)(p - ranges));
if (ret != 0) goto exit;
wolfBoot_printf("FDT: Set memory, start=0x%x, size=0x%x\n",
printf("FDT: Set memory, start=0x%x, size=0x%x\n",
DDR_ADDRESS, (uint32_t)DDR_SIZE);
}
@ -198,7 +199,7 @@ static int fdt_test(void* fdt)
liodns[0] = qp_info[i].dliodn;
liodns[1] = qp_info[i].fliodn;
wolfBoot_printf("FDT: Set %s@%d (%d), %s=%d,%d\n",
printf("FDT: Set %s@%d (%d), %s=%d,%d\n",
"qman-portal", i, off, "fsl,liodn", liodns[0], liodns[1]);
ret = fdt_setprop(fdt, off, "fsl,liodn", liodns, sizeof(liodns));
if (ret != 0) goto exit;
@ -319,10 +320,70 @@ static int load_file(const char* filename, uint8_t** buf, size_t* bufLen)
return ret;
}
int dts_parse(void* dts_addr)
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)
{
int len = 0;
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, const char* desc)
{
int off;
if (fit != NULL) {
printf("%s Image: %s\n", desc, image);
}
off = fdt_find_node_offset(fit, -1, image);
if (off > 0) {
dts_fit_image_item(fit, off, "description");
dts_fit_image_item(fit, off, "type");
dts_fit_image_item(fit, off, "os");
dts_fit_image_item(fit, off, "arch");
dts_fit_image_item(fit, off, "compression");
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");
}
}
int dts_parse_fit(void* image)
{
const char *conf = NULL, *kernel = NULL, *flat_dt = NULL;
conf = fit_find_images(image, &kernel, &flat_dt);
if (conf != NULL) {
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(image, kernel, "Kernel");
dts_parse_fit_image(image, flat_dt, "FDT");
return 0;
}
int dts_parse(void* image)
{
int ret = 0;
struct fdt_header *fdt = (struct fdt_header *)dts_addr;
struct fdt_header *fdt = (struct fdt_header *)image;
const struct fdt_property* prop;
int nlen, plen, slen;
int noff, poff, soff;
@ -331,17 +392,6 @@ int dts_parse(void* dts_addr)
#define MAX_DEPTH 24
char tabs[MAX_DEPTH+1] = "\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t";
/* check header */
ret = fdt_check_header(fdt);
if (ret != 0) {
printf("FDT check failed %d!\n", ret);
return ret;
}
/* display information */
printf("FDT Version %d, Size %d\n",
fdt_version(fdt), fdt_totalsize(fdt));
/* walk tree */
for (noff = fdt_next_node(fdt, -1, &depth);
noff >= 0;
@ -369,15 +419,31 @@ int dts_parse(void* dts_addr)
&tabs[MAX_DEPTH-depth], pstr, poff, plen);
if (plen > 32)
printf("\n%s", &tabs[MAX_DEPTH-depth-1]);
if (plen > 256) {
char file[260+1];
snprintf(file, sizeof(file), "%s.%s.bin", nstr, pstr);
printf("Saving to file %s\n", file);
write_bin(file, (const uint8_t*)prop->data, plen);
}
else {
print_bin((const uint8_t*)prop->data, plen);
printf("\n");
}
}
}
}
return ret;
}
static void Usage(void)
{
printf("Expected usage:\n");
printf("./tools/fdt-parser/fdt-parser [-t] [-i] filename\n");
printf("\t* -i: Parse Flattened uImage Tree (FIT) image\n");
printf("\t* -t: Test several updates (used with nxp_t1024.dtb)\n");
}
int main(int argc, char *argv[])
{
int ret = 0;
@ -385,13 +451,26 @@ int main(int argc, char *argv[])
size_t imageSz = 0;
const char* filename = NULL;
if (argc >= 2) {
filename = argv[1];
if (argc == 1 || (argc >= 2 &&
(strcmp(argv[1], "-?") == 0 ||
strcmp(argv[1], "-h") == 0 ||
strcmp(argv[1], "--help") == 0))) {
Usage();
return 0;
}
while (argc > 2) {
while (argc > 1) {
if (strcmp(argv[argc-1], "-t") == 0) {
gEnableUnitTest = 1;
}
else if (strcmp(argv[argc-1], "-i") == 0) {
gParseFit = 1;
}
else if (*argv[argc-1] != '-') {
filename = argv[argc-1];
}
else {
printf("Warning: Unrecognized option: %s\n", argv[argc-1]);
}
argc--;
}
@ -402,6 +481,18 @@ int main(int argc, char *argv[])
}
ret = load_file(filename, &image, &imageSz);
if (ret == 0) {
/* check header */
ret = fdt_check_header(image);
if (ret != 0) {
printf("FDT check failed %d!\n", ret);
return ret;
}
/* display information */
printf("FDT Version %d, Size %d\n",
fdt_version(image), fdt_totalsize(image));
}
if (ret == 0 && gEnableUnitTest) {
ret = fdt_test(image);
if (ret == 0) {
@ -414,8 +505,13 @@ int main(int argc, char *argv[])
}
}
if (ret == 0) {
if (gParseFit) {
ret = dts_parse_fit(image);
}
else {
ret = dts_parse(image);
}
}
free(image);
printf("Return %d\n", ret);