Skip to content

Commit

Permalink
documentation updates
Browse files Browse the repository at this point in the history
  • Loading branch information
bigbrett committed Jul 26, 2024
1 parent 39e9730 commit 9423624
Show file tree
Hide file tree
Showing 3 changed files with 73 additions and 20 deletions.
44 changes: 41 additions & 3 deletions IDE/AURIX/README.md
Original file line number Diff line number Diff line change
@@ -1,14 +1,18 @@
# Overview

This example demonstrates using wolfBoot on the Infineon AURIX TC3xx family of microcontrollers. The example is based on the TC375 Lite-Kit V2, but should be easily adaptable to other TC3xx devices. This README assumes basic familiarity with the TC375 SoC, the AURIX IDE, and Lauterbach Trace32 debugger.

The example contains two projects: `wolfBoot-tc3xx` and `test-app`. The `wolfBoot-tc3xx` project contains the wolfBoot bootloader, and the `test-app` project contains a simple firmware application that will be loaded and executed by wolfBoot. The `test-app` project is a simple blinky application that blinks LED2 on the TC375 Lite-Kit V2 once per second when running the base image, and rapidly (~3x/sec) when running the update image. The test app determines if it is a base or update image by inspecting the firmware version (obtained through the wolfBoot API). The firmware version is set in the image header by the wolfBoot keytools when signing the test app binaries. The same test app binary is used for both the base and update images, with the only difference being the firmware version set by the keytools.

## Important notes
- In the UCBs, BMDHx.STAD must point to the wolfBoot entrypoint `0xA000_0000`. This is the default value of the TC375 and so need not be changed unless it has already been modified or you wish to rearrange the memory map.
- Because TC3xx PFLASH ECC prevents reading from erased flash, the `EXT_FLASH` option is used to redirect flash reads to a HAL API, where the flash pages requested to be read can be blank-checked by hardware before reading.

- In the TC375 UCBs, BMDHx.STAD must point to the wolfBoot entrypoint `0xA000_0000`. This is the default value of the TC375 and so need not be changed unless it has already been modified or you wish to rearrange the memory map.
- Because TC3xx PFLASH ECC prevents reading from erased flash, the `EXT_FLASH` option is used to redirect flash reads to the `ext_flash_read()` HAL API, where the flash pages requested to be read can be blank-checked by hardware before reading.
- TC3xx PFLASH is write-once (`NVM_FLASH_WRITEONCE`), however wolfBoot `NVM_FLASH_WRITEONCE` does not support `EXT_FLASH`. Therefore the write-once functionality is re-implemented in the `HAL` layer.

## Flash Partitioning

The TC3xx AURIX port of wolfBoot places all images in PFLASH, and uses both PFLASH0 and PFLASH1 banks. The wolfBoot executable code and the image swap sector are located in PFLASH0, with the remainder available for use. PFLASH1 is divided in half, with the first half holding the BOOT partition and the second half holding the UPDATE partion. User firmware images are directly executed in place from the BOOT partition in PFLASH1, and so must be linked to execute within this address space, with an offset of `IMAGE_HEADER_SIZE` to account for the wolfBoot image header.
The TC3xx AURIX port of wolfBoot places all images in PFLASH, and uses both PFLASH0 and PFLASH1 banks. The wolfBoot executable code and the image swap sector are located in PFLASH0, with the remainder available for use. PFLASH1 is divided in half, with the first half holding the BOOT partition and the second half holding the UPDATE partition. User firmware images are directly executed in place from the BOOT partition in PFLASH1, and so must be linked to execute within this address space, with an offset of `IMAGE_HEADER_SIZE` to account for the wolfBoot image header.

```
+==========+
Expand Down Expand Up @@ -65,6 +69,40 @@ Please refer to the [wolfBoot](wolfBoot-tc3xx/Lcf_Gnu_Tricore_Tc.lsl) and [test-
1. Open a WSL terminal and navigate to `wolfBoot/tools/scripts/tc3xx`
2. Run `./gen-tc3xx-signed-test-apps-debug.sh` or `gen-tc3xx-signed-test-apps-release.sh` to sign either the debug or release build, respectively. This creates the signed image files `test-app_v1_signed.bin` and `test-app_v2_signed.bin` in the test-app output build directory. The v1 image is the initial image that will be loaded to the `BOOT` partition, and the v2 image is the update image that will be loaded to the `UPDATE` partition.

```
$ ./gen-tc3xx-signed-test-apps-release.sh
+ ../../keytools/sign --rsa4096 --sha256 '../../../IDE/AURIX/test-app/TriCore Release (GCC)/test-app.bin' ../../../priv.der 1
wolfBoot KeyTools (Compiled C version)
wolfBoot version 2010000
Update type: Firmware
Input image: ../../../IDE/AURIX/test-app/TriCore Release (GCC)/test-app.bin
Selected cipher: RSA4096
Selected hash : SHA256
Public key: ../../../priv.der
Output image: ../../../IDE/AURIX/test-app/TriCore Release (GCC)/test-app_v1_signed.bin
Target partition id : 1
Found RSA512 key
image header size calculated at runtime (1024 bytes)
Calculating SHA256 digest...
Signing the digest...
Output image(s) successfully created.
+ ../../keytools/sign --rsa4096 --sha256 '../../../IDE/AURIX/test-app/TriCore Release (GCC)/test-app.bin' ../../../priv.der 2
wolfBoot KeyTools (Compiled C version)
wolfBoot version 2010000
Update type: Firmware
Input image: ../../../IDE/AURIX/test-app/TriCore Release (GCC)/test-app.bin
Selected cipher: RSA4096
Selected hash : SHA256
Public key: ../../../priv.der
Output image: ../../../IDE/AURIX/test-app/TriCore Release (GCC)/test-app_v2_signed.bin
Target partition id : 1
Found RSA512 key
image header size calculated at runtime (1024 bytes)
Calculating SHA256 digest...
Signing the digest...
Output image(s) successfully created.
```

### Load and run the wolfBoot demo

8. Load wolfBoot and the firmware application images to the tc3xx device using Trace32 and a Lauterbach probe
Expand Down
32 changes: 21 additions & 11 deletions docs/HAL.md
Original file line number Diff line number Diff line change
Expand Up @@ -44,8 +44,11 @@ flash. On some targets, this function may be empty.
This function provides an implementation of the flash write function, using the
target's IAP interface. `address` is the offset from the beginning of the
flash area, `data` is the payload to be stored in the flash using the IAP interface,
and `len` is the size of the payload. `hal_flash_write` should return 0 upon success,
or a negative value in case of failure.
and `len` is the size of the payload. Implementations of this function must be able to
handle writes of any size and alignment. Targets with a minimum programmable size
> 1 byte must implement the appropriate read-modify-write logic in order to enable
wolfBoot to perform unaligned single-byte writes. `hal_flash_write` should return 0 upon
success, or a negative value in case of failure.

`void hal_flash_lock(void)`

Expand All @@ -58,8 +61,9 @@ by the bootloader at the end of every write and erase operations.
Called by the bootloader to erase part of the flash memory to allow subsequent boots.
Erase operations must be performed via the specific IAP interface of the target microcontroller.
`address` marks the start of the area that the bootloader wants to erase, and `len` specifies
the size of the area to be erased. This function must take into account the geometry of the flash
sectors, and erase all the sectors in between.
the size of the area to be erased. `address` is guaranteed to be aligned to `WOLFBOOT_SECTOR_SIZE`,
and `len` is guaranteed to be a multiple of `WOLFBOOT_SECTOR_SIZE`. This function must take into account
the geometry of the flash sectors, and erase all the sectors in between.

`void hal_prepare_boot(void)`

Expand All @@ -71,36 +75,42 @@ that the state of the microcontroller is restored to its original settings.

WolfBoot can be compiled with the makefile option `EXT_FLASH=1`. When the external flash support is
enabled, update and swap partitions can be associated to an external memory, and will use alternative
HAL function for read/write/erase access.
HAL function for read/write/erase access. It can also be used in any scenario where flash reads require
special handling and must be redirected to a custom implementation. Note that `EXT_FLASH=1` is incompatible
with the `NVM_FLASH_WRITEONCE` option.

To associate the update or the swap partition to an external memory, define `PART_UPDATE_EXT` and/or
`PART_SWAP_EXT`, respectively.

The following functions are used to access the external memory, and must be defined when `EXT\_FLASH`
The following functions are used to access the external memory, and must be defined when `EXT_FLASH`
is on:

`int ext_flash_write(uintptr_t address, const uint8_t *data, int len)`

This function provides an implementation of the flash write function, using the
external memory's specific interface. `address` is the offset from the beginning of the
addressable space in the device, `data` is the payload to be stored,
and `len` is the size of the payload. `ext_flash_write` should return 0 upon success,
and `len` is the size of the payload. The function is subject to the same restrictions as
`hal_flash_write()`. `ext_flash_write` should return 0 upon success,
or a negative value in case of failure.

`int ext_flash_read(uintptr_t address, uint8_t *data, int len)`

This function provides an indirect read of the external memory, using the
driver's specific interface. `address` is the offset from the beginning of the
addressable space in the device, `data` is a pointer where payload is stored upon a successful
call, and `len` is the maximum size allowed for the payload. `ext_flash_read` should return 0
upon success, or a negative value in case of failure.
call, and `len` is the maximum size allowed for the payload. This function must be able to handle
reads of any size and alignment. `ext_flash_read` should return 0 upon success, or a negative value
in case of failure.

`int ext_flash_erase(uintptr_t address, int len)`

Called by the bootloader to erase part of the external memory.
Erase operations must be performed via the specific interface of the target driver (e.g. SPI flash).
`address` marks the start of the area relative to the device, that the bootloader wants to erase,
and `len` specifies the size of the area to be erased. This function must take into account the
geometry of the sectors, and erase all the sectors in between.
and `len` specifies the size of the area to be erased. This function is subject to the same restrictions
as `hal_flash_erase()` and must take into account the geometry of the sectors, and erase all the sectors
in between.

`void ext_flash_lock(void)`

Expand Down
17 changes: 11 additions & 6 deletions docs/firmware_image.md
Original file line number Diff line number Diff line change
Expand Up @@ -14,15 +14,20 @@ of 256B from the beginning of the flash partition.

## Firmware image header

Each (signed) firmware image is prepended with a fixed-size **image header**, containing
useful information about the firmware. The **image header** is padded to fit in 256B, in order
to guarantee that the entry point of the actual firmware is stored on the flash starting from
a 256-Bytes aligned address. This ensures that the bootloader can relocate the vector table before
chain-loading the firmware the interrupt continue to work properly after the boot is complete.
Each (signed) firmware image is prepended with a fixed-size **image header**, containing useful information about the
firmware. The exact size of the **image header** depends on the size of the image digest and signature, which depend on
the algorithms/key sizes used. Larger key sizes will result in a larger image header. The size of the image header is
determined by the build system and provided to the application code in the `IMAGE_HEADER_SIZE` macro. The size of the generated
image header is also output by the keytools during the signing operation. The **image header** data is padded out to the next
multiple of 256B, in order to guarantee that the entry point of the actual firmware is stored on the flash starting from a
256-Bytes aligned address. This ensures that the bootloader can relocate the vector table before chain-loading the firmware
so interrupts continue to work properly after the boot is complete. When porting wolfBoot to a platform that doesn't use wolfBoot's
Makefile-based build system, extra care should be taken to ensure `IMAGE_HEADER_SIZE` is set to a value that matches the output of
the wolfBoot `sign` key tool.

![Image header](png/image_header.png)

*The image header is stored at the beginning of the slot and the actual firmware image starts 256 Bytes after it*
*The image header is stored at the beginning of the slot and the actual firmware image starts `IMAGE_HEADER_SIZE` Bytes after it*

### Image header: Tags

Expand Down

0 comments on commit 9423624

Please sign in to comment.