mirror of
https://git.yoctoproject.org/meta-arm
synced 2026-09-27 11:30:30 +00:00
Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
673e8d7c5d | ||
|
|
9dab8bdd49 | ||
|
|
19d96baf78 | ||
|
|
6049c06156 | ||
|
|
f3567691f7 | ||
|
|
0979b80429 | ||
|
|
caa36c53f7 | ||
|
|
bcc633b8ce | ||
|
|
9488c75a67 | ||
|
|
2c9968a29c | ||
|
|
80129934a6 | ||
|
|
01c33e4946 | ||
|
|
61fd528759 | ||
|
|
7d7f1fa63f | ||
|
|
bb4b6a9f7f | ||
|
|
d3b55902fb | ||
|
|
31dd0e8a89 | ||
|
|
d73bc7bea7 | ||
|
|
9b00ce191c | ||
|
|
cd1a545618 | ||
|
|
b58ffc3a09 | ||
|
|
052c2cf333 |
+1
-1
@@ -1,4 +1,4 @@
|
||||
image: ${MIRROR_GHCR}/siemens/kas/kas:5.2
|
||||
image: ${MIRROR_GHCR}/siemens/kas/kas:4.7
|
||||
|
||||
variables:
|
||||
# These are needed as the k8s executor doesn't respect the container
|
||||
|
||||
+2
-1
@@ -7,11 +7,12 @@ distro: poky
|
||||
|
||||
defaults:
|
||||
repos:
|
||||
branch: master
|
||||
branch: wrynose
|
||||
|
||||
repos:
|
||||
bitbake:
|
||||
url: https://git.openembedded.org/bitbake
|
||||
branch: "2.18"
|
||||
layers:
|
||||
bitbake: disabled
|
||||
|
||||
|
||||
@@ -5,7 +5,6 @@ header:
|
||||
|
||||
local_conf_header:
|
||||
latest_revisions: |
|
||||
PREFERRED_VERSION_trusted-firmware-a ?= "2.14.%"
|
||||
PREFERRED_VERSION_tf-a-tests ?= "2.14.%"
|
||||
PREFERRED_VERSION_trusted-firmware-m ?= "2.2.%"
|
||||
PREFERRED_VERSION_trusted-firmware-m-scripts-native ?= "2.2.%"
|
||||
PREFERRED_VERSION_trusted-firmware-a ?= "2.10.%"
|
||||
PREFERRED_VERSION_tf-a-tests ?= "2.10.%"
|
||||
PREFERRED_VERSION_trusted-firmware-m ?= "2.1.%"
|
||||
|
||||
@@ -6,6 +6,11 @@ header:
|
||||
- ci/base.yml
|
||||
- ci/meta-openembedded.yml
|
||||
|
||||
local_conf_header:
|
||||
version_for_ci: |
|
||||
# For better CI coverage, use the LTS version of tf-m
|
||||
PREFERRED_VERSION_trusted-firmware-m ?= "2.1.%"
|
||||
|
||||
machine: musca-b1
|
||||
|
||||
target:
|
||||
|
||||
@@ -6,11 +6,6 @@ header:
|
||||
- ci/base.yml
|
||||
- ci/meta-openembedded.yml
|
||||
|
||||
local_conf_header:
|
||||
version_for_ci: |
|
||||
# For better CI coverage, use the LTS version of tf-m
|
||||
PREFERRED_VERSION_trusted-firmware-m ?= "2.2.%"
|
||||
|
||||
machine: musca-s1
|
||||
|
||||
target:
|
||||
|
||||
@@ -5,5 +5,7 @@ header:
|
||||
|
||||
local_conf_header:
|
||||
sstate_mirror: |
|
||||
BB_HASHSERVE_UPSTREAM = "wss://hashserv.yoctoproject.org/ws"
|
||||
SSTATE_MIRRORS = "file://.* http://sstate.yoctoproject.org/all/PATH;downloadfilename=PATH"
|
||||
BB_HASHSERVE = "auto"
|
||||
BB_SIGNATURE_HANDLER = "OEEquivHash"
|
||||
OE_FRAGMENTS += "core/yocto/sstate-mirror-cdn"
|
||||
|
||||
@@ -5,21 +5,25 @@ distro: poky
|
||||
|
||||
defaults:
|
||||
repos:
|
||||
branch: master
|
||||
branch: wrynose
|
||||
|
||||
repos:
|
||||
bitbake:
|
||||
url: https://git.openembedded.org/bitbake
|
||||
branch: "2.18"
|
||||
commit: 22021758e66737bcf68dfd2b74adc6a0cb1d42d9
|
||||
layers:
|
||||
bitbake: disabled
|
||||
|
||||
core:
|
||||
url: https://git.openembedded.org/openembedded-core
|
||||
commit: 06dd66e6220e5ce4ed4b9af4d8231ae5f0a8ce80
|
||||
layers:
|
||||
meta:
|
||||
|
||||
meta-yocto:
|
||||
url: https://git.yoctoproject.org/meta-yocto
|
||||
commit: 8251bdad5fda780a000fb41e6eda82eadf0fa39e
|
||||
layers:
|
||||
meta-poky:
|
||||
|
||||
@@ -31,7 +35,7 @@ repos:
|
||||
|
||||
meta-openembedded:
|
||||
url: https://git.openembedded.org/meta-openembedded
|
||||
# commit: 461d85a1831318747af5abe86da193bcde3fd9b4
|
||||
commit: 9af4488d46cb4fd4c0d2d64820c86225ebd6ac71
|
||||
layers:
|
||||
meta-oe:
|
||||
meta-python:
|
||||
@@ -39,7 +43,7 @@ repos:
|
||||
|
||||
meta-secure-core:
|
||||
url: https://github.com/wind-river/meta-secure-core.git
|
||||
# commit: 59d7e90542947c342098863b9998693ac79352b0
|
||||
commit: 07a99ae241acd488a2feda1ededf87dc70dfde80
|
||||
layers:
|
||||
meta-secure-core-common:
|
||||
meta-signing-key:
|
||||
|
||||
@@ -9,7 +9,7 @@ BBFILE_COLLECTIONS += "meta-arm-bsp"
|
||||
BBFILE_PATTERN_meta-arm-bsp = "^${LAYERDIR}/"
|
||||
BBFILE_PRIORITY_meta-arm-bsp = "5"
|
||||
|
||||
LAYERSERIES_COMPAT_meta-arm-bsp = "blacksail"
|
||||
LAYERSERIES_COMPAT_meta-arm-bsp = "wrynose"
|
||||
|
||||
LAYERDEPENDS_meta-arm-bsp = "core meta-arm"
|
||||
# This won't be used by layerindex-fetch, but works everywhere else
|
||||
|
||||
@@ -60,7 +60,7 @@ FVP_CONFIG[board.msd_mmc.diagnostics] ?= "0"
|
||||
FVP_CONFIG[board.msd_mmc.p_max_block_count] ?= "0xFFFF"
|
||||
FVP_CONFIG[board.msd_config.pl180_fifo_depth] ?= "16"
|
||||
FVP_CONFIG[board.msd_mmc.support_unpadded_images] ?= "true"
|
||||
FVP_CONFIG[board.msd_mmc.p_mmc_file] ?= "${IMAGE_LINK_NAME}.wic"
|
||||
FVP_CONFIG[board.msd_mmc.p_mmc_file] ?= "${IMAGE_NAME}.wic"
|
||||
|
||||
# MMC2 card configuration
|
||||
FVP_CONFIG[board.msd_mmc_2.card_type] ?= "SDHC"
|
||||
|
||||
@@ -60,7 +60,7 @@ FVP_CONFIG[cluster0.stage12_tlb_size] ?= "1024"
|
||||
FVP_CONFIG[cluster1.stage12_tlb_size] ?= "1024"
|
||||
FVP_CONFIG[bp.secureflashloader.fname] ?= "trusted-firmware-a/bl1.bin"
|
||||
FVP_CONFIG[bp.flashloader0.fname] ?= "trusted-firmware-a/fip.bin"
|
||||
FVP_CONFIG[bp.virtioblockdevice.image_path] ?= "${IMAGE_LINK_NAME}.wic"
|
||||
FVP_CONFIG[bp.virtioblockdevice.image_path] ?= "${IMAGE_NAME}.wic"
|
||||
|
||||
# FVP Base default is 8.0, so there is no has_arm_v8-0 for it. However, this is needed for every version after. So set this accordingly
|
||||
FVP_EXTRA_ARGS = "--parameter cluster0.has_arm_v${ARM_ISA_MAJOR}-${ARM_ISA_MINOR}=1 --parameter cluster1.has_arm_v${ARM_ISA_MAJOR}-${ARM_ISA_MINOR}=1"
|
||||
|
||||
@@ -5,8 +5,7 @@ require ${TUNE_FILE}
|
||||
MACHINEOVERRIDES =. "corstone1000:"
|
||||
|
||||
# TF-M
|
||||
PREFERRED_VERSION_trusted-firmware-m ?= "2.3.%"
|
||||
PREFERRED_VERSION_trusted-firmware-m-scripts-native ?= "2.3.%"
|
||||
PREFERRED_VERSION_trusted-firmware-m ?= "2.2.%"
|
||||
|
||||
# TF-A
|
||||
TFA_PLATFORM = "corstone1000"
|
||||
@@ -17,8 +16,8 @@ TFA_BL2_BINARY = "bl2-corstone1000.bin"
|
||||
TFA_FIP_BINARY = "fip-corstone1000.bin"
|
||||
|
||||
# optee
|
||||
PREFERRED_VERSION_optee-os ?= "4.10.%"
|
||||
PREFERRED_VERSION_optee-client ?= "4.10.%"
|
||||
PREFERRED_VERSION_optee-os ?= "4.9.%"
|
||||
PREFERRED_VERSION_optee-client ?= "4.9.%"
|
||||
|
||||
# Trusted Services
|
||||
TS_PLATFORM = "arm/corstone1000"
|
||||
@@ -27,7 +26,7 @@ TS_SP_SE_PROXY_CONFIG = "corstone1000"
|
||||
MACHINE_FEATURES += "ts-smm-gateway ts-se-proxy"
|
||||
|
||||
# U-Boot
|
||||
PREFERRED_VERSION_u-boot ?= "2026.07"
|
||||
PREFERRED_VERSION_u-boot ?= "2025.10"
|
||||
MACHINE_FEATURES += "efi"
|
||||
EFI_PROVIDER ?= "grub-efi"
|
||||
|
||||
|
||||
@@ -49,15 +49,10 @@ FVP_CONFIG[board.dram_size] ?= "0x200000000"
|
||||
FVP_CONFIG[board.virtio_net.enabled] ?= "1"
|
||||
FVP_CONFIG[board.virtio_net.hostbridge.userNetworking] ?= "1"
|
||||
FVP_CONFIG[board.virtio_net.hostbridge.userNetPorts] = "2222=22"
|
||||
FVP_CONFIG[board.virtioblockdevice.image_path] ?= "${IMAGE_LINK_NAME}.wic"
|
||||
FVP_CONFIG[board.virtioblockdevice.image_path] ?= "${IMAGE_NAME}.wic"
|
||||
|
||||
FVP_CONSOLES[default] = "terminal_ns_uart_ap"
|
||||
FVP_TERMINALS[css.scp.terminal_uart_scp] ?= "SCP Console"
|
||||
FVP_TERMINALS[css.mcp.terminal_uart_mcp] ?= "MCP Console"
|
||||
FVP_TERMINALS[css.terminal_ns_uart_ap] ?= "NS Console"
|
||||
FVP_TERMINALS[css.terminal_s_uart_ap] ?= "S Console"
|
||||
|
||||
# Seeing intermittent test timeout errors in CI where the boot is almost
|
||||
# complete. Lengthen the timeout to allow for more opportunity to
|
||||
# complete successfully.
|
||||
TEST_FVP_LINUX_BOOT_TIMEOUT = "900"
|
||||
|
||||
@@ -51,15 +51,10 @@ FVP_CONFIG[board.dram_size] ?= "0x200000000"
|
||||
FVP_CONFIG[board.virtio_net.enabled] ?= "1"
|
||||
FVP_CONFIG[board.virtio_net.hostbridge.userNetworking] ?= "1"
|
||||
FVP_CONFIG[board.virtio_net.hostbridge.userNetPorts] = "2222=22"
|
||||
FVP_CONFIG[board.virtioblockdevice.image_path] ?= "${IMAGE_LINK_NAME}.wic"
|
||||
FVP_CONFIG[board.virtioblockdevice.image_path] ?= "${IMAGE_NAME}.wic"
|
||||
|
||||
FVP_CONSOLES[default] = "terminal_ns_uart_ap"
|
||||
FVP_TERMINALS[css.scp.terminal_uart_scp] ?= "SCP Console"
|
||||
FVP_TERMINALS[css.mcp.terminal_uart_mcp] ?= "MCP Console"
|
||||
FVP_TERMINALS[css.terminal_ns_uart_ap] ?= "NS Console"
|
||||
FVP_TERMINALS[css.terminal_s_uart_ap] ?= "S Console"
|
||||
|
||||
# Seeing intermittent test timeout errors in CI where the boot is almost
|
||||
# complete. Lengthen the timeout to allow for more opportunity to
|
||||
# complete successfully.
|
||||
TEST_FVP_LINUX_BOOT_TIMEOUT = "900"
|
||||
|
||||
@@ -26,8 +26,6 @@ EFI_PROVIDER ?= "${@bb.utils.contains("DISTRO_FEATURES", "systemd", "systemd-boo
|
||||
SERIAL_CONSOLES ?= "115200;ttyAMA0 115200;hvc0"
|
||||
|
||||
EXTRA_IMAGEDEPENDS += "edk2-firmware"
|
||||
#FIXME - in 2.15.0, new logic for pen hold the SMP cores was added, which breaks this platform. Hold this back until it can be resolved.
|
||||
PREFERRED_VERSION_trusted-firmware-a ?= "2.14.%"
|
||||
|
||||
QB_SYSTEM_NAME = "qemu-system-aarch64"
|
||||
QB_MACHINE = "-machine sbsa-ref"
|
||||
|
||||
@@ -192,11 +192,20 @@ The following payloads can be individually updated:
|
||||
|
||||
### Generate capsules {.reference}
|
||||
|
||||
Capsules are generated by running the `image_uefi_capsule` task for
|
||||
`corstone1000-flash-firmware-image`. The task uses EDK II's `GenerateCapsule`
|
||||
tool and creates the capsule metadata JSON automatically from the recipe settings.
|
||||
[EDK II's]($edk2_repository) `GenerateCapsule` tool is used to generate capsules and is built automatically
|
||||
for the host machine during the firmware image building process.
|
||||
The tool can be found at `${WORKSPACE}/build/tmp/sysroots-components/aarch64/edk2-basetools-native/usr/bin/edk2-BaseTools/BinWrappers/PosixLike/GenerateCapsule`.
|
||||
|
||||
The capsule's default metadata can be found in the `${WORKSPACE}/meta-arm/meta-arm-bsp/recipes-bsp/images/corstone1000-flash-firmware-image.bb`
|
||||
:::note
|
||||
The `aarch64` part of this path depends on the build host architecture
|
||||
and can be different on another host.
|
||||
:::
|
||||
|
||||
A JSON file containing metadata about the capsule payloads needs to be created using the script
|
||||
found at `${WORKSPACE}/meta-arm/meta-arm/scripts/generate_capsule_json_multiple.py`.
|
||||
This JSON file is required by EDK II's `GenerateCapsule` tool to generate the capsule.
|
||||
|
||||
The capsule's default metadata passed can be found in the `${WORKSPACE}/meta-arm/meta-arm-bsp/recipes-bsp/images/corstone1000-flash-firmware-image.bb`
|
||||
and `${WORKSPACE}/meta-arm/kas/corstone1000-image-configuration.yml` files.
|
||||
|
||||
#### Valid full capsule {.reference}
|
||||
@@ -213,39 +222,116 @@ To generate a capsule that updates only a single component, explicitly set the f
|
||||
|
||||
The partial capsule is also valid, but sets the firmware version to 7 only for the BL2 component, indicating that no other components should be updated.
|
||||
|
||||
Run the command below to generate the partial capsule:
|
||||
Use the following commands to generate the `capsule_config.json` file, which is required by the EDK2 tool for capsule creation:
|
||||
|
||||
```
|
||||
cd ${WORKSPACE}
|
||||
kas shell meta-arm/kas/corstone1000-a320-fvp.yml:meta-arm/ci/debug.yml -c '
|
||||
echo "CAPSULE_VERSION = \"7\"" >> conf/local.conf
|
||||
echo "CAPSULE_LOWEST_SUPPORTED_VERSION = \"7\"" >> conf/local.conf
|
||||
echo "CAPSULE_SELECTED_COMPONENTS = \"BL2\"" >> conf/local.conf
|
||||
bitbake corstone1000-flash-firmware-image -c image_uefi_capsule
|
||||
'
|
||||
|
||||
python3 meta-arm/meta-arm/scripts/generate_capsule_json_multiple.py \
|
||||
--selected_components DUMMY_START BL2 DUMMY_END \
|
||||
--components DUMMY_START BL2 TFM_S FIP INITRAMFS DUMMY_END \
|
||||
--fw_versions 0 7 0 0 0 0 \
|
||||
--guids \
|
||||
6f784cbf-7938-5c23-8d6e-24d2f1410fa9 \
|
||||
${BL2_GUID} ${TFM_S_GUID} ${FIP_GUID} ${INITRAMFS_GUID} \
|
||||
b57e432b-a250-5c73-93e3-90205e64baba \
|
||||
--hardware_instances 1 1 1 1 1 1 \
|
||||
--lowest_supported_versions 5 5 5 5 5 5 \
|
||||
--monotonic_counts 1 1 1 1 1 1 \
|
||||
--payloads \
|
||||
build/tmp/work/corstone1000_a320_fvp-poky-linux-musl/corstone1000-flash-firmware-image/1.0/sources/corstone1000-flash-firmware-image-1.0/dummy.bin \
|
||||
build/tmp/deploy/images/corstone1000-a320-fvp/trusted-firmware-m/bl2_signed.bin \
|
||||
build/tmp/deploy/images/corstone1000-a320-fvp/trusted-firmware-m/tfm_s_signed.bin \
|
||||
build/tmp/deploy/images/corstone1000-a320-fvp/signed_fip.bin \
|
||||
build/tmp/deploy/images/corstone1000-a320-fvp/Image.gz-initramfs-corstone1000-a320-fvp.bin \
|
||||
build/tmp/work/corstone1000_a320_fvp-poky-linux-musl/corstone1000-flash-firmware-image/1.0/sources/corstone1000-flash-firmware-image-1.0/dummy.bin \
|
||||
--update_image_indexes 5 1 2 3 4 6 \
|
||||
--private_keys \
|
||||
build/tmp/deploy/images/corstone1000-a320-fvp/corstone1000_capsule_key.key \
|
||||
build/tmp/deploy/images/corstone1000-a320-fvp/corstone1000_capsule_key.key \
|
||||
build/tmp/deploy/images/corstone1000-a320-fvp/corstone1000_capsule_key.key \
|
||||
build/tmp/deploy/images/corstone1000-a320-fvp/corstone1000_capsule_key.key \
|
||||
build/tmp/deploy/images/corstone1000-a320-fvp/corstone1000_capsule_key.key \
|
||||
build/tmp/deploy/images/corstone1000-a320-fvp/corstone1000_capsule_key.key \
|
||||
--certificates \
|
||||
build/tmp/deploy/images/corstone1000-a320-fvp/corstone1000_capsule_cert.crt \
|
||||
build/tmp/deploy/images/corstone1000-a320-fvp/corstone1000_capsule_cert.crt \
|
||||
build/tmp/deploy/images/corstone1000-a320-fvp/corstone1000_capsule_cert.crt \
|
||||
build/tmp/deploy/images/corstone1000-a320-fvp/corstone1000_capsule_cert.crt \
|
||||
build/tmp/deploy/images/corstone1000-a320-fvp/corstone1000_capsule_cert.crt \
|
||||
build/tmp/deploy/images/corstone1000-a320-fvp/corstone1000_capsule_cert.crt \
|
||||
--output capsule_config.json
|
||||
```
|
||||
|
||||
The partial capsule will be located at
|
||||
`${WORKSPACE}/build/tmp/deploy/images/corstone1000-a320-fvp/corstone1000-a320-fvp-v7.uefi.capsule`.
|
||||
Run the command below to generate the partial capsule:
|
||||
|
||||
#### Rollback capsule {.reference}
|
||||
```
|
||||
./build/tmp/sysroots-components/aarch64/edk2-basetools-native/usr/bin/edk2-BaseTools/BinWrappers/PosixLike/GenerateCapsule \
|
||||
-e \
|
||||
-j capsule_config.json \
|
||||
--capflag PersistAcrossReset \
|
||||
-o corstone1000-a320-fvp-partial-v7.uefi.capsule
|
||||
```
|
||||
|
||||
The partial capsule will be located in the `${WORKSPACE}` directory.
|
||||
|
||||
#### Invalid capsule {.reference}
|
||||
|
||||
Generate a capsule with firmware version metadata for all payloads set lower than that of a valid capsule.
|
||||
The valid capsule has a default firmware version of 6 for all payloads, while the simulated invalid capsule has the firmware version set to 5 for all payloads.
|
||||
|
||||
Run the command below to generate the rollback capsule:
|
||||
Use the following commands to generate the `capsule_config.json` file, which is required by the EDK2 tool for capsule creation:
|
||||
|
||||
```
|
||||
cd ${WORKSPACE}
|
||||
kas shell meta-arm/kas/corstone1000-a320-fvp.yml:meta-arm/ci/debug.yml -c '
|
||||
echo "CAPSULE_VERSION = \"5\"" >> conf/local.conf
|
||||
echo "CAPSULE_LOWEST_SUPPORTED_VERSION = \"5\"" >> conf/local.conf
|
||||
bitbake corstone1000-flash-firmware-image -c image_uefi_capsule
|
||||
'
|
||||
|
||||
python3 meta-arm/meta-arm/scripts/generate_capsule_json_multiple.py \
|
||||
--selected_components DUMMY_START BL2 TFM_S FIP INITRAMFS DUMMY_END \
|
||||
--components DUMMY_START BL2 TFM_S FIP INITRAMFS DUMMY_END \
|
||||
--fw_versions 5 5 5 5 5 5 \
|
||||
--guids \
|
||||
6f784cbf-7938-5c23-8d6e-24d2f1410fa9 \
|
||||
${BL2_GUID} ${TFM_S_GUID} ${FIP_GUID} ${INITRAMFS_GUID} \
|
||||
b57e432b-a250-5c73-93e3-90205e64baba \
|
||||
--hardware_instances 1 1 1 1 1 1 \
|
||||
--lowest_supported_versions 5 5 5 5 5 5 \
|
||||
--monotonic_counts 1 1 1 1 1 1 \
|
||||
--payloads \
|
||||
build/tmp/work/corstone1000_a320_fvp-poky-linux-musl/corstone1000-flash-firmware-image/1.0/sources/corstone1000-flash-firmware-image-1.0/dummy.bin \
|
||||
build/tmp/deploy/images/corstone1000-a320-fvp/trusted-firmware-m/bl2_signed.bin \
|
||||
build/tmp/deploy/images/corstone1000-a320-fvp/trusted-firmware-m/tfm_s_signed.bin \
|
||||
build/tmp/deploy/images/corstone1000-a320-fvp/signed_fip.bin \
|
||||
build/tmp/deploy/images/corstone1000-a320-fvp/Image.gz-initramfs-corstone1000-a320-fvp.bin \
|
||||
build/tmp/work/corstone1000_a320_fvp-poky-linux-musl/corstone1000-flash-firmware-image/1.0/sources/corstone1000-flash-firmware-image-1.0/dummy.bin \
|
||||
--update_image_indexes 5 1 2 3 4 6 \
|
||||
--private_keys \
|
||||
build/tmp/deploy/images/corstone1000-a320-fvp/corstone1000_capsule_key.key \
|
||||
build/tmp/deploy/images/corstone1000-a320-fvp/corstone1000_capsule_key.key \
|
||||
build/tmp/deploy/images/corstone1000-a320-fvp/corstone1000_capsule_key.key \
|
||||
build/tmp/deploy/images/corstone1000-a320-fvp/corstone1000_capsule_key.key \
|
||||
build/tmp/deploy/images/corstone1000-a320-fvp/corstone1000_capsule_key.key \
|
||||
build/tmp/deploy/images/corstone1000-a320-fvp/corstone1000_capsule_key.key \
|
||||
--certificates \
|
||||
build/tmp/deploy/images/corstone1000-a320-fvp/corstone1000_capsule_cert.crt \
|
||||
build/tmp/deploy/images/corstone1000-a320-fvp/corstone1000_capsule_cert.crt \
|
||||
build/tmp/deploy/images/corstone1000-a320-fvp/corstone1000_capsule_cert.crt \
|
||||
build/tmp/deploy/images/corstone1000-a320-fvp/corstone1000_capsule_cert.crt \
|
||||
build/tmp/deploy/images/corstone1000-a320-fvp/corstone1000_capsule_cert.crt \
|
||||
build/tmp/deploy/images/corstone1000-a320-fvp/corstone1000_capsule_cert.crt \
|
||||
--output capsule_config.json
|
||||
```
|
||||
|
||||
The rollback capsule will be located at
|
||||
`${WORKSPACE}/build/tmp/deploy/images/corstone1000-a320-fvp/corstone1000-a320-fvp-v5.uefi.capsule`.
|
||||
Run the command below to generate the invalid capsule:
|
||||
|
||||
```
|
||||
./build/tmp/sysroots-components/aarch64/edk2-basetools-native/usr/bin/edk2-BaseTools/BinWrappers/PosixLike/GenerateCapsule \
|
||||
-e \
|
||||
-j capsule_config.json \
|
||||
--capflag PersistAcrossReset \
|
||||
-o corstone1000-a320-fvp-v5.uefi.capsule
|
||||
```
|
||||
|
||||
The invalid capsule will be located in the `${WORKSPACE}` directory.
|
||||
|
||||
### Transfer capsules to target {.reference}
|
||||
|
||||
@@ -283,8 +369,8 @@ as opposed to the on-disk method (delivery of capsules using a file on a mass st
|
||||
|
||||
```
|
||||
sudo cp ${WORKSPACE}/build/tmp/deploy/images/corstone1000-a320-fvp/corstone1000-a320-fvp-v6.uefi.capsule /mnt/ir-acs-live-image-generic-arm64/
|
||||
sudo cp ${WORKSPACE}/build/tmp/deploy/images/corstone1000-a320-fvp/corstone1000-a320-fvp-v5.uefi.capsule /mnt/ir-acs-live-image-generic-arm64/
|
||||
sudo cp ${WORKSPACE}/build/tmp/deploy/images/corstone1000-a320-fvp/corstone1000-a320-fvp-v7.uefi.capsule /mnt/ir-acs-live-image-generic-arm64/
|
||||
sudo cp ${WORKSPACE}/corstone1000-a320-fvp-v5.uefi.capsule /mnt/ir-acs-live-image-generic-arm64/
|
||||
sudo cp ${WORKSPACE}/corstone1000-a320-fvp-partial-v7.uefi.capsule /mnt/ir-acs-live-image-generic-arm64/
|
||||
sync
|
||||
```
|
||||
|
||||
@@ -315,7 +401,7 @@ To run the test:
|
||||
cd ${WORKSPACE} && tmux
|
||||
```
|
||||
|
||||
2. Run the FVP within `tmux` with the IR prebuilt image which now also contains the three capsules:
|
||||
2. Run the FVP within `tmux` with the IR prebuilt image which now also contains the two capsules:
|
||||
|
||||
```
|
||||
kas shell meta-arm/kas/corstone1000-a320-fvp.yml:meta-arm/ci/debug.yml \
|
||||
@@ -440,7 +526,7 @@ Do not terminate FVP between the positive full capsule update and partial capsul
|
||||
|
||||
#### Positive partial capsule update {.reference}
|
||||
|
||||
Follow the steps for the [Positive full capsule update test], ensuring you use `corstone1000-a320-fvp-v7.uefi.capsule` instead of `corstone1000-a320-fvp-v6.uefi.capsule`.
|
||||
Follow the steps for the [Positive full capsule update test], ensuring you use `corstone1000-a320-fvp-partial-v7.uefi.capsule` instead of `corstone1000-a320-fvp-v6.uefi.capsule`.
|
||||
|
||||
Once the system has fully booted again, read [Verifying firmware versions with ESRT] to confirm that the firmware version reflects the updated capsule.
|
||||
|
||||
|
||||
@@ -91,7 +91,7 @@ Table: OP-TEE components
|
||||
| Type | Path |
|
||||
| --------- | ---------------------------------------------------------------------------------------------------------------- |
|
||||
| bbappend | `${WORKSPACE}/meta-arm/meta-arm-bsp/recipes-security/optee/optee-os_%.bbappend` |
|
||||
| Recipe | `${WORKSPACE}/meta-arm/meta-arm/recipes-security/optee/optee-os_4.10.0.bb` |
|
||||
| Recipe | `${WORKSPACE}/meta-arm/meta-arm/recipes-security/optee/optee-os_4.9.0.bb` |
|
||||
|
||||
#### U-Boot {.reference}
|
||||
|
||||
@@ -103,7 +103,7 @@ Table: U-Boot components
|
||||
| --------- | ---------------------------------------------------------------------------------------------------------------- |
|
||||
| bbappend | `${WORKSPACE}/meta-arm/meta-arm/recipes-bsp/u-boot/u-boot_%.bbappend` |
|
||||
| bbappend | `${WORKSPACE}/meta-arm/meta-arm-bsp/recipes-bsp/u-boot/u-boot_%.bbappend` |
|
||||
| Recipe | `${WORKSPACE}/core/meta/recipes-bsp/u-boot/u-boot_2026.07.bb` |
|
||||
| Recipe | `${WORKSPACE}/meta-arm/meta-arm-bsp/recipes-bsp/u-boot/u-boot_2025.10.bb` |
|
||||
|
||||
#### Linux {.reference}
|
||||
|
||||
@@ -135,7 +135,7 @@ Table: Trusted Firmware-M secure enclave components
|
||||
| Type | Path |
|
||||
| --------- | ---------------------------------------------------------------------------------------------------------------- |
|
||||
| bbappend | `${WORKSPACE}/meta-arm/meta-arm-bsp/recipes-bsp/trusted-firmware-m/trusted-firmware-m_%.bbappend` |
|
||||
| Recipe | `${WORKSPACE}/meta-arm/meta-arm/recipes-bsp/trusted-firmware-m/trusted-firmware-m_2.3.0.bb` |
|
||||
| Recipe | `${WORKSPACE}/meta-arm/meta-arm/recipes-bsp/trusted-firmware-m/trusted-firmware-m_2.2.2.bb` |
|
||||
|
||||
## Build {.reference}
|
||||
|
||||
|
||||
@@ -28,7 +28,6 @@ The following prerequisites must be available on the host system:
|
||||
- GNU Tar 1.34 or greater.
|
||||
- GNU Compiler Collection 12.2 or greater.
|
||||
- GNU Make 4.3 or greater.
|
||||
- mtools 4.0 or greater.
|
||||
- tmux 3.3 or greater.
|
||||
|
||||
Please follow the steps described in the Yocto mega manual:
|
||||
@@ -131,11 +130,11 @@ Host Processor Components
|
||||
`OP-TEE <https://git.trustedfirmware.org/OP-TEE/optee_os.git>`__
|
||||
================================================================
|
||||
|
||||
+----------+-------------------------------------------------------------------------------------------+
|
||||
| bbappend | ``${WORKSPACE}/meta-arm/meta-arm-bsp/recipes-security/optee/optee-os_%.bbappend`` |
|
||||
+----------+-------------------------------------------------------------------------------------------+
|
||||
| Recipe | ``${WORKSPACE}/meta-arm/meta-arm/recipes-security/optee/optee-os_4.10.0.bb`` |
|
||||
+----------+-------------------------------------------------------------------------------------------+
|
||||
+----------+------------------------------------------------------------------------------------------+
|
||||
| bbappend | ``${WORKSPACE}/meta-arm/meta-arm-bsp/recipes-security/optee/optee-os_%.bbappend`` |
|
||||
+----------+------------------------------------------------------------------------------------------+
|
||||
| Recipe | ``${WORKSPACE}/meta-arm/meta-arm/recipes-security/optee/optee-os_4.9.0.bb`` |
|
||||
+----------+------------------------------------------------------------------------------------------+
|
||||
|
||||
`U-Boot <https://github.com/u-boot/u-boot.git>`__
|
||||
=================================================
|
||||
@@ -145,7 +144,7 @@ Host Processor Components
|
||||
+----------+----------------------------------------------------------------------------------+
|
||||
| bbappend | ``${WORKSPACE}/meta-arm/meta-arm-bsp/recipes-bsp/u-boot/u-boot_%.bbappend`` |
|
||||
+----------+----------------------------------------------------------------------------------+
|
||||
| Recipe | ``${WORKSPACE}/core/meta/recipes-bsp/u-boot/u-boot_2026.07.bb`` |
|
||||
| Recipe | ``${WORKSPACE}/meta-arm/meta-arm-bsp/recipes-bsp/u-boot/u-boot_2025.10.bb`` |
|
||||
+----------+----------------------------------------------------------------------------------+
|
||||
|
||||
Linux
|
||||
@@ -173,7 +172,7 @@ Secure Enclave Components
|
||||
+----------+-------------------------------------------------------------------------------------------------------+
|
||||
| bbappend | ``${WORKSPACE}/meta-arm/meta-arm-bsp/recipes-bsp/trusted-firmware-m/trusted-firmware-m_%.bbappend`` |
|
||||
+----------+-------------------------------------------------------------------------------------------------------+
|
||||
| Recipe | ``${WORKSPACE}/meta-arm/meta-arm/recipes-bsp/trusted-firmware-m/trusted-firmware-m_2.3.0.bb`` |
|
||||
| Recipe | ``${WORKSPACE}/meta-arm/meta-arm/recipes-bsp/trusted-firmware-m/trusted-firmware-m_2.2.2.bb`` |
|
||||
+----------+-------------------------------------------------------------------------------------------------------+
|
||||
|
||||
************************************
|
||||
@@ -211,22 +210,13 @@ Build
|
||||
mkdir ${WORKSPACE}
|
||||
cd ${WORKSPACE}
|
||||
|
||||
#. Create a Python virtual environment and activate it.
|
||||
#. Install kas version 4.4 with ``sudo`` rights.
|
||||
|
||||
.. code-block:: console
|
||||
|
||||
python3 -m venv ${WORKSPACE}/venv_cs1k
|
||||
source ${WORKSPACE}/venv_cs1k/bin/activate
|
||||
sudo pip3 install kas==4.4
|
||||
|
||||
#. Install ``kas`` and ``wic`` inside the virtual environment.
|
||||
|
||||
.. code-block:: console
|
||||
|
||||
python3 -m pip install kas==5.1 "git+https://git.yoctoproject.org/wic@v0.3.0"
|
||||
|
||||
.. note::
|
||||
|
||||
Ensure the kas and wic installation directory is visible on the ``$PATH`` environment variable.
|
||||
Ensure the kas installation directory is visible on the ``$PATH`` environment variable.
|
||||
|
||||
#. Clone the `meta-arm` Yocto layer in the workspace ``${WORKSPACE}``.
|
||||
|
||||
@@ -449,10 +439,6 @@ MPS3
|
||||
|
||||
sudo picocom -b 115200 /dev/ttyUSB3
|
||||
|
||||
.. note::
|
||||
|
||||
If the user is a member of the ``dialout`` group, ``sudo`` is not required for this step.
|
||||
|
||||
.. important::
|
||||
Plug a connected Ethernet cable to the MPS3 or it will
|
||||
wait for a network connection for a considerable amount of time, printing the following
|
||||
@@ -878,15 +864,14 @@ The results can be fetched from the `acs_results` folder in the ``BOOT`` partiti
|
||||
|
||||
.. note::
|
||||
|
||||
Access the `acs_results` folder in FVP by copying it from the same ACS image that was used to boot the FVP.
|
||||
The following command copies the ``acs_results`` directory from the ACS image to
|
||||
``${WORKSPACE}/acs_results`` on the host development machine.
|
||||
Access the `acs_results` folder in FVP by running the following commands:
|
||||
|
||||
.. code-block:: console
|
||||
|
||||
cd ${WORKSPACE}
|
||||
wic cp ${WORKSPACE}/arm-systemready/IR/prebuilt_images/v23.09_2.1.0/ir-acs-live-image-generic-arm64.wic:1/acs_results \
|
||||
${WORKSPACE}
|
||||
sudo mkdir /mnt/test
|
||||
sudo mount -o rw,offset=1048576 \
|
||||
${WORKSPACE}/arm-systemready/IR/prebuilt_images/v23.09_2.1.0/ir-acs-live-image-generic-arm64.wic \
|
||||
/mnt/test
|
||||
|
||||
#####################################################
|
||||
|
||||
@@ -942,11 +927,20 @@ The following payloads can be individually updated:
|
||||
Generate Capsules
|
||||
*****************
|
||||
|
||||
Capsules are generated by running the ``image_uefi_capsule`` task for
|
||||
``corstone1000-flash-firmware-image``. The task uses EDK II's ``GenerateCapsule``
|
||||
tool and creates the capsule metadata JSON automatically from the recipe settings.
|
||||
`EDK II's <edk2-repository_>`__ ``GenerateCapsule`` tool is used to generate capsules and is built automatically
|
||||
for the host machine during the firmware image building process.
|
||||
The tool can be found at ``${WORKSPACE}/build/tmp/sysroots-components/aarch64/edk2-basetools-native/usr/bin/edk2-BaseTools/BinWrappers/PosixLike/GenerateCapsule``.
|
||||
|
||||
The capsule's default metadata can be found in the ``${WORKSPACE}/meta-arm/meta-arm-bsp/recipes-bsp/images/corstone1000-flash-firmware-image.bb``
|
||||
.. note::
|
||||
|
||||
The ``aarch64`` part of this path depends on the build host architecture
|
||||
and can be different on another host.
|
||||
|
||||
A JSON file containing metadata about the capsule payloads needs to be created using the script
|
||||
found at ``${WORKSPACE}/meta-arm/meta-arm/scripts/generate_capsule_json_multiple.py``.
|
||||
This JSON file is required by EDK II's ``GenerateCapsule`` tool to generate the capsule.
|
||||
|
||||
The capsule's default metadata passed can be found in the ``${WORKSPACE}/meta-arm/meta-arm-bsp/recipes-bsp/images/corstone1000-flash-firmware-image.bb``
|
||||
and ``${WORKSPACE}/meta-arm/kas/corstone1000-image-configuration.yml`` files.
|
||||
|
||||
Valid Full Capsule
|
||||
@@ -965,40 +959,118 @@ To generate a capsule that updates only a single component, explicitly set the f
|
||||
|
||||
The **partial capsule** is also valid, but sets the firmware version to **7** **only** for the **BL2** component, indicating that no other components should be updated.
|
||||
|
||||
Use the following commands to generate the `capsule_config.json` file, which is required by the EDK2 tool for capsule creation:
|
||||
|
||||
.. code-block:: console
|
||||
|
||||
cd ${WORKSPACE}
|
||||
|
||||
python3 meta-arm/meta-arm/scripts/generate_capsule_json_multiple.py \
|
||||
--selected_components DUMMY_START BL2 DUMMY_END \
|
||||
--components DUMMY_START BL2 TFM_S FIP INITRAMFS DUMMY_END \
|
||||
--fw_versions 0 7 0 0 0 0 \
|
||||
--guids \
|
||||
6f784cbf-7938-5c23-8d6e-24d2f1410fa9 \
|
||||
${BL2_GUID} ${TFM_S_GUID} ${FIP_GUID} ${INITRAMFS_GUID} \
|
||||
b57e432b-a250-5c73-93e3-90205e64baba \
|
||||
--hardware_instances 1 1 1 1 1 1 \
|
||||
--lowest_supported_versions 5 5 5 5 5 5 \
|
||||
--monotonic_counts 1 1 1 1 1 1 \
|
||||
--payloads \
|
||||
build/tmp/work/corstone1000_${TARGET}-poky-linux-musl/corstone1000-flash-firmware-image/1.0/sources/corstone1000-flash-firmware-image-1.0/dummy.bin \
|
||||
build/tmp/deploy/images/corstone1000-${TARGET}/trusted-firmware-m/bl2_signed.bin \
|
||||
build/tmp/deploy/images/corstone1000-${TARGET}/trusted-firmware-m/tfm_s_signed.bin \
|
||||
build/tmp/deploy/images/corstone1000-${TARGET}/signed_fip.bin \
|
||||
build/tmp/deploy/images/corstone1000-${TARGET}/Image.gz-initramfs-corstone1000-${TARGET}.bin \
|
||||
build/tmp/work/corstone1000_${TARGET}-poky-linux-musl/corstone1000-flash-firmware-image/1.0/sources/corstone1000-flash-firmware-image-1.0/dummy.bin \
|
||||
--update_image_indexes 5 1 2 3 4 6 \
|
||||
--private_keys \
|
||||
build/tmp/deploy/images/corstone1000-${TARGET}/corstone1000_capsule_key.key \
|
||||
build/tmp/deploy/images/corstone1000-${TARGET}/corstone1000_capsule_key.key \
|
||||
build/tmp/deploy/images/corstone1000-${TARGET}/corstone1000_capsule_key.key \
|
||||
build/tmp/deploy/images/corstone1000-${TARGET}/corstone1000_capsule_key.key \
|
||||
build/tmp/deploy/images/corstone1000-${TARGET}/corstone1000_capsule_key.key \
|
||||
build/tmp/deploy/images/corstone1000-${TARGET}/corstone1000_capsule_key.key \
|
||||
--certificates \
|
||||
build/tmp/deploy/images/corstone1000-${TARGET}/corstone1000_capsule_cert.crt \
|
||||
build/tmp/deploy/images/corstone1000-${TARGET}/corstone1000_capsule_cert.crt \
|
||||
build/tmp/deploy/images/corstone1000-${TARGET}/corstone1000_capsule_cert.crt \
|
||||
build/tmp/deploy/images/corstone1000-${TARGET}/corstone1000_capsule_cert.crt \
|
||||
build/tmp/deploy/images/corstone1000-${TARGET}/corstone1000_capsule_cert.crt \
|
||||
build/tmp/deploy/images/corstone1000-${TARGET}/corstone1000_capsule_cert.crt \
|
||||
--output capsule_config.json
|
||||
|
||||
Run the command below to generate the partial capsule:
|
||||
|
||||
.. code-block:: console
|
||||
|
||||
cd ${WORKSPACE}
|
||||
kas shell meta-arm/kas/corstone1000-${TARGET}.yml:meta-arm/ci/debug.yml -c '
|
||||
echo "CAPSULE_VERSION = \"7\"" >> conf/local.conf
|
||||
echo "CAPSULE_LOWEST_SUPPORTED_VERSION = \"7\"" >> conf/local.conf
|
||||
echo "CAPSULE_SELECTED_COMPONENTS = \"BL2\"" >> conf/local.conf
|
||||
bitbake corstone1000-flash-firmware-image -c image_uefi_capsule
|
||||
'
|
||||
./build/tmp/sysroots-components/aarch64/edk2-basetools-native/usr/bin/edk2-BaseTools/BinWrappers/PosixLike/GenerateCapsule \
|
||||
-e \
|
||||
-j capsule_config.json \
|
||||
--capflag PersistAcrossReset \
|
||||
-o corstone1000-${TARGET}-partial-v7.uefi.capsule
|
||||
|
||||
The partial capsule will be located at
|
||||
``${WORKSPACE}/build/tmp/deploy/images/corstone1000-${TARGET}/corstone1000-${TARGET}-v7.uefi.capsule``.
|
||||
The partial capsule will be located in the ``${WORKSPACE}`` directory.
|
||||
|
||||
Rollback Capsule
|
||||
================
|
||||
Invalid Capsule
|
||||
===============
|
||||
|
||||
Generate a capsule with firmware version metadata for all payloads set lower than that of a valid capsule.
|
||||
The valid capsule has a default firmware version of 6 for all payloads, while the simulated invalid capsule has the firmware version set to 5 for all payloads.
|
||||
|
||||
Run the command below to generate the rollback capsule:
|
||||
Use the following commands to generate the `capsule_config.json` file, which is required by the EDK2 tool for capsule creation:
|
||||
|
||||
.. code-block:: console
|
||||
|
||||
cd ${WORKSPACE}
|
||||
kas shell meta-arm/kas/corstone1000-${TARGET}.yml:meta-arm/ci/debug.yml -c '
|
||||
echo "CAPSULE_VERSION = \"5\"" >> conf/local.conf
|
||||
echo "CAPSULE_LOWEST_SUPPORTED_VERSION = \"5\"" >> conf/local.conf
|
||||
bitbake corstone1000-flash-firmware-image -c image_uefi_capsule
|
||||
'
|
||||
|
||||
The rollback capsule will be located at
|
||||
``${WORKSPACE}/build/tmp/deploy/images/corstone1000-${TARGET}/corstone1000-${TARGET}-v5.uefi.capsule``.
|
||||
python3 meta-arm/meta-arm/scripts/generate_capsule_json_multiple.py \
|
||||
--selected_components DUMMY_START BL2 TFM_S FIP INITRAMFS DUMMY_END \
|
||||
--components DUMMY_START BL2 TFM_S FIP INITRAMFS DUMMY_END \
|
||||
--fw_versions 5 5 5 5 5 5 \
|
||||
--guids \
|
||||
6f784cbf-7938-5c23-8d6e-24d2f1410fa9 \
|
||||
${BL2_GUID} ${TFM_S_GUID} ${FIP_GUID} ${INITRAMFS_GUID} \
|
||||
b57e432b-a250-5c73-93e3-90205e64baba \
|
||||
--hardware_instances 1 1 1 1 1 1 \
|
||||
--lowest_supported_versions 5 5 5 5 5 5 \
|
||||
--monotonic_counts 1 1 1 1 1 1 \
|
||||
--payloads \
|
||||
build/tmp/work/corstone1000_${TARGET}-poky-linux-musl/corstone1000-flash-firmware-image/1.0/sources/corstone1000-flash-firmware-image-1.0/dummy.bin \
|
||||
build/tmp/deploy/images/corstone1000-${TARGET}/trusted-firmware-m/bl2_signed.bin \
|
||||
build/tmp/deploy/images/corstone1000-${TARGET}/trusted-firmware-m/tfm_s_signed.bin \
|
||||
build/tmp/deploy/images/corstone1000-${TARGET}/signed_fip.bin \
|
||||
build/tmp/deploy/images/corstone1000-${TARGET}/Image.gz-initramfs-corstone1000-${TARGET}.bin \
|
||||
build/tmp/work/corstone1000_${TARGET}-poky-linux-musl/corstone1000-flash-firmware-image/1.0/sources/corstone1000-flash-firmware-image-1.0/dummy.bin \
|
||||
--update_image_indexes 5 1 2 3 4 6 \
|
||||
--private_keys \
|
||||
build/tmp/deploy/images/corstone1000-${TARGET}/corstone1000_capsule_key.key \
|
||||
build/tmp/deploy/images/corstone1000-${TARGET}/corstone1000_capsule_key.key \
|
||||
build/tmp/deploy/images/corstone1000-${TARGET}/corstone1000_capsule_key.key \
|
||||
build/tmp/deploy/images/corstone1000-${TARGET}/corstone1000_capsule_key.key \
|
||||
build/tmp/deploy/images/corstone1000-${TARGET}/corstone1000_capsule_key.key \
|
||||
build/tmp/deploy/images/corstone1000-${TARGET}/corstone1000_capsule_key.key \
|
||||
--certificates \
|
||||
build/tmp/deploy/images/corstone1000-${TARGET}/corstone1000_capsule_cert.crt \
|
||||
build/tmp/deploy/images/corstone1000-${TARGET}/corstone1000_capsule_cert.crt \
|
||||
build/tmp/deploy/images/corstone1000-${TARGET}/corstone1000_capsule_cert.crt \
|
||||
build/tmp/deploy/images/corstone1000-${TARGET}/corstone1000_capsule_cert.crt \
|
||||
build/tmp/deploy/images/corstone1000-${TARGET}/corstone1000_capsule_cert.crt \
|
||||
build/tmp/deploy/images/corstone1000-${TARGET}/corstone1000_capsule_cert.crt \
|
||||
--output capsule_config.json
|
||||
|
||||
|
||||
Run the command below to generate the invalid capsule:
|
||||
|
||||
.. code-block:: console
|
||||
|
||||
./build/tmp/sysroots-components/aarch64/edk2-basetools-native/usr/bin/edk2-BaseTools/BinWrappers/PosixLike/GenerateCapsule \
|
||||
-e \
|
||||
-j capsule_config.json \
|
||||
--capflag PersistAcrossReset \
|
||||
-o corstone1000-${TARGET}-v5.uefi.capsule
|
||||
|
||||
The invalid capsule will be located in the ``${WORKSPACE}`` directory.
|
||||
|
||||
***************************
|
||||
Transfer Capsules to Target
|
||||
@@ -1007,48 +1079,76 @@ Transfer Capsules to Target
|
||||
The capsule delivery process described below is the direct method (usage of capsules from the ACS image)
|
||||
as opposed to the on-disk method (delivery of capsules using a file on a mass storage device).
|
||||
|
||||
MPS3
|
||||
====
|
||||
|
||||
#. Prepare a USB drive as explained in `this <mps3-instructions-for-acs-image_>`_ section.
|
||||
|
||||
#. Copy the capsule files to the root directory of the ``BOOT`` partition in the USB drive.
|
||||
|
||||
.. code-block:: console
|
||||
|
||||
cp ${WORKSPACE}/build/tmp/deploy/images/corstone1000-mps3/corstone1000-mps3-v6.uefi.capsule /dev/sdc/BOOT/
|
||||
cp ${WORKSPACE}/corstone1000-mps3-v5.uefi.capsule /dev/sdc/EFI/BOOT/
|
||||
cp ${WORKSPACE}/corstone1000-mps3-partial-v7.uefi.capsule /dev/sdc/EFI/BOOT/
|
||||
sync
|
||||
|
||||
.. note::
|
||||
|
||||
The staging steps below are shared between ``mps3`` and ``fvp``.
|
||||
``/dev/sdc`` is the assumed path for the ACS Image USB drive.
|
||||
Replace it with the actual device path as enumerated on your development machine.
|
||||
|
||||
#. Download and extract the ACS image `as described for the MPS3 <mps3-instructions-for-acs-image_>`_.
|
||||
The ACS image extraction location will be referred below as ``${ACS_IMAGE_PATH}``.
|
||||
|
||||
#. Copy the ACS image to the workspace root directory and rename it to
|
||||
``ir-acs-live-image-generic-arm64-staged.wic``. The staged image will then be
|
||||
populated with the capsule files.
|
||||
|
||||
``${ACS_STAGED_IMAGE}`` refers to
|
||||
``${WORKSPACE}/ir-acs-live-image-generic-arm64-staged.wic``.
|
||||
|
||||
.. code-block:: console
|
||||
|
||||
cp ${ACS_IMAGE_PATH}/ir-acs-live-image-generic-arm64.wic \
|
||||
${ACS_STAGED_IMAGE}
|
||||
|
||||
#. Copy the capsules to the staged ACS image:
|
||||
|
||||
.. code-block:: console
|
||||
|
||||
cd ${WORKSPACE}
|
||||
wic cp ${WORKSPACE}/build/tmp/deploy/images/corstone1000-${TARGET}/corstone1000-${TARGET}-v6.uefi.capsule \
|
||||
${ACS_STAGED_IMAGE}:1/corstone1000-${TARGET}-v6.uefi.capsule
|
||||
wic cp ${WORKSPACE}/build/tmp/deploy/images/corstone1000-${TARGET}/corstone1000-${TARGET}-v5.uefi.capsule \
|
||||
${ACS_STAGED_IMAGE}:1/corstone1000-${TARGET}-v5.uefi.capsule
|
||||
wic cp ${WORKSPACE}/build/tmp/deploy/images/corstone1000-${TARGET}/corstone1000-${TARGET}-v7.uefi.capsule \
|
||||
${ACS_STAGED_IMAGE}:1/corstone1000-${TARGET}-v7.uefi.capsule
|
||||
|
||||
.. important::
|
||||
|
||||
The direct Capsule Update method requires that the capsule files not be placed in the ``EFI/UpdateCapsule`` directory,
|
||||
as doing so might inadvertently trigger the on-disk update method.
|
||||
|
||||
MPS3
|
||||
====
|
||||
FVP
|
||||
===
|
||||
|
||||
#. Write ``${ACS_STAGED_IMAGE}`` to the ACS USB drive by following the
|
||||
`MPS3 ACS image steps <mps3-instructions-for-acs-image_>`_ and replacing
|
||||
``ir-acs-live-image-generic-arm64.wic`` with ``${ACS_STAGED_IMAGE}``.
|
||||
#. Download and extract the ACS image `as described for the MPS3 <mps3-instructions-for-acs-image_>`_.
|
||||
The ACS image extraction location will be referred below as ``${ACS_IMAGE_PATH}``.
|
||||
|
||||
.. note::
|
||||
|
||||
Creating a USB drive with the ACS image is not required as the image will be mounted with the steps below.
|
||||
|
||||
#. Find the first partition's offset of the ``ir-acs-live-image-generic-arm64.wic`` image using the ``fdisk`` tool.
|
||||
The partition table can be listed using:
|
||||
|
||||
.. code-block:: console
|
||||
|
||||
fdisk -lu ${ACS_IMAGE_PATH}/ir-acs-live-image-generic-arm64.wic
|
||||
Device Start End Sectors Size Type
|
||||
${ACS_IMAGE_PATH}/ir-acs-live-image-generic-arm64.wic1 2048 309247 307200 150M Microsoft basic data
|
||||
${ACS_IMAGE_PATH}/ir-acs-live-image-generic-arm64.wic2 309248 1343339 1034092 505M Linux filesystem
|
||||
|
||||
|
||||
Given that the first partition starts at sector 2048 and each sector is 512 bytes in size,
|
||||
the first partition is at offset 1048576 (2048 x 512).
|
||||
|
||||
#. Mount the ``ir-acs-live-image-generic-arm64.wic`` image using the previously calculated offset:
|
||||
|
||||
.. code-block:: console
|
||||
|
||||
sudo mkdir /mnt/ir-acs-live-image-generic-arm64
|
||||
sudo mount -o rw,offset=<first_partition_offset> ${ACS_IMAGE_PATH}/ir-acs-live-image-generic-arm64.wic /mnt/ir-acs-live-image-generic-arm64
|
||||
|
||||
#. Copy the capsules:
|
||||
|
||||
.. code-block:: console
|
||||
|
||||
sudo cp ${WORKSPACE}/build/tmp/deploy/images/corstone1000-fvp/corstone1000-fvp-v6.uefi.capsule /mnt/ir-acs-live-image-generic-arm64/
|
||||
sudo cp ${WORKSPACE}/corstone1000-fvp-v5.uefi.capsule /mnt/ir-acs-live-image-generic-arm64/
|
||||
sudo cp ${WORKSPACE}/corstone1000-fvp-partial-v7.uefi.capsule /mnt/ir-acs-live-image-generic-arm64/
|
||||
sync
|
||||
|
||||
#. Unmount the IR image:
|
||||
|
||||
.. code-block:: console
|
||||
|
||||
sudo umount /mnt/ir-acs-live-image-generic-arm64
|
||||
|
||||
************************
|
||||
Run Capsule Update Tests
|
||||
@@ -1072,7 +1172,7 @@ Positive Full Capsule Update Test
|
||||
|
||||
- MPS3:
|
||||
|
||||
#. Plug the prepared USB drive which has the IR prebuilt image and three capsules to the MPS3.
|
||||
#. Plug the prepared USB drive which has the IR prebuilt image and two capsules to the MPS3.
|
||||
#. Power cycle the MPS3.
|
||||
|
||||
- FVP:
|
||||
@@ -1083,18 +1183,17 @@ Positive Full Capsule Update Test
|
||||
|
||||
cd ${WORKSPACE} && tmux
|
||||
|
||||
#. Run the FVP within ``tmux`` with the IR prebuilt image which now also contains the three capsules:
|
||||
#. Run the FVP within ``tmux`` with the IR prebuilt image which now also contains the two capsules:
|
||||
|
||||
.. code-block:: console
|
||||
|
||||
cd ${WORKSPACE}
|
||||
kas shell meta-arm/kas/corstone1000-fvp.yml:meta-arm/ci/debug.yml \
|
||||
-c "../meta-arm/scripts/runfvp --terminals=tmux \
|
||||
-- -C board.msd_mmc.p_mmc_file=${ACS_STAGED_IMAGE}"
|
||||
-- -C board.msd_mmc.p_mmc_file=${ACS_IMAGE_PATH}/ir-acs-live-image-generic-arm64.wic"
|
||||
|
||||
.. warning::
|
||||
|
||||
``${ACS_STAGED_IMAGE}`` must be an absolute path. Ensure there are no spaces before or after of ``=`` of the ``-C board.msd_mmc.p_mmc_file`` option.
|
||||
``${ACS_IMAGE_PATH}`` must be an absolute path. Ensure there are no spaces before or after of ``=`` of the ``-C board.msd_mmc.p_mmc_file`` option.
|
||||
|
||||
|
||||
#. Wait until U-Boot loads EFI from the ACS image and interrupt the EFI shell by pressing the ``Escape`` key when the following prompt is displayed on the Host Processor terminal (``ttyUSB2`` for MPS3).
|
||||
@@ -1115,7 +1214,7 @@ Positive Full Capsule Update Test
|
||||
|
||||
.. code-block:: console
|
||||
|
||||
EFI/BOOT/app/CapsuleApp.efi corstone1000-mps3-v6.uefi.capsule
|
||||
EFI/BOOT/app/CapsuleApp.efi EFI/BOOT/corstone1000-mps3-v6.uefi.capsule
|
||||
|
||||
- FVP:
|
||||
|
||||
@@ -1228,7 +1327,7 @@ Positive Partial Capsule Update Test
|
||||
====================================
|
||||
|
||||
Follow the steps for the `positive full capsule update test <positive-full-capsule-update-test_>`__ ensuring you use
|
||||
``corstone1000-${TARGET}-v7.uefi.capsule`` instead of ``corstone1000-${TARGET}-v6.uefi.capsule``.
|
||||
``corstone1000-${TARGET}-partial-v7.uefi.capsule`` instead of ``corstone1000-${TARGET}-v6.uefi.capsule``.
|
||||
|
||||
Once the system has fully booted again, `read the ESRT <verifying-firmware-versions-via-esrt_>`__ to
|
||||
confirm that the firmware version reflects the updated capsule.
|
||||
@@ -1269,7 +1368,7 @@ Rollback Protection Capsule Update Test
|
||||
|
||||
.. code-block:: console
|
||||
|
||||
EFI/BOOT/app/CapsuleApp.efi corstone1000-mps3-v5.uefi.capsule
|
||||
EFI/BOOT/app/CapsuleApp.efi EFI/BOOT/corstone1000-mps3-v5.uefi.capsule
|
||||
|
||||
- FVP:
|
||||
|
||||
@@ -1584,10 +1683,6 @@ MPS3
|
||||
|
||||
sudo picocom -b 115200 /dev/ttyUSB2
|
||||
|
||||
.. note::
|
||||
|
||||
If the user is a member of the ``dialout`` group, ``sudo`` is not required for this step.
|
||||
|
||||
#. When the installation screen is displayed on ``ttyUSB2``, plug in the (still empty) system drive to the MPS3.
|
||||
#. Start the distribution installation process.
|
||||
|
||||
@@ -1808,17 +1903,19 @@ Generate Keys, Signed Image and Unsigned Image
|
||||
|
||||
The `efitools <https://github.com/vathpela/efitools/>`__ package is required to execute the script.
|
||||
|
||||
The ``mtools`` package is required on the host development machine to execute the script.
|
||||
|
||||
``${CERTIFICATE_VALIDITY_DURATION_IN_DAYS}`` is an integer that specifies the certificate's validity period in days.
|
||||
|
||||
.. note::
|
||||
|
||||
Consult the image signing script help message (``-h``) for more information about other optional arguments.
|
||||
|
||||
The script is interactive and contains commands that require ``sudo`` level permissions.
|
||||
|
||||
|
||||
The keys, signed kernel image, and unsigned kernel image will be copied to the exisiting ESP image.
|
||||
The modified ESP image can be found at ``${WORKSPACE}/build/tmp/deploy/images/corstone1000-${TARGET}/corstone1000-esp-image-corstone1000-${TARGET}.wic``.
|
||||
|
||||
|
||||
****************************
|
||||
Run Unsigned Image Boot Test
|
||||
****************************
|
||||
@@ -2129,75 +2226,33 @@ For more information about this, see the following resources:
|
||||
- `Authenticated Debug Access Control Specification <https://developer.arm.com/documentation/den0101/latest/>`__
|
||||
- `Arm Corstone-1000 for MPS3 Application Note AN550, Chapter 7 <https://developer.arm.com/documentation/dai0550/latest/>`__
|
||||
|
||||
#. Install `Arm Development Studio <arm-ds-website_>`__ 2026.1, or Arm
|
||||
Development Studio Platinum 2026.b. These releases contain a built-in
|
||||
PSA-ADAC Secure Debug Manager.
|
||||
The Secure Debug Manager API is implemented in the `Secure Debug Manager (PSA-ADAC / SDC-600) <secure-debug-manager-repo-readme_>`__ repository.
|
||||
This repository also contains the necessary files for the Arm Development Studio support.
|
||||
The build and integration instructions can be found in its `README <secure-debug-manager-repo-readme_>`__.
|
||||
|
||||
#. Clone the `Secure Debug Manager
|
||||
<https://github.com/ARM-software/secure-debug-manager>`__
|
||||
repository to obtain the dummy test credentials.
|
||||
The `Secure Debug Manager (PSA-ADAC / SDC-600)` repository also contains the private key and chain certificate to be used during the tests.
|
||||
The private key's public pair is provisioned into the One-Time Programmable memory in TrustedFirmware-M.
|
||||
These are dummy keys that should not be used in production.
|
||||
|
||||
To test the Secure Debug feature, you'll need a debug probe from the `Arm ULINKpro family <arm-ulink-pro-website_>`__
|
||||
and `Arm Development Studio <arm-ds-website_>`__ versions 2022.2, 2022.c, or 2023.a.
|
||||
|
||||
|
||||
#. Clone the `Secure Debug Manager (PSA-ADAC / SDC-600)` repository to your workspace.
|
||||
|
||||
.. code-block:: console
|
||||
|
||||
cd ${WORKSPACE}
|
||||
git clone https://github.com/ARM-software/secure-debug-manager.git
|
||||
|
||||
Only the example private key and certificate chain are needed from this
|
||||
repository.
|
||||
|
||||
The public key corresponding to these credentials is provisioned into the
|
||||
TrustedFirmware-M One-Time Programmable memory. The supplied credentials
|
||||
are test credentials and must not be used in production.
|
||||
|
||||
#. Create a user configuration database based on the Arm Development Studio
|
||||
Corstone-1000 database. The following example assumes that Arm Development
|
||||
Studio Platinum 2026.b is installed in ``/opt/arm``:
|
||||
#. Navigate into the repository directory and checkout the specific commit in the listing below.
|
||||
|
||||
.. code-block:: console
|
||||
|
||||
export ARMDS_INSTALL_DIR=/opt/arm/developmentstudio_platinum-2026.b
|
||||
export CS1000_ADAC_DB=${WORKSPACE}/armds-cs1000-adac611
|
||||
cd ${WORKSPACE}/secure-debug-manager
|
||||
git checkout b30d6496ca749123e86b39b161b9f70ef76106d6
|
||||
|
||||
mkdir -p "${CS1000_ADAC_DB}/Boards/Arm_Development_Boards"
|
||||
cp -a \
|
||||
"${ARMDS_INSTALL_DIR}/sw/debugger/configdb/Boards/Arm Development Boards/MPS3_Corstone_1000" \
|
||||
"${CS1000_ADAC_DB}/Boards/Arm_Development_Boards/MPS3_Corstone_1000_ADAC_611"
|
||||
cp -a "${ARMDS_INSTALL_DIR}/sw/debugger/configdb/Include" "${CS1000_ADAC_DB}/"
|
||||
cp -a "${ARMDS_INSTALL_DIR}/sw/debugger/configdb/Schemas" "${CS1000_ADAC_DB}/"
|
||||
cp -a "${ARMDS_INSTALL_DIR}/sw/debugger/configdb/ATP" "${CS1000_ADAC_DB}/"
|
||||
|
||||
If Arm Development Studio is installed elsewhere, change
|
||||
``ARMDS_INSTALL_DIR`` accordingly.
|
||||
|
||||
#. Enable the built-in PSA-ADAC Secure Debug Manager in the copied database.
|
||||
In
|
||||
``${CS1000_ADAC_DB}/Boards/Arm_Development_Boards/MPS3_Corstone_1000_ADAC_611/project_types.xml``,
|
||||
add the following element alongside the existing ``dtsl_config`` parameter:
|
||||
|
||||
.. code-block:: xml
|
||||
|
||||
<secure_debug_manager type="adac_sdc600" manifest="CDB://../../../ATP/manifest.xml" device="CSAPBCOM" reset_type="nSRST"/>
|
||||
|
||||
This selects the built-in PSA-ADAC implementation, its authentication-token
|
||||
provider, the SDC-600 communication device, and the board reset signal.
|
||||
|
||||
#. Describe the Corstone-1000 debug port as DPv3. In
|
||||
``${CS1000_ADAC_DB}/Boards/Arm_Development_Boards/MPS3_Corstone_1000_ADAC_611/MPS3_Corstone_1000.sdf``,
|
||||
add the following item to the ``<device_info>`` block of the ``ARMCS-DP``
|
||||
device:
|
||||
|
||||
.. code-block:: xml
|
||||
|
||||
<device_info_item name="DP_VERSION">DPv3</device_info_item>
|
||||
|
||||
DPv3 is required so that Arm Development Studio uses the ADIv6 debug-port
|
||||
addressing needed to reach ``CSAPBCOM``.
|
||||
|
||||
In the same file, give the copied platform a unique title:
|
||||
|
||||
.. code-block:: xml
|
||||
|
||||
<platform_info info_url="" manufacturer="Arm" title="MPS3_Corstone_1000_ADAC_611"/>
|
||||
#. Follow the instructions in the `Secure Debug Manager (PSA-ADAC / SDC-600)'s README <secure-debug-manager-repo-readme_>`__ for the development machine setup.
|
||||
|
||||
#. Rebuild the software stack with Secure Debug.
|
||||
|
||||
@@ -2217,60 +2272,11 @@ For more information about this, see the following resources:
|
||||
IComPortInit : 383 : warn : init : IComPortInit: Blocked reading LPH2RA
|
||||
|
||||
|
||||
#. Open a new Arm Development Studio IDE window and add the user configuration
|
||||
database.
|
||||
#. Connect the debug probe to the MPS3 using the 20-pin 1.27mm connector with the ``CS_20W_1.27MM silkscreen`` label.
|
||||
|
||||
#. Select ``Window`` > ``Preferences``.
|
||||
#. Expand ``Arm DS`` and select ``Configuration Database``.
|
||||
#. Select ``Add``.
|
||||
#. Enter a descriptive name, such as ``Corstone-1000 Secure Debug``.
|
||||
The name does not affect the connection.
|
||||
#. Set ``Location`` to ``${WORKSPACE}/armds-cs1000-adac611``.
|
||||
#. Select ``OK`` to close the ``Add configuration database location`` dialog.
|
||||
#. Select ``Rebuild database``.
|
||||
#. Select ``Apply and Close``.
|
||||
#. Create a debug configuration in Arm Development Studio as described in the `Secure Debug Manager (PSA-ADAC / SDC-600)'s README <secure-debug-manager-armds-integration_>`__.
|
||||
|
||||
#. Create the Arm Development Studio hardware connection.
|
||||
|
||||
#. Select ``Create a debug connection...``.
|
||||
#. Select ``Hardware Connection``, then select ``Next``.
|
||||
#. Enter a descriptive debug connection name, then select ``Next``.
|
||||
The name does not affect the connection.
|
||||
#. In ``Target Selection``, select ``MPS3_Corstone_1000_ADAC_611``.
|
||||
#. Select ``Finish``.
|
||||
|
||||
#. Configure one of the following external debug connections.
|
||||
|
||||
To use an external `ULINKpro D <arm-ulink-pro-d-website_>`__ probe:
|
||||
|
||||
#. Connect the ULINKpro D probe to the MPS3 connector labelled
|
||||
``CS_20W_1.27MM``.
|
||||
#. Select ``Arm`` > ``MPS3_Corstone_1000_ADAC_611`` >
|
||||
``Bare Metal Debug`` > ``Cortex-M0+``.
|
||||
#. For ``Target Connection``, select ``ULINKpro D``.
|
||||
#. Select ``Browse...``, select the detected ULINKpro D probe, and then
|
||||
select ``Select``.
|
||||
#. Select ``JTAG/SWJ``, set the debug clock to ``500 kHz``, and select
|
||||
``Connect only``.
|
||||
|
||||
To use an external `DSTREAM <arm-dstream-website_>`__ probe:
|
||||
|
||||
#. Connect the DSTREAM probe to the MPS3 connector labelled
|
||||
``CS_20W_1.27MM``.
|
||||
#. Select ``Arm`` > ``MPS3_Corstone_1000_ADAC_611`` >
|
||||
``Bare Metal Debug`` > ``Cortex-M0+``.
|
||||
#. For ``Target Connection``, select ``DSTREAM``.
|
||||
#. Select ``Browse...``, select the detected DSTREAM probe, and then select
|
||||
``Select``.
|
||||
#. Select ``JTAG/SWJ``, set the debug clock to ``500 kHz``, and select
|
||||
``Connect only``.
|
||||
|
||||
In both cases, use ``Cortex-M0+`` because Secure Debug runs in the Secure
|
||||
Enclave. Do not select the host ``Cortex-A35`` connection.
|
||||
|
||||
#. Select ``Debug``. Arm Development Studio resets the target using ``nSRST``
|
||||
and the built-in Secure Debug Manager communicates with ``CSAPBCOM`` to
|
||||
perform authentication.
|
||||
#. Connect the debuger to the target using the debug configuration.
|
||||
|
||||
#. Provide the paths to the private key and trust chain certificate when asked by Arm Development Studio Console.
|
||||
|
||||
@@ -2279,21 +2285,21 @@ For more information about this, see the following resources:
|
||||
...
|
||||
|
||||
Please provide private key file path:
|
||||
Enter file path > ${WORKSPACE}/secure-debug-manager/example/data/keys/EcdsaP256Key-3.pem
|
||||
Enter file path > ${WORKSPACE}\secure-debug-manager\example\data\keys\EcdsaP256Key-3.pem
|
||||
|
||||
Please provide trust chain file path:
|
||||
Enter file path > ${WORKSPACE}/secure-debug-manager/example/data/chains/chain.EcdsaP256-3
|
||||
Enter file path > ${WORKSPACE}\secure-debug-manager\example\data\chains\chain.EcdsaP256-3
|
||||
|
||||
...
|
||||
|
||||
#. After authentication succeeds, verify that the image continues booting and
|
||||
is not left waiting inside the Secure Debug authentication flow.
|
||||
Authentication alone is not sufficient to pass the test. Confirm that the
|
||||
Host terminal reaches the Linux login prompt:
|
||||
#. When successful authenticated, Arm Development Studio will connect to the running MPS3 and the debug features can be used.
|
||||
The following prompt should appear in the Secure Enclave terminal (``ttyUSB1``):
|
||||
|
||||
.. code-block:: console
|
||||
|
||||
corstone1000-mps3 login:
|
||||
...
|
||||
boot_platform_init: Corstone-1000 Secure Debug is a success.
|
||||
...
|
||||
|
||||
|
||||
--------------
|
||||
@@ -2301,8 +2307,9 @@ For more information about this, see the following resources:
|
||||
*Copyright (c) 2022-2026, Arm Limited. All rights reserved.*
|
||||
|
||||
.. _arm-developer-fvp: https://developer.arm.com/tools-and-software/open-source-software/arm-platforms-software/arm-ecosystem-fvps
|
||||
.. _secure-debug-manager-repo-readme: https://github.com/ARM-software/secure-debug-manager/tree/master?tab=readme-ov-file#secure-debug-manager-psa-adac--sdc-600
|
||||
.. _secure-debug-manager-armds-integration: https://github.com/ARM-software/secure-debug-manager?tab=readme-ov-file#arm-development-studio-integration
|
||||
.. _meta-arm-repository-release-branch: https://docs.yoctoproject.org/next/migration-guides/migration-6.0.html
|
||||
.. _arm-ulink-pro-website: https://www.arm.com/products/development-tools/debug-probes/ulink-pro
|
||||
.. _arm-ds-website: https://www.arm.com/products/development-tools/embedded-and-software/arm-development-studio
|
||||
.. _arm-ulink-pro-d-website: https://www.arm.com/products/development-tools/debug-probes/ulink-pro
|
||||
.. _arm-dstream-website: https://www.arm.com/products/development-tools/debug-probes/dstream-st
|
||||
.. _edk2-repository: https://github.com/tianocore/edk2
|
||||
|
||||
@@ -23,7 +23,7 @@ part --source rawcopy --size 144k --sourceparams="file=trusted-firmware-m/bl2_si
|
||||
part --source rawcopy --size 320k --sourceparams="file=trusted-firmware-m/tfm_s_signed.bin" --align 4 --part-name="tfm_primary" --uuid 07F9616C-1233-439C-ACBA-72D75421BF70 --part-type 7FAD470E-5EC5-5C03-A2C1-4756B495DE61
|
||||
|
||||
# Rawcopy of the FIP binary
|
||||
part --source rawcopy --size 2560k --sourceparams="file=signed_fip.bin" --align 4 --part-name="FIP_A" --uuid B9C7AC9D-40FF-4675-956B-EEF4DE9DF1C5 --part-type F1933675-5A8C-5B6D-9EF4-846739E89BC8
|
||||
part --source rawcopy --size 2 --sourceparams="file=signed_fip.bin" --align 4 --part-name="FIP_A" --uuid B9C7AC9D-40FF-4675-956B-EEF4DE9DF1C5 --part-type F1933675-5A8C-5B6D-9EF4-846739E89BC8
|
||||
|
||||
# Rawcopy of kernel with initramfs
|
||||
part --source rawcopy --size 12 --sourceparams="file=Image.gz-initramfs-${MACHINE}.bin" --align 4 --part-name="kernel_primary" --uuid BF7A6142-0662-47FD-9434-6A8811980816 --part-type F771AFF9-C7E9-5F99-9EDA-2369DD694F61
|
||||
|
||||
@@ -1,3 +1,2 @@
|
||||
arch_timer: Failed to initialize memory-mapped timer.
|
||||
PCI: OF: of_root node is NULL, cannot create PCI host bridge node
|
||||
_OSC: platform retains control of PCIe features (AE_ERROR)
|
||||
|
||||
@@ -1,3 +1,2 @@
|
||||
arch_timer: Failed to initialize memory-mapped timer.
|
||||
PCI: OF: of_root node is NULL, cannot create PCI host bridge node
|
||||
_OSC: platform retains control of PCIe features (AE_ERROR)
|
||||
|
||||
+6
-7
@@ -1,18 +1,17 @@
|
||||
SUMMARY = "External system Cortex-M3 Firmware"
|
||||
DESCRIPTION = "Firmware to be loaded and run in External System Harness in\
|
||||
support to the main application CPU."
|
||||
HOMEPAGE = "https://gitlab.arm.com/arm-reference-solutions/corstone1000/external_system/rtx"
|
||||
HOMEPAGE = "https://git.linaro.org/landing-teams/working/arm/external-system.git"
|
||||
DEPENDS = "gcc-arm-none-eabi-native"
|
||||
INHIBIT_DEFAULT_DEPS = "1"
|
||||
LICENSE = "Apache-2.0 AND BSD-3-Clause"
|
||||
LIC_FILES_CHKSUM = "file://LICENSE;md5=e44b2531cd6ffe9dece394dbe988d9a0 \
|
||||
LICENSE = "BSD-3-Clause & Apache-2.0"
|
||||
LIC_FILES_CHKSUM = "file://license.md;md5=e44b2531cd6ffe9dece394dbe988d9a0 \
|
||||
file://cmsis/LICENSE.txt;md5=e3fc50a88d0a364313df4b21ef20c29e"
|
||||
|
||||
SRC_URI = "gitsm://gitlab.arm.com/arm-reference-solutions/corstone1000/external_system/rtx.git;protocol=https;branch=master \
|
||||
SRC_URI = "gitsm://git.gitlab.arm.com/arm-reference-solutions/corstone1000/external_system/rtx.git;protocol=https;branch=master \
|
||||
file://0001-tools-gen_module_code-atomically-rewrite-the-generat.patch"
|
||||
SRCREV = "3a38cef6e9582907ad6f79950e3d54330c9ab42c"
|
||||
|
||||
UPSTREAM_CHECK_COMMITS = "1"
|
||||
SRCREV = "8c9dca74b104ff6c9722fb0738ba93dd3719c080"
|
||||
PV .= "+git"
|
||||
|
||||
COMPATIBLE_MACHINE = "(corstone1000)"
|
||||
PACKAGE_ARCH = "${MACHINE_ARCH}"
|
||||
@@ -160,10 +160,9 @@ TFA_FIP_BINARY = "fip.bin"
|
||||
TFA_BL2_RE_IMAGE_LOAD_ADDRESS = "0x62353000"
|
||||
TFA_BL2_RE_SIGN_BIN_SIZE = "0x2d000"
|
||||
TFA_FIP_RE_IMAGE_LOAD_ADDRESS = "0x68130000"
|
||||
TFA_FIP_RE_SIGN_BIN_SIZE = "0x00280000"
|
||||
TFA_FIP_RE_SIGN_BIN_SIZE = "0x00200000"
|
||||
RE_LAYOUT_WRAPPER_VERSION = "0.0.7"
|
||||
TFM_SIGN_PRIVATE_KEY = "${libdir}/tfm-scripts/root-EC-P256_1.pem"
|
||||
TFM_IMAGE_SIGN_PSA_KEY_IDS = "2147451244"
|
||||
RE_IMAGE_OFFSET = "0x1000"
|
||||
|
||||
do_sign_images() {
|
||||
|
||||
@@ -11,7 +11,6 @@ SRC_URI:append = " \
|
||||
|
||||
TFA_DEBUG = "1"
|
||||
TFA_UBOOT ?= "1"
|
||||
#FIXME - this can be removed after moving to 2.15.0
|
||||
TFA_MBEDTLS = "1"
|
||||
TFA_BUILD_TARGET = "bl2 bl31 fip"
|
||||
|
||||
|
||||
@@ -55,6 +55,9 @@ TFA_PLATFORM = "fvp"
|
||||
# Disable debug build if measured boot is enabled.
|
||||
TFA_DEBUG := "${@bb.utils.contains('MACHINE_FEATURES', 'ts-attestation', '0',\
|
||||
d.getVar('TFA_DEBUG'), d)}"
|
||||
# Add mbedtls if measured boot is enabled
|
||||
TFA_MBEDTLS := "${@bb.utils.contains('MACHINE_FEATURES', 'ts-attestation',\
|
||||
'1', d.getVar('TFA_MBEDTLS'), d)}"
|
||||
TFA_UBOOT ?= "1"
|
||||
TFA_BUILD_TARGET = "bl1 bl2 bl31 dtbs fip"
|
||||
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
COMPATIBLE_MACHINE = "juno"
|
||||
TFA_PLATFORM = "juno"
|
||||
TFA_DEBUG = "1"
|
||||
TFA_MBEDTLS = "1"
|
||||
TFA_UBOOT ?= "1"
|
||||
TFA_BUILD_TARGET = "bl1 bl2 bl31 dtbs fip"
|
||||
|
||||
|
||||
@@ -27,29 +27,3 @@ SRCREV_tfa = "a4b376b128bb5b91771002f7808566f53c8d9f3a"
|
||||
SRC_URI:remove = "file://0001-feat-build-add-HOSTLDFLAGS-to-pass-flags-to-host-lin.patch"
|
||||
LIC_FILES_CHKSUM:remove = "file://docs/license.rst;md5=6ed7bace7b0bc63021c6eba7b524039e"
|
||||
LIC_FILES_CHKSUM += "file://docs/license.rst;md5=1118e32884721c0be33267bd7ae11130"
|
||||
|
||||
# sub-directory in which mbedtls will be downloaded
|
||||
# Only needed for legacy versions, as v2.15.0 added this as a git submodule
|
||||
TFA_MBEDTLS_DIR ?= "mbedtls"
|
||||
# This should be set to MBEDTLS download URL if MBEDTLS is needed
|
||||
SRC_URI_MBEDTLS ??= ""
|
||||
# This should be set to MBEDTLS LIC FILES checksum
|
||||
LIC_FILES_CHKSUM_MBEDTLS ??= ""
|
||||
# add MBEDTLS to our sources if activated
|
||||
SRC_URI:append = " ${@bb.utils.contains('TFA_MBEDTLS', '1', '${SRC_URI_MBEDTLS}', '', d)}"
|
||||
# Update license variables
|
||||
LICENSE:append = "${@bb.utils.contains('TFA_MBEDTLS', '1', ' AND Apache-2.0', '', d)}"
|
||||
LIC_FILES_CHKSUM:append = "${@bb.utils.contains('TFA_MBEDTLS', '1', ' ${LIC_FILES_CHKSUM_MBEDTLS}', '', d)}"
|
||||
# add mbed TLS to version
|
||||
SRCREV_FORMAT:append = "${@bb.utils.contains('TFA_MBEDTLS', '1', '_mbedtls', '', d)}"
|
||||
|
||||
# Handle MBEDTLS
|
||||
EXTRA_OEMAKE += "${@bb.utils.contains('TFA_MBEDTLS', '1', 'MBEDTLS_DIR=${TFA_MBEDTLS_DIR}', '', d)}"
|
||||
|
||||
# in TF-A src, docs/getting_started/prerequisites.rst lists the expected version mbedtls
|
||||
# mbedtls-3.6.5
|
||||
SRCBRANCH_MBEDTLS = "mbedtls-3.6"
|
||||
SRC_URI_MBEDTLS = "gitsm://github.com/Mbed-TLS/mbedtls;name=mbedtls;protocol=https;destsuffix=${BB_GIT_DEFAULT_DESTSUFFIX}/mbedtls;branch=${SRCBRANCH_MBEDTLS}"
|
||||
SRCREV_mbedtls = "e185d7fd85499c8ce5ca2a54f5cf8fe7dbe3f8df"
|
||||
|
||||
LIC_FILES_CHKSUM_MBEDTLS = "file://mbedtls/LICENSE;md5=379d5819937a6c2f1ef1630d341e026d"
|
||||
|
||||
@@ -27,29 +27,3 @@ SRCREV_tfa = "a4b376b128bb5b91771002f7808566f53c8d9f3a"
|
||||
SRC_URI:remove = "file://0001-feat-build-add-HOSTLDFLAGS-to-pass-flags-to-host-lin.patch"
|
||||
LIC_FILES_CHKSUM:remove = "file://docs/license.rst;md5=6ed7bace7b0bc63021c6eba7b524039e"
|
||||
LIC_FILES_CHKSUM += "file://docs/license.rst;md5=1118e32884721c0be33267bd7ae11130"
|
||||
|
||||
# sub-directory in which mbedtls will be downloaded
|
||||
# Only needed for legacy versions, as v2.15.0 added this as a git submodule
|
||||
TFA_MBEDTLS_DIR ?= "mbedtls"
|
||||
# This should be set to MBEDTLS download URL if MBEDTLS is needed
|
||||
SRC_URI_MBEDTLS ??= ""
|
||||
# This should be set to MBEDTLS LIC FILES checksum
|
||||
LIC_FILES_CHKSUM_MBEDTLS ??= ""
|
||||
# add MBEDTLS to our sources if activated
|
||||
SRC_URI:append = " ${@bb.utils.contains('TFA_MBEDTLS', '1', '${SRC_URI_MBEDTLS}', '', d)}"
|
||||
# Update license variables
|
||||
LICENSE:append = "${@bb.utils.contains('TFA_MBEDTLS', '1', ' AND Apache-2.0', '', d)}"
|
||||
LIC_FILES_CHKSUM:append = "${@bb.utils.contains('TFA_MBEDTLS', '1', ' ${LIC_FILES_CHKSUM_MBEDTLS}', '', d)}"
|
||||
# add mbed TLS to version
|
||||
SRCREV_FORMAT:append = "${@bb.utils.contains('TFA_MBEDTLS', '1', '_mbedtls', '', d)}"
|
||||
|
||||
# Handle MBEDTLS
|
||||
EXTRA_OEMAKE += "${@bb.utils.contains('TFA_MBEDTLS', '1', 'MBEDTLS_DIR=${TFA_MBEDTLS_DIR}', '', d)}"
|
||||
|
||||
# in TF-A src, docs/getting_started/prerequisites.rst lists the expected version mbedtls
|
||||
# mbedtls-3.6.5
|
||||
SRCBRANCH_MBEDTLS = "mbedtls-3.6"
|
||||
SRC_URI_MBEDTLS = "gitsm://github.com/Mbed-TLS/mbedtls;name=mbedtls;protocol=https;destsuffix=${BB_GIT_DEFAULT_DESTSUFFIX}/mbedtls;branch=${SRCBRANCH_MBEDTLS}"
|
||||
SRCREV_mbedtls = "e185d7fd85499c8ce5ca2a54f5cf8fe7dbe3f8df"
|
||||
|
||||
LIC_FILES_CHKSUM_MBEDTLS = "file://mbedtls/LICENSE;md5=379d5819937a6c2f1ef1630d341e026d"
|
||||
|
||||
+25
@@ -0,0 +1,25 @@
|
||||
From f3400c6527e6d0c073215694e19734a6268a6bc9 Mon Sep 17 00:00:00 2001
|
||||
From: Ali Can Ozaslan <ali.oezaslan@arm.com>
|
||||
Date: Wed, 24 Jan 2024 16:10:08 +0000
|
||||
Subject: [PATCH] arm/trusted-firmware-m: disable address warnings into an
|
||||
error
|
||||
|
||||
Signed-off-by: Emekcan Aras <emekcan.aras@arm.com>
|
||||
Signed-off-by: Ali Can Ozaslan <ali.oezaslan@arm.com>
|
||||
Upstream-Status: Inappropriate
|
||||
---
|
||||
toolchain_GNUARM.cmake | 1 +
|
||||
1 file changed, 1 insertion(+)
|
||||
|
||||
diff --git a/toolchain_GNUARM.cmake b/toolchain_GNUARM.cmake
|
||||
index 56a220ba8471..af80a2746676 100644
|
||||
--- a/toolchain_GNUARM.cmake
|
||||
+++ b/toolchain_GNUARM.cmake
|
||||
@@ -113,6 +113,7 @@ add_compile_options(
|
||||
-Wno-format
|
||||
-Wno-return-type
|
||||
-Wno-unused-but-set-variable
|
||||
+ -Wno-error=address
|
||||
-c
|
||||
-fdata-sections
|
||||
-ffunction-sections
|
||||
+449
@@ -0,0 +1,449 @@
|
||||
From 9ed08f26cafc2c6e5bf1d5cc04f91ca17d94a1bd Mon Sep 17 00:00:00 2001
|
||||
From: Harsimran Singh Tungal <harsimransingh.tungal@arm.com>
|
||||
Date: Wed, 13 Aug 2025 14:02:57 +0000
|
||||
Subject: [PATCH] Platform: CS1000: Remove unused BL1 files
|
||||
|
||||
These files are not referenced anywhere so removed them to prevent
|
||||
confusion.
|
||||
|
||||
Signed-off-by: Bence Balogh <bence.balogh@arm.com>
|
||||
Upstream-Status: Backport [9a7bdf9ef595196e1e518a27d3c79079aedb5bda]
|
||||
---
|
||||
.../arm/corstone1000/bl1/CMakeLists.txt | 345 ------------------
|
||||
.../arm/corstone1000/bl1/bl1_security_cnt.c | 75 ----
|
||||
2 files changed, 420 deletions(-)
|
||||
delete mode 100644 platform/ext/target/arm/corstone1000/bl1/CMakeLists.txt
|
||||
delete mode 100644 platform/ext/target/arm/corstone1000/bl1/bl1_security_cnt.c
|
||||
|
||||
diff --git a/platform/ext/target/arm/corstone1000/bl1/CMakeLists.txt b/platform/ext/target/arm/corstone1000/bl1/CMakeLists.txt
|
||||
deleted file mode 100644
|
||||
index d85b0611dd42..000000000000
|
||||
--- a/platform/ext/target/arm/corstone1000/bl1/CMakeLists.txt
|
||||
+++ /dev/null
|
||||
@@ -1,345 +0,0 @@
|
||||
-#-------------------------------------------------------------------------------
|
||||
-# Copyright (c) 2020-2024, Arm Limited. All rights reserved.
|
||||
-#
|
||||
-# SPDX-License-Identifier: BSD-3-Clause
|
||||
-#
|
||||
-#-------------------------------------------------------------------------------
|
||||
-
|
||||
-cmake_minimum_required(VERSION 3.15)
|
||||
-cmake_policy(SET CMP0079 NEW)
|
||||
-
|
||||
-project("BL1 Bootloader" VERSION 0.0.1 LANGUAGES C ASM)
|
||||
-
|
||||
-# BL1 only loads the BL2 image, image number always equals 1
|
||||
-set(BL1_IMAGE_NUMBER 1)
|
||||
-
|
||||
-# Version of BL2 image
|
||||
-set(BL2_IMAGE_VERSION "0.1.0")
|
||||
-
|
||||
-add_executable(bl1)
|
||||
-
|
||||
-set_target_properties(bl1
|
||||
- PROPERTIES
|
||||
- SUFFIX ".axf"
|
||||
- RUNTIME_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/bin"
|
||||
-)
|
||||
-
|
||||
-target_link_options(bl1
|
||||
- PRIVATE
|
||||
- $<$<C_COMPILER_ID:GNU>:-Wl,-Map=${CMAKE_BINARY_DIR}/bin/bl1.map>
|
||||
-)
|
||||
-
|
||||
-add_convert_to_bin_target(bl1)
|
||||
-
|
||||
-# bl2_crypto reused as it is, but it pulls the MCUBOOT_IMAGE_NUMBER=${MCUBOOT_IMAGE_NUMBER}
|
||||
-# configuration, where image number is 3. (Coming from BL2 build). To not to collide with BL1's
|
||||
-# build where image number is 1 mbedcrypto library is separated from the build of other source
|
||||
-# files.
|
||||
-target_link_libraries(bl1
|
||||
- PRIVATE
|
||||
- bl1_main
|
||||
- bl2_crypto
|
||||
- cmsis_stack_override
|
||||
- cmsis
|
||||
-)
|
||||
-
|
||||
-# add_convert_to_bin_target(bl1) requires at least one source file added to bl1. This sources will
|
||||
-# be built with wrong image number macro (value coming from BL2 config), so the start-up files
|
||||
-# added here, as those not use this image number macro.
|
||||
-target_sources(bl1
|
||||
- PRIVATE
|
||||
- $<$<C_COMPILER_ID:GNU>:${CMAKE_CURRENT_SOURCE_DIR}/../Device/Source/startup_corstone1000.c>
|
||||
-)
|
||||
-
|
||||
-# Needed for the GCC startup files
|
||||
-target_include_directories(bl1
|
||||
- PRIVATE
|
||||
- ${CMAKE_SOURCE_DIR}/platform/include
|
||||
- ../Device/Include
|
||||
-)
|
||||
-
|
||||
-# target_add_scatter_file(bl1) cannot be used as it would add the platform_region_defs dependency
|
||||
-# to bl1, again pulling the image number property matching with BL2 build, so scatter setup done
|
||||
-# here by hand.
|
||||
-target_link_options(bl1
|
||||
- PRIVATE
|
||||
- -T $<TARGET_OBJECTS:bl1_scatter>
|
||||
-)
|
||||
-
|
||||
-add_library(bl1_scatter OBJECT)
|
||||
-
|
||||
-add_dependencies(bl1
|
||||
- bl1_scatter
|
||||
- )
|
||||
-
|
||||
-target_sources(bl1_scatter
|
||||
- PRIVATE
|
||||
- ../Device/Source/gcc/corstone1000_bl1.ld
|
||||
-)
|
||||
-
|
||||
-set_source_files_properties(../Device/Source/gcc/corstone1000_bl1.ld
|
||||
- PROPERTIES
|
||||
- LANGUAGE C
|
||||
-)
|
||||
-
|
||||
-target_compile_options(bl1_scatter
|
||||
- PRIVATE
|
||||
- -E
|
||||
- -P
|
||||
- -xc
|
||||
-)
|
||||
-
|
||||
-target_compile_definitions(bl1_scatter
|
||||
- PRIVATE
|
||||
- MCUBOOT_IMAGE_NUMBER=${BL1_IMAGE_NUMBER}
|
||||
- BL1
|
||||
-)
|
||||
-
|
||||
-target_include_directories(bl1_scatter
|
||||
- PRIVATE
|
||||
- ../partition
|
||||
-)
|
||||
-
|
||||
-# Library to spearate build from bl2_mbedcrypto configurations
|
||||
-add_library(bl1_main STATIC)
|
||||
-
|
||||
-target_compile_definitions(bl1_main
|
||||
- PRIVATE
|
||||
- MCUBOOT_IMAGE_NUMBER=${BL1_IMAGE_NUMBER}
|
||||
- BL1
|
||||
- BL2
|
||||
- $<$<BOOL:${PLATFORM_IS_FVP}>:PLATFORM_IS_FVP>
|
||||
-)
|
||||
-
|
||||
-# Configurations based on bl2/CMakeLists.txt
|
||||
-
|
||||
-# Many files are reused form TF-M's bl2 directory
|
||||
-set(BL2_SOURCE ${CMAKE_SOURCE_DIR}/bl2)
|
||||
-
|
||||
-target_sources(bl1_main
|
||||
- PRIVATE
|
||||
- ${BL2_SOURCE}/src/flash_map.c
|
||||
- ./provisioning.c
|
||||
-)
|
||||
-
|
||||
-target_include_directories(bl1_main
|
||||
- PRIVATE
|
||||
- $<BUILD_INTERFACE:${BL2_SOURCE}/include>
|
||||
-)
|
||||
-
|
||||
-# Include path needed for mbedcrypto headers
|
||||
-target_include_directories(bl1_main
|
||||
- PRIVATE
|
||||
- $<BUILD_INTERFACE:${MBEDCRYPTO_PATH}/include>
|
||||
-)
|
||||
-
|
||||
-# Configurations based on bl2/ext/mcuboot/CMakeLists.txt
|
||||
-target_link_libraries(bl1_main
|
||||
- PRIVATE
|
||||
- mcuboot_config
|
||||
- bl2_crypto_config
|
||||
-)
|
||||
-
|
||||
-target_include_directories(bl1_main
|
||||
- PRIVATE
|
||||
- $<BUILD_INTERFACE:${BL2_SOURCE}/ext/mcuboot/include>
|
||||
-)
|
||||
-
|
||||
-target_sources(bl1_main
|
||||
- PRIVATE
|
||||
- ${BL2_SOURCE}/ext/mcuboot/bl2_main.c
|
||||
- ${BL2_SOURCE}/ext/mcuboot/keys.c
|
||||
- ${BL2_SOURCE}/ext/mcuboot/flash_map_legacy.c
|
||||
-)
|
||||
-
|
||||
-# Configurations based on ${MCUBOOT_PATH}/boot/bootutil/CMakeLists.txt
|
||||
-# add_subdirectory("${MCUBOOT_PATH}/boot/bootutil" bootutil) cannot work as we want to define different hal
|
||||
-# functions compared to BL2
|
||||
-target_sources(bl1_main
|
||||
- PRIVATE
|
||||
- ${MCUBOOT_PATH}/boot/bootutil/src/loader.c
|
||||
- ${MCUBOOT_PATH}/boot/bootutil/src/bootutil_misc.c
|
||||
- ${MCUBOOT_PATH}/boot/bootutil/src/bootutil_public.c
|
||||
- ${MCUBOOT_PATH}/boot/bootutil/src/image_validate.c
|
||||
- ${MCUBOOT_PATH}/boot/bootutil/src/image_rsa.c
|
||||
- ${MCUBOOT_PATH}/boot/bootutil/src/tlv.c
|
||||
- ${MCUBOOT_PATH}/boot/bootutil/src/boot_record.c
|
||||
- ${MCUBOOT_PATH}/boot/bootutil/src/swap_scratch.c
|
||||
- ${MCUBOOT_PATH}/boot/bootutil/src/swap_move.c
|
||||
- ${MCUBOOT_PATH}/boot/bootutil/src/swap_misc.c
|
||||
- ${MCUBOOT_PATH}/boot/bootutil/src/encrypted.c
|
||||
- ${MCUBOOT_PATH}/boot/bootutil/src/fault_injection_hardening.c
|
||||
- ${MCUBOOT_PATH}/boot/bootutil/src/fault_injection_hardening_delay_rng_mbedtls.c
|
||||
-)
|
||||
-
|
||||
-target_include_directories(bl1_main
|
||||
- PRIVATE
|
||||
- $<BUILD_INTERFACE:${MCUBOOT_PATH}/boot/bootutil/include>
|
||||
- $<BUILD_INTERFACE:${MCUBOOT_PATH}/boot/bootutil/src>
|
||||
- $<BUILD_INTERFACE:${MCUBOOT_PATH}/boot>
|
||||
-)
|
||||
-
|
||||
-# Configurations based on platform/CMakeLists.txt
|
||||
-target_include_directories(bl1_main
|
||||
- PRIVATE
|
||||
- $<BUILD_INTERFACE:${CMAKE_SOURCE_DIR}/platform/include>
|
||||
- $<BUILD_INTERFACE:${CMAKE_SOURCE_DIR}/platform/ext/driver>
|
||||
- $<BUILD_INTERFACE:${CMAKE_SOURCE_DIR}/platform/ext/common>
|
||||
- $<BUILD_INTERFACE:${CMAKE_SOURCE_DIR}/platform/ext>
|
||||
- $<$<BOOL:${CRYPTO_HW_ACCELERATOR}>:${CMAKE_SOURCE_DIR}/platform/ext/accelerator/interface>
|
||||
-)
|
||||
-
|
||||
-target_sources(bl1_main
|
||||
- PRIVATE
|
||||
- $<$<BOOL:${PLATFORM_DEFAULT_UART_STDOUT}>:${CMAKE_SOURCE_DIR}/platform/ext/common/uart_stdout.c>
|
||||
- $<$<BOOL:${PLATFORM_DEFAULT_NV_COUNTERS}>:${CMAKE_SOURCE_DIR}/platform/ext/common/template/nv_counters.c>
|
||||
- $<$<OR:$<BOOL:${PLATFORM_DEFAULT_NV_COUNTERS}>,$<BOOL:${PLATFORM_DEFAULT_OTP}>>:${CMAKE_SOURCE_DIR}/platform/ext/common/template/flash_otp_nv_counters_backend.c>
|
||||
- $<$<BOOL:${PLATFORM_DEFAULT_OTP}>:${CMAKE_SOURCE_DIR}/platform/ext/common/template/otp_flash.c>
|
||||
-)
|
||||
-
|
||||
-target_link_libraries(bl1_main
|
||||
- PRIVATE
|
||||
- bl2_hal
|
||||
- cmsis
|
||||
-)
|
||||
-
|
||||
-target_compile_definitions(bl1_main
|
||||
- PRIVATE
|
||||
- MCUBOOT_${MCUBOOT_UPGRADE_STRATEGY}
|
||||
- $<$<BOOL:${SYMMETRIC_INITIAL_ATTESTATION}>:SYMMETRIC_INITIAL_ATTESTATION>
|
||||
- $<$<BOOL:${PLATFORM_DEFAULT_NV_COUNTERS}>:PLATFORM_DEFAULT_NV_COUNTERS>
|
||||
- $<$<BOOL:${MCUBOOT_HW_KEY}>:MCUBOOT_HW_KEY>
|
||||
- MCUBOOT_FIH_PROFILE_${MCUBOOT_FIH_PROFILE}
|
||||
- $<$<BOOL:${PLATFORM_DEFAULT_NV_COUNTERS}>:PLATFORM_DEFAULT_NV_COUNTERS>
|
||||
- $<$<BOOL:${PLATFORM_DEFAULT_OTP}>:PLATFORM_DEFAULT_OTP>
|
||||
- $<$<BOOL:${OTP_NV_COUNTERS_RAM_EMULATION}>:OTP_NV_COUNTERS_RAM_EMULATION=1>
|
||||
- $<$<BOOL:${TFM_DUMMY_PROVISIONING}>:TFM_DUMMY_PROVISIONING>
|
||||
- $<$<BOOL:${PLATFORM_DEFAULT_OTP_WRITEABLE}>:OTP_WRITEABLE>
|
||||
-)
|
||||
-
|
||||
-# Configurations based on cc312 cmake files
|
||||
-target_compile_definitions(bl1_main
|
||||
- PRIVATE
|
||||
- $<$<BOOL:${CRYPTO_HW_ACCELERATOR_OTP_STATE}>:CRYPTO_HW_ACCELERATOR_OTP_${CRYPTO_HW_ACCELERATOR_OTP_STATE}>
|
||||
- $<$<BOOL:${CRYPTO_HW_ACCELERATOR}>:CRYPTO_HW_ACCELERATOR>
|
||||
- $<$<BOOL:${ENABLE_FWU_AGENT_DEBUG_LOGS}>:ENABLE_FWU_AGENT_DEBUG_LOGS>
|
||||
-)
|
||||
-
|
||||
-target_include_directories(bl1_main
|
||||
- PRIVATE
|
||||
- $<$<BOOL:${CRYPTO_HW_ACCELERATOR}>:${CMAKE_SOURCE_DIR}/platform/ext/accelerator/cc312>
|
||||
- $<$<BOOL:${CRYPTO_HW_ACCELERATOR}>:${CMAKE_SOURCE_DIR}/lib/ext/cryptocell-312-runtime/shared/include/mbedtls>
|
||||
- $<$<BOOL:${CRYPTO_HW_ACCELERATOR}>:${CMAKE_SOURCE_DIR}/lib/ext/cryptocell-312-runtime/shared/include/crypto_api/cc3x>
|
||||
- ../soft_crc
|
||||
-)
|
||||
-
|
||||
-# Configurations based on platform level cmake files
|
||||
-target_sources(bl1_main
|
||||
- PRIVATE
|
||||
- ../CMSIS_Driver/Driver_Flash.c
|
||||
- ../CMSIS_Driver/Driver_USART.c
|
||||
- ../Device/Source/device_definition.c
|
||||
- ../Device/Source/system_core_init.c
|
||||
- ../Native_Driver/firewall.c
|
||||
- ../Native_Driver/uart_pl011_drv.c
|
||||
- ../fw_update_agent/fwu_agent.c
|
||||
- ../soft_crc/soft_crc.c
|
||||
- ../Native_Driver/arm_watchdog_drv.c
|
||||
- ../Native_Driver/watchdog.c
|
||||
- bl1_boot_hal.c
|
||||
- bl1_flash_map.c
|
||||
- bl1_security_cnt.c
|
||||
- flash_map_extended.c
|
||||
- bl1_rotpk.c
|
||||
-)
|
||||
-
|
||||
-if (PLATFORM_IS_FVP)
|
||||
-target_sources(bl1_main
|
||||
- PRIVATE
|
||||
- ${PLATFORM_DIR}/ext/target/arm/drivers/flash/strata/spi_strataflashj3_flash_lib.c
|
||||
- ${PLATFORM_DIR}/ext/target/arm/drivers/flash/cfi/cfi_drv.c
|
||||
-)
|
||||
-else()
|
||||
-target_sources(bl1_main
|
||||
- PRIVATE
|
||||
- ${PLATFORM_DIR}/ext/target/arm/drivers/qspi/xilinx_pg153_axi/xilinx_pg153_axi_qspi_controller_drv.c
|
||||
- ${PLATFORM_DIR}/ext/target/arm/drivers/flash/n25q256a/spi_n25q256a_flash_lib.c
|
||||
- ${PLATFORM_DIR}/ext/target/arm/drivers/flash/sst26vf064b/spi_sst26vf064b_flash_lib.c
|
||||
-)
|
||||
-endif()
|
||||
-
|
||||
-target_include_directories(bl1_main
|
||||
- PRIVATE
|
||||
- ../partition
|
||||
- ../Device/Include
|
||||
- ../.
|
||||
- ../CMSIS_Driver/Config
|
||||
- ../Device/Config
|
||||
- ../Native_Driver
|
||||
- ../fw_update_agent
|
||||
- ${PLATFORM_DIR}/ext/target/arm/drivers/flash/common
|
||||
- ${PLATFORM_DIR}/ext/target/arm/drivers/flash/cfi
|
||||
- ${PLATFORM_DIR}/ext/target/arm/drivers/flash/strata
|
||||
- ${PLATFORM_DIR}/ext/target/arm/drivers/qspi/xilinx_pg153_axi
|
||||
- ${PLATFORM_DIR}/ext/target/arm/drivers/flash/n25q256a
|
||||
- ${PLATFORM_DIR}/ext/target/arm/drivers/flash/sst26vf064b
|
||||
-
|
||||
-)
|
||||
-
|
||||
-############################### SIGNING BL2 image ##################################
|
||||
-
|
||||
-find_package(Python3)
|
||||
-
|
||||
-set(FLASH_AREA_NUM 8)
|
||||
-configure_file(signing_layout.c.in ${CMAKE_CURRENT_BINARY_DIR}/signing_layout.c @ONLY)
|
||||
-add_library(signing_layout_for_bl2 OBJECT ${CMAKE_CURRENT_BINARY_DIR}/signing_layout.c)
|
||||
-
|
||||
-target_compile_options(signing_layout_for_bl2
|
||||
- PRIVATE
|
||||
- $<$<C_COMPILER_ID:GNU>:-E\;-xc>
|
||||
- $<$<C_COMPILER_ID:ARMClang>:-E\;-xc>
|
||||
- $<$<C_COMPILER_ID:IAR>:--preprocess=ns\;$<TARGET_OBJECTS:signing_layout_s>>
|
||||
-)
|
||||
-target_compile_definitions(signing_layout_for_bl2
|
||||
- PRIVATE
|
||||
- MCUBOOT_IMAGE_NUMBER=${BL1_IMAGE_NUMBER}
|
||||
- BL1
|
||||
-)
|
||||
-
|
||||
-target_include_directories(signing_layout_for_bl2
|
||||
- PRIVATE
|
||||
- ../partition
|
||||
-)
|
||||
-
|
||||
-if (CONFIG_TFM_BOOT_STORE_MEASUREMENTS AND CONFIG_TFM_BOOT_STORE_ENCODED_MEASUREMENTS)
|
||||
- set(MCUBOOT_MEASURED_BOOT ON)
|
||||
-endif()
|
||||
-
|
||||
-add_custom_target(bl2_signed_bin
|
||||
- ALL
|
||||
- SOURCES bl2_signed.bin
|
||||
-)
|
||||
-add_custom_command(OUTPUT bl2_signed.bin
|
||||
- DEPENDS $<TARGET_FILE_DIR:bl2>/bl2.bin
|
||||
- DEPENDS bl2_bin signing_layout_for_bl2
|
||||
- WORKING_DIRECTORY ${MCUBOOT_PATH}/scripts
|
||||
-
|
||||
- #Sign secure binary image with provided secret key
|
||||
- COMMAND ${Python3_EXECUTABLE} ${BL2_SOURCE}/ext/mcuboot/scripts/wrapper/wrapper.py
|
||||
- -v ${BL2_IMAGE_VERSION}
|
||||
- --layout $<TARGET_OBJECTS:signing_layout_for_bl2>
|
||||
- -k ${MCUBOOT_KEY_S}
|
||||
- --public-key-format $<IF:$<BOOL:${MCUBOOT_HW_KEY}>,full,hash>
|
||||
- --align 1
|
||||
- --pad
|
||||
- --pad-header
|
||||
- -H 0x400
|
||||
- -s ${MCUBOOT_SECURITY_COUNTER_S}
|
||||
- -d \"\(0,${MCUBOOT_S_IMAGE_MIN_VER}\)\"
|
||||
- $<$<STREQUAL:${MCUBOOT_UPGRADE_STRATEGY},OVERWRITE_ONLY>:--overwrite-only>
|
||||
- $<$<BOOL:${MCUBOOT_ENC_IMAGES}>:-E${MCUBOOT_KEY_ENC}>
|
||||
- $<$<BOOL:${MCUBOOT_MEASURED_BOOT}>:--measured-boot-record>
|
||||
- $<TARGET_FILE_DIR:bl2>/bl2.bin
|
||||
- ${CMAKE_CURRENT_BINARY_DIR}/bl2_signed.bin
|
||||
- COMMAND ${CMAKE_COMMAND} -E copy ${CMAKE_CURRENT_BINARY_DIR}/bl2_signed.bin $<TARGET_FILE_DIR:bl2>
|
||||
-)
|
||||
diff --git a/platform/ext/target/arm/corstone1000/bl1/bl1_security_cnt.c b/platform/ext/target/arm/corstone1000/bl1/bl1_security_cnt.c
|
||||
deleted file mode 100644
|
||||
index 32c1481cca11..000000000000
|
||||
--- a/platform/ext/target/arm/corstone1000/bl1/bl1_security_cnt.c
|
||||
+++ /dev/null
|
||||
@@ -1,75 +0,0 @@
|
||||
-/*
|
||||
- * Copyright (c) 2019-2021, Arm Limited. All rights reserved.
|
||||
- *
|
||||
- * SPDX-License-Identifier: BSD-3-Clause
|
||||
- *
|
||||
- */
|
||||
-
|
||||
-#include "bootutil/security_cnt.h"
|
||||
-#include "tfm_plat_nv_counters.h"
|
||||
-#include "tfm_plat_defs.h"
|
||||
-#include "bootutil/fault_injection_hardening.h"
|
||||
-#include <stdint.h>
|
||||
-#include "tfm_plat_provisioning.h"
|
||||
-#include "fwu_agent.h"
|
||||
-
|
||||
-fih_ret boot_nv_security_counter_init(void)
|
||||
-{
|
||||
- FIH_DECLARE(fih_rc, FIH_FAILURE);
|
||||
-
|
||||
- fih_rc = fih_ret_encode_zero_equality(tfm_plat_init_nv_counter());
|
||||
-
|
||||
- FIH_RET(fih_rc);
|
||||
-}
|
||||
-
|
||||
-fih_ret boot_nv_security_counter_get(uint32_t image_id, fih_int *security_cnt)
|
||||
-{
|
||||
- FIH_DECLARE(fih_rc, FIH_FAILURE);
|
||||
- uint32_t security_cnt_soft;
|
||||
-
|
||||
- /* Check if it's a null-pointer. */
|
||||
- if (!security_cnt) {
|
||||
- FIH_RET(FIH_FAILURE);
|
||||
- }
|
||||
-
|
||||
- if (image_id != 0) {
|
||||
- FIH_RET(FIH_FAILURE);
|
||||
- }
|
||||
-
|
||||
- fih_rc = fih_ret_encode_zero_equality(
|
||||
- tfm_plat_read_nv_counter(PLAT_NV_COUNTER_BL1_0,
|
||||
- sizeof(security_cnt_soft),
|
||||
- (uint8_t *)&security_cnt_soft));
|
||||
- *security_cnt = fih_int_encode(security_cnt_soft);
|
||||
-
|
||||
- FIH_RET(fih_rc);
|
||||
-}
|
||||
-
|
||||
-int32_t boot_nv_security_counter_update(uint32_t image_id,
|
||||
- uint32_t img_security_cnt)
|
||||
-{
|
||||
- enum tfm_plat_err_t err;
|
||||
- enum fwu_agent_error_t fwu_err;
|
||||
-
|
||||
- if (image_id != 0) {
|
||||
- return -1;
|
||||
- }
|
||||
-
|
||||
- if (tfm_plat_provisioning_is_required()) {
|
||||
-
|
||||
- err = tfm_plat_set_nv_counter(PLAT_NV_COUNTER_BL1_0, img_security_cnt);
|
||||
- if (err != TFM_PLAT_ERR_SUCCESS) {
|
||||
- return -1;
|
||||
- }
|
||||
-
|
||||
- } else {
|
||||
-
|
||||
- fwu_err = fwu_stage_nv_counter(FWU_BL2_NV_COUNTER, img_security_cnt);
|
||||
- if (fwu_err != FWU_AGENT_SUCCESS) {
|
||||
- return -1;
|
||||
- }
|
||||
-
|
||||
- }
|
||||
-
|
||||
- return 0;
|
||||
-}
|
||||
+43
@@ -0,0 +1,43 @@
|
||||
From 1d7ab426f171516c15ce8e5223541c62c91ec596 Mon Sep 17 00:00:00 2001
|
||||
From: Harsimran Singh Tungal <harsimransingh.tungal@arm.com>
|
||||
Date: Wed, 13 Aug 2025 14:31:53 +0000
|
||||
Subject: [PATCH] Platform: Corstone1000: Fix BL1 compiler switch and
|
||||
regression test failure
|
||||
|
||||
Introduce a dedicated preprocessor definition (`BL1_BUILD`) added only to the
|
||||
platform_bl1_1 target. This ensures that #if BL1 checks are evaluated correctly
|
||||
based on the actual build configuration.
|
||||
|
||||
Signed-off-by: Michael Safwat <michael.safwat@arm.com>
|
||||
Signed-off-by: Bence Balogh <bence.balogh@arm.com>
|
||||
Upstream-Status: Backport [f25649cc0de56f360069c6128670f7533ba5e14d]
|
||||
---
|
||||
platform/ext/target/arm/corstone1000/CMakeLists.txt | 8 ++++++++
|
||||
1 file changed, 8 insertions(+)
|
||||
|
||||
diff --git a/platform/ext/target/arm/corstone1000/CMakeLists.txt b/platform/ext/target/arm/corstone1000/CMakeLists.txt
|
||||
index ff7cf7330a07..66dfb2399503 100644
|
||||
--- a/platform/ext/target/arm/corstone1000/CMakeLists.txt
|
||||
+++ b/platform/ext/target/arm/corstone1000/CMakeLists.txt
|
||||
@@ -146,6 +146,7 @@ target_sources(platform_s
|
||||
rse_comms_permissions_hal.c
|
||||
mem_check_v6m_v7m_hal.c
|
||||
${PLATFORM_DIR}/ext/common/mem_check_v6m_v7m.c
|
||||
+ platform.c
|
||||
)
|
||||
|
||||
if (PLATFORM_IS_FVP)
|
||||
@@ -215,6 +216,13 @@ target_compile_definitions(platform_bl1_1
|
||||
$<$<BOOL:${CRYPTO_HW_ACCELERATOR_OTP_PROVISIONING}>:CRYPTO_HW_ACCELERATOR_OTP_PROVISIONING>
|
||||
MBEDTLS_CONFIG_FILE="${CMAKE_SOURCE_DIR}/lib/ext/mbedcrypto/mbedcrypto_config/tfm_mbedcrypto_config_default.h"
|
||||
MBEDTLS_PSA_CRYPTO_CONFIG_FILE="${CMAKE_SOURCE_DIR}/lib/ext/mbedcrypto/mbedcrypto_config/crypto_config_default.h"
|
||||
+
|
||||
+ # This definition is only added to the bl1_main target. There are
|
||||
+ # files that are shared between the BL1 and TFM_S targets. This flag
|
||||
+ # can be used if the BL1 target needs different implementation than
|
||||
+ # the TFM_S target.
|
||||
+ BL1_BUILD
|
||||
+
|
||||
)
|
||||
|
||||
target_include_directories(platform_bl1_1_interface
|
||||
-90
@@ -1,90 +0,0 @@
|
||||
From f0567aa80b2cc88d278c3adb0a5366ae9ff8cf58 Mon Sep 17 00:00:00 2001
|
||||
From: Devaraj Ranganna <devaraj.ranganna@arm.com>
|
||||
Date: Mon, 22 Sep 2025 12:59:43 +0100
|
||||
Subject: [PATCH] bl2: corstone-1000: secure debug waiting in CM LCS
|
||||
|
||||
Currently, when the device is in Secure Enable (SE) LCS state,
|
||||
setting the dcu_en register causes a CC-312 reset. Because CC-312 and
|
||||
the device share a power domain, this effectively resets the device.
|
||||
|
||||
Temporarily perform the secure-debug handshake while the device
|
||||
remains in the CM provisioned state. The long-term solution is to
|
||||
complete the secure-debug handshake, reset the device, and apply
|
||||
dcu_en during BL2.
|
||||
|
||||
Upstream-Status: Inappropriate [Need to be redesigned]
|
||||
Signed-off-by: Devaraj Ranganna <devaraj.ranganna@arm.com>
|
||||
Signed-off-by: Ahmed Gomaa <Ahmed.Gomaa@arm.com>
|
||||
---
|
||||
.../arm/corstone1000/bl2/boot_hal_bl2.c | 46 ++++++++++++-------
|
||||
1 file changed, 30 insertions(+), 16 deletions(-)
|
||||
|
||||
diff --git a/platform/ext/target/arm/corstone1000/bl2/boot_hal_bl2.c b/platform/ext/target/arm/corstone1000/bl2/boot_hal_bl2.c
|
||||
index 9bc0f20e10..d034efe59f 100644
|
||||
--- a/platform/ext/target/arm/corstone1000/bl2/boot_hal_bl2.c
|
||||
+++ b/platform/ext/target/arm/corstone1000/bl2/boot_hal_bl2.c
|
||||
@@ -187,7 +187,7 @@ int32_t boot_platform_post_init(void)
|
||||
int32_t result;
|
||||
enum tfm_plat_err_t plat_err;
|
||||
#ifdef PLATFORM_PSA_ADAC_SECURE_DEBUG
|
||||
- bool provisioning_required;
|
||||
+ /* bool provisioning_required; */
|
||||
#endif
|
||||
|
||||
#ifdef CRYPTO_HW_ACCELERATOR
|
||||
@@ -204,26 +204,40 @@ int32_t boot_platform_post_init(void)
|
||||
}
|
||||
|
||||
#ifdef PLATFORM_PSA_ADAC_SECURE_DEBUG
|
||||
- plat_err = tfm_plat_provisioning_is_required(&provisioning_required);
|
||||
+ /*
|
||||
+ * TODO: Currently, when the device is in Secure Enable (SE) LCS state,
|
||||
+ * setting `dcu_en` register causes CC-312 reset, which effectively resets
|
||||
+ * the device as they are both on the same power domain. Therefore,
|
||||
+ * temporarily perform the secure-debug handshake while the device remains
|
||||
+ * in the CM provisioned state.
|
||||
+ *
|
||||
+ * The long-term solution is to complete the secure-debug handshake, reset
|
||||
+ * the device, and apply `dcu_en` during BL2.
|
||||
+ *
|
||||
+ * TF-M 2.3 splits the provisioning check into an error return and a Boolean
|
||||
+ * output value. Keep the complete gate commented while this workaround is
|
||||
+ * required:
|
||||
+ *
|
||||
+ * plat_err = tfm_plat_provisioning_is_required(&provisioning_required);
|
||||
+ * if (plat_err != TFM_PLAT_ERR_SUCCESS) {
|
||||
+ * BOOT_LOG_ERR("Platform provisioning required check failed");
|
||||
+ * FIH_PANIC;
|
||||
+ * }
|
||||
+ *
|
||||
+ * if (!provisioning_required) {
|
||||
+ */
|
||||
+
|
||||
+ plat_err = tfm_plat_otp_read(SECURE_DEBUG_ROTPK_ID, 32, secure_debug_rotpk);
|
||||
if (plat_err != TFM_PLAT_ERR_SUCCESS) {
|
||||
- BOOT_LOG_ERR("Platform provisioning required check failed");
|
||||
- FIH_PANIC;
|
||||
+ return plat_err;
|
||||
}
|
||||
|
||||
- if (!provisioning_required) {
|
||||
-
|
||||
- plat_err = tfm_plat_otp_read(SECURE_DEBUG_ROTPK_ID, 32, secure_debug_rotpk);
|
||||
- if (plat_err != TFM_PLAT_ERR_SUCCESS) {
|
||||
- return plat_err;
|
||||
- }
|
||||
-
|
||||
#ifndef PSA_ADAC_AS_TFM_RUNTIME_SERVICE
|
||||
- result = tfm_to_psa_adac_corstone1000_secure_debug(secure_debug_rotpk, 32);
|
||||
- BOOT_LOG_INF("%s: Corstone-1000 Secure Debug is a %s.\r\n", __func__,
|
||||
- (result == 0) ? "success" : "failure");
|
||||
+ result = tfm_to_psa_adac_corstone1000_secure_debug(secure_debug_rotpk, 32);
|
||||
+ BOOT_LOG_INF("%s: Corstone-1000 Secure Debug is a %s.\r\n", __func__,
|
||||
+ (result == 0) ? "success" : "failure");
|
||||
#endif /* PSA_ADAC_AS_TFM_RUNTIME_SERVICE */
|
||||
-
|
||||
- }
|
||||
+ /* } */
|
||||
#endif /* PLATFORM_PSA_ADAC_SECURE_DEBUG */
|
||||
|
||||
return 0;
|
||||
-30
@@ -1,30 +0,0 @@
|
||||
From cc48c5782b6968a34fa69047c04f3caf99a3bf18 Mon Sep 17 00:00:00 2001
|
||||
From: Jon Mason <jon.mason@arm.com>
|
||||
Date: Mon, 23 Feb 2026 11:53:38 -0500
|
||||
Subject: [PATCH] Build: fix remaining GCC v14.2 AES type error
|
||||
|
||||
GCC v14.2 diagnoses the incompatible pointer type used when passing
|
||||
the ECB key buffer to bl1_key_to_cc3xx_key(). Cast the uint32_t key
|
||||
buffer to the uint8_t pointer type expected by the helper.
|
||||
|
||||
Upstream-Status: Inappropriate [GCC v14.2 compatibility workaround]
|
||||
|
||||
Signed-off-by: Jon Mason <jon.mason@arm.com>
|
||||
Signed-off-by: Ahmed Gomaa <Ahmed.Gomaa@arm.com>
|
||||
---
|
||||
platform/ext/target/arm/corstone1000/bl1/cc312_rom_crypto.c | 2 +-
|
||||
1 file changed, 1 insertion(+), 1 deletion(-)
|
||||
|
||||
diff --git a/platform/ext/target/arm/corstone1000/bl1/cc312_rom_crypto.c b/platform/ext/target/arm/corstone1000/bl1/cc312_rom_crypto.c
|
||||
index 6bc89fe115..2008e9641b 100644
|
||||
--- a/platform/ext/target/arm/corstone1000/bl1/cc312_rom_crypto.c
|
||||
+++ b/platform/ext/target/arm/corstone1000/bl1/cc312_rom_crypto.c
|
||||
@@ -338,7 +338,7 @@ static int32_t aes_256_ecb_encrypt(enum tfm_bl1_key_id_t key_id,
|
||||
return -1;
|
||||
}
|
||||
|
||||
- rc = bl1_key_to_cc3xx_key(key_id, &cc3xx_key_type, key_buf, sizeof(key_buf));
|
||||
+ rc = bl1_key_to_cc3xx_key(key_id, &cc3xx_key_type, (uint8_t *)key_buf, sizeof(key_buf));
|
||||
if (rc) {
|
||||
return rc;
|
||||
}
|
||||
+33
@@ -0,0 +1,33 @@
|
||||
From fdfbb3b82f62a2d4575a983ebaee14a67130d316 Mon Sep 17 00:00:00 2001
|
||||
From: Ali Can Ozaslan <ali.oezaslan@arm.com>
|
||||
Date: Tue, 15 Oct 2024 12:50:16 +0000
|
||||
Subject: [PATCH] Platform: Corstone1000: Enable FWU partition
|
||||
|
||||
Enable firmware update partition for Corstone-1000 platform.
|
||||
|
||||
Increase the necessary flags to enable firmware update partition.
|
||||
Set TFM_FWU_BOOTLOADER_LIB to use Corstone-1000 specific bootloader
|
||||
configuration. Fix linker issues caused by enablement.
|
||||
|
||||
Upstream-Status: Backport [0107057d1411ec68e374fbd0ddc0e12abd5754ec]
|
||||
Signed-off-by: Ali Can Ozaslan <ali.oezaslan@arm.com>
|
||||
Signed-off-by: Harsimran Singh Tungal <harsimransingh.tungal@arm.com>
|
||||
---
|
||||
platform/ext/target/arm/corstone1000/config.cmake | 4 ++++
|
||||
1 file changed, 4 insertions(+)
|
||||
|
||||
diff --git a/platform/ext/target/arm/corstone1000/config.cmake b/platform/ext/target/arm/corstone1000/config.cmake
|
||||
index 7a88542a32fc..6d9cb1fea750 100644
|
||||
--- a/platform/ext/target/arm/corstone1000/config.cmake
|
||||
+++ b/platform/ext/target/arm/corstone1000/config.cmake
|
||||
@@ -55,6 +55,10 @@ set(TFM_PARTITION_CRYPTO ON CACHE BOOL "Enable Cryp
|
||||
set(TFM_PARTITION_INITIAL_ATTESTATION ON CACHE BOOL "Enable Initial Attestation partition")
|
||||
set(TFM_PARTITION_INTERNAL_TRUSTED_STORAGE ON CACHE BOOL "Enable Internal Trusted Storage partition")
|
||||
|
||||
+set(TFM_PARTITION_FIRMWARE_UPDATE ON CACHE BOOL "Enable firmware update partition")
|
||||
+set(PLATFORM_HAS_FIRMWARE_UPDATE_SUPPORT ON CACHE BOOL "Wheter the platform has firmware update support")
|
||||
+set(MCUBOOT_DATA_SHARING ON CACHE BOOL "Enable Data Sharing")
|
||||
+set(TFM_FWU_BOOTLOADER_LIB "${CMAKE_CURRENT_LIST_DIR}/bootloader/mcuboot" CACHE STRING "Bootloader configure file for Firmware Update partition")
|
||||
|
||||
if (${CMAKE_BUILD_TYPE} STREQUAL Debug OR ${CMAKE_BUILD_TYPE} STREQUAL RelWithDebInfo)
|
||||
set(ENABLE_FWU_AGENT_DEBUG_LOGS TRUE CACHE BOOL "Enable Firmware update agent debug logs.")
|
||||
+5067
File diff suppressed because it is too large
Load Diff
+46
@@ -0,0 +1,46 @@
|
||||
From 78231f27db0bbc747902b603bf279dce1707a3cc Mon Sep 17 00:00:00 2001
|
||||
From: Harsimran Singh Tungal <harsimransingh.tungal@arm.com>
|
||||
Date: Mon, 16 Jun 2025 14:44:39 +0100
|
||||
Subject: [PATCH] Platform: Corstone1000: Increase buffer sizes
|
||||
|
||||
Increase PSA_MAX_ASSET_SIZE and CRYPTO_IOVEC_BUFFER_SIZE
|
||||
to accommodate large size EFI variables set by new U-Boot version.
|
||||
|
||||
This change is required to pass ACS tests related to Set/Get
|
||||
EFI variables. These ACS tests started failing after introducing new
|
||||
version of U-Boot, Trusted-Services and Trusted-Firmware-M while
|
||||
implementing PSA FWU support.
|
||||
|
||||
Upstream-Status: Backport [bd80dee733e792eadfd2115f4bfa6bad748e5ce5]
|
||||
Signed-off-by: Harsimran Singh Tungal <harsimransingh.tungal@arm.com>
|
||||
---
|
||||
platform/ext/target/arm/corstone1000/config_tfm_target.h | 6 +++---
|
||||
1 file changed, 3 insertions(+), 3 deletions(-)
|
||||
|
||||
diff --git a/platform/ext/target/arm/corstone1000/config_tfm_target.h b/platform/ext/target/arm/corstone1000/config_tfm_target.h
|
||||
index 4920f67084d4..cf13712a1806 100644
|
||||
--- a/platform/ext/target/arm/corstone1000/config_tfm_target.h
|
||||
+++ b/platform/ext/target/arm/corstone1000/config_tfm_target.h
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
- * Copyright (c) 2022-2024, Arm Limited. All rights reserved.
|
||||
+ * SPDX-FileCopyrightText: Copyright The TrustedFirmware-M Contributors
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*
|
||||
@@ -27,13 +27,13 @@
|
||||
#define ITS_MAX_ASSET_SIZE 2048
|
||||
|
||||
/* The maximum asset size to be stored in the Protected Storage */
|
||||
-#define PS_MAX_ASSET_SIZE 2592
|
||||
+#define PS_MAX_ASSET_SIZE 3500
|
||||
|
||||
/* This is needed to be able to process the EFI variables during PS writes. */
|
||||
#define CRYPTO_ENGINE_BUF_SIZE 0x5000
|
||||
|
||||
/* This is also has to be increased to fit the EFI variables into the iovecs. */
|
||||
-#define CRYPTO_IOVEC_BUFFER_SIZE 6000
|
||||
+#define CRYPTO_IOVEC_BUFFER_SIZE 7200
|
||||
|
||||
/* The Mailbox partition is used as an NS Agent so its stack size is used to
|
||||
* determine the PSP and PSPLIM during the SFN backend initialization. It has to
|
||||
+31
@@ -0,0 +1,31 @@
|
||||
From 291b717c9ff6124dd132602e84f75f320adbfda1 Mon Sep 17 00:00:00 2001
|
||||
From: Yogesh Wani <yogesh.wani@arm.com>
|
||||
Date: Wed, 30 Apr 2025 14:39:37 +0100
|
||||
Subject: [PATCH] Platform: Corstone1000: Remove duplicate configuration
|
||||
parameters for Corstone-1000
|
||||
|
||||
The PS_NUM_ASSET is duplicated in the cmake.config and the
|
||||
config_tfm_target.h file under Corstone-1000. The commit removes
|
||||
the one from the cmake.config and keeps the one in the header file.
|
||||
|
||||
The whole rationale behind this is for the vendor to be able
|
||||
to override the configuration using the cmake file.
|
||||
|
||||
Upstream-Status: Backport [948cb8e7601dcf1fe822d855c77749287fe6d9bd]
|
||||
Signed-off-by: Yogesh Wani <yogesh.wani@arm.com>
|
||||
---
|
||||
platform/ext/target/arm/corstone1000/config.cmake | 1 -
|
||||
1 file changed, 1 deletion(-)
|
||||
|
||||
diff --git a/platform/ext/target/arm/corstone1000/config.cmake b/platform/ext/target/arm/corstone1000/config.cmake
|
||||
index a923f63ca697..032265cdf4ac 100644
|
||||
--- a/platform/ext/target/arm/corstone1000/config.cmake
|
||||
+++ b/platform/ext/target/arm/corstone1000/config.cmake
|
||||
@@ -74,7 +74,6 @@ endif()
|
||||
# Platform-specific configurations
|
||||
set(CONFIG_TFM_USE_TRUSTZONE OFF)
|
||||
set(TFM_MULTI_CORE_TOPOLOGY ON)
|
||||
-set(PS_NUM_ASSETS "40" CACHE STRING "The maximum number of assets to be stored in the Protected Storage area")
|
||||
|
||||
set(MCUBOOT_USE_PSA_CRYPTO ON CACHE BOOL "Enable the cryptographic abstraction layer to use PSA Crypto APIs")
|
||||
set(MCUBOOT_SIGNATURE_TYPE "EC-P256" CACHE STRING "Algorithm to use for signature validation [RSA-2048, RSA-3072, EC-P256, EC-P384]")
|
||||
+487
@@ -0,0 +1,487 @@
|
||||
From c5bcb737352ad2e1c24cc14a0b8ddf91ad7197b4 Mon Sep 17 00:00:00 2001
|
||||
From: Harsimran Singh Tungal <harsimransingh.tungal@arm.com>
|
||||
Date: Tue, 29 Jul 2025 15:09:45 +0000
|
||||
Subject: [PATCH] plat: corstone1000: Add support for Cortex-A320 variant
|
||||
MIME-Version: 1.0
|
||||
Content-Type: text/plain; charset=UTF-8
|
||||
Content-Transfer-Encoding: 8bit
|
||||
|
||||
Add support for powering on the Cortex-A320 host in the DSU-120T
|
||||
cluster and reserve Host SRAM for the normal world on the
|
||||
Corstone-1000 platform. These changes enable secure-enclave firmware
|
||||
control of the Cortex-A320 power domain and memory access
|
||||
configuration.
|
||||
|
||||
**DSU-120T Power-Policy Unit (PPU) driver**
|
||||
|
||||
* Introduce a minimal driver to program the DSU-120T Power-Policy
|
||||
Units, allowing the secure-enclave firmware to bring the
|
||||
Cortex-A320 host cluster out of reset.
|
||||
* The DSU utility-bus registers are located at:
|
||||
* `0x6091_0000` in the Host memory map.
|
||||
* `0xC091_0000` in the Secure-Enclave memory map.
|
||||
* The FC1 firewall is configured so that only the Secure Enclave may
|
||||
write to this window.
|
||||
* Add new CMake option `CORSTONE1000_DSU_120T` and platform define to
|
||||
enable Cortex-A320 DSU-120T–specific code.
|
||||
|
||||
**Host SRAM allocation**
|
||||
|
||||
* Reserve a 4 MiB block of Host SRAM at `0x0240_0000` for the
|
||||
Cortex-A320 normal world.
|
||||
* Open the same region in the Host-side firewall (CVM, region 2)
|
||||
to allow non-secure access.
|
||||
* This configuration is compiled in when `CORSTONE1000_CORTEX_A320`
|
||||
is defined.
|
||||
|
||||
These updates prepare the Corstone-1000 platform for Cortex-A320
|
||||
integration with proper cluster power management and normal-world
|
||||
memory accessibility.
|
||||
|
||||
Upstream-Status: Submitted (https://review.trustedfirmware.org/c/TF-M/trusted-firmware-m/+/45749)
|
||||
Signed-off-by: Harsimran Singh Tungal <harsimransingh.tungal@arm.com>
|
||||
---
|
||||
.../target/arm/corstone1000/CMakeLists.txt | 31 +++
|
||||
.../Device/Include/platform_base_address.h | 8 +-
|
||||
.../arm/corstone1000/bl1/boot_hal_bl1_1.c | 50 ++++-
|
||||
.../target/arm/corstone1000/dsu-120t/ppu.c | 40 ++++
|
||||
.../target/arm/corstone1000/dsu-120t/ppu.h | 185 ++++++++++++++++++
|
||||
.../arm/corstone1000/tfm_hal_multi_core.c | 28 ++-
|
||||
6 files changed, 339 insertions(+), 3 deletions(-)
|
||||
create mode 100644 platform/ext/target/arm/corstone1000/dsu-120t/ppu.c
|
||||
create mode 100644 platform/ext/target/arm/corstone1000/dsu-120t/ppu.h
|
||||
|
||||
diff --git a/platform/ext/target/arm/corstone1000/CMakeLists.txt b/platform/ext/target/arm/corstone1000/CMakeLists.txt
|
||||
index 91bf197d86b7..993c51591fa7 100644
|
||||
--- a/platform/ext/target/arm/corstone1000/CMakeLists.txt
|
||||
+++ b/platform/ext/target/arm/corstone1000/CMakeLists.txt
|
||||
@@ -423,6 +423,37 @@ target_sources(tfm_spm
|
||||
$<$<BOOL:${TFM_S_REG_TEST}>:${CMAKE_CURRENT_SOURCE_DIR}/target_cfg.c>
|
||||
)
|
||||
|
||||
+#========================= DSU-120T ============================================#
|
||||
+if (CORSTONE1000_DSU_120T)
|
||||
+ target_sources(tfm_psa_rot_partition_ns_agent_mailbox
|
||||
+ PUBLIC
|
||||
+ dsu-120t/ppu.c
|
||||
+ )
|
||||
+
|
||||
+ target_compile_definitions(tfm_psa_rot_partition_ns_agent_mailbox
|
||||
+ PUBLIC
|
||||
+ CORSTONE1000_DSU_120T
|
||||
+ )
|
||||
+
|
||||
+ target_compile_definitions(platform_bl1_1
|
||||
+ PUBLIC
|
||||
+ CORSTONE1000_DSU_120T
|
||||
+ )
|
||||
+
|
||||
+ target_include_directories(tfm_psa_rot_partition_ns_agent_mailbox
|
||||
+ PUBLIC
|
||||
+ dsu-120t
|
||||
+ )
|
||||
+endif()
|
||||
+
|
||||
+#========================= Ethos-U NPU =========================================#
|
||||
+if (CORSTONE1000_CORTEX_A320)
|
||||
+ target_compile_definitions(platform_bl1_1
|
||||
+ PUBLIC
|
||||
+ CORSTONE1000_CORTEX_A320
|
||||
+ )
|
||||
+endif()
|
||||
+
|
||||
#========================= tfm_adac ============================================#
|
||||
|
||||
if (${PLATFORM_PSA_ADAC_SECURE_DEBUG})
|
||||
diff --git a/platform/ext/target/arm/corstone1000/Device/Include/platform_base_address.h b/platform/ext/target/arm/corstone1000/Device/Include/platform_base_address.h
|
||||
index 5f9f03ddc610..3908d69bc9bd 100644
|
||||
--- a/platform/ext/target/arm/corstone1000/Device/Include/platform_base_address.h
|
||||
+++ b/platform/ext/target/arm/corstone1000/Device/Include/platform_base_address.h
|
||||
@@ -1,5 +1,7 @@
|
||||
/*
|
||||
- * Copyright (c) 2017-2024 Arm Limited. All rights reserved.
|
||||
+ * SPDX-FileCopyrightText: Copyright The TrustedFirmware-M Contributors
|
||||
+ *
|
||||
+ * SPDX-License-Identifier: BSD-3-Clause
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -79,6 +81,10 @@
|
||||
#define CORSTONE1000_HOST_AXI_QSPI_CTRL_REG_BASE_SE_SECURE_FLASH (0x90010000U) /* AXI QSPI Controller for SE FLash */
|
||||
#define CORSTONE1000_HOST_DRAM_UEFI_CAPSULE (0xA0000000U) /* 1.5 GB DDR */
|
||||
|
||||
+#ifdef CORSTONE1000_DSU_120T
|
||||
+#define CORSTONE1000_HOST_DSU_120T_BASE (0xC0910000U) /* DSU-120T PPU */
|
||||
+#endif
|
||||
+
|
||||
/* Map Component definitions to Corstone definitions */
|
||||
#define CC3XX_BASE_S CORSTONE1000_CRYPTO_ACCELERATOR_BASE
|
||||
|
||||
diff --git a/platform/ext/target/arm/corstone1000/bl1/boot_hal_bl1_1.c b/platform/ext/target/arm/corstone1000/bl1/boot_hal_bl1_1.c
|
||||
index b51a233e9143..1a5e98ad3c35 100644
|
||||
--- a/platform/ext/target/arm/corstone1000/bl1/boot_hal_bl1_1.c
|
||||
+++ b/platform/ext/target/arm/corstone1000/bl1/boot_hal_bl1_1.c
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
- * Copyright (c) 2019-2024, Arm Limited. All rights reserved.
|
||||
+ * SPDX-FileCopyrightText: Copyright The TrustedFirmware-M Contributors
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*
|
||||
@@ -48,6 +48,15 @@ REGION_DECLARE(Image$$, ARM_LIB_HEAP, $$ZI$$Limit)[];
|
||||
#define HOST_SE_SECURE_FLASH_BASE_FVP 0x60010000
|
||||
#define HOST_AXI_QSPI_CTRL_REG_BASE_SE_SECURE_FLASH 0x60010000
|
||||
|
||||
+#ifdef CORSTONE1000_DSU_120T
|
||||
+#define HOST_DSU_120T_BASE 0x60910000
|
||||
+#endif
|
||||
+
|
||||
+#ifdef CORSTONE1000_CORTEX_A320
|
||||
+#define HOST_SECURE_SRAM_SIZE 0x400000
|
||||
+#define HOST_NONSECURE_SRAM_BASE (HOST_TRUSTED_RAM_BASE + HOST_SECURE_SRAM_SIZE)
|
||||
+#endif
|
||||
+
|
||||
#define HOST_DRAM_BASE 0x80000000
|
||||
#define HOST_DRAM_UEFI_CAPSULE 0x80000000
|
||||
|
||||
@@ -286,6 +295,25 @@ static void setup_se_firewall(void)
|
||||
fc_enable_regions();
|
||||
#endif
|
||||
|
||||
+#ifdef CORSTONE1000_DSU_120T
|
||||
+#if (PLATFORM_IS_FVP)
|
||||
+ fc_select_region(7);
|
||||
+ fc_disable_regions();
|
||||
+ fc_disable_mpe(RGN_MPE0);
|
||||
+ fc_prog_rgn(RGN_SIZE_16MB, CORSTONE1000_HOST_DSU_120T_BASE);
|
||||
+ fc_prog_rgn_upper_addr(HOST_DSU_120T_BASE);
|
||||
+ fc_enable_addr_trans();
|
||||
+ fc_init_mpl(RGN_MPE0);
|
||||
+
|
||||
+ mpl_rights = (RGN_MPL_SECURE_READ_MASK |
|
||||
+ RGN_MPL_SECURE_WRITE_MASK);
|
||||
+
|
||||
+ fc_enable_mpl(RGN_MPE0, mpl_rights);
|
||||
+ fc_prog_mid(RGN_MPE0, SE_MID);
|
||||
+ fc_enable_mpe(RGN_MPE0);
|
||||
+ fc_enable_regions();
|
||||
+#endif
|
||||
+#endif
|
||||
fc_pe_enable();
|
||||
}
|
||||
|
||||
@@ -369,6 +397,26 @@ static void setup_host_firewall(void)
|
||||
fc_enable_regions();
|
||||
fc_rgn_lock();
|
||||
|
||||
+#ifdef CORSTONE1000_CORTEX_A320
|
||||
+ /* CVM - Non Secure RAM */
|
||||
+ fc_select_region(2);
|
||||
+ fc_disable_regions();
|
||||
+ fc_disable_mpe(RGN_MPE0);
|
||||
+ fc_prog_rgn(RGN_SIZE_4MB, HOST_NONSECURE_SRAM_BASE);
|
||||
+ fc_init_mpl(RGN_MPE0);
|
||||
+
|
||||
+ mpl_rights = (RGN_MPL_ANY_MST_MASK | RGN_MPL_NONSECURE_READ_MASK |
|
||||
+ RGN_MPL_NONSECURE_WRITE_MASK |
|
||||
+ RGN_MPL_NONSECURE_EXECUTE_MASK);
|
||||
+
|
||||
+ fc_enable_mpl(RGN_MPE0, mpl_rights);
|
||||
+ fc_disable_mpl(RGN_MPE0, ~mpl_rights);
|
||||
+
|
||||
+ fc_enable_mpe(RGN_MPE0);
|
||||
+ fc_enable_regions();
|
||||
+ fc_rgn_lock();
|
||||
+#endif
|
||||
+
|
||||
fc_pe_enable();
|
||||
|
||||
/* DDR */
|
||||
diff --git a/platform/ext/target/arm/corstone1000/dsu-120t/ppu.c b/platform/ext/target/arm/corstone1000/dsu-120t/ppu.c
|
||||
new file mode 100644
|
||||
index 000000000000..d6be5982a8dd
|
||||
--- /dev/null
|
||||
+++ b/platform/ext/target/arm/corstone1000/dsu-120t/ppu.c
|
||||
@@ -0,0 +1,40 @@
|
||||
+/*
|
||||
+ * SPDX-FileCopyrightText: Copyright The TrustedFirmware-M Contributors
|
||||
+ *
|
||||
+ * SPDX-License-Identifier: BSD-3-Clause
|
||||
+ *
|
||||
+ */
|
||||
+
|
||||
+#include <stdint.h>
|
||||
+#include "ppu.h"
|
||||
+
|
||||
+void PPU_SetPowerPolicy(PPU_TypeDef *ppu, PPU_PowerPolicy_Type policy, bool isDynamic)
|
||||
+{
|
||||
+ uint32_t regval = ppu->PWPR;
|
||||
+
|
||||
+ regval &= ~(PPU_PWPR_PWR_POLICY_Msk | PPU_PWPR_PWR_DYN_EN_Msk);
|
||||
+
|
||||
+ regval |= ((policy << PPU_PWPR_PWR_POLICY_Pos) & PPU_PWPR_PWR_POLICY_Msk);
|
||||
+
|
||||
+ if (isDynamic) {
|
||||
+ regval |= PPU_PWPR_PWR_DYN_EN_Msk;
|
||||
+ }
|
||||
+
|
||||
+ ppu->PWPR = regval;
|
||||
+}
|
||||
+
|
||||
+void PPU_SetOperatingPolicy(PPU_TypeDef *ppu, PPU_OperatingPolicy_Type policy, bool isDynamic)
|
||||
+{
|
||||
+ uint32_t regval = ppu->PWPR;
|
||||
+
|
||||
+ regval &= ~(PPU_PWPR_OP_POLICY_Msk | PPU_PWPR_OP_DYN_EN_Msk);
|
||||
+
|
||||
+ regval |= ((policy << PPU_PWPR_OP_POLICY_Pos) & PPU_PWPR_OP_POLICY_Msk);
|
||||
+
|
||||
+ if (isDynamic) {
|
||||
+ regval |= PPU_PWPR_OP_DYN_EN_Msk;
|
||||
+ }
|
||||
+
|
||||
+ ppu->PWPR = regval;
|
||||
+}
|
||||
+
|
||||
diff --git a/platform/ext/target/arm/corstone1000/dsu-120t/ppu.h b/platform/ext/target/arm/corstone1000/dsu-120t/ppu.h
|
||||
new file mode 100644
|
||||
index 000000000000..05470df9a884
|
||||
--- /dev/null
|
||||
+++ b/platform/ext/target/arm/corstone1000/dsu-120t/ppu.h
|
||||
@@ -0,0 +1,185 @@
|
||||
+/*
|
||||
+ * SPDX-FileCopyrightText: Copyright The TrustedFirmware-M Contributors
|
||||
+ *
|
||||
+ * SPDX-License-Identifier: BSD-3-Clause
|
||||
+ *
|
||||
+ */
|
||||
+#ifndef PPU_H
|
||||
+#define PPU_H
|
||||
+
|
||||
+#include <stdbool.h>
|
||||
+#include <stdint.h>
|
||||
+#include "platform_base_address.h"
|
||||
+
|
||||
+// Bit definition for PPU_PWPR register
|
||||
+#define PPU_PWPR_PWR_POLICY_Pos (0U) // Power mode policy
|
||||
+#define PPU_PWPR_PWR_POLICY_Msk (0xFUL << PPU_PWPR_PWR_POLICY_Pos) // 4 bits
|
||||
+#define PPU_PWPR_PWR_POLICY_OFF (0UL << PPU_PWPR_PWR_POLICY_Pos) // Logic off and RAM off.
|
||||
+#define PPU_PWPR_PWR_POLICY_OFF_EMU (1UL << PPU_PWPR_PWR_POLICY_Pos) // Emulated Off. Logic on with RAM on. This mode is used to emulate the functional condition of OFF without removing
|
||||
+#define PPU_PWPR_PWR_POLICY_MEM_RET (2UL << PPU_PWPR_PWR_POLICY_Pos) // Memory Retention. Logic off with RAM retained.
|
||||
+#define PPU_PWPR_PWR_POLICY_MEM_RET_EMU (3UL << PPU_PWPR_PWR_POLICY_Pos) // Emulated Memory Retention. Logic on with RAM on. This mode is used to emulate the functional condition of
|
||||
+#define PPU_PWPR_PWR_POLICY_FULL_RET (5UL << PPU_PWPR_PWR_POLICY_Pos) // Full Retention. Slice logic off with RAM contents retained.
|
||||
+#define PPU_PWPR_PWR_POLICY_FUNC_RET (7UL << PPU_PWPR_PWR_POLICY_Pos) // Functional Retention. Logic on with L3 Cache and Snoop Filter retained.
|
||||
+#define PPU_PWPR_PWR_POLICY_ON (8UL << PPU_PWPR_PWR_POLICY_Pos) // Logic on with RAM on, cluster is functional.
|
||||
+#define PPU_PWPR_PWR_POLICY_WARM_RST (9UL << PPU_PWPR_PWR_POLICY_Pos) // Warm Reset. Warm reset application with logic and RAM on.
|
||||
+#define PPU_PWPR_PWR_POLICY_DBG_RECOV (10UL << PPU_PWPR_PWR_POLICY_Pos) // Debug Recovery Reset. Warm reset application with logic and RAM on.
|
||||
+#define PPU_PWPR_PWR_DYN_EN_Pos (8U) // Power mode dynamic transition enable.
|
||||
+#define PPU_PWPR_PWR_DYN_EN_Msk (0x1UL << PPU_PWPR_PWR_DYN_EN_Pos) // 1 bit
|
||||
+#define PPU_PWPR_LOCK_EN_Pos (12U) // Lock enable bit for OFF, OFF_EMU, MEM_RET and MEM_RET_EMU power modes.
|
||||
+#define PPU_PWPR_LOCK_EN_Msk (0x1UL << PPU_PWPR_LOCK_EN_Pos) // 1 bit
|
||||
+#define PPU_PWPR_OP_POLICY_Pos (16U) // Operating mode policy
|
||||
+#define PPU_PWPR_OP_POLICY_Msk (0xFUL << PPU_PWPR_OP_POLICY_Pos) // 4 bits
|
||||
+#define PPU_PWPR_OP_POLICY_OPMODE_00 (0UL << PPU_PWPR_OP_POLICY_Pos) // ONE_SLICE_SF_ONLY_ON: One L3 Cache slice is operational, the Cache RAM is powered down.
|
||||
+#define PPU_PWPR_OP_POLICY_OPMODE_01 (1UL << PPU_PWPR_OP_POLICY_Pos) // ONE_SLICE_HALF_RAM_ON: One L3 Cache slice is operational, half of the Cache RAMs are powered on.
|
||||
+#define PPU_PWPR_OP_POLICY_OPMODE_03 (3UL << PPU_PWPR_OP_POLICY_Pos) // ONE_SLICE_FULL_RAM_ON: One L3 Cache slice is operational, all of the Cache RAMs are powered on.
|
||||
+#define PPU_PWPR_OP_POLICY_OPMODE_04 (4UL << PPU_PWPR_OP_POLICY_Pos) // ALL_SLICE_SF_ONLY_ON: All L3 Cache slices are operational, the Cache RAMs in each slice are powered down.
|
||||
+#define PPU_PWPR_OP_POLICY_OPMODE_05 (5UL << PPU_PWPR_OP_POLICY_Pos) // ALL_SLICE_HALF_RAM_ON: All L3 Cache slices are operational, half of the Cache RAMs are powered on.
|
||||
+#define PPU_PWPR_OP_POLICY_OPMODE_07 (7UL << PPU_PWPR_OP_POLICY_Pos) // ALL_SLICE_FULL_RAM_ON: All L3 Cache slices are operational, all of the Cache RAMs are powered on.
|
||||
+#define PPU_PWPR_OP_POLICY_OPMODE_08 (8UL << PPU_PWPR_OP_POLICY_Pos) // HALF_SLICE_SF_ONLY_ON: Half L3 Cache slices are operational, the Cache RAMs in each slice are powered down.
|
||||
+#define PPU_PWPR_OP_POLICY_OPMODE_09 (9UL << PPU_PWPR_OP_POLICY_Pos) // HALF_SLICE_HALF_RAM_ON: Half L3 Cache slices are operational, half of the Cache RAMs are powered on.
|
||||
+#define PPU_PWPR_OP_POLICY_OPMODE_0B (11UL << PPU_PWPR_PWR_POLICY_Pos) // HALF_SLICE_FULL_RAM_ON: Half L3 Cache slices are operational, all of the Cache RAMs are powered on.
|
||||
+#define PPU_PWPR_OP_DYN_EN_Pos (24U) // Operating mode dynamic transition enable.
|
||||
+#define PPU_PWPR_OP_DYN_EN_Msk (0x1UL << PPU_PWPR_OP_DYN_EN_Pos) // 1 bit
|
||||
+
|
||||
+// Bit definition for PPU_PWSR register
|
||||
+#define PPU_PWSR_PWR_STATUS_Pos (0U)
|
||||
+#define PPU_PWSR_PWR_STATUS_Msk (0xFUL << PPU_PWSR_PWR_STATUS_Pos) // 4 bits
|
||||
+#define PPU_PWSR_PWR_STATUS_OFF (0UL << PPU_PWSR_PWR_STATUS_Pos) // Logic off and RAM off.
|
||||
+#define PPU_PWSR_PWR_STATUS_OFF_EMU (1UL << PPU_PWSR_PWR_STATUS_Pos) // Emulated Off. Logic on with RAM on. This mode is used to emulate the functional condition of OFF without removing
|
||||
+#define PPU_PWSR_PWR_STATUS_MEM_RET (2UL << PPU_PWSR_PWR_STATUS_Pos) // Memory Retention. Logic off with RAM retained.
|
||||
+#define PPU_PWSR_PWR_STATUS_MEM_RET_EMU (3UL << PPU_PWSR_PWR_STATUS_Pos) // Emulated Memory Retention. Logic on with RAM on. This mode is used to emulate the functional condition of
|
||||
+#define PPU_PWSR_PWR_STATUS_FULL_RET (5UL << PPU_PWSR_PWR_STATUS_Pos) // Full Retention. Slice logic off with RAM contents retained.
|
||||
+#define PPU_PWSR_PWR_STATUS_FUNC_RET (7UL << PPU_PWSR_PWR_STATUS_Pos) // Functional Retention. Logic on with L3 Cache and Snoop Filter retained.
|
||||
+#define PPU_PWSR_PWR_STATUS_ON (8UL << PPU_PWSR_PWR_STATUS_Pos) // Logic on with RAM on, cluster is functional.
|
||||
+#define PPU_PWSR_PWR_STATUS_WARM_RST (9UL << PPU_PWSR_PWR_STATUS_Pos) // Warm Reset. Warm reset application with logic and RAM on.
|
||||
+#define PPU_PWSR_PWR_STATUS_DBG_RECOV (10UL << PPU_PWSR_PWR_STATUS_Pos) // Debug Recovery Reset. Warm reset application with logic and RAM on.
|
||||
+#define PPU_PWSR_PWR_DYN_STATUS_Pos (8U) // Power mode dynamic transition enable.
|
||||
+#define PPU_PWSR_PWR_DYN_STATUS_Msk (0x1UL << PPU_PWSR_PWR_DYN_STATUS_Pos) // 1 bit
|
||||
+#define PPU_PWSR_LOCK_STATUS_Pos (12U) // Lock enable bit for OFF, OFF_EMU, MEM_RET and MEM_RET_EMU power modes.
|
||||
+#define PPU_PWSR_LOCK_STATUS_Msk (0x1UL << PPU_PWSR_LOCK_STATUS_Pos) // 1 bit
|
||||
+#define PPU_PWSR_OP_STATUS_Pos (16U) // Operating mode policy
|
||||
+#define PPU_PWSR_OP_STATUS_Msk (0xFUL << PPU_PWSR_OP_STATUS_Pos) // 4 bits
|
||||
+#define PPU_PWSR_OP_STATUS_OPMODE_00 (0UL << PPU_PWSR_OP_STATUS_Pos) // ONE_SLICE_SF_ONLY_ON: One L3 Cache slice is operational, only the snoop filter RAM instances are active in the slice
|
||||
+#define PPU_PWSR_OP_STATUS_OPMODE_01 (1UL << PPU_PWSR_OP_STATUS_Pos) // ONE_SLICE_HALF_RAM_ON: One L3 Cache slice is operational, half of the Cache RAMs are powered on.
|
||||
+#define PPU_PWSR_OP_STATUS_OPMODE_03 (3UL << PPU_PWSR_OP_STATUS_Pos) // ONE_SLICE_FULL_RAM_ON: One L3 Cache slice is operational, all of the Cache RAMs are powered on.
|
||||
+#define PPU_PWSR_OP_STATUS_OPMODE_04 (4UL << PPU_PWSR_OP_STATUS_Pos) // ALL_SLICE_SF_ONLY_ON: All L3 Cache slices are operational, the Cache RAMs in each slice are powered down.
|
||||
+#define PPU_PWSR_OP_STATUS_OPMODE_05 (5UL << PPU_PWSR_OP_STATUS_Pos) // ALL_SLICE_HALF_RAM_ON: All L3 Cache slices are operational, half of the Cache RAMs are powered on.
|
||||
+#define PPU_PWSR_OP_STATUS_OPMODE_07 (7UL << PPU_PWSR_OP_STATUS_Pos) // ALL_SLICE_FULL_RAM_ON: All L3 Cache slices are operational, all of the Cache RAMs are powered on.
|
||||
+#define PPU_PWSR_OP_STATUS_OPMODE_08 (8UL << PPU_PWSR_OP_STATUS_Pos) // HALF_SLICE_SF_ONLY_ON: Half L3 Cache slices are operational, the Cache RAMs in each slice are powered down.
|
||||
+#define PPU_PWSR_OP_STATUS_OPMODE_09 (9UL << PPU_PWSR_OP_STATUS_Pos) // HALF_SLICE_HALF_RAM_ON: Half L3 Cache slices are operational, half of the Cache RAMs are powered on.
|
||||
+#define PPU_PWSR_OP_STATUS_OPMODE_0B (11UL << PPU_PWSR_OP_STATUS_Pos) // HALF_SLICE_FULL_RAM_ON: Half L3 Cache slices are operational, all of the Cache RAMs are powered on.
|
||||
+#define PPU_PWSR_OP_DYN_STATUS_Pos (24U) // Operating mode dynamic transition enable.
|
||||
+#define PPU_PWSR_OP_DYN_STATUS_Msk (0x1UL << PPU_PWSR_OP_DYN_STATUS_Pos) // 1 bit
|
||||
+
|
||||
+/*!< PPU memory offsets */
|
||||
+#define DSU_120T_CLUSTER_PPU_OFFSET 0x030000
|
||||
+#define DSU_120T_CORE0_PPU_OFFSET 0x080000
|
||||
+#define DSU_120T_CORE1_PPU_OFFSET 0x180000
|
||||
+#define DSU_120T_CORE2_PPU_OFFSET 0x280000
|
||||
+#define DSU_120T_CORE3_PPU_OFFSET 0x380000
|
||||
+
|
||||
+/*!< PPU memory map */
|
||||
+#define CLUSTER_PPU_BASE (CORSTONE1000_HOST_DSU_120T_BASE + DSU_120T_CLUSTER_PPU_OFFSET)
|
||||
+#define CORE0_PPU_BASE (CORSTONE1000_HOST_DSU_120T_BASE + DSU_120T_CORE0_PPU_OFFSET)
|
||||
+#define CORE1_PPU_BASE (CORSTONE1000_HOST_DSU_120T_BASE + DSU_120T_CORE1_PPU_OFFSET)
|
||||
+#define CORE2_PPU_BASE (CORSTONE1000_HOST_DSU_120T_BASE + DSU_120T_CORE2_PPU_OFFSET)
|
||||
+#define CORE3_PPU_BASE (CORSTONE1000_HOST_DSU_120T_BASE + DSU_120T_CORE3_PPU_OFFSET)
|
||||
+
|
||||
+/*!< PPU declarations */
|
||||
+#define CLUSTER_PPU ((PPU_TypeDef *) CLUSTER_PPU_BASE)
|
||||
+#define CORE0_PPU ((PPU_TypeDef *) CORE0_PPU_BASE)
|
||||
+#define CORE1_PPU ((PPU_TypeDef *) CORE1_PPU_BASE)
|
||||
+#define CORE2_PPU ((PPU_TypeDef *) CORE2_PPU_BASE)
|
||||
+#define CORE3_PPU ((PPU_TypeDef *) CORE3_PPU_BASE)
|
||||
+
|
||||
+typedef struct
|
||||
+{
|
||||
+ volatile uint32_t PWPR; /*!< PPU Power Policy Register, Address offset: 0x00 */
|
||||
+ volatile uint32_t PMER; /*!< PPU Power Mode Emulation Enable Register, Address offset: 0x04 */
|
||||
+ volatile uint32_t PWSR; /*!< PPU Power Status Register, Address offset: 0x08 */
|
||||
+ volatile uint32_t RESERVED0; /*!< Reserved, Address offset: 0x0C */
|
||||
+ volatile uint32_t DISR; /*!< PPU Device Interface Input Current Status Register, Address offset: 0x10 */
|
||||
+ volatile uint32_t MISR; /*!< PPU Miscellaneous Input Current Status Register, Address offset: 0x14 */
|
||||
+ volatile uint32_t STSR; /*!< PPU Stored Status Register, Address offset: 0x18 */
|
||||
+ volatile uint32_t UNLK; /*!< PPU Unlock Register, Address offset: 0x1C */
|
||||
+ volatile uint32_t PWCR; /*!< PPU Power Configuration Register, Address offset: 0x20 */
|
||||
+ volatile uint32_t PTCR; /*!< PPU Power Mode Transition Register, Address offsets: 0x24 */
|
||||
+ volatile uint32_t RESERVED1[2]; /*!< Reserved: Address offsets 0x28 - 0x2C */
|
||||
+ volatile uint32_t IMR; /*!< PPU Interrupt Mask Register, Address offsets: 0x30 */
|
||||
+ volatile uint32_t AIMR; /*!< PPU Additional Interrupt Mask Register, Address offsets: 0x34 */
|
||||
+ volatile uint32_t ISR; /*!< PPU Interrupt Status Register, Address offsets: 0x38 */
|
||||
+ volatile uint32_t AISR; /*!< PPU Additional Interrupt Status Register, Address offsets: 0x3C */
|
||||
+ volatile uint32_t IESR; /*!< PPU Input Edge Sensitivity Register Address offsets: 0x040 */
|
||||
+ volatile uint32_t OPSR; /*!< PPU Operating Mode Active Edge Sensitivity Register Address offsets: 0x044 */
|
||||
+ volatile uint32_t RESERVED2[2]; /*!< Reserved: Address offsets 0x48 - 0x4C */
|
||||
+ volatile uint32_t FUNRR; /*!< Functional Retention RAM Configuration Register Address offsets: 0x050 */
|
||||
+ volatile uint32_t FULRR; /*!< Full Retention RAM Configuration Register Address offsets: 0x054 */
|
||||
+ volatile uint32_t MEMRR; /*!< Memory Retention RAM Configuration Register Address offsets: 0x058 */
|
||||
+ volatile uint32_t RESERVED3[69]; /*!< Reserved: Address offsets 0x5C - 0x16C */
|
||||
+ volatile uint32_t DCDR0; /*!< Device Control Delay Configuration Register 0 Address offsets: 0x170 */
|
||||
+ volatile uint32_t DCDR1; /*!< Device Control Delay Configuration Register 1 Address offsets: 0x174 */
|
||||
+ volatile uint32_t RESERVED4[910]; /*!< Reserved, offsets 0x178 - 0xFAC */
|
||||
+ volatile uint32_t IDR0; /*!< PPU Identification Register 0, Address offsets: 0xFB0 */
|
||||
+ volatile uint32_t IDR1; /*!< PPU Identification Register 1, Address offsets: 0xFB4 */
|
||||
+ volatile uint32_t RESERVED5[4]; /*!< Reserved, offsets 0xFB8 - 0xFC4 */
|
||||
+ volatile uint32_t IIDR; /*!< PPU Implementation Identification Register, Address offsets: 0xFC8 */
|
||||
+ volatile uint32_t AIDR; /*!< PPU Architecture Identification Register, Address offsets: 0xFCC */
|
||||
+ volatile uint32_t PIDR4; /*!< PPU Peripheral Identification Register 4, Address offsets: 0xFD0 */
|
||||
+ volatile uint32_t PIDR5; /*!< PPU Peripheral Identification Register 5, Address offsets: 0xFD4 */
|
||||
+ volatile uint32_t PIDR6; /*!< PPU Peripheral Identification Register 6, Address offsets: 0xFD8 */
|
||||
+ volatile uint32_t PIDR7; /*!< PPU Peripheral Identification Register 7, Address offsets: 0xFDC */
|
||||
+ volatile uint32_t PIDR0; /*!< PPU Peripheral Identification Register 0, Address offsets: 0xFE0 */
|
||||
+ volatile uint32_t PIDR1; /*!< PPU Peripheral Identification Register 1, Address offsets: 0xFE4 */
|
||||
+ volatile uint32_t PIDR2; /*!< PPU Peripheral Identification Register 2, Address offsets: 0xFE8 */
|
||||
+ volatile uint32_t PIDR3; /*!< PPU Peripheral Identification Register 3, Address offsets: 0xFEC */
|
||||
+ volatile uint32_t CIDR0; /*!< PPU Component Identification Register 0, Address offsets: 0xFF0 */
|
||||
+ volatile uint32_t CIDR1; /*!< PPU Component Identification Register 1, Address offsets: 0xFF4 */
|
||||
+ volatile uint32_t CIDR2; /*!< PPU Component Identification Register 2, Address offsets: 0xFF8 */
|
||||
+ volatile uint32_t CIDR3; /*!< PPU Component Identification Register 3, Address offsets: 0xFFC */
|
||||
+} PPU_TypeDef;
|
||||
+
|
||||
+typedef enum {
|
||||
+ PPU_PWR_MODE_OFF = 0, // Logic off and RAM off.
|
||||
+ PPU_PWR_MODE_OFF_EMU = 1, // Emulated Off. Logic on with RAM on. This mode is used to emulate the functional condition of OFF without removing
|
||||
+ PPU_PWR_MODE_MEM_RET = 2, // Memory Retention. Logic off with RAM retained.
|
||||
+ PPU_PWR_MODE_MEM_RET_EMU = 3, // Emulated Memory Retention. Logic on with RAM on. This mode is used to emulate the functional condition of
|
||||
+ PPU_PWR_MODE_FULL_RET = 5, // Full Retention. Slice logic off with RAM contents retained.
|
||||
+ PPU_PWR_MODE_FUNC_RET = 7, // Functional Retention. Logic on with L3 Cache and Snoop Filter retained.
|
||||
+ PPU_PWR_MODE_ON = 8, // Logic on with RAM on, cluster is functional.
|
||||
+ PPU_PWR_MODE_WARM_RST = 9, // Warm Reset. Warm reset application with logic and RAM on.
|
||||
+ PPU_PWR_MODE_DBG_RECOV = 10 // Debug Recovery Reset. Warm reset application with logic and RAM on.
|
||||
+} PPU_PowerPolicy_Type;
|
||||
+
|
||||
+typedef enum {
|
||||
+ PPU_OP_MODE_ONE_SLICE_SF_ONLY_ON = 0, // One L3 Cache slice is operational, only the snoop filter RAM instances are active in the slice
|
||||
+ PPU_OP_MODE_ONE_SLICE_HALF_RAM_ON = 1, // One L3 Cache slice is operational, half of the Cache RAMs are powered on.
|
||||
+ PPU_OP_MODE_ONE_SLICE_FULL_RAM_ON = 3, // One L3 Cache slice is operational, all of the Cache RAMs are powered on.
|
||||
+ PPU_OP_MODE_ALL_SLICE_SF_ONLY_ON = 4, // All L3 Cache slices are operational, the Cache RAMs in each slice are powered down.
|
||||
+ PPU_OP_MODE_ALL_SLICE_HALF_RAM_ON = 5, // All L3 Cache slices are operational, half of the Cache RAMs are powered on.
|
||||
+ PPU_OP_MODE_ALL_SLICE_FULL_RAM_ON = 7, // All L3 Cache slices are operational, all of the Cache RAMs are powered on.
|
||||
+ PPU_OP_MODE_HALF_SLICE_SF_ONLY_ON = 8, // Half L3 Cache slices are operational, the Cache RAMs in each slice are powered down.
|
||||
+ PPU_OP_MODE_HALF_SLICE_HALF_RAM_ON = 9, // Half L3 Cache slices are operational, half of the Cache RAMs are powered on.
|
||||
+ PPU_OP_MODE_HALF_SLICE_FULL_RAM_ON = 11 // Half L3 Cache slices are operational, all of the Cache RAMs are powered on.
|
||||
+} PPU_OperatingPolicy_Type;
|
||||
+
|
||||
+/**
|
||||
+ * @brief Set the power policy for a given PPU instance.
|
||||
+ * Only modifies PWR_POLICY and PWR_DYN_EN bits.
|
||||
+ * @param ppu: Pointer to the PPU instance (e.g., CLUSTER_PPU, CORE0_PPU1)
|
||||
+ * @param policy: Power mode policy (e.g., PPU_PWR_MODE_ON)
|
||||
+ * @param dynamic: Enable dynamic transitions enabled for power modes, allowing transitions to be initiated by changes on power mode DEVACTIVE inputs if non-zero
|
||||
+ * @retval None
|
||||
+ */
|
||||
+void PPU_SetPowerPolicy(PPU_TypeDef *ppu, PPU_PowerPolicy_Type policy, bool isDynamic);
|
||||
+
|
||||
+/**
|
||||
+ * @brief Set the operating mode policy for a given PPU instance.
|
||||
+* Only modifies OP_POLICY and OP_DYN_EN bits.
|
||||
+ * @param ppu: Pointer to the PPU instance (e.g., CLUSTER_PPU, CORE0_PPU)
|
||||
+ * @param policy: Operating mode policy (e.g., PPU_OP_MODE_ONE_SLICE_SF_ONLY_ON)
|
||||
+ * @param dynamic: Enable dynamic transitions enabled for operating modes, allowing transitions to be initiated by changes on operating mode DEVACTIVE inputs if non-zero
|
||||
+ * @retval None
|
||||
+ */
|
||||
+void PPU_SetOperatingPolicy(PPU_TypeDef *ppu, PPU_OperatingPolicy_Type policy, bool isDynamic);
|
||||
+
|
||||
+#endif /* PPU_H */
|
||||
diff --git a/platform/ext/target/arm/corstone1000/tfm_hal_multi_core.c b/platform/ext/target/arm/corstone1000/tfm_hal_multi_core.c
|
||||
index d0c6b8d590f9..10c66ac41ad2 100644
|
||||
--- a/platform/ext/target/arm/corstone1000/tfm_hal_multi_core.c
|
||||
+++ b/platform/ext/target/arm/corstone1000/tfm_hal_multi_core.c
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
- * Copyright (c) 2018-2024 Arm Limited. All rights reserved.
|
||||
+ * SPDX-FileCopyrightText: Copyright The TrustedFirmware-M Contributors
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*
|
||||
@@ -11,6 +11,10 @@
|
||||
#include "tfm_hal_multi_core.h"
|
||||
#include "fwu_agent.h"
|
||||
|
||||
+#ifdef CORSTONE1000_DSU_120T
|
||||
+#include "ppu.h"
|
||||
+#endif
|
||||
+
|
||||
#define HOST_SYS_RST_CTRL_OFFSET 0x000
|
||||
#define HOST_CPU_PE0_CONFIG_OFFSET 0x010
|
||||
#define HOST_CPU_PE1_CONFIG_OFFSET 0x020
|
||||
@@ -98,6 +102,28 @@ void tfm_hal_boot_ns_cpu(uintptr_t start_addr)
|
||||
|
||||
(void) start_addr;
|
||||
|
||||
+#ifdef CORSTONE1000_DSU_120T
|
||||
+ /* Power on DSU-120T cluster */
|
||||
+ PPU_SetOperatingPolicy(CLUSTER_PPU, PPU_OP_MODE_ONE_SLICE_SF_ONLY_ON, false);
|
||||
+ PPU_SetPowerPolicy(CLUSTER_PPU, PPU_PWR_MODE_ON, false);
|
||||
+
|
||||
+ /* Power on Cortex-A320 core0 in DSU-120T Cluster */
|
||||
+ PPU_SetOperatingPolicy(CORE0_PPU, PPU_OP_MODE_ONE_SLICE_SF_ONLY_ON, false);
|
||||
+ PPU_SetPowerPolicy(CORE0_PPU, PPU_PWR_MODE_ON, false);
|
||||
+
|
||||
+#if CORSTONE1000_FVP_MULTICORE
|
||||
+ /* Power on all Cortex-A320 cores in DSU-120T Cluster */
|
||||
+ PPU_SetOperatingPolicy(CORE1_PPU, PPU_OP_MODE_ONE_SLICE_SF_ONLY_ON, false);
|
||||
+ PPU_SetPowerPolicy(CORE1_PPU, PPU_PWR_MODE_ON, false);
|
||||
+
|
||||
+ PPU_SetOperatingPolicy(CORE2_PPU, PPU_OP_MODE_ONE_SLICE_SF_ONLY_ON, false);
|
||||
+ PPU_SetPowerPolicy(CORE2_PPU, PPU_PWR_MODE_ON, false);
|
||||
+
|
||||
+ PPU_SetOperatingPolicy(CORE3_PPU, PPU_OP_MODE_ONE_SLICE_SF_ONLY_ON, false);
|
||||
+ PPU_SetPowerPolicy(CORE3_PPU, PPU_PWR_MODE_ON, false);
|
||||
+#endif
|
||||
+#endif
|
||||
+
|
||||
#ifdef EXTERNAL_SYSTEM_SUPPORT
|
||||
/*release EXT SYS out of reset*/
|
||||
tfm_external_system_boot();
|
||||
+48
@@ -0,0 +1,48 @@
|
||||
From 3a9e209596ca0ae5850ae382c624adf9932b16b4 Mon Sep 17 00:00:00 2001
|
||||
From: Devaraj Ranganna <devaraj.ranganna@arm.com>
|
||||
Date: Mon, 22 Sep 2025 12:48:57 +0100
|
||||
Subject: [PATCH] bl2: corstone-1000: Remove
|
||||
`psa_adac_to_tfm_apply_permissions`
|
||||
|
||||
The API `psa_adac_to_tfm_apply_permissions` is added to `psa-adac`
|
||||
library. Therefore, remove it from
|
||||
`platform/ext/target/arm/corstone1000/bl2/boot_hal_bl2.c`.
|
||||
|
||||
Upstream-Status: Pending [Not submitted to upstream yet]
|
||||
Signed-off-by: Devaraj Ranganna <devaraj.ranganna@arm.com>
|
||||
---
|
||||
.../arm/corstone1000/bl2/boot_hal_bl2.c | 21 -------------------
|
||||
1 file changed, 21 deletions(-)
|
||||
|
||||
diff --git a/platform/ext/target/arm/corstone1000/bl2/boot_hal_bl2.c b/platform/ext/target/arm/corstone1000/bl2/boot_hal_bl2.c
|
||||
index 2abcfb5fd39d..8c4eb80d032c 100644
|
||||
--- a/platform/ext/target/arm/corstone1000/bl2/boot_hal_bl2.c
|
||||
+++ b/platform/ext/target/arm/corstone1000/bl2/boot_hal_bl2.c
|
||||
@@ -111,27 +111,6 @@ static bool fill_flash_map_with_fip_data(uint8_t boot_index) {
|
||||
#endif /* !TFM_S_REG_TEST */
|
||||
|
||||
#ifdef PLATFORM_PSA_ADAC_SECURE_DEBUG
|
||||
-int psa_adac_to_tfm_apply_permissions(uint8_t permissions_mask[16])
|
||||
-{
|
||||
- (void)permissions_mask;
|
||||
-
|
||||
- int ret;
|
||||
- uint32_t dcu_reg_values[4];
|
||||
-
|
||||
- /* Below values provide same access as when platform is in development
|
||||
- life cycle state */
|
||||
- dcu_reg_values[0] = 0xffffe7fc;
|
||||
- dcu_reg_values[1] = 0x800703ff;
|
||||
- dcu_reg_values[2] = 0xffffffff;
|
||||
- dcu_reg_values[3] = 0xffffffff;
|
||||
-
|
||||
- ret = crypto_hw_apply_debug_permissions((uint8_t*)dcu_reg_values, 16);
|
||||
- BOOT_LOG_INF("%s: debug permission apply %s\n\r", __func__,
|
||||
- (ret == 0) ? "success" : "fail");
|
||||
-
|
||||
- return ret;
|
||||
-}
|
||||
-
|
||||
uint8_t secure_debug_rotpk[32];
|
||||
#endif /* PLATFORM_PSA_ADAC_SECURE_DEBUG */
|
||||
|
||||
+53
@@ -0,0 +1,53 @@
|
||||
From 901a63f09369cfbed8eff8c450b8615bd4c361af Mon Sep 17 00:00:00 2001
|
||||
From: Devaraj Ranganna <devaraj.ranganna@arm.com>
|
||||
Date: Mon, 22 Sep 2025 12:59:43 +0100
|
||||
Subject: [PATCH] bl2: corstone-1000: secure debug waiting in CM LCS
|
||||
|
||||
Currently, when the device is in Secure Enable (SE) LCS state, setting
|
||||
`dcu_en` register causes CC-312 reset, which effectively resets the
|
||||
device as they are both on same power domain. Therefore, temporarily
|
||||
disable moving SE enable before waiting for secure debug notification.
|
||||
The device will be in CM provisioned state.
|
||||
|
||||
Long-term solution is to implement a solution similar to RSE, secure
|
||||
debug handshake is completed and then a reset is triggered and `dcu_en`
|
||||
is applied during bl2.
|
||||
|
||||
Upstream-Status: Inappropriate [Need to be redesigned]
|
||||
Signed-off-by: Devaraj Ranganna <devaraj.ranganna@arm.com>
|
||||
---
|
||||
.../ext/target/arm/corstone1000/bl2/boot_hal_bl2.c | 13 ++++++++++++-
|
||||
1 file changed, 12 insertions(+), 1 deletion(-)
|
||||
|
||||
diff --git a/platform/ext/target/arm/corstone1000/bl2/boot_hal_bl2.c b/platform/ext/target/arm/corstone1000/bl2/boot_hal_bl2.c
|
||||
index 8c4eb80d032c..bf7b62881ad5 100644
|
||||
--- a/platform/ext/target/arm/corstone1000/bl2/boot_hal_bl2.c
|
||||
+++ b/platform/ext/target/arm/corstone1000/bl2/boot_hal_bl2.c
|
||||
@@ -165,7 +165,18 @@ int32_t boot_platform_post_init(void)
|
||||
}
|
||||
|
||||
#ifdef PLATFORM_PSA_ADAC_SECURE_DEBUG
|
||||
+ /* TODO: Currently, when the device is in Secure Enable (SE) LCS state,
|
||||
+ setting `dcu_en` register causes CC-312 reset, which effectively resets
|
||||
+ the device as they are both on same power domain. Therefore, temporarily
|
||||
+ disable moving SE enable before waiting for secure debug notification.
|
||||
+ The device will be in CM provisioned state.
|
||||
+
|
||||
+ Long-term solution is to implement a solution similar to RSE, secure
|
||||
+ debug handshake is completed and then a reset is triggered and `dcu_en`
|
||||
+ is applied during bl2.
|
||||
+
|
||||
if (!tfm_plat_provisioning_is_required()) {
|
||||
+ */
|
||||
|
||||
plat_err = tfm_plat_otp_read(PLAT_OTP_ID_SECURE_DEBUG_PK, 32, secure_debug_rotpk);
|
||||
if (plat_err != TFM_PLAT_ERR_SUCCESS) {
|
||||
@@ -176,7 +187,7 @@ int32_t boot_platform_post_init(void)
|
||||
BOOT_LOG_INF("%s: Corstone-1000 Secure Debug is a %s.\r\n", __func__,
|
||||
(result == 0) ? "success" : "failure");
|
||||
|
||||
- }
|
||||
+ /*}*/
|
||||
#endif
|
||||
|
||||
return 0;
|
||||
+147
@@ -0,0 +1,147 @@
|
||||
From 14fff6df016dad1d76f1eda6f77dde1890836c3c Mon Sep 17 00:00:00 2001
|
||||
From: Anton Komlev <anton.komlev@arm.com>
|
||||
Date: Thu, 11 Sep 2025 17:16:43 +0100
|
||||
Subject: [PATCH] Build: adjust CS1000 platform for GCC v14.2
|
||||
MIME-Version: 1.0
|
||||
Content-Type: text/plain; charset=UTF-8
|
||||
Content-Transfer-Encoding: 8bit
|
||||
|
||||
The latest GNUARM toolchain is more strict, converting some warnings
|
||||
into errors. This change:
|
||||
- adds missing function prototypes and header files
|
||||
- explicitly typecasts incompatible types in secure side
|
||||
- prevents integer–pointer conversion errors in
|
||||
`tfm_test_suite_extra_s` CMake targets because a number of type
|
||||
mismatch is too high.
|
||||
|
||||
Signed-off-by: Anton Komlev <anton.komlev@arm.com>
|
||||
Change-Id: Ia803ebd5ceeab03ab7c7afc7c79c4e5836e03b26
|
||||
|
||||
Upstream-Status: Backport [05c174df157eac428a3e87a1c40170ed7a74af57]
|
||||
Signed-off-by: Jon Mason <jon.mason@arm.com>
|
||||
---
|
||||
.../ext/target/arm/corstone1000/bl1/boot_hal_bl1_2.c | 1 +
|
||||
.../corstone1000/ci_regression_tests/CMakeLists.txt | 2 ++
|
||||
platform/ext/target/arm/corstone1000/io/io_block.c | 1 +
|
||||
platform/ext/target/arm/corstone1000/io/io_flash.c | 10 +++++-----
|
||||
platform/ext/target/arm/corstone1000/platform.c | 8 ++++----
|
||||
.../target/arm/corstone1000/rse_comms/rse_comms_hal.h | 2 ++
|
||||
6 files changed, 15 insertions(+), 9 deletions(-)
|
||||
|
||||
diff --git a/platform/ext/target/arm/corstone1000/bl1/boot_hal_bl1_2.c b/platform/ext/target/arm/corstone1000/bl1/boot_hal_bl1_2.c
|
||||
index 8d85d2b2c9b8..b81e14e03aa9 100644
|
||||
--- a/platform/ext/target/arm/corstone1000/bl1/boot_hal_bl1_2.c
|
||||
+++ b/platform/ext/target/arm/corstone1000/bl1/boot_hal_bl1_2.c
|
||||
@@ -21,6 +21,7 @@
|
||||
#include "uart_stdout.h"
|
||||
#include "region_defs.h"
|
||||
#include "tfm_log.h"
|
||||
+#include "cc3xx_init.h"
|
||||
|
||||
#ifdef CRYPTO_HW_ACCELERATOR
|
||||
#include "cc3xx_dev.h"
|
||||
diff --git a/platform/ext/target/arm/corstone1000/ci_regression_tests/CMakeLists.txt b/platform/ext/target/arm/corstone1000/ci_regression_tests/CMakeLists.txt
|
||||
index 405b2b370237..3b023c813e02 100644
|
||||
--- a/platform/ext/target/arm/corstone1000/ci_regression_tests/CMakeLists.txt
|
||||
+++ b/platform/ext/target/arm/corstone1000/ci_regression_tests/CMakeLists.txt
|
||||
@@ -44,3 +44,5 @@ target_compile_definitions(tfm_test_suite_extra_s
|
||||
TEST_FLASH_PAGE_SIZE=${TEST_FLASH_PAGE_SIZE}
|
||||
TEST_FLASH_PROGRAM_UNIT=${TEST_FLASH_PROGRAM_UNIT}
|
||||
)
|
||||
+
|
||||
+target_compile_options(tfm_test_suite_extra_s PRIVATE -Wno-int-conversion)
|
||||
diff --git a/platform/ext/target/arm/corstone1000/io/io_block.c b/platform/ext/target/arm/corstone1000/io/io_block.c
|
||||
index f7eaf7444c38..a5c021ac5a18 100644
|
||||
--- a/platform/ext/target/arm/corstone1000/io/io_block.c
|
||||
+++ b/platform/ext/target/arm/corstone1000/io/io_block.c
|
||||
@@ -20,6 +20,7 @@
|
||||
|
||||
#include <assert.h>
|
||||
#include <errno.h>
|
||||
+#include <string.h>
|
||||
|
||||
#include "io_defs.h"
|
||||
#include "io_driver.h"
|
||||
diff --git a/platform/ext/target/arm/corstone1000/io/io_flash.c b/platform/ext/target/arm/corstone1000/io/io_flash.c
|
||||
index ff4524e9c575..b90a81a48d82 100644
|
||||
--- a/platform/ext/target/arm/corstone1000/io/io_flash.c
|
||||
+++ b/platform/ext/target/arm/corstone1000/io/io_flash.c
|
||||
@@ -71,7 +71,7 @@ static size_t flash_read(int lba, uintptr_t buf, size_t size, size_t flash_id) {
|
||||
size_t rem = info->sector_count * info->sector_size - offset;
|
||||
size_t cnt = size < rem ? size : rem;
|
||||
|
||||
- return flash_driver->ReadData(offset, buf, cnt);
|
||||
+ return flash_driver->ReadData(offset, (void *)buf, cnt);
|
||||
}
|
||||
|
||||
static size_t flash_write(int lba, const uintptr_t buf, size_t size,
|
||||
@@ -86,7 +86,7 @@ static size_t flash_write(int lba, const uintptr_t buf, size_t size,
|
||||
size_t cnt = size < rem ? size : rem;
|
||||
|
||||
flash_driver->EraseSector(offset);
|
||||
- rc = flash_driver->ProgramData(offset, buf, cnt);
|
||||
+ rc = flash_driver->ProgramData(offset, (const void *)buf, cnt);
|
||||
return rc;
|
||||
}
|
||||
|
||||
@@ -143,8 +143,8 @@ static int flash_dev_open(const uintptr_t dev_spec, io_dev_info_t **dev_info) {
|
||||
/* Check if Flash ops functions are defined for this flash */
|
||||
assert(flashs_ops[index].read && flashs_ops[index].write);
|
||||
|
||||
- flash_dev_specs[index] = dev_spec;
|
||||
- flash_driver = flash_dev_specs[index]->flash_driver;
|
||||
+ flash_dev_specs[index] = (io_flash_dev_spec_t *)dev_spec;
|
||||
+ flash_driver = (const ARM_DRIVER_FLASH *)flash_dev_specs[index]->flash_driver;
|
||||
|
||||
block_dev_spec[index].block_size = flash_driver->GetInfo()->sector_size;
|
||||
block_dev_spec[index].buffer.offset = flash_dev_specs[index]->buffer;
|
||||
@@ -153,7 +153,7 @@ static int flash_dev_open(const uintptr_t dev_spec, io_dev_info_t **dev_info) {
|
||||
|
||||
flash_driver->Initialize(NULL);
|
||||
|
||||
- block_dev_connectors[index].dev_open(&block_dev_spec[index], dev_info);
|
||||
+ block_dev_connectors[index].dev_open((uintptr_t)&block_dev_spec[index], dev_info);
|
||||
|
||||
return 0;
|
||||
}
|
||||
diff --git a/platform/ext/target/arm/corstone1000/platform.c b/platform/ext/target/arm/corstone1000/platform.c
|
||||
index c686b403ff10..d0f30b72a76d 100644
|
||||
--- a/platform/ext/target/arm/corstone1000/platform.c
|
||||
+++ b/platform/ext/target/arm/corstone1000/platform.c
|
||||
@@ -29,10 +29,10 @@ extern ARM_DRIVER_FLASH FLASH_DEV_NAME;
|
||||
static io_dev_connector_t *flash_dev_con;
|
||||
static uint8_t local_block_flash[FLASH_SECTOR_SIZE];
|
||||
static io_flash_dev_spec_t flash_dev_spec = {
|
||||
- .buffer = local_block_flash,
|
||||
+ .buffer = (uintptr_t)local_block_flash,
|
||||
.bufferlen = FLASH_SECTOR_SIZE,
|
||||
.base_addr = FLASH_BASE_ADDRESS,
|
||||
- .flash_driver = &FLASH_DEV_NAME,
|
||||
+ .flash_driver = (uintptr_t)&FLASH_DEV_NAME,
|
||||
};
|
||||
static io_block_spec_t flash_spec = {
|
||||
.offset = FLASH_BASE_ADDRESS,
|
||||
@@ -41,8 +41,8 @@ static io_block_spec_t flash_spec = {
|
||||
|
||||
static platform_image_source_t platform_image_source[] = {
|
||||
[PLATFORM_GPT_IMAGE] = {
|
||||
- .dev_handle = NULL,
|
||||
- .image_spec = &flash_spec,
|
||||
+ .dev_handle = (uintptr_t)NULL,
|
||||
+ .image_spec = (uintptr_t)&flash_spec,
|
||||
}
|
||||
};
|
||||
|
||||
diff --git a/platform/ext/target/arm/corstone1000/rse_comms/rse_comms_hal.h b/platform/ext/target/arm/corstone1000/rse_comms/rse_comms_hal.h
|
||||
index c4676cb2ef74..29be08ddb36e 100644
|
||||
--- a/platform/ext/target/arm/corstone1000/rse_comms/rse_comms_hal.h
|
||||
+++ b/platform/ext/target/arm/corstone1000/rse_comms/rse_comms_hal.h
|
||||
@@ -49,6 +49,8 @@ enum tfm_plat_err_t tfm_multi_core_hal_receive(void *mhu_receiver_dev,
|
||||
*/
|
||||
enum tfm_plat_err_t tfm_multi_core_hal_reply(struct client_request_t *req);
|
||||
|
||||
+int32_t tfm_hal_client_id_translate(void *owner, int32_t client_id_in);
|
||||
+
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
+48
@@ -0,0 +1,48 @@
|
||||
From 949ecbcd29660225f42bdfc37bdff4b79917620a Mon Sep 17 00:00:00 2001
|
||||
From: Jon Mason <jon.mason@arm.com>
|
||||
Date: Mon, 23 Feb 2026 11:53:38 -0500
|
||||
Subject: [PATCH] Workaround compile errors in AES
|
||||
|
||||
TF-M commit d7c4850d8ce3abeb2634e85631b4bbadeb343f23 removes support for
|
||||
bl1_aes_256_ctr_decrypt() API. Since backporting that is more involved
|
||||
than we want for this release. Simply do some casting to address the
|
||||
issues until the next release (which will have the commit referenced
|
||||
previously).
|
||||
|
||||
Upstream-Status: Inappropriate
|
||||
Signed-off-by: Jon Mason <jon.mason@arm.com>
|
||||
---
|
||||
platform/ext/target/arm/corstone1000/bl1/cc312_rom_crypto.c | 6 +++---
|
||||
1 file changed, 3 insertions(+), 3 deletions(-)
|
||||
|
||||
diff --git a/platform/ext/target/arm/corstone1000/bl1/cc312_rom_crypto.c b/platform/ext/target/arm/corstone1000/bl1/cc312_rom_crypto.c
|
||||
index 542fc01bc7a8..5b34d90464eb 100644
|
||||
--- a/platform/ext/target/arm/corstone1000/bl1/cc312_rom_crypto.c
|
||||
+++ b/platform/ext/target/arm/corstone1000/bl1/cc312_rom_crypto.c
|
||||
@@ -328,7 +328,7 @@ fih_int bl1_aes_256_ctr_decrypt(enum tfm_bl1_key_id_t key_id,
|
||||
uint32_t key_buf[32 / sizeof(uint32_t)];
|
||||
fih_int fih_rc;
|
||||
int32_t rc = 0;
|
||||
- const uint8_t *input_key = key_buf;
|
||||
+ const uint8_t *input_key = (const uint8_t *)key_buf;
|
||||
cc3xx_err_t err;
|
||||
|
||||
if (ciphertext_length == 0) {
|
||||
@@ -356,7 +356,7 @@ fih_int bl1_aes_256_ctr_decrypt(enum tfm_bl1_key_id_t key_id,
|
||||
}
|
||||
|
||||
err = cc3xx_lowlevel_aes_init(CC3XX_AES_DIRECTION_DECRYPT, CC3XX_AES_MODE_CTR,
|
||||
- cc3xx_key_type, input_key, CC3XX_AES_KEYSIZE_256,
|
||||
+ cc3xx_key_type, (const uint32_t *)input_key, CC3XX_AES_KEYSIZE_256,
|
||||
(uint32_t *)counter, 16);
|
||||
fih_rc = fih_int_encode_zero_equality(err);
|
||||
if (fih_not_eq(fih_rc, FIH_SUCCESS)) {
|
||||
@@ -388,7 +388,7 @@ static int32_t aes_256_ecb_encrypt(enum tfm_bl1_key_id_t key_id,
|
||||
return -1;
|
||||
}
|
||||
|
||||
- rc = bl1_key_to_cc3xx_key(key_id, &cc3xx_key_type, key_buf, sizeof(key_buf));
|
||||
+ rc = bl1_key_to_cc3xx_key(key_id, &cc3xx_key_type, (uint8_t *)key_buf, sizeof(key_buf));
|
||||
if (rc) {
|
||||
return rc;
|
||||
}
|
||||
+41
@@ -0,0 +1,41 @@
|
||||
From 3d2bdf81fee8832101fe47b633af5bdee251531a Mon Sep 17 00:00:00 2001
|
||||
From: Michael Safwat <michael.safwat@arm.com>
|
||||
Date: Fri, 13 Mar 2026 12:42:09 +0000
|
||||
Subject: [PATCH] CC312: Add barrier before first AO lock write
|
||||
|
||||
On Corstone-1000 MPS3 with GCC 15.x, TF-M can HardFault in
|
||||
CC_LibInit() on the first HOST_AO_LOCK_BITS write.
|
||||
|
||||
Add a compiler barrier before that write to keep the fix minimal and
|
||||
local to the affected sequence.
|
||||
|
||||
Signed-off-by: Michael Safwat <michael.safwat@arm.com>
|
||||
Upstream-Status: Submitted [https://review.trustedfirmware.org/c/TF-M/trusted-firmware-m/+/49269]
|
||||
---
|
||||
lib/ext/cryptocell-312-runtime/host/src/cc3x_lib/cc_lib.c | 3 +++
|
||||
1 file changed, 3 insertions(+)
|
||||
|
||||
diff --git a/lib/ext/cryptocell-312-runtime/host/src/cc3x_lib/cc_lib.c b/lib/ext/cryptocell-312-runtime/host/src/cc3x_lib/cc_lib.c
|
||||
index 4b08c02526..1e96fcac5b 100644
|
||||
--- a/lib/ext/cryptocell-312-runtime/host/src/cc3x_lib/cc_lib.c
|
||||
+++ b/lib/ext/cryptocell-312-runtime/host/src/cc3x_lib/cc_lib.c
|
||||
@@ -33,6 +33,8 @@
|
||||
#include "cc_rnd_common.h"
|
||||
#include "cc_int_general_defs.h"
|
||||
|
||||
+#define CC_COMPILER_BARRIER() __asm volatile("" ::: "memory")
|
||||
+
|
||||
CC_PalMutex CCSymCryptoMutex;
|
||||
CC_PalMutex CCAsymCryptoMutex;
|
||||
CC_PalMutex *pCCRndCryptoMutex;
|
||||
@@ -213,6 +215,7 @@ CClibRetCode_t CC_LibInit(CCRndContext_t *rndContext_ptr, CCRndWorkBuff_t *rndW
|
||||
/* turn off the DFA since Cerberus doen't support it */
|
||||
reg = CC_HAL_READ_REGISTER(CC_REG_OFFSET(HOST_RGF, HOST_AO_LOCK_BITS));
|
||||
CC_REG_FLD_SET(0, HOST_AO_LOCK_BITS, HOST_FORCE_DFA_ENABLE, reg, 0x0);
|
||||
+ CC_COMPILER_BARRIER();
|
||||
CC_HAL_WRITE_REGISTER(CC_REG_OFFSET(HOST_RGF, HOST_AO_LOCK_BITS) ,reg );
|
||||
tempVal = CC_HAL_READ_REGISTER(CC_REG_OFFSET(HOST_RGF,HOST_AO_LOCK_BITS));
|
||||
if(tempVal != reg) {
|
||||
--
|
||||
2.43.0
|
||||
|
||||
-32
@@ -1,32 +0,0 @@
|
||||
From 9edcdd272a7d2d872f7e04b3a9db5185fd24fd97 Mon Sep 17 00:00:00 2001
|
||||
From: Harsimran Singh Tungal <harsimransingh.tungal@arm.com>
|
||||
Date: Tue, 28 Apr 2026 08:57:06 +0100
|
||||
Subject: [PATCH] platform: corstone1000: Increase FIP partition size
|
||||
|
||||
Increase the FIP partition size from 2MB to 2.5MB in the
|
||||
Corstone-1000 flash layout.
|
||||
|
||||
The previous size is insufficient for current FIP images,
|
||||
which may lead to overflow during image generation or
|
||||
deployment. Expanding the partition ensures adequate
|
||||
space for firmware components packaged in the FIP.
|
||||
|
||||
Upstream-Status: Submitted [https://review.trustedfirmware.org/c/TF-M/trusted-firmware-m/+/50628]
|
||||
Signed-off-by: Harsimran Singh Tungal <harsimransingh.tungal@arm.com>
|
||||
---
|
||||
platform/ext/target/arm/corstone1000/partition/flash_layout.h | 2 +-
|
||||
1 file changed, 1 insertion(+), 1 deletion(-)
|
||||
|
||||
diff --git a/platform/ext/target/arm/corstone1000/partition/flash_layout.h b/platform/ext/target/arm/corstone1000/partition/flash_layout.h
|
||||
index e2219d80a..b7282beb2 100644
|
||||
--- a/platform/ext/target/arm/corstone1000/partition/flash_layout.h
|
||||
+++ b/platform/ext/target/arm/corstone1000/partition/flash_layout.h
|
||||
@@ -139,7 +139,7 @@
|
||||
#define TFM_PARTITION_SIZE (0x50000) /* 320 KB */
|
||||
#define TFM_PARTITION_BANK_OFFSET (SE_BL2_PARTITION_SIZE)
|
||||
|
||||
-#define FIP_PARTITION_SIZE (0x200000) /* 2 MB */
|
||||
+#define FIP_PARTITION_SIZE (0x280000) /* 2.5 MB */
|
||||
#define FIP_PARTITION_BANK_OFFSET (TFM_PARTITION_BANK_OFFSET + TFM_PARTITION_SIZE)
|
||||
|
||||
#define INITRAMFS_PARTITION_SIZE (0xC00000) /* 12 MB */
|
||||
+90
@@ -0,0 +1,90 @@
|
||||
From 9f86d644aa23589e5187f0a22394438cd525d574 Mon Sep 17 00:00:00 2001
|
||||
From: Alex Chapman <alex.chapman@arm.com>
|
||||
Date: Wed, 4 Mar 2026 13:41:59 +0000
|
||||
Subject: [PATCH] Platform: CS1K: make mutlicore support platform generic
|
||||
|
||||
To improve portability, testing coverage, and future platform enablement.
|
||||
|
||||
- Replace FVP-only multicore checks with platform-generic checks.
|
||||
|
||||
Upstream-Status: Backport [71619253e03cc10cdd4527ab7e896e3ec10afabe]
|
||||
Signed-off-by: Alex Chapman <alex.chapman@arm.com>
|
||||
---
|
||||
platform/ext/target/arm/corstone1000/CMakeLists.txt | 4 +---
|
||||
.../target/arm/corstone1000/Device/Config/device_cfg.h | 2 +-
|
||||
platform/ext/target/arm/corstone1000/tfm_hal_multi_core.c | 8 ++++----
|
||||
3 files changed, 6 insertions(+), 8 deletions(-)
|
||||
|
||||
diff --git a/platform/ext/target/arm/corstone1000/CMakeLists.txt b/platform/ext/target/arm/corstone1000/CMakeLists.txt
|
||||
index 993c51591..a13f16fd7 100644
|
||||
--- a/platform/ext/target/arm/corstone1000/CMakeLists.txt
|
||||
+++ b/platform/ext/target/arm/corstone1000/CMakeLists.txt
|
||||
@@ -407,12 +407,10 @@ target_sources(tfm_psa_rot_partition_ns_agent_mailbox
|
||||
tfm_hal_multi_core.c
|
||||
)
|
||||
|
||||
-if (PLATFORM_IS_FVP)
|
||||
target_compile_definitions(tfm_psa_rot_partition_ns_agent_mailbox
|
||||
PUBLIC
|
||||
- $<$<BOOL:${ENABLE_MULTICORE}>:CORSTONE1000_FVP_MULTICORE>
|
||||
+ $<$<BOOL:${ENABLE_MULTICORE}>:CORSTONE1000_MULTICORE>
|
||||
)
|
||||
-endif()
|
||||
#========================= tfm_spm ============================================#
|
||||
|
||||
target_sources(tfm_spm
|
||||
diff --git a/platform/ext/target/arm/corstone1000/Device/Config/device_cfg.h b/platform/ext/target/arm/corstone1000/Device/Config/device_cfg.h
|
||||
index 544475a86..0c3a9088e 100644
|
||||
--- a/platform/ext/target/arm/corstone1000/Device/Config/device_cfg.h
|
||||
+++ b/platform/ext/target/arm/corstone1000/Device/Config/device_cfg.h
|
||||
@@ -46,7 +46,7 @@
|
||||
#define CFI_S
|
||||
|
||||
/* Total number of host cores */
|
||||
-#if CORSTONE1000_FVP_MULTICORE
|
||||
+#if CORSTONE1000_MULTICORE
|
||||
#define PLATFORM_HOST_MAX_CORE_COUNT 4
|
||||
#else
|
||||
#define PLATFORM_HOST_MAX_CORE_COUNT 1
|
||||
diff --git a/platform/ext/target/arm/corstone1000/tfm_hal_multi_core.c b/platform/ext/target/arm/corstone1000/tfm_hal_multi_core.c
|
||||
index 10c66ac41..9a785bfa0 100644
|
||||
--- a/platform/ext/target/arm/corstone1000/tfm_hal_multi_core.c
|
||||
+++ b/platform/ext/target/arm/corstone1000/tfm_hal_multi_core.c
|
||||
@@ -62,7 +62,7 @@ void tfm_hal_boot_ns_cpu(uintptr_t start_addr)
|
||||
volatile uint32_t *PE0_CONFIG =
|
||||
(uint32_t *)(CORSTONE1000_HOST_BASE_SYSTEM_CONTROL_BASE
|
||||
+ HOST_CPU_PE0_CONFIG_OFFSET);
|
||||
-#if CORSTONE1000_FVP_MULTICORE
|
||||
+#if CORSTONE1000_MULTICORE
|
||||
volatile uint32_t *PE1_CONFIG =
|
||||
(uint32_t *)(CORSTONE1000_HOST_BASE_SYSTEM_CONTROL_BASE
|
||||
+ HOST_CPU_PE1_CONFIG_OFFSET);
|
||||
@@ -80,7 +80,7 @@ void tfm_hal_boot_ns_cpu(uintptr_t start_addr)
|
||||
#endif
|
||||
/* Select host CPU architecture as AArch64 */
|
||||
*PE0_CONFIG |= AA64nAA32_MASK; /* 0b1 – AArch64 */
|
||||
-#if CORSTONE1000_FVP_MULTICORE
|
||||
+#if CORSTONE1000_MULTICORE
|
||||
*PE1_CONFIG |= AA64nAA32_MASK; /* 0b1 – AArch64 */
|
||||
*PE2_CONFIG |= AA64nAA32_MASK; /* 0b1 – AArch64 */
|
||||
*PE3_CONFIG |= AA64nAA32_MASK; /* 0b1 – AArch64 */
|
||||
@@ -92,7 +92,7 @@ void tfm_hal_boot_ns_cpu(uintptr_t start_addr)
|
||||
/* Clear HOST_SYS_RST_CTRL register to bring host out of RESET */
|
||||
*reset_ctl_reg = 0;
|
||||
|
||||
-#if CORSTONE1000_FVP_MULTICORE
|
||||
+#if CORSTONE1000_MULTICORE
|
||||
/* Wake up secondary cores.
|
||||
* This should be done after bringing the primary core out of reset.*/
|
||||
for (int core_index=1; core_index < PLATFORM_HOST_MAX_CORE_COUNT; core_index++) {
|
||||
@@ -111,7 +111,7 @@ void tfm_hal_boot_ns_cpu(uintptr_t start_addr)
|
||||
PPU_SetOperatingPolicy(CORE0_PPU, PPU_OP_MODE_ONE_SLICE_SF_ONLY_ON, false);
|
||||
PPU_SetPowerPolicy(CORE0_PPU, PPU_PWR_MODE_ON, false);
|
||||
|
||||
-#if CORSTONE1000_FVP_MULTICORE
|
||||
+#if CORSTONE1000_MULTICORE
|
||||
/* Power on all Cortex-A320 cores in DSU-120T Cluster */
|
||||
PPU_SetOperatingPolicy(CORE1_PPU, PPU_OP_MODE_ONE_SLICE_SF_ONLY_ON, false);
|
||||
PPU_SetPowerPolicy(CORE1_PPU, PPU_PWR_MODE_ON, false);
|
||||
--
|
||||
2.43.0
|
||||
-68
@@ -1,68 +0,0 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Ahmed Gomaa <ahmed.gomaa@arm.com>
|
||||
Date: Wed, 2 Sep 2026 12:00:00 +0100
|
||||
Subject: [PATCH] platform: corstone1000: keep CM during secure debug
|
||||
|
||||
Add a temporary Corstone-1000 Secure Debug workaround that skips runtime
|
||||
TF-M provisioning when Secure Debug is enabled. This keeps the device in
|
||||
the CM lifecycle state and avoids the provisioning reset, allowing the
|
||||
authenticated debug session to remain active.
|
||||
|
||||
Keep this workaround until a reset-safe architecture is implemented to
|
||||
preserve the authenticated DCU_EN value across reset and apply it from BL2.
|
||||
|
||||
Upstream-Status: Inappropriate [temporary platform workaround]
|
||||
Signed-off-by: Ahmed Gomaa <ahmed.gomaa@arm.com>
|
||||
---
|
||||
secure_fw/spm/CMakeLists.txt | 1 +
|
||||
secure_fw/spm/core/main.c | 10 ++++++++++
|
||||
2 files changed, 11 insertions(+)
|
||||
|
||||
diff --git a/secure_fw/spm/CMakeLists.txt b/secure_fw/spm/CMakeLists.txt
|
||||
--- a/secure_fw/spm/CMakeLists.txt
|
||||
+++ b/secure_fw/spm/CMakeLists.txt
|
||||
@@ -111,6 +111,7 @@ target_compile_definitions(tfm_spm
|
||||
$<$<STREQUAL:${CONFIG_TFM_BRANCH_PROTECTION_FEAT},BRANCH_PROTECTION_PACRET_LEAF>:BRANCH_PROTECTION_CONTROL=2>
|
||||
$<$<STREQUAL:${CONFIG_TFM_BRANCH_PROTECTION_FEAT},BRANCH_PROTECTION_BTI>:BRANCH_PROTECTION_CONTROL=3>
|
||||
$<$<BOOL:${PLATFORM_PSA_ADAC_SECURE_DEBUG}>:PLATFORM_PSA_ADAC_SECURE_DEBUG>
|
||||
+ $<$<BOOL:${CORSTONE1000_SKIP_PROVISIONING_FOR_DEBUG}>:CORSTONE1000_SKIP_PROVISIONING_FOR_DEBUG>
|
||||
$<$<BOOL:${CONFIG_TFM_REUSE_COPY_AREA_FOR_SP_STACKS}>:CONFIG_TFM_REUSE_COPY_AREA_FOR_SP_STACKS>
|
||||
$<$<BOOL:${TFM_TZ_REENTRANCY_CHECK}>:TFM_TZ_REENTRANCY_CHECK>
|
||||
)
|
||||
diff --git a/secure_fw/spm/core/main.c b/secure_fw/spm/core/main.c
|
||||
--- a/secure_fw/spm/core/main.c
|
||||
+++ b/secure_fw/spm/core/main.c
|
||||
@@ -31,7 +31,9 @@ static fih_ret tfm_core_init(void)
|
||||
{
|
||||
enum tfm_plat_err_t plat_err = TFM_PLAT_ERR_SYSTEM_ERR;
|
||||
FIH_DECLARE(fih_rc, FIH_FAILURE);
|
||||
+#ifndef CORSTONE1000_SKIP_PROVISIONING_FOR_DEBUG
|
||||
bool provisioning_required;
|
||||
+#endif
|
||||
|
||||
/*
|
||||
* Access to any peripheral should be performed after programming
|
||||
@@ -65,6 +67,7 @@ static fih_ret tfm_core_init(void)
|
||||
FIH_RET(SPM_ERROR_GENERIC);
|
||||
}
|
||||
|
||||
+#ifndef CORSTONE1000_SKIP_PROVISIONING_FOR_DEBUG
|
||||
/* Perform provisioning. */
|
||||
plat_err = tfm_plat_provisioning_is_required(&provisioning_required);
|
||||
if (plat_err != TFM_PLAT_ERR_SUCCESS) {
|
||||
@@ -77,6 +80,12 @@ static fih_ret tfm_core_init(void)
|
||||
FIH_RET(SPM_ERROR_GENERIC);
|
||||
}
|
||||
}
|
||||
+#else
|
||||
+ /* Temporary workaround: retain CM and avoid the provisioning reset. */
|
||||
+ WARN("Skipping TF-M provisioning for Secure Debug workaround. "
|
||||
+ "Device remains unprovisioned and must not be used in "
|
||||
+ "production.\n");
|
||||
+#endif
|
||||
|
||||
TFM_COVERITY_DEVIATE_LINE(MISRA_C_2023_Rule_2_2, "Parameters can be changed by user and this code will make effect")
|
||||
tfm_plat_provisioning_check_for_dummy_keys();
|
||||
--
|
||||
2.43.0
|
||||
|
||||
+217
@@ -0,0 +1,217 @@
|
||||
From 5fc4f3857739a9fe93819cedc4a8108d33bf8241 Mon Sep 17 00:00:00 2001
|
||||
From: Frazer Carsley <frazer.carsley@arm.com>
|
||||
Date: Thu, 27 Nov 2025 10:35:58 +0000
|
||||
Subject: [PATCH] lib: efi_guid: Added EFI GUID library
|
||||
|
||||
This library can be used to generate version 4 UUID/GUIDs according to
|
||||
RFC 4122 by using a PSA crypto driver. A separate header is provided to
|
||||
give access to the struct without the need of a PSA config.
|
||||
|
||||
Change-Id: Ief35b2a4f565889ba2ea0de82e20dc12f6e824e8
|
||||
Signed-off-by: Frazer Carsley <frazer.carsley@arm.com>
|
||||
Upstream-Status: Backport [3bdd2562ebad3115457ea75e58d0554802e12dba]
|
||||
---
|
||||
CMakeLists.txt | 1 +
|
||||
lib/efi_guid/CMakeLists.txt | 26 ++++++++++++
|
||||
lib/efi_guid/inc/efi_guid.h | 36 +++++++++++++++++
|
||||
lib/efi_guid/inc/efi_guid_structs.h | 62 +++++++++++++++++++++++++++++
|
||||
lib/efi_guid/src/efi_guid.c | 33 +++++++++++++++
|
||||
5 files changed, 158 insertions(+)
|
||||
create mode 100644 lib/efi_guid/CMakeLists.txt
|
||||
create mode 100644 lib/efi_guid/inc/efi_guid.h
|
||||
create mode 100644 lib/efi_guid/inc/efi_guid_structs.h
|
||||
create mode 100644 lib/efi_guid/src/efi_guid.c
|
||||
|
||||
diff --git a/CMakeLists.txt b/CMakeLists.txt
|
||||
index 2560dd15e..b120de697 100644
|
||||
--- a/CMakeLists.txt
|
||||
+++ b/CMakeLists.txt
|
||||
@@ -44,6 +44,7 @@ project("Trusted Firmware M" VERSION ${TFM_VERSION} LANGUAGES C CXX ASM)
|
||||
|
||||
add_subdirectory(lib/backtrace)
|
||||
add_subdirectory(lib/ext)
|
||||
+add_subdirectory(lib/efi_guid)
|
||||
add_subdirectory(lib/fih)
|
||||
add_subdirectory(lib/tfm_log)
|
||||
add_subdirectory(lib/tfm_log_unpriv)
|
||||
diff --git a/lib/efi_guid/CMakeLists.txt b/lib/efi_guid/CMakeLists.txt
|
||||
new file mode 100644
|
||||
index 000000000..656eb72ea
|
||||
--- /dev/null
|
||||
+++ b/lib/efi_guid/CMakeLists.txt
|
||||
@@ -0,0 +1,26 @@
|
||||
+#-------------------------------------------------------------------------------
|
||||
+# SPDX-FileCopyrightText: Copyright The TrustedFirmware-M Contributors
|
||||
+#
|
||||
+# SPDX-License-Identifier: BSD-3-Clause
|
||||
+#
|
||||
+#-------------------------------------------------------------------------------
|
||||
+
|
||||
+add_library(tfm_efi_guid STATIC)
|
||||
+
|
||||
+target_sources(tfm_efi_guid
|
||||
+ PRIVATE
|
||||
+ src/efi_guid.c
|
||||
+)
|
||||
+
|
||||
+target_include_directories(tfm_efi_guid
|
||||
+ PUBLIC
|
||||
+ $<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/inc>
|
||||
+ PRIVATE
|
||||
+ ${CMAKE_CURRENT_SOURCE_DIR}/src
|
||||
+)
|
||||
+
|
||||
+target_link_libraries(tfm_efi_guid
|
||||
+ PUBLIC
|
||||
+ psa_interface
|
||||
+ psa_crypto_config
|
||||
+)
|
||||
diff --git a/lib/efi_guid/inc/efi_guid.h b/lib/efi_guid/inc/efi_guid.h
|
||||
new file mode 100644
|
||||
index 000000000..81f6ad507
|
||||
--- /dev/null
|
||||
+++ b/lib/efi_guid/inc/efi_guid.h
|
||||
@@ -0,0 +1,36 @@
|
||||
+/*
|
||||
+ * SPDX-FileCopyrightText: Copyright The TrustedFirmware-M Contributors
|
||||
+ *
|
||||
+ * SPDX-License-Identifier: BSD-3-Clause
|
||||
+ *
|
||||
+ */
|
||||
+
|
||||
+#ifndef __TFM_EFI_GUID_H__
|
||||
+#define __TFM_EFI_GUID_H__
|
||||
+
|
||||
+#include "psa/crypto.h"
|
||||
+#include "efi_guid_structs.h"
|
||||
+
|
||||
+#ifdef __cplusplus
|
||||
+extern "C" {
|
||||
+#endif
|
||||
+
|
||||
+/**
|
||||
+ * \brief Generates a random version 4 UUID/GUID using a PSA crypto driver.
|
||||
+ *
|
||||
+ * \note See RFC 4112 for details on UUID/GUIDs.
|
||||
+ *
|
||||
+ * \note See psa_generate_random for possible failures.
|
||||
+ *
|
||||
+ * \param[out] guid Pointer populated with the generated UUID/GUID.
|
||||
+ *
|
||||
+ * \return PSA_SUCCESS on success or a PSA error code on failure.
|
||||
+ *
|
||||
+ */
|
||||
+psa_status_t efi_guid_generate_random(struct efi_guid_t *guid);
|
||||
+
|
||||
+#ifdef __cplusplus
|
||||
+}
|
||||
+#endif
|
||||
+
|
||||
+#endif /* __TFM_EFI_GUID_H__ */
|
||||
diff --git a/lib/efi_guid/inc/efi_guid_structs.h b/lib/efi_guid/inc/efi_guid_structs.h
|
||||
new file mode 100644
|
||||
index 000000000..c89e8f692
|
||||
--- /dev/null
|
||||
+++ b/lib/efi_guid/inc/efi_guid_structs.h
|
||||
@@ -0,0 +1,62 @@
|
||||
+/*
|
||||
+ * Copyright (c) 2021, Linaro Limited
|
||||
+ * SPDX-FileCopyrightText: Copyright The TrustedFirmware-M Contributors
|
||||
+ *
|
||||
+ * SPDX-License-Identifier: BSD-3-Clause
|
||||
+ *
|
||||
+ */
|
||||
+
|
||||
+#ifndef __TFM_EFI_GUID_STRUCTS_H__
|
||||
+#define __TFM_EFI_GUID_STRUCTS_H__
|
||||
+
|
||||
+#include <stdint.h>
|
||||
+#include <string.h>
|
||||
+
|
||||
+#ifdef __cplusplus
|
||||
+extern "C" {
|
||||
+#endif
|
||||
+
|
||||
+#define EFI_GUID_NODE_LEN 6
|
||||
+
|
||||
+/**
|
||||
+ * \brief Representation that makes creating GUIDs slightly easier.
|
||||
+ */
|
||||
+struct efi_guid_t {
|
||||
+ uint32_t time_low; /**< Low 32-bits of timestamp. */
|
||||
+ uint16_t time_mid; /**< Middle 16-bits of timestamp. */
|
||||
+ uint16_t time_hi_and_version; /**< High 12-bits of timestamp with 4-bit version. */
|
||||
+ uint8_t clock_seq_hi_and_reserved; /**< High 4-bits of clock sequence with 4-bit variant. */
|
||||
+ uint8_t clock_seq_low; /**< Low 8-bits of clock sequence. */
|
||||
+ uint8_t node[EFI_GUID_NODE_LEN]; /**< 48-bit spatially unique node identifier. */
|
||||
+};
|
||||
+
|
||||
+static inline int efi_guid_cmp(const struct efi_guid_t *g1,
|
||||
+ const struct efi_guid_t *g2)
|
||||
+{
|
||||
+ return memcmp(g1, g2, sizeof(struct efi_guid_t));
|
||||
+}
|
||||
+
|
||||
+static inline void *efi_guid_cpy(const struct efi_guid_t *src,
|
||||
+ struct efi_guid_t *dst)
|
||||
+{
|
||||
+ return memcpy(dst, src, sizeof(struct efi_guid_t));
|
||||
+}
|
||||
+
|
||||
+/** \brief Helper macro to build an EFI GUID structure from individual values. */
|
||||
+#define MAKE_EFI_GUID(a, b, c, d0, d1, e0, e1, e2, e3, e4, e5) \
|
||||
+ { \
|
||||
+ (a) & 0xffffffff, (b)&0xffff, (c)&0xffff, d0, d1, { \
|
||||
+ (e0), (e1), (e2), (e3), (e4), (e5) \
|
||||
+ } \
|
||||
+ }
|
||||
+
|
||||
+/** \brief Helper macro to build the EFI GUID 00000000-0000-0000-0000-0000000000. */
|
||||
+#define NULL_GUID \
|
||||
+ MAKE_EFI_GUID(0x00000000, 0x0000, 0x0000, 0x00, 0x00, 0x00, 0x00, 0x00, \
|
||||
+ 0x00, 0x00, 0x00)
|
||||
+
|
||||
+#ifdef __cplusplus
|
||||
+}
|
||||
+#endif
|
||||
+
|
||||
+#endif /* __TFM_EFI_GUID_STRUCTS_H__ */
|
||||
diff --git a/lib/efi_guid/src/efi_guid.c b/lib/efi_guid/src/efi_guid.c
|
||||
new file mode 100644
|
||||
index 000000000..cb8730a51
|
||||
--- /dev/null
|
||||
+++ b/lib/efi_guid/src/efi_guid.c
|
||||
@@ -0,0 +1,33 @@
|
||||
+/*
|
||||
+ * SPDX-FileCopyrightText: Copyright The TrustedFirmware-M Contributors
|
||||
+ *
|
||||
+ * SPDX-License-Identifier: BSD-3-Clause
|
||||
+ */
|
||||
+
|
||||
+#include <stdint.h>
|
||||
+
|
||||
+#include "psa/crypto.h"
|
||||
+
|
||||
+#include "efi_guid_structs.h"
|
||||
+#include "efi_guid.h"
|
||||
+
|
||||
+psa_status_t efi_guid_generate_random(struct efi_guid_t *guid)
|
||||
+{
|
||||
+ const psa_status_t ret = psa_generate_random((uint8_t *)guid, sizeof(*guid));
|
||||
+ if (ret != PSA_SUCCESS) {
|
||||
+ return ret;
|
||||
+ }
|
||||
+
|
||||
+ /* According to RFC 4122, counting bits from the right:
|
||||
+ * - Bits 6 and 7 of clock_seq_hi_and_reserved need to be set to
|
||||
+ * 0 and 1 respecitively
|
||||
+ * - Bits 12 through 15 of time_hi_and_version need to be set to
|
||||
+ * 0b0100
|
||||
+ */
|
||||
+ guid->clock_seq_hi_and_reserved &= 0x3F;
|
||||
+ guid->clock_seq_hi_and_reserved |= 0x80;
|
||||
+ guid->time_hi_and_version &= 0x0FFF;
|
||||
+ guid->time_hi_and_version |= 0x4000;
|
||||
+
|
||||
+ return PSA_SUCCESS;
|
||||
+}
|
||||
+136
@@ -0,0 +1,136 @@
|
||||
From 4a47d926420bfec4a0e687b6ecc4cf52419e4f58 Mon Sep 17 00:00:00 2001
|
||||
From: Frazer Carsley <frazer.carsley@arm.com>
|
||||
Date: Thu, 27 Nov 2025 10:37:28 +0000
|
||||
Subject: [PATCH] lib: efi_soft_crc: Added EFI CRC library
|
||||
|
||||
This library can be used to perform CRC32 calculations using the
|
||||
standard CRC32 polynomial specified by the UEFI spec 2.10. It does not
|
||||
use a lookup table to save on memory. The polynomial used is in reverse
|
||||
order to match little-endian machines.
|
||||
|
||||
Change-Id: Ifce5a1cbbb3ab394bc748305be213a8467610015
|
||||
Signed-off-by: Frazer Carsley <frazer.carsley@arm.com>
|
||||
Upstream-Status: Backport [3f2b707eaadef8008f333bd5c519c1b2544458ab]
|
||||
---
|
||||
lib/ext/CMakeLists.txt | 1 +
|
||||
lib/ext/efi_soft_crc/CMakeLists.txt | 18 ++++++++++++++
|
||||
lib/ext/efi_soft_crc/inc/efi_soft_crc.h | 33 +++++++++++++++++++++++++
|
||||
lib/ext/efi_soft_crc/src/efi_soft_crc.c | 32 ++++++++++++++++++++++++
|
||||
4 files changed, 84 insertions(+)
|
||||
create mode 100644 lib/ext/efi_soft_crc/CMakeLists.txt
|
||||
create mode 100644 lib/ext/efi_soft_crc/inc/efi_soft_crc.h
|
||||
create mode 100644 lib/ext/efi_soft_crc/src/efi_soft_crc.c
|
||||
|
||||
diff --git a/lib/ext/CMakeLists.txt b/lib/ext/CMakeLists.txt
|
||||
index 05f6b8f14..1dffbacfb 100644
|
||||
--- a/lib/ext/CMakeLists.txt
|
||||
+++ b/lib/ext/CMakeLists.txt
|
||||
@@ -10,6 +10,7 @@ add_subdirectory(qcbor)
|
||||
add_subdirectory(t_cose)
|
||||
add_subdirectory(mbedcrypto)
|
||||
add_subdirectory(cmsis)
|
||||
+add_subdirectory(efi_soft_crc)
|
||||
if(BL2)
|
||||
add_subdirectory(mcuboot)
|
||||
endif()
|
||||
diff --git a/lib/ext/efi_soft_crc/CMakeLists.txt b/lib/ext/efi_soft_crc/CMakeLists.txt
|
||||
new file mode 100644
|
||||
index 000000000..47fd2d507
|
||||
--- /dev/null
|
||||
+++ b/lib/ext/efi_soft_crc/CMakeLists.txt
|
||||
@@ -0,0 +1,18 @@
|
||||
+#-------------------------------------------------------------------------------
|
||||
+# SPDX-FileCopyrightText: Copyright The TrustedFirmware-M Contributors
|
||||
+#
|
||||
+# SPDX-License-Identifier: BSD-3-Clause
|
||||
+#
|
||||
+#-------------------------------------------------------------------------------
|
||||
+
|
||||
+add_library(tfm_efi_soft_crc STATIC)
|
||||
+
|
||||
+target_sources(tfm_efi_soft_crc
|
||||
+ PRIVATE
|
||||
+ src/efi_soft_crc.c
|
||||
+)
|
||||
+
|
||||
+target_include_directories(tfm_efi_soft_crc
|
||||
+ PUBLIC
|
||||
+ $<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/inc>
|
||||
+)
|
||||
diff --git a/lib/ext/efi_soft_crc/inc/efi_soft_crc.h b/lib/ext/efi_soft_crc/inc/efi_soft_crc.h
|
||||
new file mode 100644
|
||||
index 000000000..77baa8987
|
||||
--- /dev/null
|
||||
+++ b/lib/ext/efi_soft_crc/inc/efi_soft_crc.h
|
||||
@@ -0,0 +1,33 @@
|
||||
+/*
|
||||
+ * SPDX-FileCopyrightText: Copyright The TrustedFirmware-M Contributors
|
||||
+ *
|
||||
+ * SPDX-License-Identifier: BSD-3-Clause
|
||||
+ *
|
||||
+ */
|
||||
+
|
||||
+#ifndef __TFM_EFI_SOFT_CRC_H__
|
||||
+#define __TFM_EFI_SOFT_CRC_H__
|
||||
+
|
||||
+#include <stddef.h>
|
||||
+#include <stdint.h>
|
||||
+
|
||||
+#ifdef __cplusplus
|
||||
+extern "C" {
|
||||
+#endif
|
||||
+
|
||||
+/**
|
||||
+ * \brief Updates a CRC32 calculation using ISO 3309 CRC-32.
|
||||
+ *
|
||||
+ * \param[in] old_crc Existing CRC value (0 for the first calculation).
|
||||
+ * \param[in] buf Buffer of bytes to perform the calculation over.
|
||||
+ * \param[in] len Length of \p buf in bytes.
|
||||
+ *
|
||||
+ * \return The calculated CRC32 value.
|
||||
+ */
|
||||
+uint32_t efi_soft_crc32_update(uint32_t old_crc, const uint8_t *buf, size_t len);
|
||||
+
|
||||
+#ifdef __cplusplus
|
||||
+}
|
||||
+#endif
|
||||
+
|
||||
+#endif /* __TFM_EFI_SOFT_CRC_H__ */
|
||||
diff --git a/lib/ext/efi_soft_crc/src/efi_soft_crc.c b/lib/ext/efi_soft_crc/src/efi_soft_crc.c
|
||||
new file mode 100644
|
||||
index 000000000..041a321cd
|
||||
--- /dev/null
|
||||
+++ b/lib/ext/efi_soft_crc/src/efi_soft_crc.c
|
||||
@@ -0,0 +1,32 @@
|
||||
+/* Copyright (C) 2013 Henry S. Warren Jr. You are free to use, copy,
|
||||
+ * and distribute any of the code on this web site, whether modified
|
||||
+ * by you or not.
|
||||
+ */
|
||||
+
|
||||
+#include "efi_soft_crc.h"
|
||||
+
|
||||
+/* The standard polynomial, in reverse */
|
||||
+#define POLYNOMIAL 0xEDB88320
|
||||
+
|
||||
+/* Algorithmic approach to CRC calculation: avoids lookup tables, slow. Byte
|
||||
+ * reversal is avoided by shifting the crc register right instead of left and
|
||||
+ * by using a reversed 32-bit word to represent the polynomial.
|
||||
+ *
|
||||
+ * Derived from work by Henry S. Warren Jr.
|
||||
+ */
|
||||
+uint32_t efi_soft_crc32_update(uint32_t old_crc32, const uint8_t *buf, size_t len)
|
||||
+{
|
||||
+ register uint32_t crc32 = ~old_crc32;
|
||||
+ uint32_t mask;
|
||||
+
|
||||
+ for ( ; len; --len, ++buf)
|
||||
+ {
|
||||
+ crc32 ^= *buf;
|
||||
+ for (size_t i = 0; i < 8; ++i) {
|
||||
+ mask = -(crc32 & 1);
|
||||
+ crc32 = (crc32 >> 1) ^ (POLYNOMIAL & mask);
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ return ~crc32;
|
||||
+}
|
||||
+1495
File diff suppressed because it is too large
Load Diff
+308
@@ -0,0 +1,308 @@
|
||||
From b3775fd8aa2078e5e86d5cdb4164e6fc31fabbfc Mon Sep 17 00:00:00 2001
|
||||
From: Frazer Carsley <frazer.carsley@arm.com>
|
||||
Date: Wed, 11 Feb 2026 11:16:13 +0000
|
||||
Subject: [PATCH] lib: gpt: Expanded how GPT partition can be identified
|
||||
|
||||
The GUID of a partition is not always known, particularly for tables
|
||||
that have been created outside the control of the user. Therefore,
|
||||
allowing the name or type to be used to identify a partition gives the
|
||||
user greater flexibility. These may not be unique, however, and so must
|
||||
be indexed. A single entry is returned rather than a list so as to not
|
||||
dynamically allocate such memory.
|
||||
|
||||
Change-Id: I7687bfc737b244f6e589c4fe6b61c370daf1b062
|
||||
Signed-off-by: Frazer Carsley <frazer.carsley@arm.com>
|
||||
Upstream-Status: Backport [aede42c1c58b5681fe50bbec3a797f69256d108e]
|
||||
---
|
||||
lib/gpt/inc/gpt.h | 34 +++++++++
|
||||
lib/gpt/src/gpt.c | 68 +++++++++++++++--
|
||||
lib/gpt/unittests/gpt/test_gpt.c | 127 +++++++++++++++++++++++++++++++
|
||||
3 files changed, 223 insertions(+), 6 deletions(-)
|
||||
|
||||
diff --git a/lib/gpt/inc/gpt.h b/lib/gpt/inc/gpt.h
|
||||
index d98abe980..947a6b341 100644
|
||||
--- a/lib/gpt/inc/gpt.h
|
||||
+++ b/lib/gpt/inc/gpt.h
|
||||
@@ -48,6 +48,40 @@ __attribute__((nonnull(1,2)))
|
||||
psa_status_t gpt_entry_read(const struct efi_guid_t *guid,
|
||||
struct partition_entry_t *partition_entry);
|
||||
|
||||
+/**
|
||||
+ * \brief Reads the contents of a partition entry identified by name.
|
||||
+ *
|
||||
+ * \param[in] name Name of the partition to read in unicode.
|
||||
+ * \param[in] index Index to read when multiple entries share the same name.
|
||||
+ * \param[out] partition_entry Populated partition entry on success.
|
||||
+ *
|
||||
+ * \retval PSA_SUCCESS Success.
|
||||
+ * \retval PSA_ERROR_STORAGE_FAILURE I/O error.
|
||||
+ * \retval PSA_ERROR_DOES_NOT_EXIST No entry found with the provided name at \p index. For example,
|
||||
+ * \p index was 1 (second entry) but only one entry was found.
|
||||
+ */
|
||||
+__attribute__((nonnull(1,3)))
|
||||
+psa_status_t gpt_entry_read_by_name(const char name[GPT_ENTRY_NAME_LENGTH],
|
||||
+ const uint32_t index,
|
||||
+ struct partition_entry_t *partition_entry);
|
||||
+
|
||||
+/**
|
||||
+ * \brief Reads the contents of a partition entry identified by type.
|
||||
+ *
|
||||
+ * \param[in] type Type of the partition to read.
|
||||
+ * \param[in] index Index to read when multiple entries share the same type.
|
||||
+ * \param[out] partition_entry Populated partition entry on success.
|
||||
+ *
|
||||
+ * \retval PSA_SUCCESS Success.
|
||||
+ * \retval PSA_ERROR_STORAGE_FAILURE I/O error.
|
||||
+ * \retval PSA_ERROR_DOES_NOT_EXIST No entry found with the provided type at \p index. For example,
|
||||
+ * \p index was 1 (second entry) but only one entry was found.
|
||||
+ */
|
||||
+__attribute__((nonnull(1,3)))
|
||||
+psa_status_t gpt_entry_read_by_type(const struct efi_guid_t *type,
|
||||
+ const uint32_t index,
|
||||
+ struct partition_entry_t *partition_entry);
|
||||
+
|
||||
/**
|
||||
* \brief Reads the GPT header from the second block (LBA 1).
|
||||
*
|
||||
diff --git a/lib/gpt/src/gpt.c b/lib/gpt/src/gpt.c
|
||||
index 99d735797..1662b81c2 100644
|
||||
--- a/lib/gpt/src/gpt.c
|
||||
+++ b/lib/gpt/src/gpt.c
|
||||
@@ -177,6 +177,8 @@ static inline uint64_t partition_entry_lba(const struct gpt_t *table,
|
||||
static inline uint64_t gpt_entry_per_lba_count(void);
|
||||
static psa_status_t count_used_partitions(const struct gpt_t *table,
|
||||
uint32_t *num_used);
|
||||
+static inline void parse_entry(struct gpt_entry_t *entry,
|
||||
+ struct partition_entry_t *partition_entry);
|
||||
static psa_status_t read_from_flash(uint64_t required_lba);
|
||||
static psa_status_t read_entry_from_flash(const struct gpt_t *table,
|
||||
uint32_t array_index,
|
||||
@@ -190,6 +192,8 @@ static psa_status_t find_gpt_entry(const struct gpt_t *table,
|
||||
uint32_t *array_index);
|
||||
static psa_status_t mbr_load(struct mbr_t *mbr);
|
||||
static bool gpt_entry_cmp_guid(const struct gpt_entry_t *entry, const void *guid);
|
||||
+static bool gpt_entry_cmp_name(const struct gpt_entry_t *entry, const void *name);
|
||||
+static bool gpt_entry_cmp_type(const struct gpt_entry_t *entry, const void *type);
|
||||
|
||||
/* PUBLIC API FUNCTIONS */
|
||||
|
||||
@@ -202,12 +206,37 @@ psa_status_t gpt_entry_read(const struct efi_guid_t *guid,
|
||||
return ret;
|
||||
}
|
||||
|
||||
- partition_entry->start = cached_entry.start;
|
||||
- partition_entry->size = cached_entry.end - cached_entry.start + 1;
|
||||
- memcpy(partition_entry->name, cached_entry.name, GPT_ENTRY_NAME_LENGTH);
|
||||
- partition_entry->attr = cached_entry.attr;
|
||||
- partition_entry->partition_guid = cached_entry.unique_guid;
|
||||
- partition_entry->type_guid = cached_entry.partition_type;
|
||||
+ parse_entry(&cached_entry, partition_entry);
|
||||
+
|
||||
+ return PSA_SUCCESS;
|
||||
+}
|
||||
+
|
||||
+psa_status_t gpt_entry_read_by_name(const char name[GPT_ENTRY_NAME_LENGTH],
|
||||
+ const uint32_t index,
|
||||
+ struct partition_entry_t *partition_entry)
|
||||
+{
|
||||
+ struct gpt_entry_t cached_entry;
|
||||
+ const psa_status_t ret = find_gpt_entry(&primary_gpt, gpt_entry_cmp_name, name, index, &cached_entry, NULL);
|
||||
+ if (ret != PSA_SUCCESS) {
|
||||
+ return ret;
|
||||
+ }
|
||||
+
|
||||
+ parse_entry(&cached_entry, partition_entry);
|
||||
+
|
||||
+ return PSA_SUCCESS;
|
||||
+}
|
||||
+
|
||||
+psa_status_t gpt_entry_read_by_type(const struct efi_guid_t *type,
|
||||
+ const uint32_t index,
|
||||
+ struct partition_entry_t *partition_entry)
|
||||
+{
|
||||
+ struct gpt_entry_t cached_entry;
|
||||
+ const psa_status_t ret = find_gpt_entry(&primary_gpt, gpt_entry_cmp_type, type, index, &cached_entry, NULL);
|
||||
+ if (ret != PSA_SUCCESS) {
|
||||
+ return ret;
|
||||
+ }
|
||||
+
|
||||
+ parse_entry(&cached_entry, partition_entry);
|
||||
|
||||
return PSA_SUCCESS;
|
||||
}
|
||||
@@ -322,6 +351,18 @@ static inline uint64_t gpt_entry_per_lba_count(void)
|
||||
return num_entries;
|
||||
}
|
||||
|
||||
+/* Copies information from the entry to the user visible structure */
|
||||
+static inline void parse_entry(struct gpt_entry_t *entry,
|
||||
+ struct partition_entry_t *partition_entry)
|
||||
+{
|
||||
+ partition_entry->start = entry->start;
|
||||
+ partition_entry->size = entry->end - entry->start + 1;
|
||||
+ memcpy(partition_entry->name, entry->name, GPT_ENTRY_NAME_LENGTH);
|
||||
+ partition_entry->attr = entry->attr;
|
||||
+ partition_entry->partition_guid = entry->unique_guid;
|
||||
+ partition_entry->type_guid = entry->partition_type;
|
||||
+}
|
||||
+
|
||||
/* Compare the entry with the given guid */
|
||||
static bool gpt_entry_cmp_guid(const struct gpt_entry_t *entry, const void *guid)
|
||||
{
|
||||
@@ -331,6 +372,21 @@ static bool gpt_entry_cmp_guid(const struct gpt_entry_t *entry, const void *guid
|
||||
return efi_guid_cmp(&entry_guid, cmp_guid) == 0;
|
||||
}
|
||||
|
||||
+/* Compare the entry with the given name */
|
||||
+static bool gpt_entry_cmp_name(const struct gpt_entry_t *entry, const void *name)
|
||||
+{
|
||||
+ return memcmp(name, entry->name, GPT_ENTRY_NAME_LENGTH) == 0;
|
||||
+}
|
||||
+
|
||||
+/* Compare the entry with the given type */
|
||||
+static bool gpt_entry_cmp_type(const struct gpt_entry_t *entry, const void *type)
|
||||
+{
|
||||
+ const struct efi_guid_t *cmp_type = (const struct efi_guid_t *)type;
|
||||
+ const struct efi_guid_t entry_type = entry->partition_type;
|
||||
+
|
||||
+ return efi_guid_cmp(&entry_type, cmp_type) == 0;
|
||||
+}
|
||||
+
|
||||
/* Read entry with given GUID from given table and return it if found. */
|
||||
static psa_status_t find_gpt_entry(const struct gpt_t *table,
|
||||
gpt_entry_cmp_t compare,
|
||||
diff --git a/lib/gpt/unittests/gpt/test_gpt.c b/lib/gpt/unittests/gpt/test_gpt.c
|
||||
index 325887fae..d6671f3fc 100644
|
||||
--- a/lib/gpt/unittests/gpt/test_gpt.c
|
||||
+++ b/lib/gpt/unittests/gpt/test_gpt.c
|
||||
@@ -381,3 +381,130 @@ void test_gpt_entry_read_should_failWhenEntryNotExisting(void)
|
||||
register_mocked_read(&test_partition_array, sizeof(test_partition_array));
|
||||
TEST_ASSERT_EQUAL(PSA_ERROR_DOES_NOT_EXIST, gpt_entry_read(&non_existing, &entry));
|
||||
}
|
||||
+
|
||||
+void test_gpt_entry_read_by_name_should_populateEntry(void)
|
||||
+{
|
||||
+ /* Start with a populated GPT */
|
||||
+ setup_valid_gpt();
|
||||
+
|
||||
+ /* Ensure an entry is found, even with repeat names */
|
||||
+ struct partition_entry_t entry;
|
||||
+ struct gpt_entry_t *desired1 = &(test_partition_array[0]);
|
||||
+ struct efi_guid_t test_guid1 = desired1->guid;
|
||||
+ struct efi_guid_t test_type1 = desired1->type;
|
||||
+
|
||||
+ /* Change the name of something else and ensure it is found */
|
||||
+ struct gpt_entry_t *desired2 = &(test_partition_array[1]);
|
||||
+ struct efi_guid_t test_guid2 = desired2->guid;
|
||||
+ struct efi_guid_t test_type2 = desired2->type;
|
||||
+ memcpy(desired2->name, desired1->name, GPT_ENTRY_NAME_LENGTH);
|
||||
+
|
||||
+ register_mocked_read(&test_partition_array, sizeof(test_partition_array));
|
||||
+ TEST_ASSERT_EQUAL(PSA_SUCCESS, gpt_entry_read_by_name(desired1->name, 0, &entry));
|
||||
+
|
||||
+ /* Ensure this is the correct entry */
|
||||
+ TEST_ASSERT_EQUAL(0, efi_guid_cmp(&test_guid1, &(entry.partition_guid)));
|
||||
+ TEST_ASSERT_EQUAL(0, efi_guid_cmp(&test_type1, &(entry.type_guid)));
|
||||
+ TEST_ASSERT_EQUAL(desired1->start, entry.start);
|
||||
+ TEST_ASSERT_EQUAL(desired1->end, entry.start + entry.size - 1);
|
||||
+
|
||||
+ TEST_ASSERT_EQUAL_MEMORY(desired1->name, entry.name, GPT_ENTRY_NAME_LENGTH);
|
||||
+
|
||||
+ /* Do again but the next entry */
|
||||
+ TEST_ASSERT_EQUAL(PSA_SUCCESS, gpt_entry_read_by_name(desired1->name, 1, &entry));
|
||||
+
|
||||
+ /* Ensure this is the correct entry */
|
||||
+ TEST_ASSERT_EQUAL(0, efi_guid_cmp(&test_guid2, &(entry.partition_guid)));
|
||||
+ TEST_ASSERT_EQUAL(0, efi_guid_cmp(&test_type2, &(entry.type_guid)));
|
||||
+ TEST_ASSERT_EQUAL(desired2->start, entry.start);
|
||||
+ TEST_ASSERT_EQUAL(desired2->end, entry.start + entry.size - 1);
|
||||
+
|
||||
+ TEST_ASSERT_EQUAL_MEMORY(desired2->name, entry.name, GPT_ENTRY_NAME_LENGTH);
|
||||
+}
|
||||
+
|
||||
+void test_gpt_entry_read_by_name_should_failWhenEntryNotExisting(void)
|
||||
+{
|
||||
+ /* Start with an empty GPT */
|
||||
+ setup_empty_gpt();
|
||||
+
|
||||
+ /* Try to read something */
|
||||
+ struct partition_entry_t entry;
|
||||
+ char test_name[GPT_ENTRY_NAME_LENGTH] = {'\0'};
|
||||
+ TEST_ASSERT_EQUAL(PSA_ERROR_DOES_NOT_EXIST, gpt_entry_read_by_name(test_name, 0, &entry));
|
||||
+
|
||||
+ /* Now, have a non-empty GPT but search for a name that won't exist */
|
||||
+ setup_valid_gpt();
|
||||
+
|
||||
+ /* Each entry should be read */
|
||||
+ register_mocked_read(&test_partition_array, sizeof(test_partition_array));
|
||||
+ TEST_ASSERT_EQUAL(PSA_ERROR_DOES_NOT_EXIST, gpt_entry_read_by_name(test_name, 0, &entry));
|
||||
+
|
||||
+ /* Finally, search for the second entry of a name that appears only once */
|
||||
+ memcpy(test_name, test_partition_array[0].name, GPT_ENTRY_NAME_LENGTH);
|
||||
+ TEST_ASSERT_EQUAL(PSA_ERROR_DOES_NOT_EXIST, gpt_entry_read_by_name(test_name, 1, &entry));
|
||||
+ TEST_ASSERT_EQUAL(PSA_ERROR_DOES_NOT_EXIST, gpt_entry_read_by_name(test_name, TEST_DEFAULT_NUM_PARTITIONS, &entry));
|
||||
+}
|
||||
+
|
||||
+void test_gpt_entry_read_by_type_should_populateEntry(void)
|
||||
+{
|
||||
+ /* Start with a populated GPT */
|
||||
+ setup_valid_gpt();
|
||||
+
|
||||
+ /* Ensure an entry is found, even with repeat types */
|
||||
+ struct partition_entry_t entry;
|
||||
+ struct gpt_entry_t *desired1 = &(test_partition_array[0]);
|
||||
+ struct efi_guid_t test_guid1 = desired1->guid;
|
||||
+ struct efi_guid_t test_type1 = desired1->type;
|
||||
+
|
||||
+ struct gpt_entry_t *desired2 = &(test_partition_array[1]);
|
||||
+ struct efi_guid_t test_guid2 = desired2->guid;
|
||||
+ struct efi_guid_t test_type2 = test_type1;
|
||||
+ desired2->type = test_type2;
|
||||
+
|
||||
+ register_mocked_read(&test_partition_array, sizeof(test_partition_array));
|
||||
+ TEST_ASSERT_EQUAL(PSA_SUCCESS, gpt_entry_read_by_type(&test_type1, 0, &entry));
|
||||
+
|
||||
+ /* Ensure this is the correct entry */
|
||||
+ TEST_ASSERT_EQUAL(0, efi_guid_cmp(&test_guid1, &(entry.partition_guid)));
|
||||
+ TEST_ASSERT_EQUAL(0, efi_guid_cmp(&test_type1, &(entry.type_guid)));
|
||||
+ TEST_ASSERT_EQUAL(desired1->start, entry.start);
|
||||
+ TEST_ASSERT_EQUAL(desired1->end, entry.start + entry.size - 1);
|
||||
+
|
||||
+ /* Name is unicode */
|
||||
+ TEST_ASSERT_EQUAL_MEMORY(desired1->name, entry.name, GPT_ENTRY_NAME_LENGTH);
|
||||
+
|
||||
+ /* Do again but the next entry */
|
||||
+ TEST_ASSERT_EQUAL(PSA_SUCCESS, gpt_entry_read_by_type(&test_type1, 1, &entry));
|
||||
+
|
||||
+ /* Ensure this is the correct entry */
|
||||
+ TEST_ASSERT_EQUAL(0, efi_guid_cmp(&test_guid2, &(entry.partition_guid)));
|
||||
+ TEST_ASSERT_EQUAL(0, efi_guid_cmp(&test_type2, &(entry.type_guid)));
|
||||
+ TEST_ASSERT_EQUAL(desired2->start, entry.start);
|
||||
+ TEST_ASSERT_EQUAL(desired2->end, entry.start + entry.size - 1);
|
||||
+
|
||||
+ TEST_ASSERT_EQUAL_MEMORY(desired2->name, entry.name, GPT_ENTRY_NAME_LENGTH);
|
||||
+}
|
||||
+
|
||||
+void test_gpt_entry_read_by_type_should_failWhenEntryNotExisting(void)
|
||||
+{
|
||||
+ /* Start with an empty GPT */
|
||||
+ setup_empty_gpt();
|
||||
+
|
||||
+ /* Try to read something */
|
||||
+ struct partition_entry_t entry;
|
||||
+ struct efi_guid_t test_type = MAKE_EFI_GUID(11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1);
|
||||
+ TEST_ASSERT_EQUAL(PSA_ERROR_DOES_NOT_EXIST, gpt_entry_read_by_type(&test_type, 0, &entry));
|
||||
+
|
||||
+ /* Now, have a non-empty GPT but search for a type that won't exist */
|
||||
+ setup_valid_gpt();
|
||||
+
|
||||
+ /* Each entry should be read */
|
||||
+ register_mocked_read(&test_partition_array, sizeof(test_partition_array));
|
||||
+ TEST_ASSERT_EQUAL(PSA_ERROR_DOES_NOT_EXIST, gpt_entry_read_by_type(&test_type, 0, &entry));
|
||||
+
|
||||
+ /* Finally, search for the second entry of a type that appears only once */
|
||||
+ struct efi_guid_t existing_type = test_partition_array[0].type;
|
||||
+ efi_guid_cpy(&existing_type, &test_type);
|
||||
+ TEST_ASSERT_EQUAL(PSA_ERROR_DOES_NOT_EXIST, gpt_entry_read_by_type(&test_type, 1, &entry));
|
||||
+ TEST_ASSERT_EQUAL(PSA_ERROR_DOES_NOT_EXIST, gpt_entry_read_by_type(&test_type, TEST_DEFAULT_NUM_PARTITIONS, &entry));
|
||||
+}
|
||||
+961
@@ -0,0 +1,961 @@
|
||||
From 02ec696240d0225ed6473ea5b01ec6617d897a41 Mon Sep 17 00:00:00 2001
|
||||
From: Frazer Carsley <frazer.carsley@arm.com>
|
||||
Date: Wed, 11 Feb 2026 11:23:31 +0000
|
||||
Subject: [PATCH] lib: gpt: Added operations to modify partitions
|
||||
|
||||
The operations added allow the user to modify existing GPT partitions,
|
||||
apart from moving them; that is, they are all metadata changes. The
|
||||
library also handles updating both primary and backup partition entry
|
||||
arrays and headers after each modification.
|
||||
|
||||
Each modification on an entry is buffered in order to reduce the number
|
||||
of flash erase operations. A simple heuristic of "write on every n
|
||||
operations" is used to prevent infinite buffering. The buffering is most
|
||||
effective when consecutive entries are operated on. If the mapping of
|
||||
LBA to flash sector is not 1:1, the flash driver the platform registers
|
||||
with the library may implement its own buffering for further
|
||||
optimisation.
|
||||
|
||||
Change-Id: Ie358464427d66883e1681497a2630a8ef281e528
|
||||
Signed-off-by: Frazer Carsley <frazer.carsley@arm.com>
|
||||
Upstream-Status: Backport [ab942ecb7cb62bcfe1e5701f3f3adbf1eebd330a]
|
||||
---
|
||||
lib/gpt/CMakeLists.txt | 1 +
|
||||
lib/gpt/inc/gpt.h | 69 +++++
|
||||
lib/gpt/inc/gpt_flash.h | 41 ++-
|
||||
lib/gpt/src/gpt.c | 419 +++++++++++++++++++++++++++++-
|
||||
lib/gpt/unittests/gpt/test_gpt.c | 187 +++++++++++++
|
||||
lib/gpt/unittests/gpt/utcfg.cmake | 2 +
|
||||
6 files changed, 712 insertions(+), 7 deletions(-)
|
||||
|
||||
diff --git a/lib/gpt/CMakeLists.txt b/lib/gpt/CMakeLists.txt
|
||||
index 2b5d6af8f..25d0de9cd 100644
|
||||
--- a/lib/gpt/CMakeLists.txt
|
||||
+++ b/lib/gpt/CMakeLists.txt
|
||||
@@ -37,4 +37,5 @@ target_link_libraries(tfm_gpt
|
||||
tfm_log_headers
|
||||
PRIVATE
|
||||
tfm_efi_guid
|
||||
+ tfm_efi_soft_crc
|
||||
)
|
||||
diff --git a/lib/gpt/inc/gpt.h b/lib/gpt/inc/gpt.h
|
||||
index 947a6b341..6e7bb360e 100644
|
||||
--- a/lib/gpt/inc/gpt.h
|
||||
+++ b/lib/gpt/inc/gpt.h
|
||||
@@ -82,6 +82,75 @@ psa_status_t gpt_entry_read_by_type(const struct efi_guid_t *type,
|
||||
const uint32_t index,
|
||||
struct partition_entry_t *partition_entry);
|
||||
|
||||
+/**
|
||||
+ * \brief Renames a partition entry.
|
||||
+ *
|
||||
+ * \param[in] guid Entry to rename.
|
||||
+ * \param[in] name New unicode name for the entry.
|
||||
+ *
|
||||
+ * \retval PSA_SUCCESS Success.
|
||||
+ * \retval PSA_ERROR_STORAGE_FAILURE I/O error.
|
||||
+ * \retval PSA_ERROR_DOES_NOT_EXIST No entry found with the provided GUID.
|
||||
+ * \retval PSA_ERROR_INVALID_ARGUMENT Empty name.
|
||||
+ */
|
||||
+__attribute__((nonnull(1,2)))
|
||||
+psa_status_t gpt_entry_rename(const struct efi_guid_t *guid,
|
||||
+ const char name[GPT_ENTRY_NAME_LENGTH]);
|
||||
+
|
||||
+/**
|
||||
+ * \brief Changes the type of a partition.
|
||||
+ *
|
||||
+ * \param[in] guid Entry to update.
|
||||
+ * \param[in] type New type GUID.
|
||||
+ *
|
||||
+ * \retval PSA_SUCCESS Success.
|
||||
+ * \retval PSA_ERROR_STORAGE_FAILURE I/O error.
|
||||
+ * \retval PSA_ERROR_INVALID_ARGUMENT \p type is the null GUID.
|
||||
+ * \retval PSA_ERROR_DOES_NOT_EXIST No entry found with the provided GUID.
|
||||
+ */
|
||||
+__attribute__((nonnull(1,2)))
|
||||
+psa_status_t gpt_entry_change_type(const struct efi_guid_t *guid,
|
||||
+ const struct efi_guid_t *type);
|
||||
+
|
||||
+/**
|
||||
+ * \brief Adds attributes to a partition entry.
|
||||
+ *
|
||||
+ * \param[in] guid Entry to modify.
|
||||
+ * \param[in] attr Attributes to add.
|
||||
+ *
|
||||
+ * \retval PSA_SUCCESS Success.
|
||||
+ * \retval PSA_ERROR_STORAGE_FAILURE I/O error.
|
||||
+ * \retval PSA_ERROR_DOES_NOT_EXIST No entry found with the provided GUID.
|
||||
+ */
|
||||
+__attribute__((nonnull(1)))
|
||||
+psa_status_t gpt_attr_add(const struct efi_guid_t *guid, const uint64_t attr);
|
||||
+
|
||||
+/**
|
||||
+ * \brief Removes attributes from a partition entry.
|
||||
+ *
|
||||
+ * \param[in] guid Entry to modify.
|
||||
+ * \param[in] attr Attributes to remove.
|
||||
+ *
|
||||
+ * \retval PSA_SUCCESS Success.
|
||||
+ * \retval PSA_ERROR_STORAGE_FAILURE I/O error.
|
||||
+ * \retval PSA_ERROR_DOES_NOT_EXIST No entry found with the provided GUID.
|
||||
+ */
|
||||
+__attribute__((nonnull(1)))
|
||||
+psa_status_t gpt_attr_remove(const struct efi_guid_t *guid, const uint64_t attr);
|
||||
+
|
||||
+/**
|
||||
+ * \brief Sets attributes for a partition entry.
|
||||
+ *
|
||||
+ * \param[in] guid Entry to modify.
|
||||
+ * \param[in] attr Attributes to set.
|
||||
+ *
|
||||
+ * \retval PSA_SUCCESS Success.
|
||||
+ * \retval PSA_ERROR_STORAGE_FAILURE I/O error.
|
||||
+ * \retval PSA_ERROR_DOES_NOT_EXIST No entry found with the provided GUID.
|
||||
+ */
|
||||
+__attribute__((nonnull(1)))
|
||||
+psa_status_t gpt_attr_set(const struct efi_guid_t *guid, const uint64_t attr);
|
||||
+
|
||||
/**
|
||||
* \brief Reads the GPT header from the second block (LBA 1).
|
||||
*
|
||||
diff --git a/lib/gpt/inc/gpt_flash.h b/lib/gpt/inc/gpt_flash.h
|
||||
index 2b43390c1..ada5f6932 100644
|
||||
--- a/lib/gpt/inc/gpt_flash.h
|
||||
+++ b/lib/gpt/inc/gpt_flash.h
|
||||
@@ -57,13 +57,48 @@ __attribute__((nonnull(2)))
|
||||
typedef ssize_t (*gpt_flash_read_t)(uint64_t lba,
|
||||
void *buf);
|
||||
|
||||
+/**
|
||||
+ * \brief Function that writes to a logical block address.
|
||||
+ *
|
||||
+ * \param[in] lba Logical block address to write to.
|
||||
+ * \param[in] buf Buffer to write from. Must be at least the size of an LBA.
|
||||
+ *
|
||||
+ * \return Number of bytes written on success or a negative error code on failure.
|
||||
+ * \retval GPT_FLASH_NOT_INIT The flash driver has not been initialised.
|
||||
+ * \retval GPT_FLASH_UNAVAILABLE The flash driver is unavailable.
|
||||
+ * \retval GPT_FLASH_BAD_PARAM \p lba is not a valid address (for example larger than the flash size).
|
||||
+ * \retval GPT_FLASH_GENERIC_ERROR Unspecified error.
|
||||
+ */
|
||||
+__attribute__((nonnull(2)))
|
||||
+typedef ssize_t (*gpt_flash_write_t)(uint64_t lba,
|
||||
+ const void *buf);
|
||||
+
|
||||
+/**
|
||||
+ * \brief Function that erases consecutive logical blocks.
|
||||
+ *
|
||||
+ * \param[in] lba Starting logical block address.
|
||||
+ * \param[in] num_blocks Number of blocks to erase.
|
||||
+ *
|
||||
+ * \return Number of blocks erased on success or a negative error code on failure.
|
||||
+ * \retval GPT_FLASH_NOT_INIT The flash driver has not been initialised.
|
||||
+ * \retval GPT_FLASH_UNAVAILABLE The flash driver is unavailable.
|
||||
+ * \retval GPT_FLASH_BAD_PARAM \p num_blocks is zero.
|
||||
+ * \retval GPT_FLASH_BAD_PARAM One of the requested blocks is invalid (for example,
|
||||
+ * \p lba + \p num_blocks exceeds the flash size).
|
||||
+ * \retval GPT_FLASH_BAD_PARAM \p lba is not a valid address (for example larger than the flash size).
|
||||
+ * \retval GPT_FLASH_GENERIC_ERROR Unspecified error.
|
||||
+ */
|
||||
+typedef ssize_t (*gpt_flash_erase_t)(uint64_t lba, size_t num_blocks);
|
||||
+
|
||||
/**
|
||||
* \brief Interface for interacting with the flash driver.
|
||||
*/
|
||||
struct gpt_flash_driver_t {
|
||||
- gpt_flash_init_t init; /**< Flash initialisation routine. */
|
||||
- gpt_flash_uninit_t uninit; /**< Flash deinitialisation routine. */
|
||||
- gpt_flash_read_t read; /**< Routine used to read a logical block. */
|
||||
+ gpt_flash_init_t init; /**< Flash initialisation routine. */
|
||||
+ gpt_flash_uninit_t uninit; /**< Flash deinitialisation routine. */
|
||||
+ gpt_flash_read_t read; /**< Routine used to read a logical block. */
|
||||
+ gpt_flash_write_t write; /**< Routine used to write a logical block. */
|
||||
+ gpt_flash_erase_t erase; /**< Routine used to erase logical blocks. */
|
||||
};
|
||||
|
||||
#ifdef __cplusplus
|
||||
diff --git a/lib/gpt/src/gpt.c b/lib/gpt/src/gpt.c
|
||||
index 1662b81c2..2cfcdff07 100644
|
||||
--- a/lib/gpt/src/gpt.c
|
||||
+++ b/lib/gpt/src/gpt.c
|
||||
@@ -14,6 +14,7 @@
|
||||
#include "gpt_flash.h"
|
||||
#include "tfm_log.h"
|
||||
#include "efi_guid_structs.h"
|
||||
+#include "efi_soft_crc.h"
|
||||
|
||||
/* This needs to be defined by the platform and is used by the GPT library as
|
||||
* the number of bytes in a Logical Block Address (LBA)
|
||||
@@ -146,6 +147,15 @@ typedef bool (*gpt_entry_cmp_t)(const struct gpt_entry_t *, const void *);
|
||||
/* The LBA for the backup table */
|
||||
static uint64_t backup_gpt_lba = 0;
|
||||
|
||||
+/* The LBA for the partition array for the backup table. Rather than storing
|
||||
+ * the entire table header in memory, just this is stored so that updates can
|
||||
+ * be done without reading from flash
|
||||
+ */
|
||||
+static uint64_t backup_gpt_array_lba = 0;
|
||||
+
|
||||
+/* CRC for backup header. Because the LBAs differ, so too will the CRC */
|
||||
+static uint32_t backup_crc32 = 0;
|
||||
+
|
||||
/* The flash driver, used to perform I/O */
|
||||
static struct gpt_flash_driver_t *plat_flash_driver = NULL;
|
||||
|
||||
@@ -165,6 +175,9 @@ static uint8_t lba_buf[TFM_GPT_BLOCK_SIZE] = {0};
|
||||
*/
|
||||
static uint64_t cached_lba = 0;
|
||||
|
||||
+/* True if write was buffered */
|
||||
+static bool write_buffered = false;
|
||||
+
|
||||
/* Helper function prototypes */
|
||||
__attribute__((unused))
|
||||
static void print_guid(struct efi_guid_t guid);
|
||||
@@ -174,7 +187,9 @@ __attribute__((unused))
|
||||
static psa_status_t unicode_to_ascii(const char *unicode, char *ascii);
|
||||
static inline uint64_t partition_entry_lba(const struct gpt_t *table,
|
||||
uint32_t array_index);
|
||||
+static inline uint64_t partition_array_last_lba(const struct gpt_t *table);
|
||||
static inline uint64_t gpt_entry_per_lba_count(void);
|
||||
+static inline void swap_headers(const struct gpt_header_t *src, struct gpt_header_t *dst);
|
||||
static psa_status_t count_used_partitions(const struct gpt_t *table,
|
||||
uint32_t *num_used);
|
||||
static inline void parse_entry(struct gpt_entry_t *entry,
|
||||
@@ -184,6 +199,15 @@ static psa_status_t read_entry_from_flash(const struct gpt_t *table,
|
||||
uint32_t array_index,
|
||||
struct gpt_entry_t *entry);
|
||||
static psa_status_t read_table_from_flash(struct gpt_t *table, bool is_primary);
|
||||
+static psa_status_t flush_lba_buf(void);
|
||||
+static psa_status_t write_to_flash(uint64_t lba);
|
||||
+static psa_status_t write_entries_to_flash(uint32_t lbas_into_array, bool no_header_update);
|
||||
+static psa_status_t write_entry(uint32_t array_index,
|
||||
+ const struct gpt_entry_t *entry,
|
||||
+ bool no_header_update);
|
||||
+static psa_status_t write_header_to_flash(const struct gpt_t *table);
|
||||
+static psa_status_t write_headers_to_flash(void);
|
||||
+static psa_status_t update_header(uint32_t num_partitions);
|
||||
static psa_status_t find_gpt_entry(const struct gpt_t *table,
|
||||
gpt_entry_cmp_t compare,
|
||||
const void *attr,
|
||||
@@ -241,16 +265,146 @@ psa_status_t gpt_entry_read_by_type(const struct efi_guid_t *type,
|
||||
return PSA_SUCCESS;
|
||||
}
|
||||
|
||||
+psa_status_t gpt_entry_rename(const struct efi_guid_t *guid, const char name[GPT_ENTRY_NAME_LENGTH])
|
||||
+{
|
||||
+ if (name[0] == '\0') {
|
||||
+ return PSA_ERROR_INVALID_ARGUMENT;
|
||||
+ }
|
||||
+
|
||||
+ struct gpt_entry_t cached_entry;
|
||||
+ uint32_t cached_index;
|
||||
+ const psa_status_t ret = find_gpt_entry(
|
||||
+ &primary_gpt,
|
||||
+ gpt_entry_cmp_guid,
|
||||
+ guid,
|
||||
+ 0,
|
||||
+ &cached_entry,
|
||||
+ &cached_index);
|
||||
+ if (ret != PSA_SUCCESS) {
|
||||
+ return ret;
|
||||
+ }
|
||||
+
|
||||
+ /* NOOP if no name change. Prevents header update. */
|
||||
+ if (memcmp(cached_entry.name, name, GPT_ENTRY_NAME_LENGTH) == 0) {
|
||||
+ return PSA_SUCCESS;
|
||||
+ }
|
||||
+
|
||||
+ memcpy(cached_entry.name, name, GPT_ENTRY_NAME_LENGTH);
|
||||
+ cached_entry.name[GPT_ENTRY_NAME_LENGTH - 1] = '\0';
|
||||
+ cached_entry.name[GPT_ENTRY_NAME_LENGTH - 2] = '\0';
|
||||
+ return write_entry(cached_index, &cached_entry, false);
|
||||
+}
|
||||
+
|
||||
+psa_status_t gpt_entry_change_type(const struct efi_guid_t *guid, const struct efi_guid_t *type)
|
||||
+{
|
||||
+ struct efi_guid_t null_type = NULL_GUID;
|
||||
+ if (efi_guid_cmp(&null_type, type) == 0) {
|
||||
+ ERROR("Cannot set type to null-GUID; delete instead\n");
|
||||
+ return PSA_ERROR_INVALID_ARGUMENT;
|
||||
+ }
|
||||
+
|
||||
+ struct gpt_entry_t cached_entry;
|
||||
+ uint32_t cached_index;
|
||||
+ const psa_status_t ret = find_gpt_entry(
|
||||
+ &primary_gpt,
|
||||
+ gpt_entry_cmp_guid,
|
||||
+ guid,
|
||||
+ 0,
|
||||
+ &cached_entry,
|
||||
+ &cached_index);
|
||||
+ if (ret != PSA_SUCCESS) {
|
||||
+ return ret;
|
||||
+ }
|
||||
+
|
||||
+ cached_entry.partition_type = *type;
|
||||
+
|
||||
+ return write_entry(cached_index, &cached_entry, false);
|
||||
+}
|
||||
+
|
||||
+psa_status_t gpt_attr_add(const struct efi_guid_t *guid, const uint64_t attr)
|
||||
+{
|
||||
+ /* This quick check prevents I/O from happening for a no-op */
|
||||
+ if (attr == 0) {
|
||||
+ return PSA_SUCCESS;
|
||||
+ }
|
||||
+
|
||||
+ struct gpt_entry_t cached_entry;
|
||||
+ uint32_t cached_index;
|
||||
+ const psa_status_t ret = find_gpt_entry(
|
||||
+ &primary_gpt,
|
||||
+ gpt_entry_cmp_guid,
|
||||
+ guid,
|
||||
+ 0,
|
||||
+ &cached_entry,
|
||||
+ &cached_index);
|
||||
+ if (ret != PSA_SUCCESS) {
|
||||
+ return ret;
|
||||
+ }
|
||||
+
|
||||
+ cached_entry.attr |= attr;
|
||||
+
|
||||
+ return write_entry(cached_index, &cached_entry, false);
|
||||
+}
|
||||
+
|
||||
+psa_status_t gpt_attr_remove(const struct efi_guid_t *guid, const uint64_t attr)
|
||||
+{
|
||||
+ /* This quick check prevents I/O from happening for a no-op */
|
||||
+ if (attr == 0) {
|
||||
+ return PSA_SUCCESS;
|
||||
+ }
|
||||
+
|
||||
+ struct gpt_entry_t cached_entry;
|
||||
+ uint32_t cached_index;
|
||||
+ const psa_status_t ret = find_gpt_entry(
|
||||
+ &primary_gpt,
|
||||
+ gpt_entry_cmp_guid,
|
||||
+ guid,
|
||||
+ 0,
|
||||
+ &cached_entry,
|
||||
+ &cached_index);
|
||||
+ if (ret != PSA_SUCCESS) {
|
||||
+ return ret;
|
||||
+ }
|
||||
+
|
||||
+ cached_entry.attr &= ~(attr);
|
||||
+
|
||||
+ return write_entry(cached_index, &cached_entry, false);
|
||||
+}
|
||||
+
|
||||
+psa_status_t gpt_attr_set(const struct efi_guid_t *guid, const uint64_t attr)
|
||||
+{
|
||||
+ struct gpt_entry_t cached_entry;
|
||||
+ uint32_t cached_index;
|
||||
+ const psa_status_t ret = find_gpt_entry(
|
||||
+ &primary_gpt,
|
||||
+ gpt_entry_cmp_guid,
|
||||
+ guid,
|
||||
+ 0,
|
||||
+ &cached_entry,
|
||||
+ &cached_index);
|
||||
+ if (ret != PSA_SUCCESS) {
|
||||
+ return ret;
|
||||
+ }
|
||||
+
|
||||
+ cached_entry.attr = attr;
|
||||
+
|
||||
+ return write_entry(cached_index, &cached_entry, false);
|
||||
+}
|
||||
+
|
||||
/* Initialises GPT from first block. */
|
||||
psa_status_t gpt_init(struct gpt_flash_driver_t *flash_driver, uint64_t max_partitions)
|
||||
{
|
||||
cached_lba = 0;
|
||||
+ write_buffered = false;
|
||||
if (max_partitions < GPT_MIN_PARTITIONS) {
|
||||
ERROR("Minimum number of partitions is %d\n", GPT_MIN_PARTITIONS);
|
||||
return PSA_ERROR_INVALID_ARGUMENT;
|
||||
}
|
||||
|
||||
- if (flash_driver->read == NULL) {
|
||||
+ if (flash_driver->read == NULL ||
|
||||
+ flash_driver->write == NULL ||
|
||||
+ flash_driver->erase == NULL)
|
||||
+ {
|
||||
ERROR("I/O functions must be defined\n");
|
||||
return PSA_ERROR_INVALID_ARGUMENT;
|
||||
}
|
||||
@@ -303,6 +457,7 @@ psa_status_t gpt_init(struct gpt_flash_driver_t *flash_driver, uint64_t max_part
|
||||
if (ret != PSA_SUCCESS) {
|
||||
goto fail_load;
|
||||
}
|
||||
+ backup_gpt_array_lba = backup_gpt.header.array_lba;
|
||||
} else {
|
||||
WARN("Backup GPT location is unknown!\n");
|
||||
}
|
||||
@@ -314,7 +469,9 @@ fail_load:
|
||||
plat_flash_driver = NULL;
|
||||
plat_max_partitions = 0;
|
||||
backup_gpt_lba = 0;
|
||||
+ backup_gpt_array_lba = 0;
|
||||
cached_lba = 0;
|
||||
+ write_buffered = false;
|
||||
|
||||
return ret;
|
||||
}
|
||||
@@ -324,6 +481,11 @@ psa_status_t gpt_uninit(void)
|
||||
psa_status_t ret = PSA_SUCCESS;
|
||||
|
||||
if (plat_flash_driver) {
|
||||
+ /* Flush the in-memory buffer */
|
||||
+ if (write_buffered) {
|
||||
+ ret = flush_lba_buf();
|
||||
+ }
|
||||
+
|
||||
/* Uninitialise driver if function provided */
|
||||
if (plat_flash_driver->uninit != NULL) {
|
||||
if (plat_flash_driver->uninit() != 0) {
|
||||
@@ -336,7 +498,9 @@ psa_status_t gpt_uninit(void)
|
||||
plat_flash_driver = NULL;
|
||||
plat_max_partitions = 0;
|
||||
backup_gpt_lba = 0;
|
||||
+ backup_gpt_array_lba = 0;
|
||||
cached_lba = 0;
|
||||
+ write_buffered = false;
|
||||
|
||||
return ret;
|
||||
}
|
||||
@@ -422,6 +586,47 @@ static psa_status_t find_gpt_entry(const struct gpt_t *table,
|
||||
return io_failure ? PSA_ERROR_STORAGE_FAILURE : PSA_ERROR_DOES_NOT_EXIST;
|
||||
}
|
||||
|
||||
+/* Updates the header of the GPT based on new number of partitions */
|
||||
+static psa_status_t update_header(uint32_t num_partitions)
|
||||
+{
|
||||
+ primary_gpt.num_used_partitions = num_partitions;
|
||||
+ struct gpt_header_t *header = &(primary_gpt.header);
|
||||
+
|
||||
+ /* Take the CRC of the partition array */
|
||||
+ uint32_t crc = 0;
|
||||
+ for (uint32_t i = 0; i < header->num_partitions; ++i) {
|
||||
+ uint8_t entry_buf[header->entry_size];
|
||||
+ memset(entry_buf, 0, header->entry_size);
|
||||
+ struct gpt_entry_t *entry = (struct gpt_entry_t *)entry_buf;
|
||||
+
|
||||
+ psa_status_t ret = read_entry_from_flash(&primary_gpt, i, entry);
|
||||
+ if (ret != PSA_SUCCESS) {
|
||||
+ return ret;
|
||||
+ }
|
||||
+ crc = efi_soft_crc32_update(crc, entry_buf, header->entry_size);
|
||||
+ }
|
||||
+ header->array_crc = crc;
|
||||
+
|
||||
+ /* Calculate new CRC32 for primary header */
|
||||
+ header->header_crc = 0;
|
||||
+ header->header_crc = efi_soft_crc32_update(0, (uint8_t *)header, GPT_HEADER_SIZE);
|
||||
+
|
||||
+ /* Calculate new CRC32 for backup header */
|
||||
+ struct gpt_header_t backup_header = {0};
|
||||
+ swap_headers(header, &backup_header);
|
||||
+ backup_header.header_crc = 0;
|
||||
+ backup_crc32 = efi_soft_crc32_update(0, (uint8_t *)&backup_header, GPT_HEADER_SIZE);
|
||||
+
|
||||
+ /* Write headers */
|
||||
+ const psa_status_t ret = write_headers_to_flash();
|
||||
+ if (ret != PSA_SUCCESS) {
|
||||
+ ERROR("Unable to write headers to flash\n");
|
||||
+ return ret;
|
||||
+ }
|
||||
+
|
||||
+ return PSA_SUCCESS;
|
||||
+}
|
||||
+
|
||||
/* Load MBR from flash */
|
||||
static psa_status_t mbr_load(struct mbr_t *mbr)
|
||||
{
|
||||
@@ -452,10 +657,16 @@ static psa_status_t mbr_load(struct mbr_t *mbr)
|
||||
*/
|
||||
static psa_status_t read_from_flash(uint64_t required_lba)
|
||||
{
|
||||
- ssize_t ret;
|
||||
-
|
||||
if (required_lba != cached_lba) {
|
||||
- ret = plat_flash_driver->read(required_lba, lba_buf);
|
||||
+ if (write_buffered && cached_lba != 0) {
|
||||
+ psa_status_t ret = flush_lba_buf();
|
||||
+ if (ret != PSA_SUCCESS) {
|
||||
+ return ret;
|
||||
+ }
|
||||
+ }
|
||||
+ write_buffered = false;
|
||||
+
|
||||
+ ssize_t ret = plat_flash_driver->read(required_lba, lba_buf);
|
||||
if (ret != TFM_GPT_BLOCK_SIZE) {
|
||||
ERROR("Unable to read from flash at block 0x%08x%08x\n",
|
||||
(uint32_t)(required_lba >> 32),
|
||||
@@ -477,6 +688,14 @@ static uint64_t inline partition_entry_lba(const struct gpt_t *table,
|
||||
return table->header.array_lba + (array_index / gpt_entry_per_lba_count());
|
||||
}
|
||||
|
||||
+/* Returns the last LBA used by the partition entry array */
|
||||
+static uint64_t inline partition_array_last_lba(const struct gpt_t *table)
|
||||
+{
|
||||
+ return (table->num_used_partitions == 0 ?
|
||||
+ table->header.array_lba :
|
||||
+ partition_entry_lba(table, table->num_used_partitions - 1));
|
||||
+}
|
||||
+
|
||||
/* Returns the number of partition entries used in the array, assuming the
|
||||
* array is not sparse
|
||||
*/
|
||||
@@ -539,6 +758,198 @@ static psa_status_t read_table_from_flash(struct gpt_t *table, bool is_primary)
|
||||
return PSA_SUCCESS;
|
||||
}
|
||||
|
||||
+/* Writes the in-memory LBA buffer to flash, taking care of multiple writes if
|
||||
+ * needed.
|
||||
+ */
|
||||
+static psa_status_t flush_lba_buf(void)
|
||||
+{
|
||||
+ /* Prevent recursive calls, as the various writes below may attempt to
|
||||
+ * flush, particularly those making multiple writes
|
||||
+ */
|
||||
+ static bool in_flush = false;
|
||||
+ if (in_flush) {
|
||||
+ return PSA_SUCCESS;
|
||||
+ }
|
||||
+ in_flush = true;
|
||||
+ write_buffered = false;
|
||||
+ psa_status_t ret = PSA_SUCCESS;
|
||||
+
|
||||
+ /* Commit to flash what is in the buffer. Also update the backup table if
|
||||
+ * the cached LBA was part of the primary table (or vise-versa)
|
||||
+ */
|
||||
+ uint64_t array_size = partition_array_last_lba(&primary_gpt) - primary_gpt.header.array_lba + 1;
|
||||
+
|
||||
+ if (cached_lba == PRIMARY_GPT_LBA || (backup_gpt_lba != 0 && cached_lba == backup_gpt_lba)) {
|
||||
+ /* Write both backup and primary headers */
|
||||
+ ret = write_headers_to_flash();
|
||||
+ } else if (PRIMARY_GPT_ARRAY_LBA <= cached_lba &&
|
||||
+ cached_lba <= partition_array_last_lba(&primary_gpt))
|
||||
+ {
|
||||
+ /* Primary array entry. Write to backup and primary array */
|
||||
+ ret = write_entries_to_flash(cached_lba - PRIMARY_GPT_ARRAY_LBA, false);
|
||||
+ } else if (backup_gpt_array_lba != 0 &&
|
||||
+ backup_gpt_array_lba <= cached_lba &&
|
||||
+ cached_lba <= backup_gpt_array_lba + array_size - 1)
|
||||
+ {
|
||||
+ /* Backup array entry. Write to backup and primary array */
|
||||
+ ret = write_entries_to_flash(cached_lba - backup_gpt_array_lba, false);
|
||||
+ } else {
|
||||
+ /* Shouldn't be possible */
|
||||
+ ERROR("Unknown data in LBA cache, discarding\n");
|
||||
+ }
|
||||
+
|
||||
+ in_flush = false;
|
||||
+ return ret;
|
||||
+}
|
||||
+
|
||||
+/* Write to the flash at the specified LBA */
|
||||
+static psa_status_t write_to_flash(uint64_t lba)
|
||||
+{
|
||||
+ if (plat_flash_driver->erase(lba, 1) != 1) {
|
||||
+ ERROR("Unable to erase flash at LBA 0x%08x%08x\n",
|
||||
+ (uint32_t)(lba >> 32),
|
||||
+ (uint32_t)lba);
|
||||
+ return PSA_ERROR_STORAGE_FAILURE;
|
||||
+ }
|
||||
+
|
||||
+ if (plat_flash_driver->write(lba, lba_buf) != TFM_GPT_BLOCK_SIZE) {
|
||||
+ ERROR("Unable to program flash at LBA 0x%08x%08x\n",
|
||||
+ (uint32_t)(lba >> 32),
|
||||
+ (uint32_t)lba);
|
||||
+ return PSA_ERROR_STORAGE_FAILURE;
|
||||
+ }
|
||||
+
|
||||
+ return PSA_SUCCESS;
|
||||
+}
|
||||
+
|
||||
+/* Writes the in-memory buffer to both the primary and backup partition arrays.
|
||||
+ * This should only be used when it is certain that the cached lba is part of
|
||||
+ * either the primary or backup partition array
|
||||
+ */
|
||||
+static psa_status_t write_entries_to_flash(uint32_t lbas_into_array, bool no_header_update)
|
||||
+{
|
||||
+ psa_status_t ret;
|
||||
+
|
||||
+ if (backup_gpt_array_lba != 0) {
|
||||
+ ret = write_to_flash(backup_gpt_array_lba + lbas_into_array);
|
||||
+ if (ret != PSA_SUCCESS) {
|
||||
+ ERROR("Unable to write entry to backup partition array\n");
|
||||
+ return ret;
|
||||
+ }
|
||||
+ } else {
|
||||
+ WARN("Backup array LBA unknown!\n");
|
||||
+ }
|
||||
+
|
||||
+ ret = write_to_flash(PRIMARY_GPT_ARRAY_LBA + lbas_into_array);
|
||||
+ if (ret != PSA_SUCCESS) {
|
||||
+ ERROR("Unable to write entry to primary partition array\n");
|
||||
+ return ret;
|
||||
+ }
|
||||
+
|
||||
+ /* Update the header unless the user specifies not to, This might be useful
|
||||
+ * if it is known that multiple entries are being written, such as on removal
|
||||
+ * or defragmentation operations
|
||||
+ */
|
||||
+ if (!no_header_update) {
|
||||
+ return update_header(primary_gpt.num_used_partitions);
|
||||
+ }
|
||||
+
|
||||
+ return PSA_SUCCESS;
|
||||
+}
|
||||
+
|
||||
+/* Writes a GPT entry to flash or the in-memory buffer. The buffer is flushed
|
||||
+ * to both the primary and backup partition entry arrays ocassionally. When the
|
||||
+ * buffer is flushed, the header is updated unless no_header_update is true.
|
||||
+ */
|
||||
+static psa_status_t write_entry(uint32_t array_index,
|
||||
+ const struct gpt_entry_t *entry,
|
||||
+ bool no_header_update)
|
||||
+{
|
||||
+ /* Use this for a very simple, very dumb buffering heuristic. Flush every
|
||||
+ * time an LBA's worth of entries have been written (flush every nth
|
||||
+ * operation).
|
||||
+ */
|
||||
+ static uint32_t num_writes = 0;
|
||||
+
|
||||
+ /* First, ensure the entry is part of the buffered block. In most cases,
|
||||
+ * this will be a no-op
|
||||
+ */
|
||||
+ psa_status_t ret = read_from_flash(partition_entry_lba(&primary_gpt, array_index));
|
||||
+ if (ret != PSA_SUCCESS) {
|
||||
+ return ret;
|
||||
+ }
|
||||
+
|
||||
+ /* Copy into buffer */
|
||||
+ uint32_t index_in_lba = array_index % gpt_entry_per_lba_count();
|
||||
+ memcpy(lba_buf + index_in_lba * primary_gpt.header.entry_size, entry, GPT_ENTRY_SIZE);
|
||||
+
|
||||
+ /* Write on every nth operation. */
|
||||
+ if (++num_writes == gpt_entry_per_lba_count()) {
|
||||
+ /* Write the buffer to flash */
|
||||
+ num_writes = 0;
|
||||
+ write_buffered = false;
|
||||
+
|
||||
+ ret = write_entries_to_flash(cached_lba - PRIMARY_GPT_ARRAY_LBA, no_header_update);
|
||||
+ if (ret != PSA_SUCCESS) {
|
||||
+ return ret;
|
||||
+ }
|
||||
+ } else {
|
||||
+ write_buffered = true;
|
||||
+ }
|
||||
+
|
||||
+ return PSA_SUCCESS;
|
||||
+}
|
||||
+
|
||||
+/* Writes GPT header to flash. Returns PSA_SUCCESS on success or a PSA error on failure */
|
||||
+static psa_status_t write_header_to_flash(const struct gpt_t *table)
|
||||
+{
|
||||
+ /* Ensure the in-memory LBA buffer has the header. Because the header is
|
||||
+ * also in memory, there is no need to read it again before writing.
|
||||
+ */
|
||||
+ uint8_t temp_buf[GPT_HEADER_SIZE];
|
||||
+ memcpy(temp_buf, lba_buf, GPT_HEADER_SIZE);
|
||||
+ memcpy(lba_buf, &(table->header), GPT_HEADER_SIZE);
|
||||
+ const psa_status_t ret = write_to_flash(table->header.current_lba);
|
||||
+ memcpy(lba_buf, temp_buf, GPT_HEADER_SIZE);
|
||||
+
|
||||
+ return ret;
|
||||
+}
|
||||
+
|
||||
+/* Writes GPT headers for backup and primary tables to flash. */
|
||||
+static psa_status_t write_headers_to_flash(void)
|
||||
+{
|
||||
+ /* Backup table first, then primary */
|
||||
+ struct gpt_t backup_gpt;
|
||||
+ swap_headers(&(primary_gpt.header), &(backup_gpt.header));
|
||||
+ backup_gpt.header.header_crc = backup_crc32;
|
||||
+ psa_status_t ret = write_header_to_flash(&backup_gpt);
|
||||
+ if (ret != PSA_SUCCESS) {
|
||||
+ ERROR("Unable to write backup GPT header\n");
|
||||
+ return ret;
|
||||
+ }
|
||||
+
|
||||
+ ret = write_header_to_flash(&primary_gpt);
|
||||
+ if (ret != PSA_SUCCESS) {
|
||||
+ ERROR("Unable to write primary GPT header\n");
|
||||
+ }
|
||||
+
|
||||
+ return ret;
|
||||
+}
|
||||
+
|
||||
+/* Copies one header to another and swaps the fields referring to self
|
||||
+ * and alternate headers. This is useful for primary to backup copies
|
||||
+ * and vice-versa.
|
||||
+ */
|
||||
+static inline void swap_headers(const struct gpt_header_t *src, struct gpt_header_t *dst)
|
||||
+{
|
||||
+ memcpy(dst, src, GPT_HEADER_SIZE);
|
||||
+ dst->backup_lba = src->current_lba;
|
||||
+ dst->current_lba = src->backup_lba;
|
||||
+ dst->array_lba = (src->current_lba == PRIMARY_GPT_LBA ?
|
||||
+ backup_gpt_array_lba :
|
||||
+ primary_gpt.header.array_lba);
|
||||
+}
|
||||
+
|
||||
/* Converts unicode string to valid ascii */
|
||||
static psa_status_t unicode_to_ascii(const char *unicode, char *ascii)
|
||||
{
|
||||
diff --git a/lib/gpt/unittests/gpt/test_gpt.c b/lib/gpt/unittests/gpt/test_gpt.c
|
||||
index d6671f3fc..1121f7c73 100644
|
||||
--- a/lib/gpt/unittests/gpt/test_gpt.c
|
||||
+++ b/lib/gpt/unittests/gpt/test_gpt.c
|
||||
@@ -10,6 +10,7 @@
|
||||
|
||||
#include "unity.h"
|
||||
|
||||
+#include "mock_efi_soft_crc.h"
|
||||
#include "mock_tfm_log.h"
|
||||
#include "mock_tfm_vprintf.h"
|
||||
|
||||
@@ -133,12 +134,16 @@ struct gpt_header_t {
|
||||
|
||||
static void register_mocked_read(void *buf, size_t num_bytes);
|
||||
static ssize_t test_driver_read(uint64_t lba, void *buf);
|
||||
+static ssize_t test_driver_write(uint64_t lba, const void *buf);
|
||||
+static ssize_t test_driver_erase(uint64_t lba, size_t num_blocks);
|
||||
|
||||
/* LBA driver used in test module */
|
||||
static struct gpt_flash_driver_t mock_driver = {
|
||||
.init = NULL,
|
||||
.uninit = NULL,
|
||||
.read = test_driver_read,
|
||||
+ .write = test_driver_write,
|
||||
+ .erase = test_driver_erase,
|
||||
};
|
||||
|
||||
/* Valid MBR. Only signature is required to be valid */
|
||||
@@ -227,6 +232,17 @@ static ssize_t test_driver_read(uint64_t lba, void *buf)
|
||||
return TEST_BLOCK_SIZE;
|
||||
}
|
||||
|
||||
+/* Driver function that always succeeds in writing all data */
|
||||
+static ssize_t test_driver_write(uint64_t lba, const void *buf)
|
||||
+{
|
||||
+ return TEST_BLOCK_SIZE;
|
||||
+}
|
||||
+
|
||||
+static ssize_t test_driver_erase(uint64_t lba, size_t num_blocks)
|
||||
+{
|
||||
+ return num_blocks;
|
||||
+}
|
||||
+
|
||||
/* Creates backup table from test table and registers a read for it */
|
||||
static void setup_backup_gpt(void)
|
||||
{
|
||||
@@ -285,6 +301,9 @@ void setUp(void)
|
||||
|
||||
test_mbr.partitions[0].os_type = TEST_MBR_TYPE_GPT;
|
||||
|
||||
+ /* Any time this is called, return the same number and ignore the arguments */
|
||||
+ efi_soft_crc32_update_IgnoreAndReturn(test_header.header_crc);
|
||||
+
|
||||
/* Ignore all logging calls */
|
||||
tfm_log_Ignore();
|
||||
|
||||
@@ -337,6 +356,174 @@ void test_gpt_init_should_failWhenFlashDriverNotFullyDefined(void)
|
||||
mock_driver.read = NULL;
|
||||
TEST_ASSERT_EQUAL(PSA_ERROR_INVALID_ARGUMENT, gpt_init(&mock_driver, TEST_MAX_PARTITIONS));
|
||||
mock_driver.read = read_fn;
|
||||
+
|
||||
+ gpt_flash_write_t write_fn = mock_driver.write;
|
||||
+ mock_driver.write = NULL;
|
||||
+ TEST_ASSERT_EQUAL(PSA_ERROR_INVALID_ARGUMENT, gpt_init(&mock_driver, TEST_MAX_PARTITIONS));
|
||||
+ mock_driver.write = write_fn;
|
||||
+
|
||||
+ gpt_flash_erase_t erase_fn = mock_driver.erase;
|
||||
+ mock_driver.erase = NULL;
|
||||
+ TEST_ASSERT_EQUAL(PSA_ERROR_INVALID_ARGUMENT, gpt_init(&mock_driver, TEST_MAX_PARTITIONS));
|
||||
+ mock_driver.erase = erase_fn;
|
||||
+}
|
||||
+
|
||||
+void test_gpt_attr_set_should_setAttributes(void)
|
||||
+{
|
||||
+ /* Start with a populated GPT */
|
||||
+ setup_valid_gpt();
|
||||
+
|
||||
+ /* Entries are read */
|
||||
+ register_mocked_read(&test_partition_array, sizeof(test_partition_array));
|
||||
+
|
||||
+ struct efi_guid_t guid = test_partition_array[0].guid;
|
||||
+ TEST_ASSERT_EQUAL(PSA_SUCCESS, gpt_attr_set(&guid, 0x1));
|
||||
+}
|
||||
+
|
||||
+void test_gpt_attr_set_should_failWhenEntryNotExisting(void)
|
||||
+{
|
||||
+ setup_valid_gpt();
|
||||
+
|
||||
+ /* Read every entry */
|
||||
+ register_mocked_read(&test_partition_array, sizeof(test_partition_array));
|
||||
+
|
||||
+ struct efi_guid_t non_existing = NULL_GUID;
|
||||
+ TEST_ASSERT_EQUAL(PSA_ERROR_DOES_NOT_EXIST, gpt_attr_set(&non_existing, 0x1));
|
||||
+}
|
||||
+
|
||||
+void test_gpt_attr_remove_should_removeAttributes(void)
|
||||
+{
|
||||
+ /* Start with a populated GPT */
|
||||
+ struct gpt_entry_t *test_entry = &(test_partition_array[0]);
|
||||
+ uint64_t test_attr = 0x1;
|
||||
+ test_entry->attr = test_attr;
|
||||
+ setup_valid_gpt();
|
||||
+
|
||||
+ /* First entry is read */
|
||||
+ register_mocked_read(&test_partition_array, sizeof(test_partition_array));
|
||||
+
|
||||
+ struct efi_guid_t test_guid = test_entry->guid;
|
||||
+ TEST_ASSERT_EQUAL(PSA_SUCCESS, gpt_attr_set(&test_guid, test_attr));
|
||||
+}
|
||||
+
|
||||
+void test_gpt_attr_remove_should_failWhenEntryNotExisting(void)
|
||||
+{
|
||||
+ setup_valid_gpt();
|
||||
+
|
||||
+ /* Read every entry */
|
||||
+ register_mocked_read(&test_partition_array, sizeof(test_partition_array));
|
||||
+
|
||||
+ struct efi_guid_t non_existing = NULL_GUID;
|
||||
+ TEST_ASSERT_EQUAL(PSA_ERROR_DOES_NOT_EXIST, gpt_attr_remove(&non_existing, 0x1));
|
||||
+}
|
||||
+
|
||||
+void test_gpt_attr_add_should_addAttributes(void)
|
||||
+{
|
||||
+ /* Start with a populated GPT */
|
||||
+ struct gpt_entry_t *test_entry = &(test_partition_array[0]);
|
||||
+ setup_valid_gpt();
|
||||
+
|
||||
+ /* First entry is read */
|
||||
+ register_mocked_read(&test_partition_array, sizeof(test_partition_array));
|
||||
+
|
||||
+ struct efi_guid_t test_guid = test_entry->guid;
|
||||
+ TEST_ASSERT_EQUAL(PSA_SUCCESS, gpt_attr_add(&test_guid, 0x1));
|
||||
+}
|
||||
+
|
||||
+void test_gpt_attr_add_should_failWhenEntryNotExisting(void)
|
||||
+{
|
||||
+ setup_valid_gpt();
|
||||
+
|
||||
+ /* Read every entry */
|
||||
+ register_mocked_read(&test_partition_array, sizeof(test_partition_array));
|
||||
+
|
||||
+ struct efi_guid_t non_existing = NULL_GUID;
|
||||
+ TEST_ASSERT_EQUAL(PSA_ERROR_DOES_NOT_EXIST, gpt_attr_add(&non_existing, 0x1));
|
||||
+}
|
||||
+
|
||||
+void test_gpt_entry_change_type_should_setNewType(void)
|
||||
+{
|
||||
+ /* Start with a populated GPT */
|
||||
+ struct gpt_entry_t *test_entry = &(test_partition_array[0]);
|
||||
+ setup_valid_gpt();
|
||||
+
|
||||
+ /* First entry is read */
|
||||
+ register_mocked_read(&test_partition_array, sizeof(test_partition_array));
|
||||
+
|
||||
+ struct efi_guid_t test_guid = test_entry->guid;
|
||||
+
|
||||
+ /* Type validation is not a function of the library, as this is OS
|
||||
+ * dependent, so anything will do here.
|
||||
+ */
|
||||
+ struct efi_guid_t new_type = MAKE_EFI_GUID(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11);
|
||||
+ TEST_ASSERT_EQUAL(PSA_SUCCESS, gpt_entry_change_type(&test_guid, &new_type));
|
||||
+}
|
||||
+
|
||||
+void test_gpt_entry_change_type_should_failWhenEntryNotExisting(void)
|
||||
+{
|
||||
+ setup_valid_gpt();
|
||||
+
|
||||
+ /* Read every entry */
|
||||
+ register_mocked_read(&test_partition_array, sizeof(test_partition_array));
|
||||
+
|
||||
+ struct efi_guid_t non_existing = NULL_GUID;
|
||||
+ struct efi_guid_t new_type = MAKE_EFI_GUID(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11);
|
||||
+ TEST_ASSERT_EQUAL(PSA_ERROR_DOES_NOT_EXIST, gpt_entry_change_type(&non_existing, &new_type));
|
||||
+}
|
||||
+
|
||||
+void test_gpt_entry_change_type_should_failWhenSettingTypeToNullGuid(void)
|
||||
+{
|
||||
+ setup_valid_gpt();
|
||||
+
|
||||
+ struct gpt_entry_t *test_entry = &(test_partition_array[0]);
|
||||
+
|
||||
+ /* First entry is read */
|
||||
+ register_mocked_read(&test_partition_array, sizeof(test_partition_array));
|
||||
+
|
||||
+ struct efi_guid_t test_guid = test_entry->guid;
|
||||
+ struct efi_guid_t new_type = NULL_GUID;
|
||||
+
|
||||
+ TEST_ASSERT_EQUAL(PSA_ERROR_INVALID_ARGUMENT, gpt_entry_change_type(&test_guid, &new_type));
|
||||
+}
|
||||
+
|
||||
+void test_gpt_entry_rename_should_renameEntry(void)
|
||||
+{
|
||||
+ /* Start with a populated GPT */
|
||||
+ struct gpt_entry_t *test_entry = &(test_partition_array[0]);
|
||||
+ setup_valid_gpt();
|
||||
+
|
||||
+ /* First entry is read */
|
||||
+ register_mocked_read(&test_partition_array, sizeof(test_partition_array));
|
||||
+
|
||||
+ char new_name[GPT_ENTRY_NAME_LENGTH] = {'\0'};
|
||||
+ new_name[0] = 'a';
|
||||
+ struct efi_guid_t test_guid = test_entry->guid;
|
||||
+ TEST_ASSERT_EQUAL(PSA_SUCCESS, gpt_entry_rename(&test_guid, new_name));
|
||||
+}
|
||||
+
|
||||
+void test_gpt_entry_rename_should_failWhenNameIsEmpty(void)
|
||||
+{
|
||||
+ /* Start with a populated GPT */
|
||||
+ struct gpt_entry_t *test_entry = &(test_partition_array[0]);
|
||||
+ setup_valid_gpt();
|
||||
+
|
||||
+ /* Try to change name to an empty string */
|
||||
+ struct efi_guid_t test_guid = test_entry->guid;
|
||||
+ char name[GPT_ENTRY_NAME_LENGTH] = {'\0'};
|
||||
+ TEST_ASSERT_EQUAL(PSA_ERROR_INVALID_ARGUMENT, gpt_entry_rename(&test_guid, name));
|
||||
+}
|
||||
+
|
||||
+void test_gpt_entry_rename_should_failWhenEntryNotExisting(void)
|
||||
+{
|
||||
+ setup_valid_gpt();
|
||||
+
|
||||
+ /* Read every entry */
|
||||
+ register_mocked_read(&test_partition_array, sizeof(test_partition_array));
|
||||
+
|
||||
+ struct efi_guid_t non_existing = NULL_GUID;
|
||||
+ char new_name[GPT_ENTRY_NAME_LENGTH] = {'\0'};
|
||||
+ new_name[0] = 'a';
|
||||
+ TEST_ASSERT_EQUAL(PSA_ERROR_DOES_NOT_EXIST, gpt_entry_rename(&non_existing, new_name));
|
||||
}
|
||||
|
||||
void test_gpt_entry_read_should_populateEntry(void)
|
||||
diff --git a/lib/gpt/unittests/gpt/utcfg.cmake b/lib/gpt/unittests/gpt/utcfg.cmake
|
||||
index 37d72d138..620d15b4c 100644
|
||||
--- a/lib/gpt/unittests/gpt/utcfg.cmake
|
||||
+++ b/lib/gpt/unittests/gpt/utcfg.cmake
|
||||
@@ -15,12 +15,14 @@ set(UNIT_TEST_SUITE ${CMAKE_CURRENT_LIST_DIR}/test_gpt.c)
|
||||
list(APPEND UNIT_TEST_INCLUDE_DIRS ${TFM_ROOT_DIR}/interface/include)
|
||||
list(APPEND UNIT_TEST_INCLUDE_DIRS ${TFM_ROOT_DIR}/lib/efi_guid/inc)
|
||||
list(APPEND UNIT_TEST_INCLUDE_DIRS ${TFM_ROOT_DIR}/lib/gpt/inc)
|
||||
+list(APPEND UNIT_TEST_INCLUDE_DIRS ${TFM_ROOT_DIR}/lib/ext/efi_soft_crc/inc)
|
||||
list(APPEND UNIT_TEST_INCLUDE_DIRS ${TFM_ROOT_DIR}/lib/tfm_log/inc)
|
||||
list(APPEND UNIT_TEST_INCLUDE_DIRS ${TFM_ROOT_DIR}/lib/tfm_vprintf/inc)
|
||||
|
||||
# Headers to be mocked
|
||||
list(APPEND MOCK_HEADERS ${TFM_ROOT_DIR}/lib/tfm_log/inc/tfm_log.h)
|
||||
list(APPEND MOCK_HEADERS ${TFM_ROOT_DIR}/lib/tfm_vprintf/inc/tfm_vprintf.h)
|
||||
+list(APPEND MOCK_HEADERS ${TFM_ROOT_DIR}/lib/ext/efi_soft_crc/inc/efi_soft_crc.h)
|
||||
|
||||
# Compile-time definitions
|
||||
list(APPEND UNIT_TEST_COMPILE_DEFS LOG_LEVEL=LOG_LEVEL_VERBOSE)
|
||||
+374
@@ -0,0 +1,374 @@
|
||||
From 7a453edd736c919eccc40eec567e8e97c0597bba Mon Sep 17 00:00:00 2001
|
||||
From: Frazer Carsley <frazer.carsley@arm.com>
|
||||
Date: Tue, 30 Dec 2025 09:13:07 +0000
|
||||
Subject: [PATCH] lib: gpt: Added operation to move entry
|
||||
|
||||
The operation to move or resize an entry is not just a metadata change
|
||||
and actually moves the data the partition entry points to as well.
|
||||
|
||||
Change-Id: Id6b98dcb3d77366db19e453acfbe4af59697eaf6
|
||||
Signed-off-by: Frazer Carsley <frazer.carsley@arm.com>
|
||||
Upstream-Status: Backport [cbab5fd7757e9c06952c15ac7d30b0809b21406c]
|
||||
---
|
||||
lib/gpt/inc/gpt.h | 19 ++++
|
||||
lib/gpt/src/gpt.c | 156 ++++++++++++++++++++++++++++++-
|
||||
lib/gpt/unittests/gpt/test_gpt.c | 128 +++++++++++++++++++++++++
|
||||
3 files changed, 301 insertions(+), 2 deletions(-)
|
||||
|
||||
diff --git a/lib/gpt/inc/gpt.h b/lib/gpt/inc/gpt.h
|
||||
index 6e7bb360e..85f9bed9c 100644
|
||||
--- a/lib/gpt/inc/gpt.h
|
||||
+++ b/lib/gpt/inc/gpt.h
|
||||
@@ -151,6 +151,25 @@ psa_status_t gpt_attr_remove(const struct efi_guid_t *guid, const uint64_t attr)
|
||||
__attribute__((nonnull(1)))
|
||||
psa_status_t gpt_attr_set(const struct efi_guid_t *guid, const uint64_t attr);
|
||||
|
||||
+/**
|
||||
+ * \brief Moves (or resizes) a partition entry.
|
||||
+ *
|
||||
+ * \param[in] guid Entry to move.
|
||||
+ * \param[in] start New start LBA.
|
||||
+ * \param[in] end New end LBA.
|
||||
+ *
|
||||
+ * \retval PSA_SUCCESS Success.
|
||||
+ * \retval PSA_ERROR_STORAGE_FAILURE I/O error.
|
||||
+ * \retval PSA_ERROR_DOES_NOT_EXIST No entry found with the provided GUID.
|
||||
+ * \retval PSA_ERROR_INVALID_ARGUMENT Move would overlap with an existing partition.
|
||||
+ * \retval PSA_ERROR_INVALID_ARGUMENT \p end is less than \p start.
|
||||
+ * \retval PSA_ERROR_INVALID_ARGUMENT Part of the partition would move off flash.
|
||||
+ */
|
||||
+__attribute__((nonnull(1)))
|
||||
+psa_status_t gpt_entry_move(const struct efi_guid_t *guid,
|
||||
+ const uint64_t start,
|
||||
+ const uint64_t end);
|
||||
+
|
||||
/**
|
||||
* \brief Reads the GPT header from the second block (LBA 1).
|
||||
*
|
||||
diff --git a/lib/gpt/src/gpt.c b/lib/gpt/src/gpt.c
|
||||
index 2cfcdff07..40b73f3e9 100644
|
||||
--- a/lib/gpt/src/gpt.c
|
||||
+++ b/lib/gpt/src/gpt.c
|
||||
@@ -214,6 +214,10 @@ static psa_status_t find_gpt_entry(const struct gpt_t *table,
|
||||
const uint32_t repeat_index,
|
||||
struct gpt_entry_t *entry,
|
||||
uint32_t *array_index);
|
||||
+static psa_status_t move_lba(const uint64_t old_lba, const uint64_t new_lba);
|
||||
+static psa_status_t move_partition(const uint64_t old_lba,
|
||||
+ const uint64_t new_lba,
|
||||
+ const uint64_t num_blocks);
|
||||
static psa_status_t mbr_load(struct mbr_t *mbr);
|
||||
static bool gpt_entry_cmp_guid(const struct gpt_entry_t *entry, const void *guid);
|
||||
static bool gpt_entry_cmp_name(const struct gpt_entry_t *entry, const void *name);
|
||||
@@ -391,6 +395,111 @@ psa_status_t gpt_attr_set(const struct efi_guid_t *guid, const uint64_t attr)
|
||||
return write_entry(cached_index, &cached_entry, false);
|
||||
}
|
||||
|
||||
+psa_status_t gpt_entry_move(const struct efi_guid_t *guid,
|
||||
+ const uint64_t start,
|
||||
+ const uint64_t end)
|
||||
+{
|
||||
+ if (end < start) {
|
||||
+ return PSA_ERROR_INVALID_ARGUMENT;
|
||||
+ }
|
||||
+
|
||||
+ /* Must fit on flash */
|
||||
+ if (start < primary_gpt.header.first_lba ||
|
||||
+ end < primary_gpt.header.first_lba ||
|
||||
+ start > primary_gpt.header.last_lba ||
|
||||
+ end > primary_gpt.header.last_lba)
|
||||
+ {
|
||||
+ ERROR("Requested move would not be on disk\n");
|
||||
+ return PSA_ERROR_INVALID_ARGUMENT;
|
||||
+ }
|
||||
+
|
||||
+ struct gpt_entry_t cached_entry;
|
||||
+ uint32_t cached_index;
|
||||
+ psa_status_t ret = find_gpt_entry(
|
||||
+ &primary_gpt,
|
||||
+ gpt_entry_cmp_guid,
|
||||
+ guid,
|
||||
+ 0,
|
||||
+ &cached_entry,
|
||||
+ &cached_index);
|
||||
+ if (ret != PSA_SUCCESS) {
|
||||
+ return ret;
|
||||
+ }
|
||||
+
|
||||
+ /* Prevent unecessary I/O */
|
||||
+ if (start == cached_entry.start && end == cached_entry.end) {
|
||||
+ return PSA_SUCCESS;
|
||||
+ }
|
||||
+
|
||||
+ /* It is not possible to move a partition such that it overlaps with an
|
||||
+ * existing partition (other than itself). Check the currently cached LBA
|
||||
+ * first, then the others to avoid reading this LBA twice
|
||||
+ */
|
||||
+ struct gpt_entry_t entry;
|
||||
+ const uint64_t checked_lba = cached_lba;
|
||||
+ const uint64_t array_end_lba = partition_array_last_lba(&primary_gpt);
|
||||
+ uint32_t num_entries_in_cached_lba;
|
||||
+ if (cached_lba == array_end_lba) {
|
||||
+ /* If this is 0, then the last LBA is full */
|
||||
+ uint32_t num_entries_in_last_lba = primary_gpt.num_used_partitions % gpt_entry_per_lba_count();
|
||||
+ if (num_entries_in_last_lba == 0) {
|
||||
+ num_entries_in_cached_lba = gpt_entry_per_lba_count();
|
||||
+ } else {
|
||||
+ num_entries_in_cached_lba = num_entries_in_last_lba;
|
||||
+ }
|
||||
+ } else {
|
||||
+ num_entries_in_cached_lba = gpt_entry_per_lba_count();
|
||||
+ }
|
||||
+
|
||||
+ /* Cached LBA */
|
||||
+ for (uint32_t i = 0; i < num_entries_in_cached_lba; ++i) {
|
||||
+ memcpy(&entry, lba_buf + (i * primary_gpt.header.entry_size), GPT_ENTRY_SIZE);
|
||||
+
|
||||
+ const struct efi_guid_t ent_guid = entry.unique_guid;
|
||||
+ if (efi_guid_cmp(&ent_guid, guid) == 0) {
|
||||
+ continue;
|
||||
+ }
|
||||
+
|
||||
+ if ((start >= entry.start && start <= entry.end) ||
|
||||
+ (end >= entry.start && end <= entry.end) ||
|
||||
+ (start <= entry.start && end >= entry.end))
|
||||
+ {
|
||||
+ return PSA_ERROR_INVALID_ARGUMENT;
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ /* All the rest */
|
||||
+ for (uint32_t i = 0; i < primary_gpt.num_used_partitions; ++i) {
|
||||
+ if (partition_entry_lba(&primary_gpt, i) == checked_lba) {
|
||||
+ continue;
|
||||
+ }
|
||||
+
|
||||
+ ret = read_entry_from_flash(&primary_gpt, i, &entry);
|
||||
+ if (ret != PSA_SUCCESS) {
|
||||
+ return ret;
|
||||
+ }
|
||||
+
|
||||
+ if ((start >= entry.start && start <= entry.end) ||
|
||||
+ (end >= entry.start && end <= entry.end) ||
|
||||
+ (start <= entry.start && end >= entry.end))
|
||||
+ {
|
||||
+ return PSA_ERROR_INVALID_ARGUMENT;
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ ret = move_partition(
|
||||
+ cached_entry.start,
|
||||
+ start,
|
||||
+ end - start + 1);
|
||||
+ if (ret != PSA_SUCCESS) {
|
||||
+ return ret;
|
||||
+ }
|
||||
+ cached_entry.start = start;
|
||||
+ cached_entry.end = end;
|
||||
+
|
||||
+ return write_entry(cached_index, &cached_entry, false);
|
||||
+}
|
||||
+
|
||||
/* Initialises GPT from first block. */
|
||||
psa_status_t gpt_init(struct gpt_flash_driver_t *flash_driver, uint64_t max_partitions)
|
||||
{
|
||||
@@ -586,6 +695,49 @@ static psa_status_t find_gpt_entry(const struct gpt_t *table,
|
||||
return io_failure ? PSA_ERROR_STORAGE_FAILURE : PSA_ERROR_DOES_NOT_EXIST;
|
||||
}
|
||||
|
||||
+/* Move a single LBAs data to somewhere else */
|
||||
+static psa_status_t move_lba(const uint64_t old_lba, const uint64_t new_lba)
|
||||
+{
|
||||
+ const psa_status_t ret = read_from_flash(old_lba);
|
||||
+ if (ret != PSA_SUCCESS) {
|
||||
+ return ret;
|
||||
+ }
|
||||
+
|
||||
+ return write_to_flash(new_lba);
|
||||
+}
|
||||
+
|
||||
+/* Moves a partition's data to start from one logical block to another */
|
||||
+static psa_status_t move_partition(const uint64_t old_lba,
|
||||
+ const uint64_t new_lba,
|
||||
+ const uint64_t num_blocks)
|
||||
+{
|
||||
+ if (old_lba == new_lba) {
|
||||
+ return PSA_SUCCESS;
|
||||
+ }
|
||||
+
|
||||
+ if (old_lba < new_lba) {
|
||||
+ /* Move block by block backwards */
|
||||
+ for (uint64_t block = num_blocks; block > 0; --block) {
|
||||
+ const psa_status_t ret = move_lba(old_lba + block - 1, new_lba + block - 1);
|
||||
+ if (ret != PSA_SUCCESS) {
|
||||
+ return ret;
|
||||
+ }
|
||||
+ }
|
||||
+ } else {
|
||||
+ /* Move block by block forwards */
|
||||
+ for (uint64_t block = 0; block < num_blocks; ++block) {
|
||||
+ const psa_status_t ret = move_lba(old_lba + block, new_lba + block);
|
||||
+ if (ret != PSA_SUCCESS) {
|
||||
+ return ret;
|
||||
+ }
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ write_buffered = false;
|
||||
+
|
||||
+ return PSA_SUCCESS;
|
||||
+}
|
||||
+
|
||||
/* Updates the header of the GPT based on new number of partitions */
|
||||
static psa_status_t update_header(uint32_t num_partitions)
|
||||
{
|
||||
@@ -794,8 +946,8 @@ static psa_status_t flush_lba_buf(void)
|
||||
/* Backup array entry. Write to backup and primary array */
|
||||
ret = write_entries_to_flash(cached_lba - backup_gpt_array_lba, false);
|
||||
} else {
|
||||
- /* Shouldn't be possible */
|
||||
- ERROR("Unknown data in LBA cache, discarding\n");
|
||||
+ /* Some other LBA is cached, possibly data. Write it anyway */
|
||||
+ ret = write_to_flash(cached_lba);
|
||||
}
|
||||
|
||||
in_flush = false;
|
||||
diff --git a/lib/gpt/unittests/gpt/test_gpt.c b/lib/gpt/unittests/gpt/test_gpt.c
|
||||
index 1121f7c73..251b04ee9 100644
|
||||
--- a/lib/gpt/unittests/gpt/test_gpt.c
|
||||
+++ b/lib/gpt/unittests/gpt/test_gpt.c
|
||||
@@ -368,6 +368,134 @@ void test_gpt_init_should_failWhenFlashDriverNotFullyDefined(void)
|
||||
mock_driver.erase = erase_fn;
|
||||
}
|
||||
|
||||
+void test_gpt_entry_move_should_moveEntry(void)
|
||||
+{
|
||||
+ /* Start with a populated GPT */
|
||||
+ setup_valid_gpt();
|
||||
+ struct gpt_entry_t *test_entry = &(test_partition_array[TEST_DEFAULT_NUM_PARTITIONS - 1]);
|
||||
+ struct efi_guid_t test_guid = test_entry->guid;
|
||||
+
|
||||
+ /* First all entries are read to determine for overlap */
|
||||
+ register_mocked_read(&test_partition_array, sizeof(test_partition_array));
|
||||
+
|
||||
+ /* Move the partition. Read each block to then write. It doesn't matter what
|
||||
+ * the data is
|
||||
+ */
|
||||
+ char unused_read_data = 'X';
|
||||
+ register_mocked_read(&unused_read_data, sizeof(unused_read_data));
|
||||
+
|
||||
+ /* Header update - reads partition array to calculate crc32 and also then
|
||||
+ * reads the header to modify and write back
|
||||
+ */
|
||||
+ register_mocked_read(&test_partition_array, sizeof(test_partition_array));
|
||||
+ register_mocked_read(&test_header, sizeof(test_header));
|
||||
+
|
||||
+ /* Do a valid move and resize in one */
|
||||
+ TEST_ASSERT_EQUAL(PSA_SUCCESS, gpt_entry_move(
|
||||
+ &test_guid,
|
||||
+ TEST_GPT_THIRD_PARTITION_END + 1,
|
||||
+ TEST_GPT_THIRD_PARTITION_END + 1));
|
||||
+}
|
||||
+
|
||||
+void test_gpt_entry_move_should_failWhenEntryNotExisting(void)
|
||||
+{
|
||||
+ setup_valid_gpt();
|
||||
+
|
||||
+ /* Read every entry */
|
||||
+ register_mocked_read(&test_partition_array, sizeof(test_partition_array));
|
||||
+
|
||||
+ struct efi_guid_t non_existing = NULL_GUID;
|
||||
+ TEST_ASSERT_EQUAL(PSA_ERROR_DOES_NOT_EXIST, gpt_entry_move(
|
||||
+ &non_existing,
|
||||
+ TEST_GPT_THIRD_PARTITION_END + 1,
|
||||
+ TEST_GPT_THIRD_PARTITION_END + 1));
|
||||
+}
|
||||
+
|
||||
+void test_gpt_entry_move_should_failWhenEndLessThanStart(void)
|
||||
+{
|
||||
+ setup_valid_gpt();
|
||||
+
|
||||
+ struct efi_guid_t test_guid = test_partition_array[0].guid;
|
||||
+ TEST_ASSERT_EQUAL(PSA_ERROR_INVALID_ARGUMENT, gpt_entry_move(
|
||||
+ &test_guid,
|
||||
+ TEST_GPT_THIRD_PARTITION_END + 2,
|
||||
+ TEST_GPT_THIRD_PARTITION_END + 1));
|
||||
+}
|
||||
+
|
||||
+void test_gpt_entry_move_should_failWhenLbaOverlapping(void)
|
||||
+{
|
||||
+ setup_valid_gpt();
|
||||
+
|
||||
+ /* Try to move an entry. Each entry is read to determine for overlap */
|
||||
+ size_t test_index = 1;
|
||||
+ struct gpt_entry_t *test_entry = &(test_partition_array[test_index]);
|
||||
+ struct efi_guid_t test_guid = test_entry->guid;
|
||||
+ register_mocked_read(&test_partition_array, sizeof(test_partition_array));
|
||||
+
|
||||
+ /* Try to move the test entry into the middle of the entry just read.
|
||||
+ * Starting at the same LBA
|
||||
+ */
|
||||
+ TEST_ASSERT_EQUAL(PSA_ERROR_INVALID_ARGUMENT, gpt_entry_move(
|
||||
+ &test_guid,
|
||||
+ TEST_GPT_FIRST_PARTITION_START,
|
||||
+ TEST_GPT_SECOND_PARTITION_END));
|
||||
+
|
||||
+ /* Try to move the test entry into the middle of the entry just read.
|
||||
+ * Starting in the middle
|
||||
+ */
|
||||
+ TEST_ASSERT_EQUAL(PSA_ERROR_INVALID_ARGUMENT, gpt_entry_move(
|
||||
+ &test_guid,
|
||||
+ TEST_GPT_FIRST_PARTITION_START + 1,
|
||||
+ TEST_GPT_SECOND_PARTITION_END));
|
||||
+
|
||||
+ TEST_ASSERT_EQUAL(PSA_ERROR_INVALID_ARGUMENT, gpt_entry_move(
|
||||
+ &test_guid,
|
||||
+ TEST_GPT_SECOND_PARTITION_START,
|
||||
+ TEST_GPT_THIRD_PARTITION_START));
|
||||
+
|
||||
+ /* Try to move the test entry into the middle of the entry just read.
|
||||
+ * Starting and ending in the middle.
|
||||
+ */
|
||||
+ TEST_ASSERT_EQUAL(PSA_ERROR_INVALID_ARGUMENT, gpt_entry_move(
|
||||
+ &test_guid,
|
||||
+ TEST_GPT_FIRST_PARTITION_START + 1,
|
||||
+ TEST_GPT_FIRST_PARTITION_START + 1));
|
||||
+}
|
||||
+
|
||||
+void test_gpt_entry_move_should_failWhenLbaOffDisk(void)
|
||||
+{
|
||||
+ setup_valid_gpt();
|
||||
+
|
||||
+ /* Try to move an entry. */
|
||||
+ size_t test_index = 1;
|
||||
+ struct gpt_entry_t *test_entry = &(test_partition_array[test_index]);
|
||||
+ struct efi_guid_t test_guid = test_entry->guid;
|
||||
+
|
||||
+ /* First start on disk, then go off the disk */
|
||||
+ TEST_ASSERT_EQUAL(PSA_ERROR_INVALID_ARGUMENT, gpt_entry_move(
|
||||
+ &test_guid,
|
||||
+ TEST_GPT_THIRD_PARTITION_END + 1,
|
||||
+ TEST_DISK_NUM_BLOCKS + 1));
|
||||
+
|
||||
+ /* Second, start off the disk entirely */
|
||||
+ TEST_ASSERT_EQUAL(PSA_ERROR_INVALID_ARGUMENT, gpt_entry_move(
|
||||
+ &test_guid,
|
||||
+ TEST_DISK_NUM_BLOCKS + 1,
|
||||
+ TEST_DISK_NUM_BLOCKS + 2));
|
||||
+
|
||||
+ /* Third, do the same but in the header area */
|
||||
+ TEST_ASSERT_EQUAL(PSA_ERROR_INVALID_ARGUMENT, gpt_entry_move(
|
||||
+ &test_guid,
|
||||
+ TEST_GPT_PRIMARY_LBA,
|
||||
+ TEST_GPT_THIRD_PARTITION_END + 2));
|
||||
+
|
||||
+ /* Fourth, start in the backup header area */
|
||||
+ TEST_ASSERT_EQUAL(PSA_ERROR_INVALID_ARGUMENT, gpt_entry_move(
|
||||
+ &test_guid,
|
||||
+ TEST_GPT_BACKUP_LBA,
|
||||
+ TEST_GPT_BACKUP_LBA + 1));
|
||||
+}
|
||||
+
|
||||
void test_gpt_attr_set_should_setAttributes(void)
|
||||
{
|
||||
/* Start with a populated GPT */
|
||||
+713
@@ -0,0 +1,713 @@
|
||||
From bec8f44a2732c20e8f69a06841637673af90c37e Mon Sep 17 00:00:00 2001
|
||||
From: Frazer Carsley <frazer.carsley@arm.com>
|
||||
Date: Tue, 30 Dec 2025 10:16:21 +0000
|
||||
Subject: [PATCH] lib: gpt: Added ability to create and remove partitions
|
||||
|
||||
With this change, new GPT partitions can be created and added to the
|
||||
table and old partitions can be removed. Both of these are metadata
|
||||
changes and only make changes to the partition entry array and header
|
||||
(primary and backup).
|
||||
|
||||
New partitions must be created in empty space only. The data that the
|
||||
partition points to is not cleared and if desired this should be done by
|
||||
the caller before or after creation.
|
||||
|
||||
When a partition is removed, the data it pointed to is not cleared so
|
||||
this should be done by the caller if desired. After removal, that data
|
||||
is considered empty space.
|
||||
|
||||
Change-Id: Iecccb814aaf8f48cbdd8e29b3d2b54fb5b58aae8
|
||||
Signed-off-by: Frazer Carsley <frazer.carsley@arm.com>
|
||||
Upstream-Status: Backport [4d69babc99917e3cc2df284a311ec37004c3ee3f]
|
||||
---
|
||||
lib/gpt/CMakeLists.txt | 1 +
|
||||
lib/gpt/inc/gpt.h | 37 +++
|
||||
lib/gpt/src/gpt.c | 249 ++++++++++++++-
|
||||
lib/gpt/unittests/gpt/test_gpt.c | 284 ++++++++++++++++++
|
||||
lib/gpt/unittests/gpt/utcfg.cmake | 2 +
|
||||
.../include/mbedtls/mbedtls_config.h | 18 ++
|
||||
6 files changed, 590 insertions(+), 1 deletion(-)
|
||||
create mode 100644 lib/gpt/unittests/include/mbedtls/mbedtls_config.h
|
||||
|
||||
diff --git a/lib/gpt/CMakeLists.txt b/lib/gpt/CMakeLists.txt
|
||||
index 25d0de9cd..5befc346f 100644
|
||||
--- a/lib/gpt/CMakeLists.txt
|
||||
+++ b/lib/gpt/CMakeLists.txt
|
||||
@@ -23,6 +23,7 @@ target_sources(tfm_gpt
|
||||
target_include_directories(tfm_gpt
|
||||
PUBLIC
|
||||
$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/inc>
|
||||
+ $<INSTALL_INTERFACE:inc>
|
||||
)
|
||||
|
||||
target_compile_definitions(tfm_gpt
|
||||
diff --git a/lib/gpt/inc/gpt.h b/lib/gpt/inc/gpt.h
|
||||
index 85f9bed9c..f04643957 100644
|
||||
--- a/lib/gpt/inc/gpt.h
|
||||
+++ b/lib/gpt/inc/gpt.h
|
||||
@@ -170,6 +170,43 @@ psa_status_t gpt_entry_move(const struct efi_guid_t *guid,
|
||||
const uint64_t start,
|
||||
const uint64_t end);
|
||||
|
||||
+/**
|
||||
+ * \brief Creates a partition entry in the table.
|
||||
+ *
|
||||
+ * \param[in] type Partition type.
|
||||
+ * \param[in] start Starting LBA (0 uses the lowest free LBA possible).
|
||||
+ * \param[in] size Size of the partition in LBAs.
|
||||
+ * \param[in] attr Attributes for the partition.
|
||||
+ * \param[in] name Partition name in unicode.
|
||||
+ * \param[out] guid GUID populated on success for subsequent API calls.
|
||||
+ *
|
||||
+ * \retval PSA_SUCCESS Success.
|
||||
+ * \retval PSA_ERROR_STORAGE_FAILURE I/O error.
|
||||
+ * \retval PSA_ERROR_INSUFFICIENT_STORAGE Maximum number of partitions reached.
|
||||
+ * \retval PSA_ERROR_INVALID_ARGUMENT Partition would extend beyond the flash.
|
||||
+ * \retval PSA_ERROR_INVALID_ARGUMENT New entry would overlap an existing partition, the name is empty,
|
||||
+ * or \p size is zero.
|
||||
+ */
|
||||
+__attribute__((nonnull(1,5,6)))
|
||||
+psa_status_t gpt_entry_create(const struct efi_guid_t *type,
|
||||
+ const uint64_t start,
|
||||
+ const uint64_t size,
|
||||
+ const uint64_t attr,
|
||||
+ const char name[GPT_ENTRY_NAME_LENGTH],
|
||||
+ struct efi_guid_t *guid);
|
||||
+
|
||||
+/**
|
||||
+ * \brief Removes a partition entry from the table.
|
||||
+ *
|
||||
+ * \param[in] guid Entry to remove.
|
||||
+ *
|
||||
+ * \retval PSA_SUCCESS Success.
|
||||
+ * \retval PSA_ERROR_STORAGE_FAILURE I/O error.
|
||||
+ * \retval PSA_ERROR_DOES_NOT_EXIST No entry found with the provided GUID.
|
||||
+ */
|
||||
+__attribute__((nonnull(1)))
|
||||
+psa_status_t gpt_entry_remove(const struct efi_guid_t *guid);
|
||||
+
|
||||
/**
|
||||
* \brief Reads the GPT header from the second block (LBA 1).
|
||||
*
|
||||
diff --git a/lib/gpt/src/gpt.c b/lib/gpt/src/gpt.c
|
||||
index 40b73f3e9..676f04fd6 100644
|
||||
--- a/lib/gpt/src/gpt.c
|
||||
+++ b/lib/gpt/src/gpt.c
|
||||
@@ -9,11 +9,12 @@
|
||||
#include <string.h>
|
||||
#include <inttypes.h>
|
||||
|
||||
-#include "psa/error.h"
|
||||
+#include "psa/crypto.h"
|
||||
#include "gpt.h"
|
||||
#include "gpt_flash.h"
|
||||
#include "tfm_log.h"
|
||||
#include "efi_guid_structs.h"
|
||||
+#include "efi_guid.h"
|
||||
#include "efi_soft_crc.h"
|
||||
|
||||
/* This needs to be defined by the platform and is used by the GPT library as
|
||||
@@ -500,6 +501,252 @@ psa_status_t gpt_entry_move(const struct efi_guid_t *guid,
|
||||
return write_entry(cached_index, &cached_entry, false);
|
||||
}
|
||||
|
||||
+psa_status_t gpt_entry_create(const struct efi_guid_t *type,
|
||||
+ const uint64_t start,
|
||||
+ const uint64_t size,
|
||||
+ const uint64_t attr,
|
||||
+ const char name[GPT_ENTRY_NAME_LENGTH],
|
||||
+ struct efi_guid_t *guid)
|
||||
+{
|
||||
+ /* Using inequlity here handles when reading an initial GPT has more than
|
||||
+ * the maximum defined number of partitions.
|
||||
+ */
|
||||
+ if (primary_gpt.num_used_partitions >= plat_max_partitions) {
|
||||
+ ERROR("Maximum number of partitions reached\n");
|
||||
+ return PSA_ERROR_INSUFFICIENT_STORAGE;
|
||||
+ }
|
||||
+ if (size == 0) {
|
||||
+ ERROR("Cannot create entry of size 0\n");
|
||||
+ return PSA_ERROR_INVALID_ARGUMENT;
|
||||
+ }
|
||||
+ if (name[0] == '\0') {
|
||||
+ ERROR("Cannot create entry with no name\n");
|
||||
+ return PSA_ERROR_INVALID_ARGUMENT;
|
||||
+ }
|
||||
+
|
||||
+ uint64_t start_lba = start;
|
||||
+ psa_status_t ret = PSA_SUCCESS;
|
||||
+ if (start_lba == 0) {
|
||||
+ /* Use the lowest free LBA possible. Each partition uses contiguous space,
|
||||
+ * so if there is a gap between partitions, that will be shown by the end
|
||||
+ * and start not being contiguous.
|
||||
+ */
|
||||
+ uint64_t prev_end = primary_gpt.header.first_lba;
|
||||
+ for (uint32_t i = 0; i < primary_gpt.header.num_partitions; ++i) {
|
||||
+ struct gpt_entry_t entry = {0};
|
||||
+ ret = read_entry_from_flash(&primary_gpt, i, &entry);
|
||||
+ if (ret != PSA_SUCCESS) {
|
||||
+ return ret;
|
||||
+ }
|
||||
+
|
||||
+ if (entry.start - 1 > prev_end) {
|
||||
+ start_lba = prev_end + 1;
|
||||
+ break;
|
||||
+ }
|
||||
+ prev_end = entry.end;
|
||||
+ }
|
||||
+
|
||||
+ if (start_lba != prev_end + 1) {
|
||||
+ /* No free space */
|
||||
+ ERROR("No free space on device!\n");
|
||||
+ return PSA_ERROR_INSUFFICIENT_STORAGE;
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ /* Must fit on flash */
|
||||
+ const uint64_t end_lba = start_lba + size - 1;
|
||||
+ if (start_lba < primary_gpt.header.first_lba ||
|
||||
+ end_lba < primary_gpt.header.first_lba ||
|
||||
+ start_lba > primary_gpt.header.last_lba ||
|
||||
+ end_lba > primary_gpt.header.last_lba)
|
||||
+ {
|
||||
+ ERROR("Requested partition would not be on disk\n");
|
||||
+ return PSA_ERROR_INVALID_ARGUMENT;
|
||||
+ }
|
||||
+
|
||||
+ /* Do not allow overlapping partitions */
|
||||
+ struct gpt_entry_t entry;
|
||||
+ for (uint32_t i = 0; i < primary_gpt.num_used_partitions; ++i) {
|
||||
+ ret = read_entry_from_flash(&primary_gpt, i, &entry);
|
||||
+ if (ret != PSA_SUCCESS) {
|
||||
+ return ret;
|
||||
+ }
|
||||
+
|
||||
+ if ((start_lba >= entry.start && start_lba <= entry.end) ||
|
||||
+ (end_lba >= entry.start && end_lba <= entry.end) ||
|
||||
+ (start_lba <= entry.start && end_lba >= entry.end))
|
||||
+ {
|
||||
+ return PSA_ERROR_INVALID_ARGUMENT;
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ /* Generate the new random GUID */
|
||||
+ if (efi_guid_generate_random(guid) != PSA_SUCCESS) {
|
||||
+ ERROR("Unable to generate GUID\n");
|
||||
+ return PSA_ERROR_STORAGE_FAILURE;
|
||||
+ }
|
||||
+
|
||||
+ /* Set new entry's metadata */
|
||||
+ struct gpt_entry_t new_entry = {0};
|
||||
+ new_entry.start = start_lba;
|
||||
+ new_entry.end = end_lba;
|
||||
+ new_entry.attr = attr;
|
||||
+ memcpy(new_entry.name, name, GPT_ENTRY_NAME_LENGTH);
|
||||
+ new_entry.partition_type = *type;
|
||||
+ new_entry.unique_guid = *guid;
|
||||
+
|
||||
+ /* Write the new entry. Skip header update as it is explicitely called
|
||||
+ * below with new number of partitions
|
||||
+ */
|
||||
+ ret = write_entry(primary_gpt.num_used_partitions++, &new_entry, true);
|
||||
+ if (ret != PSA_SUCCESS) {
|
||||
+ --primary_gpt.num_used_partitions;
|
||||
+ return ret;
|
||||
+ }
|
||||
+
|
||||
+ /* Flush the buffered LBA if not done so. This will cause the header to be
|
||||
+ * updated
|
||||
+ */
|
||||
+ if (write_buffered) {
|
||||
+ /* flush_lba_buf will update the header */
|
||||
+ ret = flush_lba_buf();
|
||||
+ } else {
|
||||
+ ret = update_header(primary_gpt.num_used_partitions);
|
||||
+ }
|
||||
+
|
||||
+ if (ret != PSA_SUCCESS) {
|
||||
+ return ret;
|
||||
+ }
|
||||
+
|
||||
+ return PSA_SUCCESS;
|
||||
+}
|
||||
+
|
||||
+psa_status_t gpt_entry_remove(const struct efi_guid_t *guid)
|
||||
+{
|
||||
+ struct gpt_entry_t cached_entry;
|
||||
+ uint32_t cached_index;
|
||||
+ psa_status_t ret = find_gpt_entry(
|
||||
+ &primary_gpt,
|
||||
+ gpt_entry_cmp_guid,
|
||||
+ guid,
|
||||
+ 0,
|
||||
+ &cached_entry,
|
||||
+ &cached_index);
|
||||
+ if (ret != PSA_SUCCESS) {
|
||||
+ return ret;
|
||||
+ }
|
||||
+
|
||||
+ /* Shuffle the remainder of the array up. This will overwrite the
|
||||
+ * most previous entry.
|
||||
+ *
|
||||
+ * The first LBA to potentially modify is in memory. It doesn't need
|
||||
+ * to be modified if the last entry in the array was moved or if it is
|
||||
+ * the only LBA used by the partition array
|
||||
+ */
|
||||
+ if (cached_index != primary_gpt.num_used_partitions - 1 ||
|
||||
+ cached_index < gpt_entry_per_lba_count())
|
||||
+ {
|
||||
+ /* Shuffle up the remainder of the LBA. If it was the last entry
|
||||
+ * in the LBA, there is nothing to do.
|
||||
+ */
|
||||
+ const uint32_t lba_index = cached_index % gpt_entry_per_lba_count();
|
||||
+ if (lba_index + 1 != gpt_entry_per_lba_count()) {
|
||||
+ memmove(
|
||||
+ lba_buf + lba_index * primary_gpt.header.entry_size,
|
||||
+ lba_buf + (lba_index + 1) * primary_gpt.header.entry_size,
|
||||
+ (gpt_entry_per_lba_count() - lba_index - 1) * primary_gpt.header.entry_size);
|
||||
+ }
|
||||
+
|
||||
+ /* If this is not the last LBA, then read the next LBA into memory and
|
||||
+ * place it's first element in the final slot of the currently modified
|
||||
+ * LBA. Repeat this for each LBA read.
|
||||
+ *
|
||||
+ * Use a second buffer to read each consecutive LBA and copy that to
|
||||
+ * the global LBA buffer to then write afterwards.
|
||||
+ */
|
||||
+ const uint64_t array_end_lba = partition_array_last_lba(&primary_gpt);
|
||||
+ for (uint64_t i = partition_entry_lba(&primary_gpt, cached_index) + 1;
|
||||
+ i <= array_end_lba;
|
||||
+ ++i)
|
||||
+ {
|
||||
+ uint8_t array_buf[TFM_GPT_BLOCK_SIZE] = {0};
|
||||
+ int read_ret = plat_flash_driver->read(i, array_buf);
|
||||
+ if (read_ret != TFM_GPT_BLOCK_SIZE) {
|
||||
+ ERROR("Unable to read LBA 0x%08x%08x\n",
|
||||
+ (uint32_t)(i >> 32), (uint32_t)i);
|
||||
+ return PSA_ERROR_STORAGE_FAILURE;
|
||||
+ }
|
||||
+
|
||||
+ memcpy(
|
||||
+ lba_buf + primary_gpt.header.entry_size * (gpt_entry_per_lba_count() - 1),
|
||||
+ array_buf,
|
||||
+ GPT_ENTRY_SIZE);
|
||||
+
|
||||
+ /* Write to backup first, then primary partition array */
|
||||
+ if (backup_gpt_array_lba != 0) {
|
||||
+ ret = write_to_flash(backup_gpt_array_lba + i - 1 - PRIMARY_GPT_ARRAY_LBA);
|
||||
+ if (ret != PSA_SUCCESS) {
|
||||
+ return ret;
|
||||
+ }
|
||||
+ }
|
||||
+ ret = write_to_flash(i - 1);
|
||||
+ if (ret != PSA_SUCCESS) {
|
||||
+ return ret;
|
||||
+ }
|
||||
+
|
||||
+ memmove(
|
||||
+ array_buf,
|
||||
+ array_buf + primary_gpt.header.entry_size,
|
||||
+ sizeof(array_buf) - primary_gpt.header.entry_size);
|
||||
+ memcpy(lba_buf, array_buf, TFM_GPT_BLOCK_SIZE);
|
||||
+ }
|
||||
+
|
||||
+ /* What was the final LBA is now cached and may be empty or partially-filled */
|
||||
+ cached_lba = array_end_lba;
|
||||
+ write_buffered = false;
|
||||
+ uint32_t entries_in_last_lba = (--primary_gpt.num_used_partitions) % gpt_entry_per_lba_count();
|
||||
+ if (entries_in_last_lba == 0) {
|
||||
+ /* There's nothing left in this LBA, so zero it all and write it out.
|
||||
+ * There is also no need to do an erase just to zero afterwards.
|
||||
+ */
|
||||
+ memset(lba_buf, 0, TFM_GPT_BLOCK_SIZE);
|
||||
+ if (backup_gpt_array_lba != 0) {
|
||||
+ int write_ret = plat_flash_driver->write(
|
||||
+ backup_gpt_array_lba + array_end_lba - PRIMARY_GPT_ARRAY_LBA,
|
||||
+ lba_buf);
|
||||
+ if (write_ret != TFM_GPT_BLOCK_SIZE) {
|
||||
+ return PSA_ERROR_STORAGE_FAILURE;
|
||||
+ }
|
||||
+ }
|
||||
+ int write_ret = plat_flash_driver->write(array_end_lba, lba_buf);
|
||||
+ if (write_ret != TFM_GPT_BLOCK_SIZE) {
|
||||
+ return PSA_ERROR_STORAGE_FAILURE;
|
||||
+ }
|
||||
+ } else {
|
||||
+ /* Zero what is not needed anymore */
|
||||
+ memset(
|
||||
+ lba_buf + primary_gpt.header.entry_size * entries_in_last_lba,
|
||||
+ 0,
|
||||
+ (gpt_entry_per_lba_count() - entries_in_last_lba) * primary_gpt.header.entry_size);
|
||||
+ if (backup_gpt_array_lba != 0) {
|
||||
+ ret = write_to_flash(backup_gpt_array_lba + array_end_lba - PRIMARY_GPT_ARRAY_LBA);
|
||||
+ if (ret != PSA_SUCCESS) {
|
||||
+ return ret;
|
||||
+ }
|
||||
+ }
|
||||
+ ret = write_to_flash(array_end_lba);
|
||||
+ if (ret != PSA_SUCCESS) {
|
||||
+ return ret;
|
||||
+ }
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ /* Update the header after flash changes */
|
||||
+ ret = update_header(primary_gpt.num_used_partitions);
|
||||
+
|
||||
+ return ret;
|
||||
+}
|
||||
+
|
||||
/* Initialises GPT from first block. */
|
||||
psa_status_t gpt_init(struct gpt_flash_driver_t *flash_driver, uint64_t max_partitions)
|
||||
{
|
||||
diff --git a/lib/gpt/unittests/gpt/test_gpt.c b/lib/gpt/unittests/gpt/test_gpt.c
|
||||
index 251b04ee9..18cf2c8f3 100644
|
||||
--- a/lib/gpt/unittests/gpt/test_gpt.c
|
||||
+++ b/lib/gpt/unittests/gpt/test_gpt.c
|
||||
@@ -10,6 +10,7 @@
|
||||
|
||||
#include "unity.h"
|
||||
|
||||
+#include "mock_efi_guid.h"
|
||||
#include "mock_efi_soft_crc.h"
|
||||
#include "mock_tfm_log.h"
|
||||
#include "mock_tfm_vprintf.h"
|
||||
@@ -368,6 +369,260 @@ void test_gpt_init_should_failWhenFlashDriverNotFullyDefined(void)
|
||||
mock_driver.erase = erase_fn;
|
||||
}
|
||||
|
||||
+void test_gpt_entry_create_should_createNewEntry(void)
|
||||
+{
|
||||
+ /* Add an entry. It must not overlap with an existing entry and must also
|
||||
+ * fit on the storage device. The GUID should be populated with something.
|
||||
+ */
|
||||
+ setup_valid_gpt();
|
||||
+
|
||||
+ /* Each entry will be read in order to check that it doesn't overlap with
|
||||
+ * any of them
|
||||
+ */
|
||||
+ register_mocked_read(&test_partition_array, sizeof(test_partition_array));
|
||||
+
|
||||
+ /* Update header. Read each entry for CRC calculation. */
|
||||
+ struct gpt_entry_t new_entry = {
|
||||
+ .type = NULL_GUID,
|
||||
+ .start = TEST_GPT_THIRD_PARTITION_END + 1,
|
||||
+ .end = TEST_GPT_THIRD_PARTITION_END + 1,
|
||||
+ .attr = 0,
|
||||
+ .name = "Fourth partition"
|
||||
+ };
|
||||
+
|
||||
+ /* Mock out the call to create a new GUID */
|
||||
+ struct efi_guid_t expected_guid = MAKE_EFI_GUID(5, 5, 5, 5, 5, 6, 7, 8, 9, 10, 11);
|
||||
+ efi_guid_generate_random_ExpectAnyArgsAndReturn(PSA_SUCCESS);
|
||||
+ efi_guid_generate_random_ReturnThruPtr_guid(&expected_guid);
|
||||
+
|
||||
+ /* Ensure also the that a new GUID is assigned */
|
||||
+ struct efi_guid_t new_guid = MAKE_EFI_GUID(4, 4, 4, 4, 5, 6, 7, 8, 9, 10, 11);
|
||||
+ TEST_ASSERT_EQUAL(PSA_SUCCESS, gpt_entry_create(
|
||||
+ &expected_guid,
|
||||
+ new_entry.start,
|
||||
+ new_entry.end - new_entry.start + 1,
|
||||
+ new_entry.attr,
|
||||
+ new_entry.name,
|
||||
+ &new_guid));
|
||||
+ TEST_ASSERT_EQUAL_MEMORY(&expected_guid, &new_guid, sizeof(new_guid));
|
||||
+}
|
||||
+
|
||||
+void test_gpt_entry_create_should_createNewEntryNextToLastEntry(void)
|
||||
+{
|
||||
+ /* Add an entry, allowing the library to choose the start LBA.
|
||||
+ * The GUID should be populated with something.
|
||||
+ */
|
||||
+ setup_valid_gpt();
|
||||
+
|
||||
+ /* Each entry will be read in order to check that it doesn't overlap with
|
||||
+ * any of them
|
||||
+ */
|
||||
+ register_mocked_read(&test_partition_array, sizeof(test_partition_array));
|
||||
+
|
||||
+ /* Update header. Read each entry for CRC calculation. */
|
||||
+ struct gpt_entry_t new_entry = {
|
||||
+ .type = NULL_GUID,
|
||||
+ .start = TEST_GPT_THIRD_PARTITION_END + 1,
|
||||
+ .end = TEST_GPT_THIRD_PARTITION_END + 1,
|
||||
+ .attr = 0,
|
||||
+ .name = "Fourth partition"
|
||||
+ };
|
||||
+
|
||||
+ /* Mock out the call to create a new GUID */
|
||||
+ struct efi_guid_t expected_guid = MAKE_EFI_GUID(5, 5, 5, 5, 5, 6, 7, 8, 9, 10, 11);
|
||||
+ efi_guid_generate_random_ExpectAnyArgsAndReturn(PSA_SUCCESS);
|
||||
+ efi_guid_generate_random_ReturnThruPtr_guid(&expected_guid);
|
||||
+
|
||||
+ /* Ensure also the that a new GUID is assigned */
|
||||
+ struct efi_guid_t new_guid = MAKE_EFI_GUID(4, 4, 4, 4, 5, 6, 7, 8, 9, 10, 11);
|
||||
+ char name[GPT_ENTRY_NAME_LENGTH] = {'\0'};
|
||||
+ name[0] = 'a';
|
||||
+
|
||||
+ /* Ensure also the that a new GUID is assigned */
|
||||
+ TEST_ASSERT_EQUAL(PSA_SUCCESS, gpt_entry_create(
|
||||
+ &expected_guid,
|
||||
+ 0,
|
||||
+ 1,
|
||||
+ new_entry.attr,
|
||||
+ name,
|
||||
+ &new_guid));
|
||||
+ TEST_ASSERT_EQUAL_MEMORY(&expected_guid, &new_guid, sizeof(new_guid));
|
||||
+}
|
||||
+
|
||||
+void test_gpt_entry_create_should_failToCreateEntryWhenLowestFreeLbaDoesNotHaveSpace(void)
|
||||
+{
|
||||
+ /* Add an entry, allowing the library to choose the start LBA.
|
||||
+ * The GUID should be populated with something.
|
||||
+ */
|
||||
+ setup_valid_gpt();
|
||||
+
|
||||
+ /* Each entry will be read in order to check that it doesn't overlap with
|
||||
+ * any of them
|
||||
+ */
|
||||
+ register_mocked_read(&test_partition_array, sizeof(test_partition_array));
|
||||
+
|
||||
+ /* Ensure also the that a new GUID is assigned */
|
||||
+ struct efi_guid_t existing_guid = MAKE_EFI_GUID(4, 4, 4, 4, 5, 6, 7, 8, 9, 10, 11);
|
||||
+ struct efi_guid_t new_guid;
|
||||
+ char name[GPT_ENTRY_NAME_LENGTH] = {'\0'};
|
||||
+ name[0] = 'a';
|
||||
+ TEST_ASSERT_EQUAL(PSA_ERROR_INVALID_ARGUMENT, gpt_entry_create(
|
||||
+ &(existing_guid),
|
||||
+ 0,
|
||||
+ TEST_DISK_NUM_BLOCKS,
|
||||
+ 0,
|
||||
+ name,
|
||||
+ &(new_guid)));
|
||||
+}
|
||||
+
|
||||
+void test_gpt_entry_create_should_failWhenTableFull(void)
|
||||
+{
|
||||
+ /* Start with a full array of entries */
|
||||
+ struct gpt_entry_t new_entry = {
|
||||
+ .type = MAKE_EFI_GUID(4, 4, 4, 4, 5, 6, 7, 8, 9, 10, 11),
|
||||
+ .start = TEST_GPT_THIRD_PARTITION_END + 1,
|
||||
+ .end = TEST_GPT_THIRD_PARTITION_END + 1,
|
||||
+ .attr = 0,
|
||||
+ .guid = MAKE_EFI_GUID(4, 4, 4, 4, 5, 6, 7, 8, 9, 10, 11),
|
||||
+ .name = "Fourth partition"
|
||||
+ };
|
||||
+ test_partition_array[TEST_MAX_PARTITIONS - 1] = new_entry;
|
||||
+ setup_valid_gpt();
|
||||
+
|
||||
+ struct efi_guid_t type = MAKE_EFI_GUID(5, 5, 5, 5, 5, 6, 7, 8, 9, 10, 11);
|
||||
+ struct efi_guid_t guid;
|
||||
+ char name[GPT_ENTRY_NAME_LENGTH] = {'\0'};
|
||||
+ name[0] = 'a';
|
||||
+ TEST_ASSERT_EQUAL(PSA_ERROR_INSUFFICIENT_STORAGE, gpt_entry_create(
|
||||
+ &type,
|
||||
+ TEST_GPT_THIRD_PARTITION_END + 4,
|
||||
+ 1,
|
||||
+ 0,
|
||||
+ name,
|
||||
+ &guid));
|
||||
+}
|
||||
+
|
||||
+void test_gpt_entry_create_should_failWhenLbaOffDisk(void)
|
||||
+{
|
||||
+ setup_valid_gpt();
|
||||
+
|
||||
+ /* First start on disk, then go off the disk */
|
||||
+ struct efi_guid_t type = NULL_GUID;
|
||||
+ struct efi_guid_t guid;
|
||||
+ char name[GPT_ENTRY_NAME_LENGTH] = {'\0'};
|
||||
+ name[0] = 'a';
|
||||
+ TEST_ASSERT_EQUAL(PSA_ERROR_INVALID_ARGUMENT, gpt_entry_create(
|
||||
+ &type,
|
||||
+ TEST_GPT_THIRD_PARTITION_END + 1,
|
||||
+ 1000,
|
||||
+ 0,
|
||||
+ name,
|
||||
+ &guid));
|
||||
+
|
||||
+ /* Second, start off the disk entirely */
|
||||
+ TEST_ASSERT_EQUAL(PSA_ERROR_INVALID_ARGUMENT, gpt_entry_create(
|
||||
+ &type,
|
||||
+ TEST_DISK_NUM_BLOCKS + 100,
|
||||
+ 1,
|
||||
+ 0,
|
||||
+ name,
|
||||
+ &guid));
|
||||
+
|
||||
+ /* Third, do the same but in the header area */
|
||||
+ TEST_ASSERT_EQUAL(PSA_ERROR_INVALID_ARGUMENT, gpt_entry_create(
|
||||
+ &type,
|
||||
+ TEST_GPT_PRIMARY_LBA,
|
||||
+ 1,
|
||||
+ 0,
|
||||
+ name,
|
||||
+ &guid));
|
||||
+
|
||||
+ /* Fourth, start in the backup header area */
|
||||
+ TEST_ASSERT_EQUAL(PSA_ERROR_INVALID_ARGUMENT, gpt_entry_create(
|
||||
+ &type,
|
||||
+ TEST_GPT_BACKUP_LBA,
|
||||
+ 1,
|
||||
+ 0,
|
||||
+ name,
|
||||
+ &guid));
|
||||
+}
|
||||
+
|
||||
+void test_gpt_entry_create_should_failWhenOverlapping(void)
|
||||
+{
|
||||
+ setup_valid_gpt();
|
||||
+
|
||||
+ /* Since the disk is not fragmented by default, there are two test cases:
|
||||
+ * 1. start in the middle of a partition and end in the middle of a partition
|
||||
+ * 2. start in the middle of a partition and end in free space
|
||||
+ */
|
||||
+ register_mocked_read(&test_partition_array, sizeof(test_partition_array));
|
||||
+ struct efi_guid_t type = NULL_GUID;
|
||||
+ struct efi_guid_t guid;
|
||||
+ char name[GPT_ENTRY_NAME_LENGTH] = {'\0'};
|
||||
+ name[0] = 'a';
|
||||
+ TEST_ASSERT_EQUAL(PSA_ERROR_INVALID_ARGUMENT, gpt_entry_create(
|
||||
+ &type,
|
||||
+ TEST_GPT_FIRST_PARTITION_START,
|
||||
+ TEST_GPT_FIRST_PARTITION_END - TEST_GPT_FIRST_PARTITION_START + 1,
|
||||
+ 0,
|
||||
+ name,
|
||||
+ &guid));
|
||||
+
|
||||
+ register_mocked_read(&test_partition_array, sizeof(test_partition_array));
|
||||
+ TEST_ASSERT_EQUAL(PSA_ERROR_INVALID_ARGUMENT, gpt_entry_create(
|
||||
+ &type,
|
||||
+ TEST_GPT_FIRST_PARTITION_START,
|
||||
+ TEST_GPT_LAST_USABLE_LBA - TEST_GPT_FIRST_PARTITION_START,
|
||||
+ 0,
|
||||
+ name,
|
||||
+ &guid));
|
||||
+}
|
||||
+
|
||||
+void test_gpt_entry_create_should_failWhenNameIsEmpty(void)
|
||||
+{
|
||||
+ /* Start with a populated GPT */
|
||||
+ setup_valid_gpt();
|
||||
+
|
||||
+ struct efi_guid_t type = NULL_GUID;
|
||||
+ struct gpt_entry_t new_entry = {
|
||||
+ .type = type,
|
||||
+ .start = TEST_GPT_THIRD_PARTITION_END + 1,
|
||||
+ .end = TEST_GPT_THIRD_PARTITION_END + 1,
|
||||
+ .attr = 0,
|
||||
+ };
|
||||
+
|
||||
+ /* Make an entry with an empty name */
|
||||
+ char name[GPT_ENTRY_NAME_LENGTH] = {'\0'};
|
||||
+ struct efi_guid_t new_guid;
|
||||
+ TEST_ASSERT_EQUAL(PSA_ERROR_INVALID_ARGUMENT, gpt_entry_create(
|
||||
+ &type,
|
||||
+ new_entry.start,
|
||||
+ 1,
|
||||
+ 0,
|
||||
+ name,
|
||||
+ &new_guid));
|
||||
+}
|
||||
+
|
||||
+void test_gpt_entry_create_should_failWhenSizeIsZero(void)
|
||||
+{
|
||||
+ /* Start with a populated GPT */
|
||||
+ setup_valid_gpt();
|
||||
+
|
||||
+ struct efi_guid_t type = NULL_GUID;
|
||||
+
|
||||
+ /* Make the size zero */
|
||||
+ struct efi_guid_t new_guid;
|
||||
+ char name[GPT_ENTRY_NAME_LENGTH] = {'\0'};
|
||||
+ name[0] = 'a';
|
||||
+ TEST_ASSERT_EQUAL(PSA_ERROR_INVALID_ARGUMENT, gpt_entry_create(
|
||||
+ &type,
|
||||
+ TEST_GPT_THIRD_PARTITION_END + 1,
|
||||
+ 0,
|
||||
+ 0,
|
||||
+ name,
|
||||
+ &new_guid));
|
||||
+}
|
||||
+
|
||||
void test_gpt_entry_move_should_moveEntry(void)
|
||||
{
|
||||
/* Start with a populated GPT */
|
||||
@@ -654,6 +909,35 @@ void test_gpt_entry_rename_should_failWhenEntryNotExisting(void)
|
||||
TEST_ASSERT_EQUAL(PSA_ERROR_DOES_NOT_EXIST, gpt_entry_rename(&non_existing, new_name));
|
||||
}
|
||||
|
||||
+void test_gpt_entry_remove_should_removeEntry(void)
|
||||
+{
|
||||
+ /* Start with a populated GPT */
|
||||
+ setup_valid_gpt();
|
||||
+
|
||||
+ /* Each entry is read */
|
||||
+ struct gpt_entry_t *test_entry = &(default_partition_array[TEST_DEFAULT_NUM_PARTITIONS - 1]);
|
||||
+ struct efi_guid_t test_guid = test_entry->guid;
|
||||
+ register_mocked_read(&test_partition_array, sizeof(test_partition_array));
|
||||
+
|
||||
+ TEST_ASSERT_EQUAL(PSA_SUCCESS, gpt_entry_remove(&test_guid));
|
||||
+}
|
||||
+
|
||||
+void test_gpt_entry_remove_should_failWhenEntryNotExisting(void)
|
||||
+{
|
||||
+ /* Start by trying to remove from an empty table */
|
||||
+ setup_empty_gpt();
|
||||
+
|
||||
+ struct efi_guid_t non_existing = NULL_GUID;
|
||||
+ TEST_ASSERT_EQUAL(PSA_ERROR_DOES_NOT_EXIST, gpt_entry_remove(&non_existing));
|
||||
+
|
||||
+ /* Now, have a non-empty GPT but search for a non-existing GUID */
|
||||
+ setup_valid_gpt();
|
||||
+
|
||||
+ /* Each entry should be read. */
|
||||
+ register_mocked_read(&test_partition_array, sizeof(test_partition_array));
|
||||
+ TEST_ASSERT_EQUAL(PSA_ERROR_DOES_NOT_EXIST, gpt_entry_remove(&non_existing));
|
||||
+}
|
||||
+
|
||||
void test_gpt_entry_read_should_populateEntry(void)
|
||||
{
|
||||
/* Start with a populated GPT */
|
||||
diff --git a/lib/gpt/unittests/gpt/utcfg.cmake b/lib/gpt/unittests/gpt/utcfg.cmake
|
||||
index 620d15b4c..f3f4e7dcc 100644
|
||||
--- a/lib/gpt/unittests/gpt/utcfg.cmake
|
||||
+++ b/lib/gpt/unittests/gpt/utcfg.cmake
|
||||
@@ -15,11 +15,13 @@ set(UNIT_TEST_SUITE ${CMAKE_CURRENT_LIST_DIR}/test_gpt.c)
|
||||
list(APPEND UNIT_TEST_INCLUDE_DIRS ${TFM_ROOT_DIR}/interface/include)
|
||||
list(APPEND UNIT_TEST_INCLUDE_DIRS ${TFM_ROOT_DIR}/lib/efi_guid/inc)
|
||||
list(APPEND UNIT_TEST_INCLUDE_DIRS ${TFM_ROOT_DIR}/lib/gpt/inc)
|
||||
+list(APPEND UNIT_TEST_INCLUDE_DIRS ${TFM_ROOT_DIR}/lib/gpt/unittests/include)
|
||||
list(APPEND UNIT_TEST_INCLUDE_DIRS ${TFM_ROOT_DIR}/lib/ext/efi_soft_crc/inc)
|
||||
list(APPEND UNIT_TEST_INCLUDE_DIRS ${TFM_ROOT_DIR}/lib/tfm_log/inc)
|
||||
list(APPEND UNIT_TEST_INCLUDE_DIRS ${TFM_ROOT_DIR}/lib/tfm_vprintf/inc)
|
||||
|
||||
# Headers to be mocked
|
||||
+list(APPEND MOCK_HEADERS ${TFM_ROOT_DIR}/lib/efi_guid/inc/efi_guid.h)
|
||||
list(APPEND MOCK_HEADERS ${TFM_ROOT_DIR}/lib/tfm_log/inc/tfm_log.h)
|
||||
list(APPEND MOCK_HEADERS ${TFM_ROOT_DIR}/lib/tfm_vprintf/inc/tfm_vprintf.h)
|
||||
list(APPEND MOCK_HEADERS ${TFM_ROOT_DIR}/lib/ext/efi_soft_crc/inc/efi_soft_crc.h)
|
||||
diff --git a/lib/gpt/unittests/include/mbedtls/mbedtls_config.h b/lib/gpt/unittests/include/mbedtls/mbedtls_config.h
|
||||
new file mode 100644
|
||||
index 000000000..5144daae3
|
||||
--- /dev/null
|
||||
+++ b/lib/gpt/unittests/include/mbedtls/mbedtls_config.h
|
||||
@@ -0,0 +1,18 @@
|
||||
+/*
|
||||
+ * SPDX-FileCopyrightText: Copyright The TrustedFirmware-M Contributors
|
||||
+ *
|
||||
+ * SPDX-License-Identifier: BSD-3-Clause
|
||||
+ */
|
||||
+
|
||||
+#ifndef MBEDTLS_CONFIG_H
|
||||
+#define MBEDTLS_CONFIG_H
|
||||
+
|
||||
+#ifdef __cplusplus
|
||||
+extern "C" {
|
||||
+#endif
|
||||
+
|
||||
+#ifdef __cplusplus
|
||||
+}
|
||||
+#endif
|
||||
+
|
||||
+#endif
|
||||
+412
@@ -0,0 +1,412 @@
|
||||
From c0037dc1779d181ce7d7dbd5871519c9d218440a Mon Sep 17 00:00:00 2001
|
||||
From: Frazer Carsley <frazer.carsley@arm.com>
|
||||
Date: Tue, 30 Dec 2025 10:29:47 +0000
|
||||
Subject: [PATCH] lib: gpt: Added table validation operations
|
||||
|
||||
Added validate and restore operations. Both of these operate on the
|
||||
entirety of the table and allow the caller to:
|
||||
|
||||
1. determine if the GPT is valid or not.
|
||||
2. restore a GPT from the alternative at the other end of the storage
|
||||
device.
|
||||
|
||||
Both of these operations can be performed on either the primary or
|
||||
backup table to allow full recovery.
|
||||
|
||||
Change-Id: Ie5ac2fdc42858cb439a2dcd08f4203eb181d4e88
|
||||
Signed-off-by: Frazer Carsley <frazer.carsley@arm.com>
|
||||
Upstream-Status: Backport [62a038e80574e094e64617953748633737cd760d]
|
||||
---
|
||||
lib/gpt/inc/gpt.h | 22 ++++
|
||||
lib/gpt/src/gpt.c | 184 +++++++++++++++++++++++++++++++
|
||||
lib/gpt/unittests/gpt/test_gpt.c | 135 +++++++++++++++++++++++
|
||||
3 files changed, 341 insertions(+)
|
||||
|
||||
diff --git a/lib/gpt/inc/gpt.h b/lib/gpt/inc/gpt.h
|
||||
index f04643957..0ce4d04ab 100644
|
||||
--- a/lib/gpt/inc/gpt.h
|
||||
+++ b/lib/gpt/inc/gpt.h
|
||||
@@ -207,6 +207,28 @@ psa_status_t gpt_entry_create(const struct efi_guid_t *type,
|
||||
__attribute__((nonnull(1)))
|
||||
psa_status_t gpt_entry_remove(const struct efi_guid_t *guid);
|
||||
|
||||
+/**
|
||||
+ * \brief Validates the GPT.
|
||||
+ *
|
||||
+ * \param[in] is_primary True to validate the primary table, false to validate the backup.
|
||||
+ *
|
||||
+ * \retval PSA_SUCCESS GPT is valid.
|
||||
+ * \retval PSA_ERROR_STORAGE_FAILURE I/O error.
|
||||
+ * \retval PSA_ERROR_INVALID_SIGNATURE GPT is invalid.
|
||||
+ */
|
||||
+psa_status_t gpt_validate(bool is_primary);
|
||||
+
|
||||
+/**
|
||||
+ * \brief Restores either the primary or backup GPT from the other copy.
|
||||
+ *
|
||||
+ * \param[in] is_primary True to restore the primary table, false to restore the backup.
|
||||
+ *
|
||||
+ * \retval PSA_SUCCESS GPT restored.
|
||||
+ * \retval PSA_ERROR_STORAGE_FAILURE I/O error.
|
||||
+ * \retval PSA_ERROR_INVALID_SIGNATURE Restoring GPT invalid; cannot restore.
|
||||
+ */
|
||||
+psa_status_t gpt_restore(bool is_primary);
|
||||
+
|
||||
/**
|
||||
* \brief Reads the GPT header from the second block (LBA 1).
|
||||
*
|
||||
diff --git a/lib/gpt/src/gpt.c b/lib/gpt/src/gpt.c
|
||||
index 676f04fd6..1bc592bb3 100644
|
||||
--- a/lib/gpt/src/gpt.c
|
||||
+++ b/lib/gpt/src/gpt.c
|
||||
@@ -223,6 +223,8 @@ static psa_status_t mbr_load(struct mbr_t *mbr);
|
||||
static bool gpt_entry_cmp_guid(const struct gpt_entry_t *entry, const void *guid);
|
||||
static bool gpt_entry_cmp_name(const struct gpt_entry_t *entry, const void *name);
|
||||
static bool gpt_entry_cmp_type(const struct gpt_entry_t *entry, const void *type);
|
||||
+static psa_status_t validate_table(struct gpt_t *table, bool is_primary);
|
||||
+static psa_status_t restore_table(struct gpt_t *restore_from, bool is_primary);
|
||||
|
||||
/* PUBLIC API FUNCTIONS */
|
||||
|
||||
@@ -747,6 +749,76 @@ psa_status_t gpt_entry_remove(const struct efi_guid_t *guid)
|
||||
return ret;
|
||||
}
|
||||
|
||||
+psa_status_t gpt_validate(bool is_primary)
|
||||
+{
|
||||
+ if (!is_primary && (backup_gpt_lba == 0 || backup_gpt_array_lba == 0)) {
|
||||
+ ERROR("Backup GPT location unknown!\n");
|
||||
+ return PSA_ERROR_STORAGE_FAILURE;
|
||||
+ }
|
||||
+
|
||||
+ /* Flush and invalidate the in-memory buffer before attempting to validate
|
||||
+ * a table. The in-memory header needs to be updated if the flushed LBA was
|
||||
+ * part of the entry array
|
||||
+ */
|
||||
+ psa_status_t ret;
|
||||
+ if (write_buffered) {
|
||||
+ ret = flush_lba_buf();
|
||||
+ if (ret != PSA_SUCCESS) {
|
||||
+ return ret;
|
||||
+ }
|
||||
+ write_buffered = false;
|
||||
+ }
|
||||
+ cached_lba = 0;
|
||||
+
|
||||
+ if (is_primary) {
|
||||
+ return validate_table(&primary_gpt, true);
|
||||
+ } else {
|
||||
+ struct gpt_t backup_gpt;
|
||||
+ ret = read_table_from_flash(&backup_gpt, false);
|
||||
+ if (ret != PSA_SUCCESS) {
|
||||
+ return ret;
|
||||
+ }
|
||||
+ return validate_table(&backup_gpt, false);
|
||||
+ }
|
||||
+}
|
||||
+
|
||||
+psa_status_t gpt_restore(bool is_primary)
|
||||
+{
|
||||
+ if (!is_primary && (backup_gpt_lba == 0 || backup_gpt_array_lba == 0)) {
|
||||
+ ERROR("Backup GPT location unknown!\n");
|
||||
+ return PSA_ERROR_STORAGE_FAILURE;
|
||||
+ }
|
||||
+
|
||||
+ /* Flush and invalidate the in-memory buffer before attempting to restore a
|
||||
+ * table. The in-memory header needs to be updated if the flushed LBA was
|
||||
+ * part of the entry array
|
||||
+ */
|
||||
+ psa_status_t ret;
|
||||
+ if (write_buffered) {
|
||||
+ ret = flush_lba_buf();
|
||||
+ if (ret != PSA_SUCCESS) {
|
||||
+ return ret;
|
||||
+ }
|
||||
+ write_buffered = false;
|
||||
+ }
|
||||
+ cached_lba = 0;
|
||||
+
|
||||
+ if (is_primary) {
|
||||
+ struct gpt_t backup_gpt;
|
||||
+ ret = read_table_from_flash(&backup_gpt, false);
|
||||
+ if (ret != PSA_SUCCESS) {
|
||||
+ return ret;
|
||||
+ }
|
||||
+ ret = count_used_partitions(&backup_gpt, &backup_gpt.num_used_partitions);
|
||||
+ if (ret != PSA_SUCCESS) {
|
||||
+ return ret;
|
||||
+ }
|
||||
+ return restore_table(&backup_gpt, false);
|
||||
+ } else {
|
||||
+ return restore_table(&primary_gpt, true);
|
||||
+ }
|
||||
+}
|
||||
+
|
||||
/* Initialises GPT from first block. */
|
||||
psa_status_t gpt_init(struct gpt_flash_driver_t *flash_driver, uint64_t max_partitions)
|
||||
{
|
||||
@@ -1349,6 +1421,118 @@ static inline void swap_headers(const struct gpt_header_t *src, struct gpt_heade
|
||||
primary_gpt.header.array_lba);
|
||||
}
|
||||
|
||||
+/* Validates a specific GPT. */
|
||||
+static psa_status_t validate_table(struct gpt_t *table, bool is_primary)
|
||||
+{
|
||||
+ struct gpt_header_t *header = &(table->header);
|
||||
+
|
||||
+ /* Check signature */
|
||||
+ if (strncmp(header->signature, GPT_SIG, GPT_SIG_LEN) != 0) {
|
||||
+ ERROR("Invalid GPT signature\n");
|
||||
+ return PSA_ERROR_INVALID_SIGNATURE;
|
||||
+ }
|
||||
+
|
||||
+ /* Check header CRC */
|
||||
+ uint32_t calc_crc = 0;
|
||||
+ uint32_t old_crc = header->header_crc;
|
||||
+ header->header_crc = 0;
|
||||
+ calc_crc = efi_soft_crc32_update(calc_crc, (uint8_t *)header, GPT_HEADER_SIZE);
|
||||
+ header->header_crc = old_crc;
|
||||
+
|
||||
+ if (old_crc != calc_crc) {
|
||||
+ ERROR("CRC of header does not match, expected 0x%x got 0x%x\n",
|
||||
+ old_crc, calc_crc);
|
||||
+ return PSA_ERROR_INVALID_SIGNATURE;
|
||||
+ }
|
||||
+
|
||||
+ /* Check MyLBA field points to this table */
|
||||
+ const uint64_t table_lba = (is_primary ? PRIMARY_GPT_LBA : backup_gpt_lba);
|
||||
+ if (table_lba != header->current_lba) {
|
||||
+ ERROR("MyLBA not pointing to this GPT, expected 0x%08x%08x, got 0x%08x%08x\n",
|
||||
+ (uint32_t)(table_lba >> 32),
|
||||
+ (uint32_t)table_lba,
|
||||
+ (uint32_t)(header->current_lba >> 32),
|
||||
+ (uint32_t)(header->current_lba));
|
||||
+ return PSA_ERROR_INVALID_SIGNATURE;
|
||||
+ }
|
||||
+
|
||||
+ /* Check the CRC of the partition array */
|
||||
+ calc_crc = 0;
|
||||
+ for (uint32_t i = 0; i < header->num_partitions; ++i) {
|
||||
+ uint8_t entry_buf[header->entry_size];
|
||||
+ memset(entry_buf, 0, header->entry_size);
|
||||
+ struct gpt_entry_t *entry = (struct gpt_entry_t *)entry_buf;
|
||||
+
|
||||
+ psa_status_t ret = read_entry_from_flash(table, i, entry);
|
||||
+ if (ret != PSA_SUCCESS) {
|
||||
+ return ret;
|
||||
+ }
|
||||
+ calc_crc = efi_soft_crc32_update(calc_crc, (uint8_t *)entry, header->entry_size);
|
||||
+ }
|
||||
+
|
||||
+ if (calc_crc != header->array_crc) {
|
||||
+ ERROR("CRC of partition array does not match, expected 0x%x got 0x%x\n",
|
||||
+ calc_crc, header->array_crc);
|
||||
+ return PSA_ERROR_INVALID_SIGNATURE;
|
||||
+ }
|
||||
+
|
||||
+ if (is_primary) {
|
||||
+ /* Any time the primary table is considered valid, cache the backup
|
||||
+ * LBA field
|
||||
+ */
|
||||
+ backup_gpt_lba = header->backup_lba;
|
||||
+ } else {
|
||||
+ /* Any time backup table is considered valid, cache its array LBA
|
||||
+ * field and crc32
|
||||
+ */
|
||||
+ backup_gpt_array_lba = header->array_lba;
|
||||
+ backup_crc32 = header->header_crc;
|
||||
+ }
|
||||
+ return PSA_SUCCESS;
|
||||
+}
|
||||
+
|
||||
+/* Restore a table from another. The second parameter indicates whether the
|
||||
+ * restoring table is the primary GPT or not
|
||||
+ */
|
||||
+static psa_status_t restore_table(struct gpt_t *restore_from, bool is_primary)
|
||||
+{
|
||||
+ /* Determine if the restoring GPT is valid */
|
||||
+ psa_status_t ret = validate_table(restore_from, is_primary);
|
||||
+ if (ret != PSA_SUCCESS) {
|
||||
+ return ret;
|
||||
+ }
|
||||
+
|
||||
+ struct gpt_t restore_to;
|
||||
+ swap_headers(&(restore_from->header), &(restore_to.header));
|
||||
+
|
||||
+ /* Copy the partition array as well */
|
||||
+ ret = move_partition(
|
||||
+ restore_from->header.array_lba,
|
||||
+ restore_to.header.array_lba,
|
||||
+ (restore_from->header.num_partitions +
|
||||
+ gpt_entry_per_lba_count() - 1) / gpt_entry_per_lba_count());
|
||||
+ if (ret != PSA_SUCCESS) {
|
||||
+ return ret;
|
||||
+ }
|
||||
+
|
||||
+ /* Write the header */
|
||||
+ ret = write_header_to_flash(&restore_to);
|
||||
+ if (ret != PSA_SUCCESS) {
|
||||
+ ERROR("Unable to write %s GPT header\n", is_primary ? "backup" : "primary");
|
||||
+ return ret;
|
||||
+ }
|
||||
+
|
||||
+ /* The primary GPT is cached in memory */
|
||||
+ if (!is_primary) {
|
||||
+ memcpy(&(primary_gpt.header), &(restore_to.header), GPT_HEADER_SIZE);
|
||||
+ primary_gpt.num_used_partitions = restore_from->num_used_partitions;
|
||||
+ }
|
||||
+
|
||||
+ INFO("Successfully restored %s GPT table\n", is_primary ? "backup" : "primary");
|
||||
+
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
/* Converts unicode string to valid ascii */
|
||||
static psa_status_t unicode_to_ascii(const char *unicode, char *ascii)
|
||||
{
|
||||
diff --git a/lib/gpt/unittests/gpt/test_gpt.c b/lib/gpt/unittests/gpt/test_gpt.c
|
||||
index 18cf2c8f3..f15a0a737 100644
|
||||
--- a/lib/gpt/unittests/gpt/test_gpt.c
|
||||
+++ b/lib/gpt/unittests/gpt/test_gpt.c
|
||||
@@ -369,6 +369,141 @@ void test_gpt_init_should_failWhenFlashDriverNotFullyDefined(void)
|
||||
mock_driver.erase = erase_fn;
|
||||
}
|
||||
|
||||
+void test_gpt_validate_should_validateWhenGptGood(void)
|
||||
+{
|
||||
+ setup_test_gpt();
|
||||
+
|
||||
+ /* Each entry will be read in order to check the partition array CRC */
|
||||
+ register_mocked_read(&test_partition_array, sizeof(test_partition_array));
|
||||
+
|
||||
+ TEST_ASSERT_EQUAL(PSA_SUCCESS, gpt_validate(true));
|
||||
+
|
||||
+ /* Now do the backup */
|
||||
+ setup_backup_gpt();
|
||||
+ register_mocked_read(&test_partition_array, sizeof(test_partition_array));
|
||||
+
|
||||
+ TEST_ASSERT_EQUAL(PSA_SUCCESS, gpt_validate(false));
|
||||
+}
|
||||
+
|
||||
+void test_gpt_validate_should_failWhenGptSigBad(void)
|
||||
+{
|
||||
+ test_header.signature[0] = '\0';
|
||||
+ setup_test_gpt();
|
||||
+
|
||||
+ TEST_ASSERT_EQUAL(PSA_ERROR_INVALID_SIGNATURE, gpt_validate(true));
|
||||
+
|
||||
+ /* Now do the backup */
|
||||
+ setup_backup_gpt();
|
||||
+ TEST_ASSERT_EQUAL(PSA_ERROR_INVALID_SIGNATURE, gpt_validate(false));
|
||||
+}
|
||||
+
|
||||
+void test_gpt_validate_should_failWhenHeaderCrcBad(void)
|
||||
+{
|
||||
+ test_header.header_crc--;
|
||||
+ setup_test_gpt();
|
||||
+ TEST_ASSERT_EQUAL(PSA_ERROR_INVALID_SIGNATURE, gpt_validate(true));
|
||||
+
|
||||
+ /* Now do the backup */
|
||||
+ struct gpt_header_t backup_header;
|
||||
+ MAKE_BACKUP_HEADER(backup_header, test_header);
|
||||
+ backup_header.header_crc--;
|
||||
+ register_mocked_read(&backup_header, sizeof(backup_header));
|
||||
+
|
||||
+ TEST_ASSERT_EQUAL(PSA_ERROR_INVALID_SIGNATURE, gpt_validate(false));
|
||||
+}
|
||||
+
|
||||
+void test_gpt_validate_should_failWhenLbaPointerBad(void)
|
||||
+{
|
||||
+ test_header.current_lba = 2;
|
||||
+ test_header.backup_lba = 3;
|
||||
+ setup_test_gpt();
|
||||
+ TEST_ASSERT_EQUAL(PSA_ERROR_INVALID_SIGNATURE, gpt_validate(true));
|
||||
+
|
||||
+ /* Now set the backup LBA to be something different that what it should be
|
||||
+ * to force a mismatch
|
||||
+ */
|
||||
+ test_header.current_lba = default_header.current_lba;
|
||||
+ test_header.backup_lba = default_header.backup_lba - 1;
|
||||
+
|
||||
+ /* Now do the backup */
|
||||
+ struct gpt_header_t backup_header;
|
||||
+ MAKE_BACKUP_HEADER(backup_header, test_header);
|
||||
+ register_mocked_read(&backup_header, sizeof(backup_header));
|
||||
+
|
||||
+ TEST_ASSERT_EQUAL(PSA_ERROR_INVALID_SIGNATURE, gpt_validate(false));
|
||||
+}
|
||||
+
|
||||
+void test_gpt_validate_should_failWhenArrayCrcBad(void)
|
||||
+{
|
||||
+ test_header.array_crc--;
|
||||
+ setup_test_gpt();
|
||||
+
|
||||
+ /* Each entry will be read in order to check the partition array CRC */
|
||||
+ register_mocked_read(&test_partition_array, sizeof(test_partition_array));
|
||||
+
|
||||
+ TEST_ASSERT_EQUAL(PSA_ERROR_INVALID_SIGNATURE, gpt_validate(true));
|
||||
+
|
||||
+ /* Now do the backup */
|
||||
+ struct gpt_header_t backup_header;
|
||||
+ MAKE_BACKUP_HEADER(backup_header, test_header);
|
||||
+ backup_header.array_crc--;
|
||||
+ register_mocked_read(&backup_header, sizeof(test_partition_array));
|
||||
+ register_mocked_read(&test_partition_array, sizeof(test_partition_array));
|
||||
+
|
||||
+ TEST_ASSERT_EQUAL(PSA_ERROR_INVALID_SIGNATURE, gpt_validate(false));
|
||||
+}
|
||||
+
|
||||
+void test_gpt_restore_should_restorePrimaryFromBackup(void)
|
||||
+{
|
||||
+ /* Start with a valid GPT */
|
||||
+ setup_valid_gpt();
|
||||
+
|
||||
+ /* The backup table is read and checked for validity, including taking
|
||||
+ * CRC32 of partition array
|
||||
+ */
|
||||
+ setup_backup_gpt();
|
||||
+ register_mocked_read(&test_partition_array, sizeof(test_partition_array));
|
||||
+
|
||||
+ TEST_ASSERT_EQUAL(PSA_SUCCESS, gpt_restore(true));
|
||||
+}
|
||||
+
|
||||
+void test_gpt_restore_should_failToRestoreWhenBackupIsBad(void)
|
||||
+{
|
||||
+ /* Start with a valid GPT */
|
||||
+ setup_valid_gpt();
|
||||
+
|
||||
+ /* The backup table is read and checked for validity. Corrupt it in
|
||||
+ * various ways
|
||||
+ */
|
||||
+ struct gpt_header_t backup_header;
|
||||
+
|
||||
+ /* Bad signature */
|
||||
+ MAKE_BACKUP_HEADER(backup_header, test_header);
|
||||
+ backup_header.signature[0] = '\0';
|
||||
+ register_mocked_read(&backup_header, sizeof(backup_header));
|
||||
+ TEST_ASSERT_EQUAL(PSA_ERROR_INVALID_SIGNATURE, gpt_restore(true));
|
||||
+
|
||||
+ /* Bad header CRC */
|
||||
+ MAKE_BACKUP_HEADER(backup_header, test_header);
|
||||
+ backup_header.header_crc = 0;
|
||||
+ register_mocked_read(&backup_header, sizeof(backup_header));
|
||||
+ TEST_ASSERT_EQUAL(PSA_ERROR_INVALID_SIGNATURE, gpt_restore(true));
|
||||
+
|
||||
+ /* Bad LBA */
|
||||
+ test_header.backup_lba = 2;
|
||||
+ MAKE_BACKUP_HEADER(backup_header, test_header);
|
||||
+ register_mocked_read(&backup_header, sizeof(backup_header));
|
||||
+ TEST_ASSERT_EQUAL(PSA_ERROR_INVALID_SIGNATURE, gpt_restore(true));
|
||||
+ test_header.backup_lba = default_header.backup_lba;
|
||||
+
|
||||
+ /* Bad array CRC. Will involve reading array entries */
|
||||
+ MAKE_BACKUP_HEADER(backup_header, test_header);
|
||||
+ backup_header.array_crc = 0;
|
||||
+ register_mocked_read(&backup_header, sizeof(backup_header));
|
||||
+ register_mocked_read(&test_partition_array, sizeof(test_partition_array));
|
||||
+ TEST_ASSERT_EQUAL(PSA_ERROR_INVALID_SIGNATURE, gpt_restore(true));
|
||||
+}
|
||||
+
|
||||
void test_gpt_entry_create_should_createNewEntry(void)
|
||||
{
|
||||
/* Add an entry. It must not overlap with an existing entry and must also
|
||||
+280
@@ -0,0 +1,280 @@
|
||||
From ba38f0f304ad69047ce9830b81a4f9cfbccb8fcb Mon Sep 17 00:00:00 2001
|
||||
From: Frazer Carsley <frazer.carsley@arm.com>
|
||||
Date: Tue, 30 Dec 2025 10:51:57 +0000
|
||||
Subject: [PATCH] lib: gpt: Added defragmentation operation
|
||||
|
||||
Defragmentation moves all of used data of the device to the beginning
|
||||
such that all of the free space is afterwards towards the end. This is
|
||||
less meaningful on flash devices however is still provided as an
|
||||
operation for completeness. This is done by ordering the partition entry
|
||||
array first, so that it is safe to shuffle data in one direction without
|
||||
risk of data loss/overwriting.
|
||||
|
||||
Change-Id: Ic401c79ac8c1fba2489ab2680efc02139c759c66
|
||||
Signed-off-by: Frazer Carsley <frazer.carsley@arm.com>
|
||||
Upstream-Status: Backport [21ff1f85c0b5463c1ea75fd61d872c0029eed902]
|
||||
---
|
||||
lib/gpt/inc/gpt.h | 8 ++
|
||||
lib/gpt/src/gpt.c | 190 +++++++++++++++++++++++++++++++
|
||||
lib/gpt/unittests/gpt/test_gpt.c | 7 ++
|
||||
3 files changed, 205 insertions(+)
|
||||
|
||||
diff --git a/lib/gpt/inc/gpt.h b/lib/gpt/inc/gpt.h
|
||||
index 0ce4d04ab..baf4767f9 100644
|
||||
--- a/lib/gpt/inc/gpt.h
|
||||
+++ b/lib/gpt/inc/gpt.h
|
||||
@@ -229,6 +229,14 @@ psa_status_t gpt_validate(bool is_primary);
|
||||
*/
|
||||
psa_status_t gpt_restore(bool is_primary);
|
||||
|
||||
+/**
|
||||
+ * \brief Defragments the GPT, ensuring free space becomes contiguous.
|
||||
+ *
|
||||
+ * \retval PSA_SUCCESS Success.
|
||||
+ * \retval PSA_ERROR_STORAGE_FAILURE I/O failure.
|
||||
+ */
|
||||
+psa_status_t gpt_defragment(void);
|
||||
+
|
||||
/**
|
||||
* \brief Reads the GPT header from the second block (LBA 1).
|
||||
*
|
||||
diff --git a/lib/gpt/src/gpt.c b/lib/gpt/src/gpt.c
|
||||
index 1bc592bb3..b1d4597cd 100644
|
||||
--- a/lib/gpt/src/gpt.c
|
||||
+++ b/lib/gpt/src/gpt.c
|
||||
@@ -6,6 +6,7 @@
|
||||
|
||||
#include <stdbool.h>
|
||||
#include <stdint.h>
|
||||
+#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <inttypes.h>
|
||||
|
||||
@@ -225,6 +226,7 @@ static bool gpt_entry_cmp_name(const struct gpt_entry_t *entry, const void *name
|
||||
static bool gpt_entry_cmp_type(const struct gpt_entry_t *entry, const void *type);
|
||||
static psa_status_t validate_table(struct gpt_t *table, bool is_primary);
|
||||
static psa_status_t restore_table(struct gpt_t *restore_from, bool is_primary);
|
||||
+static psa_status_t sort_partition_array(struct gpt_t *table);
|
||||
|
||||
/* PUBLIC API FUNCTIONS */
|
||||
|
||||
@@ -819,6 +821,66 @@ psa_status_t gpt_restore(bool is_primary)
|
||||
}
|
||||
}
|
||||
|
||||
+psa_status_t gpt_defragment(void)
|
||||
+{
|
||||
+ /* First, sort the partition array according to start LBA. This means that
|
||||
+ * moving partitions towards the start of the flash sequentially is safe
|
||||
+ * and will not result in lost data.
|
||||
+ */
|
||||
+ psa_status_t ret = sort_partition_array(&primary_gpt);
|
||||
+ if (ret != PSA_SUCCESS) {
|
||||
+ WARN("Unable to defragment flash!\n");
|
||||
+ return ret;
|
||||
+ }
|
||||
+
|
||||
+ uint64_t prev_end = primary_gpt.header.first_lba;
|
||||
+ struct gpt_entry_t entry;
|
||||
+
|
||||
+ for (uint32_t i = 0; i < primary_gpt.num_used_partitions; ++i) {
|
||||
+ ret = read_entry_from_flash(&primary_gpt, i, &entry);
|
||||
+ if (ret != PSA_SUCCESS) {
|
||||
+ return ret;
|
||||
+ }
|
||||
+
|
||||
+ /* Move to be next to previous entry. Continue if already where it
|
||||
+ * needs to be.
|
||||
+ */
|
||||
+ if (prev_end == entry.start) {
|
||||
+ prev_end = entry.end + 1;
|
||||
+ continue;
|
||||
+ }
|
||||
+
|
||||
+ const uint64_t num_blocks = entry.end - entry.start + 1;
|
||||
+ ret = move_partition(entry.start, prev_end, num_blocks);
|
||||
+ if (ret != PSA_SUCCESS) {
|
||||
+ return ret;
|
||||
+ }
|
||||
+
|
||||
+ /* Update header information */
|
||||
+ entry.start = prev_end;
|
||||
+ entry.end = entry.start + num_blocks - 1;
|
||||
+ prev_end = entry.end + 1;
|
||||
+
|
||||
+ /* Write the entry change, skipping header update until every entry
|
||||
+ * written
|
||||
+ */
|
||||
+ ret = write_entry(i, &entry, true);
|
||||
+ if (ret != PSA_SUCCESS) {
|
||||
+ return ret;
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ /* Write everything to flash after defragmentation if not done so already.
|
||||
+ * The previous loop will write the last entry to the LBA buffer, which may
|
||||
+ * or not may not be flushed
|
||||
+ */
|
||||
+ if (write_buffered) {
|
||||
+ return flush_lba_buf();
|
||||
+ }
|
||||
+
|
||||
+ return update_header(primary_gpt.num_used_partitions);
|
||||
+}
|
||||
+
|
||||
/* Initialises GPT from first block. */
|
||||
psa_status_t gpt_init(struct gpt_flash_driver_t *flash_driver, uint64_t max_partitions)
|
||||
{
|
||||
@@ -1533,6 +1595,134 @@ static psa_status_t restore_table(struct gpt_t *restore_from, bool is_primary)
|
||||
return 0;
|
||||
}
|
||||
|
||||
+/* Comparison function to pass to qsort */
|
||||
+static int cmp_u64(const void *a, const void *b)
|
||||
+{
|
||||
+ const uint64_t *a_u64 = (const uint64_t *)a;
|
||||
+ const uint64_t *b_u64 = (const uint64_t *)b;
|
||||
+ return (*a_u64 > *b_u64) - (*a_u64 < *b_u64);
|
||||
+}
|
||||
+
|
||||
+/* bsearch but returns the index rather than the item */
|
||||
+static int64_t bsearch_index(uint64_t arr[], uint32_t len, uint64_t key)
|
||||
+{
|
||||
+ uint32_t l = 0;
|
||||
+ uint32_t r = len;
|
||||
+
|
||||
+ while (l < r) {
|
||||
+ uint32_t m = l + (r - l) / 2;
|
||||
+ uint64_t item = arr[m];
|
||||
+
|
||||
+ if (item < key) {
|
||||
+ l = m + 1;
|
||||
+ } else if (item > key) {
|
||||
+ r = m;
|
||||
+ } else {
|
||||
+ return (int64_t)m;
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ return -1;
|
||||
+}
|
||||
+
|
||||
+/* Sorts the partition array for the given table by the start LBA for each
|
||||
+ * partition. This makes defragmentation easier.
|
||||
+ */
|
||||
+static psa_status_t sort_partition_array(struct gpt_t *table)
|
||||
+{
|
||||
+ /* To avoid as much I/O as possible, the LBA's for each entry are sorted in
|
||||
+ * memory and then the entries rearranged on flash after
|
||||
+ */
|
||||
+ uint64_t lba_arr[table->num_used_partitions];
|
||||
+ psa_status_t ret;
|
||||
+ for (uint32_t i = 0; i < table->num_used_partitions; ++i) {
|
||||
+ struct gpt_entry_t entry;
|
||||
+ ret = read_entry_from_flash(table, i, &entry);
|
||||
+ if (ret != PSA_SUCCESS) {
|
||||
+ return ret;
|
||||
+ }
|
||||
+ lba_arr[i] = entry.start;
|
||||
+ }
|
||||
+
|
||||
+ qsort(lba_arr, table->num_used_partitions, sizeof(uint64_t), cmp_u64);
|
||||
+
|
||||
+ /* Now read and place the entries in the correct spot, starting with the
|
||||
+ * first. Each entry is dealt with as it is encountered. When an entry is
|
||||
+ * found and already in the correct spot, the next smallest index not yet
|
||||
+ * handled becomes the next.
|
||||
+ */
|
||||
+ struct gpt_entry_t saved_entry = {0};
|
||||
+ struct gpt_entry_t curr_entry;
|
||||
+ uint8_t handled_indices[table->num_used_partitions];
|
||||
+ memset(handled_indices, 0, table->num_used_partitions);
|
||||
+
|
||||
+ ret = read_entry_from_flash(table, 0, &curr_entry);
|
||||
+ if (ret != PSA_SUCCESS) {
|
||||
+ return ret;
|
||||
+ }
|
||||
+
|
||||
+ for (uint32_t i = 0; i < table->num_used_partitions; ++i) {
|
||||
+ const int64_t new_index = bsearch_index(
|
||||
+ lba_arr,
|
||||
+ table->num_used_partitions,
|
||||
+ curr_entry.start);
|
||||
+ if (new_index < 0) {
|
||||
+ ERROR("Encountered unknown partition entry!\n");
|
||||
+ return PSA_ERROR_STORAGE_FAILURE;
|
||||
+ }
|
||||
+
|
||||
+ /* For final entry, just write it out */
|
||||
+ if (i == table->num_used_partitions - 1) {
|
||||
+ ret = write_entry((uint32_t)new_index, &curr_entry, false);
|
||||
+ if (ret != PSA_SUCCESS) {
|
||||
+ return ret;
|
||||
+ }
|
||||
+ break;
|
||||
+ }
|
||||
+
|
||||
+ /* Replace the entry in the new_index place with the current entry */
|
||||
+ ret = read_entry_from_flash(table, (uint32_t)new_index, &saved_entry);
|
||||
+ if (ret != PSA_SUCCESS) {
|
||||
+ return ret;
|
||||
+ }
|
||||
+
|
||||
+ struct efi_guid_t saved_guid = saved_entry.unique_guid;
|
||||
+ struct efi_guid_t curr_guid = curr_entry.unique_guid;
|
||||
+ if (efi_guid_cmp(&saved_guid, &curr_guid) == 0) {
|
||||
+ /* This entry is already where it needs to be, so try the smallest
|
||||
+ * index not yet handled next
|
||||
+ */
|
||||
+ handled_indices[new_index] = 1;
|
||||
+ uint32_t next_entry = 0;
|
||||
+ while(next_entry < table->num_used_partitions && handled_indices[next_entry]) {
|
||||
+ ++next_entry;
|
||||
+ }
|
||||
+
|
||||
+ if (next_entry == table->num_used_partitions) {
|
||||
+ /* Done everything */
|
||||
+ break;
|
||||
+ }
|
||||
+
|
||||
+ ret = read_entry_from_flash(table, next_entry, &saved_entry);
|
||||
+ if (ret != PSA_SUCCESS) {
|
||||
+ return ret;
|
||||
+ }
|
||||
+ } else {
|
||||
+ /* Write, skipping header update until very end */
|
||||
+ ret = write_entry((uint32_t)new_index, &curr_entry, true);
|
||||
+ if (ret != PSA_SUCCESS) {
|
||||
+ return ret;
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ /* Ready up for the next loop */
|
||||
+ curr_entry = saved_entry;
|
||||
+ handled_indices[new_index] = 1;
|
||||
+ }
|
||||
+
|
||||
+ return PSA_SUCCESS;
|
||||
+}
|
||||
+
|
||||
/* Converts unicode string to valid ascii */
|
||||
static psa_status_t unicode_to_ascii(const char *unicode, char *ascii)
|
||||
{
|
||||
diff --git a/lib/gpt/unittests/gpt/test_gpt.c b/lib/gpt/unittests/gpt/test_gpt.c
|
||||
index f15a0a737..2f05a6b4a 100644
|
||||
--- a/lib/gpt/unittests/gpt/test_gpt.c
|
||||
+++ b/lib/gpt/unittests/gpt/test_gpt.c
|
||||
@@ -504,6 +504,13 @@ void test_gpt_restore_should_failToRestoreWhenBackupIsBad(void)
|
||||
TEST_ASSERT_EQUAL(PSA_ERROR_INVALID_SIGNATURE, gpt_restore(true));
|
||||
}
|
||||
|
||||
+void test_gpt_defragment_should_succeedWhenNoIOFailure(void)
|
||||
+{
|
||||
+ setup_valid_gpt();
|
||||
+
|
||||
+ TEST_ASSERT_EQUAL(PSA_SUCCESS, gpt_defragment());
|
||||
+}
|
||||
+
|
||||
void test_gpt_entry_create_should_createNewEntry(void)
|
||||
{
|
||||
/* Add an entry. It must not overlap with an existing entry and must also
|
||||
+74
@@ -0,0 +1,74 @@
|
||||
From f9e4d1f48a4553278dc4de82b0d2f4d82b1e5193 Mon Sep 17 00:00:00 2001
|
||||
From: Antonio de Angelis <antonio.deangelis@arm.com>
|
||||
Date: Wed, 4 Mar 2026 13:05:51 +0000
|
||||
Subject: [PATCH] lib: GPT: Fix cppcheck warnings
|
||||
|
||||
Change-Id: Ia9e99dc59cbf869b804a24ba029f19f7170860b4
|
||||
Signed-off-by: Antonio de Angelis <antonio.deangelis@arm.com>
|
||||
Upstream-Status: Backport [92d5b6b7d296c174364e684508089c0a0678e3bb]
|
||||
---
|
||||
lib/gpt/src/gpt.c | 15 ++++++++++-----
|
||||
1 file changed, 10 insertions(+), 5 deletions(-)
|
||||
|
||||
diff --git a/lib/gpt/src/gpt.c b/lib/gpt/src/gpt.c
|
||||
index b1d4597cd..a9dbb918e 100644
|
||||
--- a/lib/gpt/src/gpt.c
|
||||
+++ b/lib/gpt/src/gpt.c
|
||||
@@ -4,6 +4,7 @@
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*/
|
||||
|
||||
+#include <assert.h>
|
||||
#include <stdbool.h>
|
||||
#include <stdint.h>
|
||||
#include <stdlib.h>
|
||||
@@ -194,7 +195,7 @@ static inline uint64_t gpt_entry_per_lba_count(void);
|
||||
static inline void swap_headers(const struct gpt_header_t *src, struct gpt_header_t *dst);
|
||||
static psa_status_t count_used_partitions(const struct gpt_t *table,
|
||||
uint32_t *num_used);
|
||||
-static inline void parse_entry(struct gpt_entry_t *entry,
|
||||
+static inline void parse_entry(const struct gpt_entry_t *entry,
|
||||
struct partition_entry_t *partition_entry);
|
||||
static psa_status_t read_from_flash(uint64_t required_lba);
|
||||
static psa_status_t read_entry_from_flash(const struct gpt_t *table,
|
||||
@@ -226,7 +227,7 @@ static bool gpt_entry_cmp_name(const struct gpt_entry_t *entry, const void *name
|
||||
static bool gpt_entry_cmp_type(const struct gpt_entry_t *entry, const void *type);
|
||||
static psa_status_t validate_table(struct gpt_t *table, bool is_primary);
|
||||
static psa_status_t restore_table(struct gpt_t *restore_from, bool is_primary);
|
||||
-static psa_status_t sort_partition_array(struct gpt_t *table);
|
||||
+static psa_status_t sort_partition_array(const struct gpt_t *table);
|
||||
|
||||
/* PUBLIC API FUNCTIONS */
|
||||
|
||||
@@ -1006,7 +1007,7 @@ static inline uint64_t gpt_entry_per_lba_count(void)
|
||||
}
|
||||
|
||||
/* Copies information from the entry to the user visible structure */
|
||||
-static inline void parse_entry(struct gpt_entry_t *entry,
|
||||
+static inline void parse_entry(const struct gpt_entry_t *entry,
|
||||
struct partition_entry_t *partition_entry)
|
||||
{
|
||||
partition_entry->start = entry->start;
|
||||
@@ -1604,7 +1605,7 @@ static int cmp_u64(const void *a, const void *b)
|
||||
}
|
||||
|
||||
/* bsearch but returns the index rather than the item */
|
||||
-static int64_t bsearch_index(uint64_t arr[], uint32_t len, uint64_t key)
|
||||
+static int64_t bsearch_index(const uint64_t arr[], uint32_t len, uint64_t key)
|
||||
{
|
||||
uint32_t l = 0;
|
||||
uint32_t r = len;
|
||||
@@ -1628,8 +1629,12 @@ static int64_t bsearch_index(uint64_t arr[], uint32_t len, uint64_t key)
|
||||
/* Sorts the partition array for the given table by the start LBA for each
|
||||
* partition. This makes defragmentation easier.
|
||||
*/
|
||||
-static psa_status_t sort_partition_array(struct gpt_t *table)
|
||||
+static psa_status_t sort_partition_array(const struct gpt_t *table)
|
||||
{
|
||||
+ if (table->num_used_partitions == 0) {
|
||||
+ assert(table->num_used_partitions > 0);
|
||||
+ return PSA_ERROR_INVALID_ARGUMENT;
|
||||
+ }
|
||||
/* To avoid as much I/O as possible, the LBA's for each entry are sorted in
|
||||
* memory and then the entries rearranged on flash after
|
||||
*/
|
||||
+28
@@ -0,0 +1,28 @@
|
||||
From 31cd6d9eb82792efd5af7d99802581eace13a083 Mon Sep 17 00:00:00 2001
|
||||
From: Frazer Carsley <frazer.carsley@arm.com>
|
||||
Date: Fri, 13 Mar 2026 17:10:25 +0000
|
||||
Subject: [PATCH] lib: efi_guid: Remove unecessary include folder
|
||||
|
||||
There are no header files in the src folder, so there is nothing to
|
||||
include. This line was redundant.
|
||||
|
||||
Change-Id: I5289932119629fc1ef6a71f0a0ceb63e5a466c96
|
||||
Signed-off-by: Frazer Carsley <frazer.carsley@arm.com>
|
||||
Upstream-Status: Backport [e74a1f467317c16487b9d41f43f147dd41985cb9]
|
||||
---
|
||||
lib/efi_guid/CMakeLists.txt | 2 --
|
||||
1 file changed, 2 deletions(-)
|
||||
|
||||
diff --git a/lib/efi_guid/CMakeLists.txt b/lib/efi_guid/CMakeLists.txt
|
||||
index 656eb72ea..9c4771cba 100644
|
||||
--- a/lib/efi_guid/CMakeLists.txt
|
||||
+++ b/lib/efi_guid/CMakeLists.txt
|
||||
@@ -15,8 +15,6 @@ target_sources(tfm_efi_guid
|
||||
target_include_directories(tfm_efi_guid
|
||||
PUBLIC
|
||||
$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/inc>
|
||||
- PRIVATE
|
||||
- ${CMAKE_CURRENT_SOURCE_DIR}/src
|
||||
)
|
||||
|
||||
target_link_libraries(tfm_efi_guid
|
||||
+28
@@ -0,0 +1,28 @@
|
||||
From 0b6a2e681b0f76c425896990ebc4afcbc65419d3 Mon Sep 17 00:00:00 2001
|
||||
From: Frazer Carsley <frazer.carsley@arm.com>
|
||||
Date: Fri, 13 Mar 2026 17:11:05 +0000
|
||||
Subject: [PATCH] lib: efi_guid: Correct included folder
|
||||
|
||||
The use of the variables is unecessary and has no real effect. This
|
||||
change is therefore simplified.
|
||||
|
||||
Change-Id: I0811b4768502d15b62f1af3ef90a56db3e9df525
|
||||
Signed-off-by: Frazer Carsley <frazer.carsley@arm.com>
|
||||
Upstream-Status: Backport [7bb11e81cd69718df3b11a3f8b42a3b5edf4c42d]
|
||||
---
|
||||
lib/efi_guid/CMakeLists.txt | 2 +-
|
||||
1 file changed, 1 insertion(+), 1 deletion(-)
|
||||
|
||||
diff --git a/lib/efi_guid/CMakeLists.txt b/lib/efi_guid/CMakeLists.txt
|
||||
index 9c4771cba..95d7b8f1e 100644
|
||||
--- a/lib/efi_guid/CMakeLists.txt
|
||||
+++ b/lib/efi_guid/CMakeLists.txt
|
||||
@@ -14,7 +14,7 @@ target_sources(tfm_efi_guid
|
||||
|
||||
target_include_directories(tfm_efi_guid
|
||||
PUBLIC
|
||||
- $<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/inc>
|
||||
+ inc
|
||||
)
|
||||
|
||||
target_link_libraries(tfm_efi_guid
|
||||
+25
@@ -0,0 +1,25 @@
|
||||
From f1862245d39a726c8e37f58498dd433c6fd99d1b Mon Sep 17 00:00:00 2001
|
||||
From: Frazer Carsley <frazer.carsley@arm.com>
|
||||
Date: Fri, 13 Mar 2026 17:13:07 +0000
|
||||
Subject: [PATCH] lib: efi_soft_crc: Correct include directory
|
||||
|
||||
The variables had no real effect, so this is therefore simplified.
|
||||
|
||||
Change-Id: Ifa03bc23e0419f9d6d598e7753f23dfde57c7bf6
|
||||
Signed-off-by: Frazer Carsley <frazer.carsley@arm.com>
|
||||
Upstream-Status: Backport [3856d55117b727c6c21bb821fa4236b113fb08ef]
|
||||
---
|
||||
lib/ext/efi_soft_crc/CMakeLists.txt | 2 +-
|
||||
1 file changed, 1 insertion(+), 1 deletion(-)
|
||||
|
||||
diff --git a/lib/ext/efi_soft_crc/CMakeLists.txt b/lib/ext/efi_soft_crc/CMakeLists.txt
|
||||
index 47fd2d507..d77310167 100644
|
||||
--- a/lib/ext/efi_soft_crc/CMakeLists.txt
|
||||
+++ b/lib/ext/efi_soft_crc/CMakeLists.txt
|
||||
@@ -14,5 +14,5 @@ target_sources(tfm_efi_soft_crc
|
||||
|
||||
target_include_directories(tfm_efi_soft_crc
|
||||
PUBLIC
|
||||
- $<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/inc>
|
||||
+ inc
|
||||
)
|
||||
+27
@@ -0,0 +1,27 @@
|
||||
From 343bba6c20802555dfb92c3e2b22a7e07c10a57a Mon Sep 17 00:00:00 2001
|
||||
From: Frazer Carsley <frazer.carsley@arm.com>
|
||||
Date: Fri, 13 Mar 2026 17:16:00 +0000
|
||||
Subject: [PATCH] lib: gpt: Add missing link library
|
||||
|
||||
tfm_log requires tfm_vprintf. When building for a platform with logging
|
||||
enabled, these headers are therefore required.
|
||||
|
||||
Change-Id: I63b35d5af818ea5ad7b1fe76200250ad98584a63
|
||||
Signed-off-by: Frazer Carsley <frazer.carsley@arm.com>
|
||||
Upstream-Status: Backport [92a3738634fe121766705599d66e4a8b772ce06e]
|
||||
---
|
||||
lib/gpt/CMakeLists.txt | 1 +
|
||||
1 file changed, 1 insertion(+)
|
||||
|
||||
diff --git a/lib/gpt/CMakeLists.txt b/lib/gpt/CMakeLists.txt
|
||||
index 5befc346f..ed31adfbe 100644
|
||||
--- a/lib/gpt/CMakeLists.txt
|
||||
+++ b/lib/gpt/CMakeLists.txt
|
||||
@@ -36,6 +36,7 @@ target_compile_definitions(tfm_gpt
|
||||
target_link_libraries(tfm_gpt
|
||||
PUBLIC
|
||||
tfm_log_headers
|
||||
+ tfm_vprintf_headers
|
||||
PRIVATE
|
||||
tfm_efi_guid
|
||||
tfm_efi_soft_crc
|
||||
+24
@@ -0,0 +1,24 @@
|
||||
From 1ae97df8db8babcaa999e47d9641c83c4ee8424a Mon Sep 17 00:00:00 2001
|
||||
From: Frazer Carsley <frazer.carsley@arm.com>
|
||||
Date: Fri, 13 Mar 2026 17:17:33 +0000
|
||||
Subject: [PATCH] lib: gpt: Correct variable name used
|
||||
|
||||
Change-Id: I86d616b3c86cf0a1fd053b732565477278030d89
|
||||
Signed-off-by: Frazer Carsley <frazer.carsley@arm.com>
|
||||
Upstream-Status: Backport [bc9522f5c47c7e3f3a92189073166e73323010e9]
|
||||
---
|
||||
lib/gpt/unittests/gpt/utcfg.cmake | 2 +-
|
||||
1 file changed, 1 insertion(+), 1 deletion(-)
|
||||
|
||||
diff --git a/lib/gpt/unittests/gpt/utcfg.cmake b/lib/gpt/unittests/gpt/utcfg.cmake
|
||||
index f3f4e7dcc..69a1d10bd 100644
|
||||
--- a/lib/gpt/unittests/gpt/utcfg.cmake
|
||||
+++ b/lib/gpt/unittests/gpt/utcfg.cmake
|
||||
@@ -27,6 +27,6 @@ list(APPEND MOCK_HEADERS ${TFM_ROOT_DIR}/lib/tfm_vprintf/inc/tfm_vprintf.h)
|
||||
list(APPEND MOCK_HEADERS ${TFM_ROOT_DIR}/lib/ext/efi_soft_crc/inc/efi_soft_crc.h)
|
||||
|
||||
# Compile-time definitions
|
||||
-list(APPEND UNIT_TEST_COMPILE_DEFS LOG_LEVEL=LOG_LEVEL_VERBOSE)
|
||||
+list(APPEND UNIT_TEST_COMPILE_DEFS GPT_LOG_LEVEL=LOG_LEVEL_VERBOSE)
|
||||
list(APPEND UNIT_TEST_COMPILE_DEFS TFM_GPT_BLOCK_SIZE=512)
|
||||
|
||||
+27
@@ -0,0 +1,27 @@
|
||||
From eb934a532bbc8385cd9b062fc80cece61350f086 Mon Sep 17 00:00:00 2001
|
||||
From: Frazer Carsley <frazer.carsley@arm.com>
|
||||
Date: Fri, 13 Mar 2026 17:19:50 +0000
|
||||
Subject: [PATCH] lib: gpt: Correct include directory
|
||||
|
||||
The variables have no real effect, so therefore this is simplified.
|
||||
|
||||
Change-Id: Ie912941f8eafd9cd5bf4dd88927640ad70d0676a
|
||||
Signed-off-by: Frazer Carsley <frazer.carsley@arm.com>
|
||||
Upstream-Status: Backport [369c897be0b9102cec8141c53b3d3fe6abb56b6e]
|
||||
---
|
||||
lib/gpt/CMakeLists.txt | 2 +-
|
||||
1 file changed, 1 insertion(+), 1 deletion(-)
|
||||
|
||||
diff --git a/lib/gpt/CMakeLists.txt b/lib/gpt/CMakeLists.txt
|
||||
index ed31adfbe..19cfe5bc2 100644
|
||||
--- a/lib/gpt/CMakeLists.txt
|
||||
+++ b/lib/gpt/CMakeLists.txt
|
||||
@@ -22,7 +22,7 @@ target_sources(tfm_gpt
|
||||
|
||||
target_include_directories(tfm_gpt
|
||||
PUBLIC
|
||||
- $<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/inc>
|
||||
+ inc
|
||||
$<INSTALL_INTERFACE:inc>
|
||||
)
|
||||
|
||||
+51
@@ -0,0 +1,51 @@
|
||||
From ce3a4f3dd8900c068f2bfe951d55b895e3c10d43 Mon Sep 17 00:00:00 2001
|
||||
From: Frazer Carsley <frazer.carsley@arm.com>
|
||||
Date: Fri, 13 Mar 2026 17:29:04 +0000
|
||||
Subject: [PATCH] lib: gpt: Move contents of CMake config file
|
||||
|
||||
A config.cmake used in a library can be a little confusing, especially
|
||||
considering that such files are used for platform configurations. The
|
||||
contents of the file are placed directly in the CMakeLists.txt that was
|
||||
including it.
|
||||
|
||||
Change-Id: I8a88971feebaf37498828af5854de94e74e16f2c
|
||||
Signed-off-by: Frazer Carsley <frazer.carsley@arm.com>
|
||||
Upstream-Status: Backport [4b569b02b98a577e45e833f4dd9886e54df71a7d]
|
||||
---
|
||||
lib/gpt/CMakeLists.txt | 6 +++---
|
||||
lib/gpt/config.cmake | 8 --------
|
||||
2 files changed, 3 insertions(+), 11 deletions(-)
|
||||
delete mode 100644 lib/gpt/config.cmake
|
||||
|
||||
diff --git a/lib/gpt/CMakeLists.txt b/lib/gpt/CMakeLists.txt
|
||||
index 19cfe5bc2..4a15173fd 100644
|
||||
--- a/lib/gpt/CMakeLists.txt
|
||||
+++ b/lib/gpt/CMakeLists.txt
|
||||
@@ -9,10 +9,10 @@ cmake_minimum_required(VERSION 3.21)
|
||||
|
||||
add_library(tfm_gpt STATIC)
|
||||
|
||||
-include(./config.cmake)
|
||||
+set(GPT_LOG_LEVEL LOG_LEVEL_INFO CACHE STRING "Set default log level for the GPT library")
|
||||
|
||||
-if(NOT DEFINED TFM_GPT_BLOCK_SIZE OR NOT DEFINED GPT_LOG_LEVEL)
|
||||
- message(FATAL_ERROR "TFM_GPT_BLOCK_SIZE and GPT_LOG_LEVEL must be defined to use GPT library")
|
||||
+if(NOT DEFINED TFM_GPT_BLOCK_SIZE)
|
||||
+ message(FATAL_ERROR "TFM_GPT_BLOCK_SIZE must be defined to use GPT library")
|
||||
endif()
|
||||
|
||||
target_sources(tfm_gpt
|
||||
diff --git a/lib/gpt/config.cmake b/lib/gpt/config.cmake
|
||||
deleted file mode 100644
|
||||
index 9575aa8a8..000000000
|
||||
--- a/lib/gpt/config.cmake
|
||||
+++ /dev/null
|
||||
@@ -1,8 +0,0 @@
|
||||
-#-------------------------------------------------------------------------------
|
||||
-# SPDX-FileCopyrightText: Copyright The TrustedFirmware-M Contributors
|
||||
-#
|
||||
-# SPDX-License-Identifier: BSD-3-Clause
|
||||
-#
|
||||
-#-------------------------------------------------------------------------------
|
||||
-
|
||||
-set(GPT_LOG_LEVEL LOG_LEVEL_INFO CACHE STRING "Set default log level for the GPT library")
|
||||
+261
@@ -0,0 +1,261 @@
|
||||
From 9402dd67413e74284bc598225b4c5399fbd1a099 Mon Sep 17 00:00:00 2001
|
||||
From: Frazer Carsley <frazer.carsley@arm.com>
|
||||
Date: Wed, 19 Nov 2025 17:12:13 +0000
|
||||
Subject: [PATCH] plat: cs1k: Fixed formatting errors
|
||||
|
||||
Many of these were tab characters, however the style guide for this repo
|
||||
is clear that spaces shall be used.
|
||||
|
||||
Sometimes the wrong number of spaces was used and that is fixed here as
|
||||
well.
|
||||
|
||||
Change-Id: I4c797d1de9723961eac707476e249062653aece0
|
||||
Signed-off-by: Frazer Carsley <frazer.carsley@arm.com>
|
||||
Upstream-Status: Submitted [https://review.trustedfirmware.org/c/TF-M/trusted-firmware-m/+/49423]
|
||||
---
|
||||
.../target/arm/corstone1000/CMakeLists.txt | 6 +-
|
||||
.../bootloader/mcuboot/tfm_mcuboot_fwu.c | 60 +++++++++----------
|
||||
2 files changed, 33 insertions(+), 33 deletions(-)
|
||||
|
||||
diff --git a/platform/ext/target/arm/corstone1000/CMakeLists.txt b/platform/ext/target/arm/corstone1000/CMakeLists.txt
|
||||
index 993c51591..58edae74e 100644
|
||||
--- a/platform/ext/target/arm/corstone1000/CMakeLists.txt
|
||||
+++ b/platform/ext/target/arm/corstone1000/CMakeLists.txt
|
||||
@@ -242,7 +242,7 @@ target_include_directories(platform_bl1_1_interface
|
||||
${PLATFORM_DIR}/ext/target/arm/drivers/usart/pl011
|
||||
$<$<BOOL:${CRYPTO_HW_ACCELERATOR}>:${CMAKE_SOURCE_DIR}/platform/ext/accelerator/interface>
|
||||
${PLATFORM_DIR}/ext/accelerator/cc312/
|
||||
- ${CMAKE_SOURCE_DIR}/lib/fih/inc/
|
||||
+ ${CMAKE_SOURCE_DIR}/lib/fih/inc/
|
||||
)
|
||||
|
||||
target_link_libraries(platform_bl1_1
|
||||
@@ -289,7 +289,7 @@ target_include_directories(platform_bl1_2
|
||||
${PLATFORM_DIR}/ext/target/arm/drivers/flash/n25q256a/
|
||||
${PLATFORM_DIR}/ext/target/arm/drivers/flash/sst26vf064b/
|
||||
${PLATFORM_DIR}/ext/accelerator/cc312/
|
||||
- ${CMAKE_SOURCE_DIR}/interface/include # for psa/error.h
|
||||
+ ${CMAKE_SOURCE_DIR}/interface/include # for psa/error.h
|
||||
)
|
||||
|
||||
#========================= Platform BL2 =======================================#
|
||||
@@ -397,7 +397,7 @@ target_include_directories(platform_bl2
|
||||
${MCUBOOT_PATH}/boot/bootutil/include # for fault_injection_hardening.h only
|
||||
${CMAKE_BINARY_DIR}/bl2/ext/mcuboot # for mcuboot_config.h only
|
||||
$<BUILD_INTERFACE:${BL2_SOURCE}/ext/mcuboot/include>
|
||||
- ${CMAKE_SOURCE_DIR}/interface/include # for psa/error.h
|
||||
+ ${CMAKE_SOURCE_DIR}/interface/include # for psa/error.h
|
||||
)
|
||||
|
||||
#========================= ns_agent_mailbox ===================================#
|
||||
diff --git a/platform/ext/target/arm/corstone1000/bootloader/mcuboot/tfm_mcuboot_fwu.c b/platform/ext/target/arm/corstone1000/bootloader/mcuboot/tfm_mcuboot_fwu.c
|
||||
index a458b5478..cff80b755 100644
|
||||
--- a/platform/ext/target/arm/corstone1000/bootloader/mcuboot/tfm_mcuboot_fwu.c
|
||||
+++ b/platform/ext/target/arm/corstone1000/bootloader/mcuboot/tfm_mcuboot_fwu.c
|
||||
@@ -995,7 +995,7 @@ psa_status_t fwu_metadata_provision(void)
|
||||
static uint8_t get_fwu_image_state(
|
||||
struct fwu_metadata *metadata,
|
||||
struct fwu_private_metadata *priv_metadata,
|
||||
- uint32_t fwu_image_index)
|
||||
+ uint32_t fwu_image_index)
|
||||
{
|
||||
FWU_LOG_MSG("%s: enter\n\r", __func__);
|
||||
|
||||
@@ -1305,12 +1305,12 @@ psa_status_t corstone1000_fwu_host_ack(void)
|
||||
|
||||
ret = PSA_SUCCESS; /* nothing to be done */
|
||||
|
||||
- for (int i = 0; i < NR_OF_IMAGES_IN_FW_BANK; i++) {
|
||||
- fmp_set_image_info(&fwu_image[i].image_guid,
|
||||
- priv_metadata.fmp_version[i],
|
||||
- priv_metadata.fmp_last_attempt_version[i],
|
||||
- priv_metadata.fmp_last_attempt_status[i]);
|
||||
- }
|
||||
+ for (int i = 0; i < NR_OF_IMAGES_IN_FW_BANK; i++) {
|
||||
+ fmp_set_image_info(&fwu_image[i].image_guid,
|
||||
+ priv_metadata.fmp_version[i],
|
||||
+ priv_metadata.fmp_last_attempt_version[i],
|
||||
+ priv_metadata.fmp_last_attempt_status[i]);
|
||||
+ }
|
||||
|
||||
goto out;
|
||||
|
||||
@@ -1322,13 +1322,13 @@ psa_status_t corstone1000_fwu_host_ack(void)
|
||||
|
||||
/* firmware update failed, revert back to previous bank */
|
||||
|
||||
- for (int i = 0; i < NR_OF_IMAGES_IN_FW_BANK; i++) {
|
||||
+ for (int i = 0; i < NR_OF_IMAGES_IN_FW_BANK; i++) {
|
||||
if(get_fwu_image_state(&_metadata, &priv_metadata, i) == PSA_FWU_TRIAL) {
|
||||
priv_metadata.fmp_last_attempt_version[i] =
|
||||
_metadata.fw_desc.img_entry[i].img_props[_metadata.active_index].version;
|
||||
|
||||
priv_metadata.fmp_last_attempt_status[i] = LAST_ATTEMPT_STATUS_ERROR_UNSUCCESSFUL;
|
||||
- }
|
||||
+ }
|
||||
}
|
||||
ret = fwu_select_previous(&_metadata, &priv_metadata);
|
||||
|
||||
@@ -1455,14 +1455,14 @@ psa_status_t fwu_stage_nv_counter(enum fwu_nv_counter_index_t index,
|
||||
|
||||
psa_status_t corstone1000_fwu_flash_image(void)
|
||||
{
|
||||
- return PSA_SUCCESS;
|
||||
+ return PSA_SUCCESS;
|
||||
}
|
||||
|
||||
/* Verify if image index is valid or not */
|
||||
bool is_image_index_valid(uint8_t fwu_image_index) {
|
||||
return (fwu_image_index != FWU_FAKE_IMAGE_INDEX &&
|
||||
fwu_image_index != FWU_IMAGE_INDEX_ESRT &&
|
||||
- fwu_image_index < FWU_COMPONENT_NUMBER);
|
||||
+ fwu_image_index < FWU_COMPONENT_NUMBER);
|
||||
}
|
||||
|
||||
static psa_status_t get_esrt_data(struct fwu_esrt_data_wrapper *esrt)
|
||||
@@ -1585,8 +1585,8 @@ static void fmp_header_image_info_init()
|
||||
for (int i=0; i<FWU_COMPONENT_NUMBER; i++)
|
||||
{
|
||||
fmp_header_image_info[i].fmp_hdr_size_recvd = 0;
|
||||
- fmp_header_image_info[i].image_size_recvd = 0;
|
||||
- memset(&fmp_header_image_info[i].fmp_hdr, 0, sizeof(fmp_header_image_info[i].fmp_hdr));
|
||||
+ fmp_header_image_info[i].image_size_recvd = 0;
|
||||
+ memset(&fmp_header_image_info[i].fmp_hdr, 0, sizeof(fmp_header_image_info[i].fmp_hdr));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1598,7 +1598,7 @@ static psa_status_t erase_staging_area(struct fwu_metadata* metadata, psa_fwu_co
|
||||
|
||||
if (!is_image_index_valid(component)) {
|
||||
FWU_LOG_MSG("%s: Invalid Component received \n\r", __func__);
|
||||
- return PSA_ERROR_GENERIC_ERROR;
|
||||
+ return PSA_ERROR_GENERIC_ERROR;
|
||||
}
|
||||
|
||||
uint32_t active_index = metadata->active_index;
|
||||
@@ -1691,7 +1691,7 @@ psa_status_t parse_fmp_header(psa_fwu_component_t component, const void *block,
|
||||
(sizeof(fmp_header_image_info[component].fmp_hdr) - fmp_header_image_info[component].fmp_hdr_size_recvd));
|
||||
|
||||
fmp_header_image_info[component].fmp_hdr_size_recvd = sizeof(fmp_header_image_info[component].fmp_hdr);
|
||||
- return PSA_SUCCESS;
|
||||
+ return PSA_SUCCESS;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1738,7 +1738,7 @@ psa_status_t fwu_bootloader_load_image(psa_fwu_component_t component,
|
||||
}
|
||||
if (ret == PSA_SUCCESS) {
|
||||
block_size -= fmp_header_image_info[fwu_image_index].fmp_hdr_size_recvd;
|
||||
- block += fmp_header_image_info[fwu_image_index].fmp_hdr_size_recvd;
|
||||
+ block += fmp_header_image_info[fwu_image_index].fmp_hdr_size_recvd;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1774,7 +1774,7 @@ psa_status_t fwu_bootloader_load_image(psa_fwu_component_t component,
|
||||
if (fw_version <=
|
||||
_metadata.fw_desc.img_entry[fwu_image_index].img_props[active_index].version)
|
||||
{
|
||||
- /* Version is extracted from the fmp_payload_header */
|
||||
+ /* Version is extracted from the fmp_payload_header */
|
||||
priv_metadata.fmp_last_attempt_version[fwu_image_index] = fmp_header_image_info[fwu_image_index].fmp_hdr.fw_version;
|
||||
priv_metadata.fmp_last_attempt_status[fwu_image_index] = LAST_ATTEMPT_STATUS_ERROR_UNSUCCESSFUL;
|
||||
private_metadata_write(&priv_metadata);
|
||||
@@ -1785,8 +1785,8 @@ psa_status_t fwu_bootloader_load_image(psa_fwu_component_t component,
|
||||
priv_metadata.fmp_last_attempt_status[fwu_image_index]);
|
||||
|
||||
FWU_LOG_MSG("ERROR: %s: version error\n\r",__func__);
|
||||
- ret = PSA_OPERATION_INCOMPLETE;
|
||||
- goto out;
|
||||
+ ret = PSA_OPERATION_INCOMPLETE;
|
||||
+ goto out;
|
||||
}
|
||||
|
||||
if (active_index == BANK_0) {
|
||||
@@ -1828,7 +1828,7 @@ psa_status_t fwu_bootloader_load_image(psa_fwu_component_t component,
|
||||
priv_metadata.fmp_last_attempt_version[fwu_image_index],
|
||||
priv_metadata.fmp_last_attempt_status[fwu_image_index]);
|
||||
ret = PSA_OPERATION_INCOMPLETE;
|
||||
- goto out;
|
||||
+ goto out;
|
||||
}
|
||||
else {
|
||||
ret = PSA_SUCCESS;
|
||||
@@ -1871,7 +1871,7 @@ static psa_status_t fwu_update_metadata(const psa_fwu_component_t *candidates, u
|
||||
} else {
|
||||
FWU_LOG_MSG("ERROR: %s: active_index %d\n\r",__func__,active_index);
|
||||
ret = PSA_ERROR_DATA_INVALID;
|
||||
- goto out;
|
||||
+ goto out;
|
||||
}
|
||||
|
||||
_metadata.active_index = previous_active_index;
|
||||
@@ -1881,7 +1881,7 @@ static psa_status_t fwu_update_metadata(const psa_fwu_component_t *candidates, u
|
||||
/* Change system state to trial bank state */
|
||||
for (int i = 0; i < number; i++) {
|
||||
/* Skip image with index 0 and ESRT image */
|
||||
- if(!is_image_index_valid(candidates[i])) {
|
||||
+ if(!is_image_index_valid(candidates[i])) {
|
||||
FWU_LOG_MSG("%s: Invalid image index received \n\r", __func__);
|
||||
continue;
|
||||
}
|
||||
@@ -1946,7 +1946,7 @@ static psa_status_t copy_image_from_other_bank(int image_index,
|
||||
}
|
||||
|
||||
offset_read += data_size;
|
||||
-
|
||||
+
|
||||
/* write image data to flash */
|
||||
data_transferred_count = FWU_METADATA_FLASH_DEV.ProgramData(offset_write, data, data_size);
|
||||
if (data_transferred_count < 0) {
|
||||
@@ -1961,7 +1961,7 @@ static psa_status_t copy_image_from_other_bank(int image_index,
|
||||
}
|
||||
|
||||
offset_write += data_size;
|
||||
- remaining_size -= data_size;
|
||||
+ remaining_size -= data_size;
|
||||
}
|
||||
|
||||
FWU_LOG_MSG("%s: exit \n\r", __func__);
|
||||
@@ -2004,8 +2004,8 @@ static psa_status_t maintain_bank_consistency(void)
|
||||
ret = copy_image_from_other_bank(i, active_index, previous_active_index);
|
||||
if(ret) {
|
||||
FWU_LOG_MSG("ERROR: %s: copy_image_from_other_bank failed for Image : %d\n\r",__func__, i);
|
||||
- return ret;
|
||||
- }
|
||||
+ return ret;
|
||||
+ }
|
||||
|
||||
_metadata.fw_desc.img_entry[i].img_props[previous_active_index].version =
|
||||
_metadata.fw_desc.img_entry[i].img_props[active_index].version;
|
||||
@@ -2110,7 +2110,7 @@ psa_status_t fwu_bootloader_mark_image_accepted(const psa_fwu_component_t *trial
|
||||
|
||||
/* firmware update successful */
|
||||
for (int i = 0; i < number; i++) {
|
||||
- if(!is_image_index_valid(trials[i])) {
|
||||
+ if(!is_image_index_valid(trials[i])) {
|
||||
FWU_LOG_MSG("%s: Invalid image index received \n\r", __func__);
|
||||
continue;
|
||||
}
|
||||
@@ -2201,7 +2201,7 @@ psa_status_t fwu_bootloader_reject_staged_image(psa_fwu_component_t component)
|
||||
} else {
|
||||
FWU_LOG_MSG("ERROR: %s: active_index %d\n\r",__func__,active_index);
|
||||
ret = PSA_ERROR_GENERIC_ERROR;
|
||||
- goto out;
|
||||
+ goto out;
|
||||
}
|
||||
|
||||
image_offset = bank_offset + fwu_image[image_index].image_offset;
|
||||
@@ -2308,11 +2308,11 @@ psa_status_t fwu_bootloader_get_image_info(psa_fwu_component_t component,
|
||||
ret = get_esrt_data(&esrt);
|
||||
if (ret) {
|
||||
FWU_LOG_MSG("%s: ERROR : Unable to populate ESRT \n\r", __func__);
|
||||
- goto out;
|
||||
+ goto out;
|
||||
}
|
||||
|
||||
memcpy(&info->impl.candidate_digest, &esrt, esrt_size);
|
||||
- if (query_state) {
|
||||
+ if (query_state) {
|
||||
info->state = PSA_FWU_READY;
|
||||
}
|
||||
}
|
||||
+6
-7
@@ -1,4 +1,4 @@
|
||||
From 3dcaa54afe671534b11a0586a49a9036b2bb2011 Mon Sep 17 00:00:00 2001
|
||||
From c579565c25937ae9455efe9cc3fbcace84c3e580 Mon Sep 17 00:00:00 2001
|
||||
From: Frazer Carsley <frazer.carsley@arm.com>
|
||||
Date: Mon, 29 Dec 2025 11:28:47 +0000
|
||||
Subject: [PATCH] plat: cs1k: Removed unused variables
|
||||
@@ -6,16 +6,15 @@ Subject: [PATCH] plat: cs1k: Removed unused variables
|
||||
Change-Id: I0dd3ff834c47c58dc833586c74791deca679a3ab
|
||||
Signed-off-by: Frazer Carsley <frazer.carsley@arm.com>
|
||||
Upstream-Status: Backport
|
||||
Signed-off-by: Ahmed Gomaa <Ahmed.Gomaa@arm.com>
|
||||
---
|
||||
.../arm/corstone1000/bootloader/mcuboot/tfm_mcuboot_fwu.c | 4 ----
|
||||
1 file changed, 4 deletions(-)
|
||||
|
||||
diff --git a/platform/ext/target/arm/corstone1000/bootloader/mcuboot/tfm_mcuboot_fwu.c b/platform/ext/target/arm/corstone1000/bootloader/mcuboot/tfm_mcuboot_fwu.c
|
||||
index 9fe9df0..89c2696 100644
|
||||
index cff80b755..83b0bd27d 100644
|
||||
--- a/platform/ext/target/arm/corstone1000/bootloader/mcuboot/tfm_mcuboot_fwu.c
|
||||
+++ b/platform/ext/target/arm/corstone1000/bootloader/mcuboot/tfm_mcuboot_fwu.c
|
||||
@@ -1594,7 +1594,6 @@ static psa_status_t fwu_accept_image(struct fwu_metadata *metadata,
|
||||
@@ -1511,7 +1511,6 @@ static psa_status_t fwu_accept_image(struct fwu_metadata *metadata,
|
||||
uint8_t number)
|
||||
{
|
||||
uint8_t current_state;
|
||||
@@ -23,7 +22,7 @@ index 9fe9df0..89c2696 100644
|
||||
uint32_t active_bank_index;
|
||||
uint32_t fwu_image_index;
|
||||
psa_status_t ret;
|
||||
@@ -2070,7 +2069,6 @@ static psa_status_t fwu_update_metadata(const psa_fwu_component_t *candidates, u
|
||||
@@ -1848,7 +1847,6 @@ static psa_status_t fwu_update_metadata(const psa_fwu_component_t *candidates, u
|
||||
{
|
||||
int ret;
|
||||
uint32_t active_index;
|
||||
@@ -31,8 +30,8 @@ index 9fe9df0..89c2696 100644
|
||||
uint32_t previous_active_index;
|
||||
uint8_t fwu_image_index;
|
||||
|
||||
@@ -2085,10 +2083,8 @@ static psa_status_t fwu_update_metadata(const psa_fwu_component_t *candidates, u
|
||||
active_index = _metadata.active_index;
|
||||
@@ -1864,10 +1862,8 @@ static psa_status_t fwu_update_metadata(const psa_fwu_component_t *candidates, u
|
||||
|
||||
if (active_index == BANK_0) {
|
||||
previous_active_index = BANK_1;
|
||||
- bank_offset = BANK_1_PARTITION_OFFSET;
|
||||
+40
@@ -0,0 +1,40 @@
|
||||
From 50db5724ef37d5c7cec019254d135b3dcfd0d340 Mon Sep 17 00:00:00 2001
|
||||
From: Frazer Carsley <frazer.carsley@arm.com>
|
||||
Date: Mon, 29 Dec 2025 11:30:32 +0000
|
||||
Subject: [PATCH] plat: cs1k: Fixed bad function returns
|
||||
|
||||
The rest of the functions would go to a label to perform some cleanup
|
||||
before exiting the function, however these particular errors did not. The
|
||||
cleanup would reset the write mode on flash, which is required since the
|
||||
errors occur after it being changed.
|
||||
|
||||
Change-Id: Ic8277a3295398922b2f05fcaddfb5a188b14e537
|
||||
Signed-off-by: Frazer Carsley <frazer.carsley@arm.com>
|
||||
Upstream-Status: Submitted [https://review.trustedfirmware.org/c/TF-M/trusted-firmware-m/+/49425]
|
||||
---
|
||||
.../arm/corstone1000/bootloader/mcuboot/tfm_mcuboot_fwu.c | 5 +++--
|
||||
1 file changed, 3 insertions(+), 2 deletions(-)
|
||||
|
||||
diff --git a/platform/ext/target/arm/corstone1000/bootloader/mcuboot/tfm_mcuboot_fwu.c b/platform/ext/target/arm/corstone1000/bootloader/mcuboot/tfm_mcuboot_fwu.c
|
||||
index 52db60bbc..2c17d4b79 100644
|
||||
--- a/platform/ext/target/arm/corstone1000/bootloader/mcuboot/tfm_mcuboot_fwu.c
|
||||
+++ b/platform/ext/target/arm/corstone1000/bootloader/mcuboot/tfm_mcuboot_fwu.c
|
||||
@@ -1798,7 +1798,8 @@ psa_status_t fwu_bootloader_load_image(psa_fwu_component_t component,
|
||||
bank_offset = BANK_0_PARTITION_OFFSET;
|
||||
} else {
|
||||
FWU_LOG_MSG("ERROR: %s: active_index %d\n\r",__func__,active_index);
|
||||
- return PSA_ERROR_DATA_INVALID;
|
||||
+ ret = PSA_ERROR_DATA_INVALID;
|
||||
+ goto out;
|
||||
}
|
||||
|
||||
image_offset = bank_offset + fwu_image[fwu_image_index].image_offset;
|
||||
@@ -2002,7 +2003,7 @@ static psa_status_t maintain_bank_consistency(void)
|
||||
ret = copy_image_from_other_bank(i, active_index, previous_active_index);
|
||||
if(ret) {
|
||||
FWU_LOG_MSG("ERROR: %s: copy_image_from_other_bank failed for Image : %d\n\r",__func__, i);
|
||||
- return ret;
|
||||
+ goto out;
|
||||
}
|
||||
|
||||
_metadata.fw_desc.img_entry[i].img_props[previous_active_index].version =
|
||||
+48
@@ -0,0 +1,48 @@
|
||||
From f48a0a6b60309433269c7927dac992eff06f3745 Mon Sep 17 00:00:00 2001
|
||||
From: Frazer Carsley <frazer.carsley@arm.com>
|
||||
Date: Mon, 29 Dec 2025 11:29:33 +0000
|
||||
Subject: [PATCH] plat: cs1k: Improved logging in function
|
||||
|
||||
The enter log statement claims to log when the function is entered,
|
||||
however it was possible for the function to return before reaching it.
|
||||
The error cases have now been given log statements too in order to make
|
||||
it easier to track when and why the function exited.
|
||||
|
||||
Change-Id: I7fe610ca6a596b6af1e48720a503b76064eed3ff
|
||||
Signed-off-by: Frazer Carsley <frazer.carsley@arm.com>
|
||||
Upstream-Status: Submitted [https://review.trustedfirmware.org/c/TF-M/trusted-firmware-m/+/49424]
|
||||
---
|
||||
.../arm/corstone1000/bootloader/mcuboot/tfm_mcuboot_fwu.c | 8 +++++---
|
||||
1 file changed, 5 insertions(+), 3 deletions(-)
|
||||
|
||||
diff --git a/platform/ext/target/arm/corstone1000/bootloader/mcuboot/tfm_mcuboot_fwu.c b/platform/ext/target/arm/corstone1000/bootloader/mcuboot/tfm_mcuboot_fwu.c
|
||||
index 83b0bd27d..52db60bbc 100644
|
||||
--- a/platform/ext/target/arm/corstone1000/bootloader/mcuboot/tfm_mcuboot_fwu.c
|
||||
+++ b/platform/ext/target/arm/corstone1000/bootloader/mcuboot/tfm_mcuboot_fwu.c
|
||||
@@ -1700,11 +1700,16 @@ psa_status_t fwu_bootloader_load_image(psa_fwu_component_t component,
|
||||
size_t block_size)
|
||||
{
|
||||
|
||||
+ FWU_LOG_MSG("%s: enter: block_offset = %u, block = 0x%p, block_size = %u\n\r"
|
||||
+ , __func__, block_offset, block, block_size);
|
||||
+
|
||||
if (block == NULL) {
|
||||
+ FWU_LOG_MSG("%s: exit: block is NULL\n\r", __func__);
|
||||
return PSA_ERROR_INVALID_ARGUMENT;
|
||||
}
|
||||
|
||||
if (!is_initialized) {
|
||||
+ FWU_LOG_MSG("%s: exit: not initialised\n\r", __func__);
|
||||
return PSA_ERROR_BAD_STATE;
|
||||
}
|
||||
|
||||
@@ -1726,9 +1731,6 @@ psa_status_t fwu_bootloader_load_image(psa_fwu_component_t component,
|
||||
uint8_t fwu_image_index = component - FWU_FAKE_IMAGES_INDEX_COUNT;
|
||||
struct fwu_private_metadata priv_metadata;
|
||||
|
||||
- FWU_LOG_MSG("%s: enter: block_offset = %u, block = 0x%p, block_size = %u\n\r"
|
||||
- , __func__, block_offset, block, block_size);
|
||||
-
|
||||
/* Parse the incoming block to make sure complete FMP header is received */
|
||||
if (fmp_header_image_info[fwu_image_index].fmp_hdr_size_recvd != sizeof(fmp_header_image_info[fwu_image_index].fmp_hdr)) {
|
||||
ret = parse_fmp_header(fwu_image_index, block, block_size);
|
||||
+93
@@ -0,0 +1,93 @@
|
||||
From bd6d7dc80556e8c4261343141d675e865d4e960b Mon Sep 17 00:00:00 2001
|
||||
From: Frazer Carsley <frazer.carsley@arm.com>
|
||||
Date: Fri, 2 Jan 2026 13:33:25 +0000
|
||||
Subject: [PATCH] plat: cs1k: Remove unused function
|
||||
|
||||
Change-Id: I6e054213dc1ec94a6dc8304705d4cb6e6da701cc
|
||||
Signed-off-by: Frazer Carsley <frazer.carsley@arm.com>
|
||||
Upstream-Status: Submitted [https://review.trustedfirmware.org/c/TF-M/trusted-firmware-m/+/49426]
|
||||
---
|
||||
.../bootloader/mcuboot/tfm_mcuboot_fwu.c | 70 -------------------
|
||||
1 file changed, 70 deletions(-)
|
||||
|
||||
diff --git a/platform/ext/target/arm/corstone1000/bootloader/mcuboot/tfm_mcuboot_fwu.c b/platform/ext/target/arm/corstone1000/bootloader/mcuboot/tfm_mcuboot_fwu.c
|
||||
index 2c17d4b79..76ee8a3dc 100644
|
||||
--- a/platform/ext/target/arm/corstone1000/bootloader/mcuboot/tfm_mcuboot_fwu.c
|
||||
+++ b/platform/ext/target/arm/corstone1000/bootloader/mcuboot/tfm_mcuboot_fwu.c
|
||||
@@ -501,76 +501,6 @@ static psa_status_t metadata_validate(struct fwu_metadata *metadata)
|
||||
return PSA_SUCCESS;
|
||||
}
|
||||
|
||||
-#ifdef BL1_BUILD
|
||||
-static psa_status_t metadata_read_without_validation(struct fwu_metadata *metadata)
|
||||
-{
|
||||
- FWU_LOG_MSG("%s: enter: flash addr = %u, size = %d\n\r", __func__,
|
||||
- FWU_METADATA_REPLICA_1_OFFSET, sizeof(*metadata));
|
||||
-
|
||||
- if (!metadata) {
|
||||
- FWU_LOG_MSG("%s: ERROR - Null pointer received\n\r", __func__);
|
||||
- return PSA_ERROR_INVALID_ARGUMENT;
|
||||
- }
|
||||
-
|
||||
- int ret = FWU_METADATA_FLASH_DEV.ReadData(FWU_METADATA_REPLICA_1_OFFSET,
|
||||
- metadata, sizeof(*metadata));
|
||||
- if (ret < 0) {
|
||||
- FWU_LOG_MSG("%s: ERROR - Flash read failed (ret = %d)\n\r", __func__, ret);
|
||||
- return PSA_ERROR_STORAGE_FAILURE;
|
||||
- }
|
||||
-
|
||||
- if (ret != sizeof(*metadata)) {
|
||||
- FWU_LOG_MSG("%s: ERROR - Incomplete metadata read (expected %zu, got %d)\n\r",
|
||||
- __func__, sizeof(*metadata), ret);
|
||||
- return PSA_ERROR_INSUFFICIENT_DATA;
|
||||
- }
|
||||
-
|
||||
- FWU_LOG_MSG("%s: success: active = %u, previous = %d\n\r", __func__,
|
||||
- metadata->active_index, metadata->previous_active_index);
|
||||
-
|
||||
- return PSA_SUCCESS;
|
||||
-}
|
||||
-#else
|
||||
-static psa_status_t metadata_read_without_validation(struct fwu_metadata *metadata)
|
||||
-{
|
||||
- uuid_t metadata_uuid = FWU_METADATA_TYPE_UUID;
|
||||
- partition_entry_t *part;
|
||||
-
|
||||
- if (!metadata) {
|
||||
- FWU_LOG_MSG("%s: ERROR - Null pointer received\n\r", __func__);
|
||||
- return PSA_ERROR_INVALID_ARGUMENT;
|
||||
- }
|
||||
-
|
||||
- part = get_partition_entry_by_type(&metadata_uuid);
|
||||
- if (!part) {
|
||||
- FWU_LOG_MSG("%s: FWU metadata partition not found\n\r", __func__);
|
||||
- return PSA_ERROR_GENERIC_ERROR;
|
||||
- }
|
||||
-
|
||||
- FWU_LOG_MSG("%s: enter: flash addr = %u, size = %d\n\r", __func__,
|
||||
- part->start, sizeof(*metadata));
|
||||
-
|
||||
-
|
||||
- int ret = FWU_METADATA_FLASH_DEV.ReadData(part->start,
|
||||
- metadata, sizeof(*metadata));
|
||||
- if (ret < 0) {
|
||||
- FWU_LOG_MSG("%s: ERROR - Flash read failed (ret = %d)\n\r", __func__, ret);
|
||||
- return PSA_ERROR_STORAGE_FAILURE;
|
||||
- }
|
||||
-
|
||||
- if (ret != sizeof(*metadata)) {
|
||||
- FWU_LOG_MSG("%s: ERROR - Incomplete metadata read (expected %zu, got %d)\n\r",
|
||||
- __func__, sizeof(*metadata), ret);
|
||||
- return PSA_ERROR_INSUFFICIENT_DATA;
|
||||
- }
|
||||
-
|
||||
- FWU_LOG_MSG("%s: success: active = %u, previous = %d\n\r", __func__,
|
||||
- metadata->active_index, metadata->previous_active_index);
|
||||
-
|
||||
- return PSA_SUCCESS;
|
||||
-}
|
||||
-#endif
|
||||
-
|
||||
#ifdef BL1_BUILD
|
||||
static psa_status_t metadata_read(struct fwu_metadata *metadata, uint8_t replica_num)
|
||||
{
|
||||
+464
@@ -0,0 +1,464 @@
|
||||
From 939d18a0d8dcedd2b5c4b6220e1a0f6c6855fcf6 Mon Sep 17 00:00:00 2001
|
||||
From: Frazer Carsley <frazer.carsley@arm.com>
|
||||
Date: Fri, 2 Jan 2026 14:21:57 +0000
|
||||
Subject: [PATCH] plat: cs1k: Reduce BL1 binary size
|
||||
|
||||
The size of the BL1 binary is nearly at its maximum allowable size of
|
||||
64KiB. By making logging a bit more consistent, string literals can be
|
||||
re-used and reduce the size of the binary. This allows more space for
|
||||
BL1_2.
|
||||
|
||||
Some functions also had two or more "entry" logging statements, and so
|
||||
the redundant statements were removed.
|
||||
|
||||
The size of BL1_1 has been updated to reflect these changes.
|
||||
|
||||
Change-Id: Id52dd0d319fb252d7d05e40b6f8f640d27d45ddb
|
||||
Signed-off-by: Frazer Carsley <frazer.carsley@arm.com>
|
||||
Upstream-Status: Submitted [https://review.trustedfirmware.org/c/TF-M/trusted-firmware-m/+/49427]
|
||||
---
|
||||
.../bootloader/mcuboot/tfm_mcuboot_fwu.c | 101 ++++++++++--------
|
||||
.../arm/corstone1000/partition/region_defs.h | 2 +-
|
||||
2 files changed, 56 insertions(+), 47 deletions(-)
|
||||
|
||||
diff --git a/platform/ext/target/arm/corstone1000/bootloader/mcuboot/tfm_mcuboot_fwu.c b/platform/ext/target/arm/corstone1000/bootloader/mcuboot/tfm_mcuboot_fwu.c
|
||||
index 76ee8a3dc..dc7503d41 100644
|
||||
--- a/platform/ext/target/arm/corstone1000/bootloader/mcuboot/tfm_mcuboot_fwu.c
|
||||
+++ b/platform/ext/target/arm/corstone1000/bootloader/mcuboot/tfm_mcuboot_fwu.c
|
||||
@@ -56,6 +56,13 @@
|
||||
#define FWU_FAKE_IMAGES_INDEX_COUNT 1
|
||||
#define FWU_FAKE_IMAGE_INDEX 0
|
||||
|
||||
+/* These macros provide consistent logging for simple function enter and
|
||||
+ * successful exit. This helps reduce the number of string literals in the
|
||||
+ * final binary, thus reducing its size
|
||||
+ */
|
||||
+#define FWU_LOG_FUNC_ENTER FWU_LOG_MSG("%s: enter\n\r", __func__)
|
||||
+#define FWU_LOG_FUNC_EXIT_SUCCESS FWU_LOG_MSG("%s: success\n\r", __func__)
|
||||
+
|
||||
/*
|
||||
* Metadata version 2 data structures defined by PSA_FW update specification
|
||||
* at https://developer.arm.com/documentation/den0118/latest/
|
||||
@@ -334,7 +341,7 @@ extern ARM_DRIVER_FLASH FWU_METADATA_FLASH_DEV;
|
||||
static psa_status_t private_metadata_read(
|
||||
struct fwu_private_metadata* priv_metadata)
|
||||
{
|
||||
- FWU_LOG_MSG("%s: enter\n\r", __func__);
|
||||
+ FWU_LOG_FUNC_ENTER;
|
||||
|
||||
if (!priv_metadata) {
|
||||
FWU_LOG_MSG("%s: ERROR - Null pointer received\n\r", __func__);
|
||||
@@ -366,7 +373,7 @@ static psa_status_t private_metadata_read(
|
||||
partition_entry_t *part;
|
||||
uuid_t private_uuid = PRIVATE_METADATA_TYPE_UUID;
|
||||
|
||||
- FWU_LOG_MSG("%s: enter\n\r", __func__);
|
||||
+ FWU_LOG_FUNC_ENTER;
|
||||
|
||||
if (!priv_metadata) {
|
||||
FWU_LOG_MSG("%s: ERROR - Null pointer received\n\r", __func__);
|
||||
@@ -430,7 +437,7 @@ static psa_status_t private_metadata_write(
|
||||
return PSA_ERROR_INSUFFICIENT_DATA;
|
||||
}
|
||||
|
||||
- FWU_LOG_MSG("%s: success\n\r", __func__);
|
||||
+ FWU_LOG_FUNC_EXIT_SUCCESS;
|
||||
return PSA_SUCCESS;
|
||||
}
|
||||
#else
|
||||
@@ -473,14 +480,14 @@ static psa_status_t private_metadata_write(
|
||||
return PSA_ERROR_INSUFFICIENT_DATA;
|
||||
}
|
||||
|
||||
- FWU_LOG_MSG("%s: success\n\r", __func__);
|
||||
+ FWU_LOG_FUNC_EXIT_SUCCESS;
|
||||
return PSA_SUCCESS;
|
||||
}
|
||||
#endif
|
||||
|
||||
static psa_status_t metadata_validate(struct fwu_metadata *metadata)
|
||||
{
|
||||
- FWU_LOG_MSG("%s: enter:\n\r", __func__);
|
||||
+ FWU_LOG_FUNC_ENTER;
|
||||
|
||||
if (!metadata) {
|
||||
FWU_LOG_MSG("%s: ERROR - Null pointer received\n\r", __func__);
|
||||
@@ -496,7 +503,7 @@ static psa_status_t metadata_validate(struct fwu_metadata *metadata)
|
||||
return PSA_ERROR_GENERIC_ERROR;
|
||||
}
|
||||
|
||||
- FWU_LOG_MSG("%s: success\n\r", __func__);
|
||||
+ FWU_LOG_FUNC_EXIT_SUCCESS;
|
||||
|
||||
return PSA_SUCCESS;
|
||||
}
|
||||
@@ -506,7 +513,7 @@ static psa_status_t metadata_read(struct fwu_metadata *metadata, uint8_t replica
|
||||
{
|
||||
uint32_t replica_offset = 0;
|
||||
|
||||
- FWU_LOG_MSG("%s: enter\n\r", __func__);
|
||||
+ FWU_LOG_FUNC_ENTER;
|
||||
|
||||
if (!metadata) {
|
||||
FWU_LOG_MSG("%s: ERROR - Null pointer received\n\r", __func__);
|
||||
@@ -525,7 +532,6 @@ static psa_status_t metadata_read(struct fwu_metadata *metadata, uint8_t replica
|
||||
FWU_LOG_MSG("%s: flash addr = %u, size = %d\n\r", __func__,
|
||||
replica_offset, sizeof(*metadata));
|
||||
|
||||
-
|
||||
int ret = FWU_METADATA_FLASH_DEV.ReadData(replica_offset,
|
||||
metadata, sizeof(*metadata));
|
||||
if (ret < 0) {
|
||||
@@ -555,7 +561,7 @@ static psa_status_t metadata_read(struct fwu_metadata *metadata, uint8_t replica
|
||||
uuid_t metadata_uuid = FWU_METADATA_TYPE_UUID;
|
||||
partition_entry_t *part;
|
||||
|
||||
- FWU_LOG_MSG("%s: enter\n\r", __func__);
|
||||
+ FWU_LOG_FUNC_ENTER;
|
||||
|
||||
if (!metadata) {
|
||||
FWU_LOG_MSG("%s: ERROR - Null pointer received\n\r", __func__);
|
||||
@@ -611,7 +617,7 @@ static psa_status_t metadata_write(
|
||||
{
|
||||
uint32_t replica_offset = 0;
|
||||
|
||||
- FWU_LOG_MSG("%s: enter\n\r", __func__);
|
||||
+ FWU_LOG_FUNC_ENTER;
|
||||
|
||||
if (!metadata) {
|
||||
FWU_LOG_MSG("%s: ERROR - Null pointer received\n\r", __func__);
|
||||
@@ -627,10 +633,9 @@ static psa_status_t metadata_write(
|
||||
return PSA_ERROR_GENERIC_ERROR;
|
||||
}
|
||||
|
||||
- FWU_LOG_MSG("%s: enter: flash addr = %u, size = %d\n\r", __func__,
|
||||
+ FWU_LOG_MSG("%s: flash addr = %u, size = %d\n\r", __func__,
|
||||
replica_offset, sizeof(*metadata));
|
||||
|
||||
-
|
||||
int ret = FWU_METADATA_FLASH_DEV.EraseSector(replica_offset);
|
||||
if (ret != ARM_DRIVER_OK) {
|
||||
FWU_LOG_MSG("%s: ERROR - Flash erase failed (ret = %d)\n\r", __func__, ret);
|
||||
@@ -661,6 +666,8 @@ static psa_status_t metadata_write(
|
||||
uuid_t metadata_uuid = FWU_METADATA_TYPE_UUID;
|
||||
partition_entry_t *part;
|
||||
|
||||
+ FWU_LOG_FUNC_ENTER;
|
||||
+
|
||||
if (!metadata) {
|
||||
FWU_LOG_MSG("%s: ERROR - Null pointer received\n\r", __func__);
|
||||
return PSA_ERROR_INVALID_ARGUMENT;
|
||||
@@ -888,7 +895,7 @@ psa_status_t fwu_metadata_provision(void)
|
||||
{
|
||||
psa_status_t ret;
|
||||
|
||||
- FWU_LOG_MSG("%s: enter\n\r", __func__);
|
||||
+ FWU_LOG_FUNC_ENTER;
|
||||
|
||||
ret = fwu_metadata_init();
|
||||
if (ret) {
|
||||
@@ -918,7 +925,7 @@ psa_status_t fwu_metadata_provision(void)
|
||||
return ret;
|
||||
}
|
||||
|
||||
- FWU_LOG_MSG("%s: FWU METADATA PROVISIONED.\n\r", __func__);
|
||||
+ FWU_LOG_FUNC_EXIT_SUCCESS;
|
||||
return PSA_SUCCESS;
|
||||
}
|
||||
|
||||
@@ -927,7 +934,7 @@ static uint8_t get_fwu_image_state(
|
||||
struct fwu_private_metadata *priv_metadata,
|
||||
uint32_t fwu_image_index)
|
||||
{
|
||||
- FWU_LOG_MSG("%s: enter\n\r", __func__);
|
||||
+ FWU_LOG_FUNC_ENTER;
|
||||
|
||||
if ((metadata->fw_desc.img_entry[fwu_image_index].img_props[metadata->active_index].accepted)
|
||||
== (IMAGE_NOT_ACCEPTED)) {
|
||||
@@ -943,7 +950,7 @@ static uint8_t get_fwu_agent_state(
|
||||
struct fwu_metadata *metadata,
|
||||
struct fwu_private_metadata *priv_metadata)
|
||||
{
|
||||
- FWU_LOG_MSG("%s: enter\n\r", __func__);
|
||||
+ FWU_LOG_FUNC_ENTER;
|
||||
|
||||
if (priv_metadata->boot_index != metadata->active_index) {
|
||||
FWU_LOG_MSG("%s: exit: FWU Agent PSA_FWU_TRIAL (index mismatch)\n\r", __func__);
|
||||
@@ -966,7 +973,7 @@ static psa_status_t erase_image(uint32_t image_offset, uint32_t image_size)
|
||||
int ret;
|
||||
uint32_t sectors;
|
||||
|
||||
- FWU_LOG_MSG("%s: enter\n\r", __func__);
|
||||
+ FWU_LOG_FUNC_ENTER;
|
||||
|
||||
if ((image_offset % FWU_METADATA_FLASH_SECTOR_SIZE) != 0) {
|
||||
return PSA_ERROR_INVALID_ARGUMENT;
|
||||
@@ -989,7 +996,7 @@ static psa_status_t erase_image(uint32_t image_offset, uint32_t image_size)
|
||||
}
|
||||
}
|
||||
|
||||
- FWU_LOG_MSG("%s: exit\n\r", __func__);
|
||||
+ FWU_LOG_FUNC_EXIT_SUCCESS;
|
||||
return PSA_SUCCESS;
|
||||
}
|
||||
|
||||
@@ -1001,7 +1008,7 @@ static psa_status_t fwu_select_previous(
|
||||
uint8_t current_state;
|
||||
uint32_t index;
|
||||
|
||||
- FWU_LOG_MSG("%s: enter\n\r", __func__);
|
||||
+ FWU_LOG_FUNC_ENTER;
|
||||
|
||||
/* it is expected to receive this call only when
|
||||
in trial state */
|
||||
@@ -1049,8 +1056,8 @@ static psa_status_t fwu_select_previous(
|
||||
FWU_LOG_MSG("%s: in regular state by choosing previous active bank\n\r",
|
||||
__func__);
|
||||
|
||||
- FWU_LOG_MSG("%s: exit: ret = %d\n\r", __func__, ret);
|
||||
- return ret;
|
||||
+ FWU_LOG_FUNC_EXIT_SUCCESS;
|
||||
+ return PSA_SUCCESS;
|
||||
|
||||
}
|
||||
|
||||
@@ -1061,7 +1068,7 @@ void bl1_get_active_bl2_image(uint32_t *offset)
|
||||
uint32_t boot_attempted;
|
||||
uint32_t boot_index;
|
||||
|
||||
- FWU_LOG_MSG("%s: enter\n\r", __func__);
|
||||
+ FWU_LOG_FUNC_ENTER;
|
||||
|
||||
if (fwu_metadata_init()) {
|
||||
FWU_ASSERT(0);
|
||||
@@ -1125,7 +1132,7 @@ uint8_t bl2_get_boot_bank(void)
|
||||
{
|
||||
uint8_t boot_index;
|
||||
struct fwu_private_metadata priv_metadata;
|
||||
- FWU_LOG_MSG("%s: enter", __func__);
|
||||
+ FWU_LOG_FUNC_ENTER;
|
||||
if (fwu_metadata_init()) {
|
||||
FWU_ASSERT(0);
|
||||
}
|
||||
@@ -1150,7 +1157,7 @@ static psa_status_t update_nv_counters(
|
||||
uint32_t security_cnt;
|
||||
enum tfm_nv_counter_t tfm_nv_counter_i;
|
||||
|
||||
- FWU_LOG_MSG("%s: enter\n\r", __func__);
|
||||
+ FWU_LOG_FUNC_ENTER;
|
||||
|
||||
/* The FWU_BL2_NV_COUNTER (0) is not mirrored in the private metadata. It is
|
||||
* directly updated in the bl1_2_validate_image_at_addr() function, in
|
||||
@@ -1194,7 +1201,7 @@ static psa_status_t update_nv_counters(
|
||||
|
||||
}
|
||||
|
||||
- FWU_LOG_MSG("%s: exit\n\r", __func__);
|
||||
+ FWU_LOG_FUNC_EXIT_SUCCESS;
|
||||
return PSA_SUCCESS;
|
||||
}
|
||||
|
||||
@@ -1204,7 +1211,7 @@ psa_status_t corstone1000_fwu_host_ack(void)
|
||||
struct fwu_private_metadata priv_metadata;
|
||||
uint8_t current_state;
|
||||
|
||||
- FWU_LOG_MSG("%s: enter\n\r", __func__);
|
||||
+ FWU_LOG_FUNC_ENTER;
|
||||
|
||||
if (!is_initialized) {
|
||||
return PSA_ERROR_BAD_STATE;
|
||||
@@ -1309,7 +1316,7 @@ void host_acknowledgement_timer_to_reset(void)
|
||||
struct fwu_private_metadata priv_metadata;
|
||||
uint8_t current_state;
|
||||
|
||||
- FWU_LOG_MSG("%s: enter\n\r", __func__);
|
||||
+ FWU_LOG_FUNC_ENTER;
|
||||
|
||||
Select_Write_Mode_For_Shared_Flash();
|
||||
|
||||
@@ -1342,7 +1349,7 @@ void host_acknowledgement_timer_to_reset(void)
|
||||
}
|
||||
}
|
||||
|
||||
- FWU_LOG_MSG("%s: exit\n\r", __func__);
|
||||
+ FWU_LOG_FUNC_EXIT_SUCCESS;
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -1379,7 +1386,7 @@ psa_status_t fwu_stage_nv_counter(enum fwu_nv_counter_index_t index,
|
||||
}
|
||||
}
|
||||
|
||||
- FWU_LOG_MSG("%s: exit\n\r", __func__);
|
||||
+ FWU_LOG_FUNC_EXIT_SUCCESS;
|
||||
return PSA_SUCCESS;
|
||||
}
|
||||
|
||||
@@ -1397,7 +1404,7 @@ bool is_image_index_valid(uint8_t fwu_image_index) {
|
||||
|
||||
static psa_status_t get_esrt_data(struct fwu_esrt_data_wrapper *esrt)
|
||||
{
|
||||
- FWU_LOG_MSG("%s: enter\n\r", __func__);
|
||||
+ FWU_LOG_FUNC_ENTER;
|
||||
|
||||
if (!esrt)
|
||||
{
|
||||
@@ -1445,7 +1452,7 @@ static psa_status_t fwu_accept_image(struct fwu_metadata *metadata,
|
||||
uint32_t fwu_image_index;
|
||||
psa_status_t ret;
|
||||
|
||||
- FWU_LOG_MSG("%s: enter\n\r", __func__);
|
||||
+ FWU_LOG_FUNC_ENTER;
|
||||
|
||||
|
||||
/* booted from previous_active_bank, not expected
|
||||
@@ -1492,8 +1499,8 @@ static psa_status_t fwu_accept_image(struct fwu_metadata *metadata,
|
||||
return ret;
|
||||
}
|
||||
|
||||
- FWU_LOG_MSG("%s: exit: fwu state is changed to regular, ret - %d\n\r", __func__, ret);
|
||||
- return ret;
|
||||
+ FWU_LOG_MSG("%s: success: fwu state is changed to regular\n\r", __func__);
|
||||
+ return PSA_SUCCESS;
|
||||
}
|
||||
|
||||
static psa_status_t uint_to_image_version(uint32_t ver_in, psa_fwu_image_version_t *ver_out)
|
||||
@@ -1525,6 +1532,8 @@ static psa_status_t erase_staging_area(struct fwu_metadata* metadata, psa_fwu_co
|
||||
return PSA_ERROR_INVALID_ARGUMENT;
|
||||
}
|
||||
|
||||
+ FWU_LOG_FUNC_ENTER;
|
||||
+
|
||||
if (!is_image_index_valid(component)) {
|
||||
FWU_LOG_MSG("%s: Invalid Component received \n\r", __func__);
|
||||
return PSA_ERROR_GENERIC_ERROR;
|
||||
@@ -1535,8 +1544,6 @@ static psa_status_t erase_staging_area(struct fwu_metadata* metadata, psa_fwu_co
|
||||
uint32_t image_offset;
|
||||
uint8_t fwu_image_index = component - FWU_FAKE_IMAGES_INDEX_COUNT; /* Decrement to get the correct fwu image index */
|
||||
|
||||
- FWU_LOG_MSG("%s: enter\n\r", __func__);
|
||||
-
|
||||
if (active_index == BANK_0) {
|
||||
bank_offset = BANK_1_PARTITION_OFFSET;
|
||||
} else if (active_index == BANK_1) {
|
||||
@@ -1551,7 +1558,7 @@ static psa_status_t erase_staging_area(struct fwu_metadata* metadata, psa_fwu_co
|
||||
return PSA_ERROR_GENERIC_ERROR;
|
||||
}
|
||||
|
||||
- FWU_LOG_MSG("%s: exit: Staging area erased succesfully \n\r", __func__);
|
||||
+ FWU_LOG_FUNC_EXIT_SUCCESS;
|
||||
return PSA_SUCCESS;
|
||||
}
|
||||
|
||||
@@ -1559,7 +1566,7 @@ psa_status_t fwu_bootloader_init(void)
|
||||
{
|
||||
psa_status_t ret;
|
||||
|
||||
- FWU_LOG_MSG("%s: enter\n\r", __func__);
|
||||
+ FWU_LOG_FUNC_ENTER;
|
||||
|
||||
ret = fwu_metadata_init();
|
||||
if (ret) {
|
||||
@@ -1569,7 +1576,7 @@ psa_status_t fwu_bootloader_init(void)
|
||||
/* Initialize the fmp_header_image_info object */
|
||||
fmp_header_image_info_init();
|
||||
|
||||
- FWU_LOG_MSG("%s: exit: Initialized\n\r", __func__);
|
||||
+ FWU_LOG_FUNC_EXIT_SUCCESS;
|
||||
|
||||
return PSA_SUCCESS;
|
||||
}
|
||||
@@ -1588,7 +1595,7 @@ psa_status_t fwu_bootloader_staging_area_init(psa_fwu_component_t component,
|
||||
|
||||
psa_status_t ret;
|
||||
|
||||
- FWU_LOG_MSG("%s: enter\n\r", __func__);
|
||||
+ FWU_LOG_FUNC_ENTER;
|
||||
|
||||
Select_Write_Mode_For_Shared_Flash();
|
||||
|
||||
@@ -1783,7 +1790,7 @@ static psa_status_t fwu_update_metadata(const psa_fwu_component_t *candidates, u
|
||||
uint32_t previous_active_index;
|
||||
uint8_t fwu_image_index;
|
||||
|
||||
- FWU_LOG_MSG("%s: enter function\n\r", __func__);
|
||||
+ FWU_LOG_FUNC_ENTER;
|
||||
|
||||
Select_Write_Mode_For_Shared_Flash();
|
||||
|
||||
@@ -1842,6 +1849,8 @@ static psa_status_t copy_image_from_other_bank(int image_index,
|
||||
uint32_t active_index,
|
||||
uint32_t previous_active_index)
|
||||
{
|
||||
+ FWU_LOG_FUNC_ENTER;
|
||||
+
|
||||
uint32_t bank_offset[NR_OF_FW_BANKS] = {BANK_0_PARTITION_OFFSET, BANK_1_PARTITION_OFFSET};
|
||||
uint8_t data[FLASH_CHUNK_SIZE];
|
||||
size_t remaining_size = fwu_image[image_index].image_size;
|
||||
@@ -1904,7 +1913,7 @@ static psa_status_t maintain_bank_consistency(void)
|
||||
uint32_t previous_active_index;
|
||||
struct fwu_private_metadata priv_metadata;
|
||||
|
||||
- FWU_LOG_MSG("%s: Enter \n\r", __func__);
|
||||
+ FWU_LOG_FUNC_ENTER;
|
||||
Select_Write_Mode_For_Shared_Flash();
|
||||
|
||||
if (metadata_read(&_metadata, 1) || private_metadata_read(&priv_metadata)) {
|
||||
@@ -1979,7 +1988,7 @@ psa_status_t fwu_bootloader_install_image(const psa_fwu_component_t *candidates,
|
||||
}
|
||||
|
||||
psa_status_t ret;
|
||||
- FWU_LOG_MSG("%s: enter function\n\r", __func__);
|
||||
+ FWU_LOG_FUNC_ENTER;
|
||||
|
||||
/* Copy images from other bank which are not received by FWU client */
|
||||
ret = maintain_bank_consistency();
|
||||
@@ -2015,7 +2024,7 @@ psa_status_t fwu_bootloader_mark_image_accepted(const psa_fwu_component_t *trial
|
||||
uint8_t current_state;
|
||||
uint8_t fwu_image_index;
|
||||
|
||||
- FWU_LOG_MSG("%s: enter\n\r", __func__);
|
||||
+ FWU_LOG_FUNC_ENTER;
|
||||
|
||||
Select_Write_Mode_For_Shared_Flash();
|
||||
|
||||
@@ -2114,7 +2123,7 @@ psa_status_t fwu_bootloader_reject_staged_image(psa_fwu_component_t component)
|
||||
uint32_t image_offset;
|
||||
uint8_t image_index = component - FWU_FAKE_IMAGES_INDEX_COUNT; /* Decrement to get the correct fwu image index */
|
||||
|
||||
- FWU_LOG_MSG("%s: enter\n\r", __func__);
|
||||
+ FWU_LOG_FUNC_ENTER;
|
||||
Select_Write_Mode_For_Shared_Flash();
|
||||
|
||||
if (metadata_read(&_metadata, 1)) {
|
||||
@@ -2158,7 +2167,7 @@ psa_status_t fwu_bootloader_reject_trial_image(psa_fwu_component_t component)
|
||||
int ret;
|
||||
uint8_t fwu_image_index = component - FWU_FAKE_IMAGES_INDEX_COUNT; /* Decrement to get the correct fwu image index */
|
||||
|
||||
- FWU_LOG_MSG("%s: enter\n\r", __func__);
|
||||
+ FWU_LOG_FUNC_ENTER;
|
||||
|
||||
/* Disable host ackowledgement timer */
|
||||
disable_host_ack_timer();
|
||||
@@ -2213,7 +2222,7 @@ psa_status_t fwu_bootloader_get_image_info(psa_fwu_component_t component,
|
||||
uint8_t current_state;
|
||||
psa_status_t ret;
|
||||
|
||||
- FWU_LOG_MSG("%s: enter\n\r", __func__);
|
||||
+ FWU_LOG_FUNC_ENTER;
|
||||
|
||||
|
||||
Select_Write_Mode_For_Shared_Flash();
|
||||
diff --git a/platform/ext/target/arm/corstone1000/partition/region_defs.h b/platform/ext/target/arm/corstone1000/partition/region_defs.h
|
||||
index 92e01c0e3..1feee7841 100644
|
||||
--- a/platform/ext/target/arm/corstone1000/partition/region_defs.h
|
||||
+++ b/platform/ext/target/arm/corstone1000/partition/region_defs.h
|
||||
@@ -94,7 +94,7 @@
|
||||
|
||||
/* SE BL1 regions */
|
||||
#define BL1_1_CODE_START (0)
|
||||
-#define BL1_1_CODE_SIZE (0x0000E800) /* 58 KiB */
|
||||
+#define BL1_1_CODE_SIZE (0x0000E748) /* 58 KiB */
|
||||
#define BL1_1_CODE_LIMIT (BL1_1_CODE_START + BL1_1_CODE_SIZE - 1)
|
||||
|
||||
#define PROVISIONING_DATA_START (BL1_1_CODE_START + BL1_1_CODE_SIZE)
|
||||
+35
@@ -0,0 +1,35 @@
|
||||
From b4fd75b96b49756c4815685fc19089793fcc9356 Mon Sep 17 00:00:00 2001
|
||||
From: Frazer Carsley <frazer.carsley@arm.com>
|
||||
Date: Wed, 14 Jan 2026 14:00:12 +0000
|
||||
Subject: [PATCH] plat: cs1k: Update license identifier
|
||||
|
||||
Change-Id: I26af0dbf66359e76b7164b3abdbbf3ace3f358c6
|
||||
Signed-off-by: Frazer Carsley <frazer.carsley@arm.com>
|
||||
Upstream-Status: Submitted [https://review.trustedfirmware.org/c/TF-M/trusted-firmware-m/+/49428]
|
||||
---
|
||||
platform/ext/target/arm/corstone1000/platform.c | 2 +-
|
||||
platform/ext/target/arm/corstone1000/platform.h | 2 +-
|
||||
2 files changed, 2 insertions(+), 2 deletions(-)
|
||||
|
||||
diff --git a/platform/ext/target/arm/corstone1000/platform.c b/platform/ext/target/arm/corstone1000/platform.c
|
||||
index d0f30b72a..32fdc55aa 100644
|
||||
--- a/platform/ext/target/arm/corstone1000/platform.c
|
||||
+++ b/platform/ext/target/arm/corstone1000/platform.c
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
- * Copyright (c) 2023, Arm Limited. All rights reserved.
|
||||
+ * SPDX-FileCopyrightText: Copyright The TrustedFirmware-M Contributors
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*
|
||||
diff --git a/platform/ext/target/arm/corstone1000/platform.h b/platform/ext/target/arm/corstone1000/platform.h
|
||||
index a88093ed4..906a8f9ae 100644
|
||||
--- a/platform/ext/target/arm/corstone1000/platform.h
|
||||
+++ b/platform/ext/target/arm/corstone1000/platform.h
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
- * Copyright (c) 2023, Arm Limited. All rights reserved.
|
||||
+ * SPDX-FileCopyrightText: Copyright The TrustedFirmware-M Contributors
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*
|
||||
+4536
File diff suppressed because it is too large
Load Diff
+55
@@ -0,0 +1,55 @@
|
||||
From 201166be49ca4c0079cf804f208534f201cb4b65 Mon Sep 17 00:00:00 2001
|
||||
From: Frazer Carsley <frazer.carsley@arm.com>
|
||||
Date: Fri, 13 Mar 2026 16:53:54 +0000
|
||||
Subject: [PATCH] plat: cs1k: Move variable from stack to data
|
||||
|
||||
The firmware update secure partition stack is only 0x600 bytes in size.
|
||||
The variable moved is a buffer of size 0x200, consituting one third of
|
||||
the available stack. Moving this to the much larger .data section allows
|
||||
much more stack space if required.
|
||||
|
||||
Change-Id: I59d68e80acefaeea36c7060442e005998217d923
|
||||
Signed-off-by: Frazer Carsley <frazer.carsley@arm.com>
|
||||
Upstream-Status: Submitted [https://review.trustedfirmware.org/c/TF-M/trusted-firmware-m/+/49430]
|
||||
---
|
||||
.../arm/corstone1000/bootloader/mcuboot/tfm_mcuboot_fwu.c | 6 +++---
|
||||
1 file changed, 3 insertions(+), 3 deletions(-)
|
||||
|
||||
diff --git a/platform/ext/target/arm/corstone1000/bootloader/mcuboot/tfm_mcuboot_fwu.c b/platform/ext/target/arm/corstone1000/bootloader/mcuboot/tfm_mcuboot_fwu.c
|
||||
index 5e1c4ecc5..a35125b00 100644
|
||||
--- a/platform/ext/target/arm/corstone1000/bootloader/mcuboot/tfm_mcuboot_fwu.c
|
||||
+++ b/platform/ext/target/arm/corstone1000/bootloader/mcuboot/tfm_mcuboot_fwu.c
|
||||
@@ -39,6 +39,7 @@
|
||||
* This is used when bank consistency is maintained during partial capsule update
|
||||
*/
|
||||
#define FLASH_CHUNK_SIZE 512
|
||||
+static uint8_t flash_data_buf[FLASH_CHUNK_SIZE];
|
||||
|
||||
/* Possible states of the bank.
|
||||
* Naming convention here matches the implementation in U-Boot
|
||||
@@ -1978,7 +1979,6 @@ static psa_status_t copy_image_from_other_bank(int image_index,
|
||||
FWU_LOG_FUNC_ENTER;
|
||||
|
||||
uint32_t bank_offset[NR_OF_FW_BANKS] = {BANK_0_PARTITION_OFFSET, BANK_1_PARTITION_OFFSET};
|
||||
- uint8_t data[FLASH_CHUNK_SIZE];
|
||||
size_t remaining_size = fwu_image[image_index].image_size;
|
||||
size_t data_size;
|
||||
size_t offset_read = bank_offset[active_index] + fwu_image[image_index].image_offset;
|
||||
@@ -1997,7 +1997,7 @@ static psa_status_t copy_image_from_other_bank(int image_index,
|
||||
data_size = (remaining_size > FLASH_CHUNK_SIZE) ? FLASH_CHUNK_SIZE : remaining_size;
|
||||
|
||||
/* read image data from flash */
|
||||
- data_transferred_count = FWU_METADATA_FLASH_DEV.ReadData(offset_read, data, data_size);
|
||||
+ data_transferred_count = FWU_METADATA_FLASH_DEV.ReadData(offset_read, flash_data_buf, data_size);
|
||||
if (data_transferred_count < 0) {
|
||||
FWU_LOG_MSG("%s: ERROR - Flash read failed (ret = %d)\n\r", __func__, data_transferred_count);
|
||||
return PSA_ERROR_STORAGE_FAILURE;
|
||||
@@ -2012,7 +2012,7 @@ static psa_status_t copy_image_from_other_bank(int image_index,
|
||||
offset_read += data_size;
|
||||
|
||||
/* write image data to flash */
|
||||
- data_transferred_count = FWU_METADATA_FLASH_DEV.ProgramData(offset_write, data, data_size);
|
||||
+ data_transferred_count = FWU_METADATA_FLASH_DEV.ProgramData(offset_write, flash_data_buf, data_size);
|
||||
if (data_transferred_count < 0) {
|
||||
FWU_LOG_MSG("%s: ERROR - Flash read failed (ret = %d)\n\r", __func__, data_transferred_count);
|
||||
return PSA_ERROR_STORAGE_FAILURE;
|
||||
+521
@@ -0,0 +1,521 @@
|
||||
From 93101e6de045c0c4d633c502616ccf184c07e70a Mon Sep 17 00:00:00 2001
|
||||
From: Frazer Carsley <frazer.carsley@arm.com>
|
||||
Date: Fri, 13 Mar 2026 13:42:16 +0000
|
||||
Subject: [PATCH] plat: cs1k: Create and remove FWU image partitions
|
||||
|
||||
Previous to this commit, the GPT library was used only to read each
|
||||
firmware update image partition. However, the library now is used to
|
||||
create new partitions, if they don't exist, at the start of an update
|
||||
and remove the unused partitions at the end of an update, regardless of
|
||||
whether the images were accepted or rejected.
|
||||
|
||||
The images are not moved and are still placed in fixed offsets, so the
|
||||
idea of a ping-pong between banks still persists.
|
||||
|
||||
Change-Id: Ie2a2f0246a500c01019e3b498ac131466a2b3c84
|
||||
Signed-off-by: Frazer Carsley <frazer.carsley@arm.com>
|
||||
Upstream-Status: Submitted [https://review.trustedfirmware.org/c/TF-M/trusted-firmware-m/+/49431]
|
||||
---
|
||||
.../arm/corstone1000/bootloader/fwu_agent.h | 7 +-
|
||||
.../bootloader/mcuboot/tfm_mcuboot_fwu.c | 313 +++++++++++++++++-
|
||||
2 files changed, 302 insertions(+), 18 deletions(-)
|
||||
|
||||
diff --git a/platform/ext/target/arm/corstone1000/bootloader/fwu_agent.h b/platform/ext/target/arm/corstone1000/bootloader/fwu_agent.h
|
||||
index 4393f5f7b..729e1594c 100644
|
||||
--- a/platform/ext/target/arm/corstone1000/bootloader/fwu_agent.h
|
||||
+++ b/platform/ext/target/arm/corstone1000/bootloader/fwu_agent.h
|
||||
@@ -8,6 +8,7 @@
|
||||
#ifndef FWU_AGENT_H
|
||||
#define FWU_AGENT_H
|
||||
|
||||
+#include "flash_layout.h"
|
||||
#include "psa/error.h"
|
||||
#include "efi_guid_structs.h"
|
||||
#include "gpt.h"
|
||||
@@ -47,7 +48,7 @@ typedef struct {
|
||||
size_t image_size_recvd;
|
||||
} __packed fmp_header_image_info_t;
|
||||
|
||||
-/* Image information common for both the banks */
|
||||
+/* Image information for each bank */
|
||||
typedef struct {
|
||||
/* Total size of the image */
|
||||
uint32_t image_size;
|
||||
@@ -55,8 +56,8 @@ typedef struct {
|
||||
/* Offset of image within a bank. */
|
||||
uint32_t image_offset;
|
||||
|
||||
- /* Name of the image in ascii */
|
||||
- char image_name[FWU_IMAGE_NAME_LENGTH];
|
||||
+ /* Names of the image in ascii, one for each bank */
|
||||
+ const char image_names[NR_OF_FW_BANKS][FWU_IMAGE_NAME_LENGTH];
|
||||
|
||||
/* Image-type GUID */
|
||||
struct efi_guid_t image_type;
|
||||
diff --git a/platform/ext/target/arm/corstone1000/bootloader/mcuboot/tfm_mcuboot_fwu.c b/platform/ext/target/arm/corstone1000/bootloader/mcuboot/tfm_mcuboot_fwu.c
|
||||
index a35125b00..71a91ade5 100644
|
||||
--- a/platform/ext/target/arm/corstone1000/bootloader/mcuboot/tfm_mcuboot_fwu.c
|
||||
+++ b/platform/ext/target/arm/corstone1000/bootloader/mcuboot/tfm_mcuboot_fwu.c
|
||||
@@ -214,7 +214,7 @@ const fwu_image_info_t fwu_image[NR_OF_IMAGES_IN_FW_BANK] = {
|
||||
#if PLATFORM_IS_FVP
|
||||
// FVP payloads GUIDs
|
||||
{
|
||||
- .image_name = "bl2_secondary",
|
||||
+ .image_names = {"bl2_primary", "bl2_secondary"},
|
||||
.image_size = SE_BL2_PARTITION_SIZE,
|
||||
.image_offset = SE_BL2_PARTITION_BANK_OFFSET,
|
||||
.image_type = {
|
||||
@@ -227,7 +227,7 @@ const fwu_image_info_t fwu_image[NR_OF_IMAGES_IN_FW_BANK] = {
|
||||
},
|
||||
},
|
||||
{
|
||||
- .image_name = "tfm_secondary",
|
||||
+ .image_names = {"tfm_primary", "tfm_secondary"},
|
||||
.image_size = TFM_PARTITION_SIZE,
|
||||
.image_offset = TFM_PARTITION_BANK_OFFSET,
|
||||
.image_type = {
|
||||
@@ -240,7 +240,7 @@ const fwu_image_info_t fwu_image[NR_OF_IMAGES_IN_FW_BANK] = {
|
||||
},
|
||||
},
|
||||
{
|
||||
- .image_name = "FIP_B",
|
||||
+ .image_names = {"FIP_A", "FIP_B"},
|
||||
.image_size = FIP_PARTITION_SIZE,
|
||||
.image_offset = FIP_PARTITION_BANK_OFFSET,
|
||||
.image_type = {
|
||||
@@ -253,7 +253,7 @@ const fwu_image_info_t fwu_image[NR_OF_IMAGES_IN_FW_BANK] = {
|
||||
},
|
||||
},
|
||||
{
|
||||
- .image_name = "kernel_secondary",
|
||||
+ .image_names = {"kernel_primary", "kernel_secondary"},
|
||||
.image_size = INITRAMFS_PARTITION_SIZE,
|
||||
.image_offset = INITRAMFS_PARTITION_BANK_OFFSET,
|
||||
.image_type = {
|
||||
@@ -268,7 +268,7 @@ const fwu_image_info_t fwu_image[NR_OF_IMAGES_IN_FW_BANK] = {
|
||||
#else
|
||||
// MPS3 payloads GUIDs
|
||||
{
|
||||
- .image_name = "bl2_secondary",
|
||||
+ .image_names = {"bl2_primary", "bl2_secondary"},
|
||||
.image_size = SE_BL2_PARTITION_SIZE,
|
||||
.image_offset = SE_BL2_PARTITION_BANK_OFFSET,
|
||||
.image_type = {
|
||||
@@ -281,7 +281,7 @@ const fwu_image_info_t fwu_image[NR_OF_IMAGES_IN_FW_BANK] = {
|
||||
},
|
||||
},
|
||||
{
|
||||
- .image_name = "tfm_secondary",
|
||||
+ .image_names = {"tfm_primary", "tfm_secondary"},
|
||||
.image_size = TFM_PARTITION_SIZE,
|
||||
.image_offset = TFM_PARTITION_BANK_OFFSET,
|
||||
.image_type = {
|
||||
@@ -294,7 +294,7 @@ const fwu_image_info_t fwu_image[NR_OF_IMAGES_IN_FW_BANK] = {
|
||||
}
|
||||
},
|
||||
{
|
||||
- .image_name = "FIP_B",
|
||||
+ .image_names = {"FIP_A", "FIP_B"},
|
||||
.image_size = FIP_PARTITION_SIZE,
|
||||
.image_offset = FIP_PARTITION_BANK_OFFSET,
|
||||
.image_type = {
|
||||
@@ -307,7 +307,7 @@ const fwu_image_info_t fwu_image[NR_OF_IMAGES_IN_FW_BANK] = {
|
||||
}
|
||||
},
|
||||
{
|
||||
- .image_name = "kernel_secondary",
|
||||
+ .image_names = {"kernel_primary", "kernel_secondary"},
|
||||
.image_size = INITRAMFS_PARTITION_SIZE,
|
||||
.image_offset = INITRAMFS_PARTITION_BANK_OFFSET,
|
||||
.image_type = {
|
||||
@@ -354,6 +354,15 @@ extern ARM_DRIVER_FLASH FWU_METADATA_FLASH_DEV;
|
||||
* This is the value decided after monitoring the total time
|
||||
* taken by the host to boot both on FVP and FPGA.
|
||||
*/
|
||||
+#ifndef BL1_BUILD
|
||||
+static void ascii_to_unicode(const char *ascii, char *unicode)
|
||||
+{
|
||||
+ for (int i = 0; i < strlen(ascii) + 1; ++i) {
|
||||
+ unicode[i << 1] = ascii[i];
|
||||
+ unicode[(i << 1) + 1] = '\0';
|
||||
+ }
|
||||
+}
|
||||
+#endif
|
||||
|
||||
#ifdef BL1_BUILD
|
||||
static psa_status_t private_metadata_read(
|
||||
@@ -856,6 +865,11 @@ psa_status_t fwu_metadata_init(void)
|
||||
if (ret != PSA_SUCCESS) {
|
||||
return ret;
|
||||
}
|
||||
+
|
||||
+ ret = psa_crypto_init();
|
||||
+ if (ret != PSA_SUCCESS) {
|
||||
+ return ret;
|
||||
+ }
|
||||
#endif
|
||||
|
||||
/* Code assumes everything fits into a sector */
|
||||
@@ -1146,6 +1160,45 @@ static psa_status_t fwu_select_previous(
|
||||
return ret;
|
||||
}
|
||||
|
||||
+#ifndef BL1_BUILD
|
||||
+ /* Remove the GPT partitions for the rejected images. It is always the newer
|
||||
+ * (second) partitions that are rejected, as they are created during the
|
||||
+ * fwu process
|
||||
+ */
|
||||
+ for (int i = 0; i < NR_OF_IMAGES_IN_FW_BANK; ++i) {
|
||||
+ struct partition_entry_t part;
|
||||
+ ret = gpt_entry_read_by_type(&(fwu_image[i].image_type), 1, &part);
|
||||
+
|
||||
+ if (ret == PSA_ERROR_DOES_NOT_EXIST) {
|
||||
+ FWU_LOG_MSG("%s: Unable to find partition '%s'\r\n",
|
||||
+ __func__, fwu_image[i].image_names[index]);
|
||||
+ return ret;
|
||||
+ } else if (ret == PSA_ERROR_STORAGE_FAILURE) {
|
||||
+ FWU_LOG_MSG("%s: Flash error whilst reading GPT partition '%s'\r\n",
|
||||
+ __func__, fwu_image[i].image_names[index]);
|
||||
+ return ret;
|
||||
+ } else if (ret < 0) {
|
||||
+ FWU_LOG_MSG("%s: Unable to read partition '%s'\r\n",
|
||||
+ __func__, fwu_image[i].image_names[index]);
|
||||
+ return ret;
|
||||
+ }
|
||||
+
|
||||
+ ret = gpt_entry_remove(&(part.partition_guid));
|
||||
+ if (ret == PSA_ERROR_STORAGE_FAILURE) {
|
||||
+ FWU_LOG_MSG("%s: Flash error whilst removing GPT partition '%s'\r\n",
|
||||
+ __func__, fwu_image[i].image_names[index]);
|
||||
+ return ret;
|
||||
+ } else if (ret < 0) {
|
||||
+ FWU_LOG_MSG("%s: Unable to remove partition '%s'\r\n",
|
||||
+ __func__, fwu_image[i].image_names[index]);
|
||||
+ return ret;
|
||||
+ }
|
||||
+
|
||||
+ FWU_LOG_MSG("%s: Removed GPT partition '%s'\r\n",
|
||||
+ __func__, fwu_image[i].image_names[index]);
|
||||
+ }
|
||||
+#endif /* BL1_BUILD */
|
||||
+
|
||||
FWU_LOG_MSG("%s: in regular state by choosing previous active bank\n\r",
|
||||
__func__);
|
||||
|
||||
@@ -1594,6 +1647,47 @@ static psa_status_t fwu_accept_image(struct fwu_metadata *metadata,
|
||||
return ret;
|
||||
}
|
||||
|
||||
+#ifndef BL1_BUILD
|
||||
+ /* Remove the old (first) partitions from the GPT header. It is always the
|
||||
+ * older images to be removed, as they were not created by the update
|
||||
+ * process but existed before
|
||||
+ */
|
||||
+ uint32_t previous_bank_index = metadata->previous_active_index;
|
||||
+
|
||||
+ for (int i = 0; i < NR_OF_IMAGES_IN_FW_BANK; ++i) {
|
||||
+ struct partition_entry_t part;
|
||||
+
|
||||
+ ret = gpt_entry_read_by_type(
|
||||
+ &(fwu_image[i].image_type),
|
||||
+ 0,
|
||||
+ &part);
|
||||
+ if (ret == PSA_ERROR_DOES_NOT_EXIST) {
|
||||
+ FWU_LOG_MSG("%s: Unable to find partition '%s'\r\n",
|
||||
+ __func__, fwu_image[i].image_names[previous_bank_index]);
|
||||
+ return ret;
|
||||
+ } else if (ret == PSA_ERROR_STORAGE_FAILURE) {
|
||||
+ FWU_LOG_MSG("%s: Flash error whilst reading GPT partition '%s'\r\n",
|
||||
+ __func__, fwu_image[i].image_names[previous_bank_index]);
|
||||
+ return ret;
|
||||
+ } else if (ret < 0) {
|
||||
+ FWU_LOG_MSG("%s: Unable to read partition '%s'\r\n",
|
||||
+ __func__, fwu_image[i].image_names[previous_bank_index]);
|
||||
+ return ret;
|
||||
+ }
|
||||
+
|
||||
+ ret = gpt_entry_remove(&(part.partition_guid));
|
||||
+ if (ret == PSA_ERROR_DOES_NOT_EXIST) {
|
||||
+ FWU_LOG_MSG("%s: Flash error whilst removing GPT partition '%s'\r\n",
|
||||
+ __func__, fwu_image[i].image_names[previous_bank_index]);
|
||||
+ return ret;
|
||||
+ } else if (ret < 0) {
|
||||
+ FWU_LOG_MSG("%s: Unable to remove partition '%s'\r\n",
|
||||
+ __func__, fwu_image[i].image_names[previous_bank_index]);
|
||||
+ return ret;
|
||||
+ }
|
||||
+ }
|
||||
+#endif
|
||||
+
|
||||
FWU_LOG_MSG("%s: success: fwu state is changed to regular\n\r", __func__);
|
||||
return PSA_SUCCESS;
|
||||
}
|
||||
@@ -1635,21 +1729,81 @@ static psa_status_t erase_staging_area(struct fwu_metadata* metadata, psa_fwu_co
|
||||
}
|
||||
|
||||
uint32_t active_index = metadata->active_index;
|
||||
+ uint32_t previous_active_index;
|
||||
uint32_t bank_offset;
|
||||
uint32_t image_offset;
|
||||
+ uint32_t image_size;
|
||||
uint8_t fwu_image_index = component - FWU_FAKE_IMAGES_INDEX_COUNT; /* Decrement to get the correct fwu image index */
|
||||
|
||||
if (active_index == BANK_0) {
|
||||
bank_offset = BANK_1_PARTITION_OFFSET;
|
||||
+ previous_active_index = BANK_1;
|
||||
} else if (active_index == BANK_1) {
|
||||
bank_offset = BANK_0_PARTITION_OFFSET;
|
||||
+ previous_active_index = BANK_0;
|
||||
} else {
|
||||
FWU_LOG_MSG("ERROR: %s: active_index %d\n\r",__func__,active_index);
|
||||
return PSA_ERROR_GENERIC_ERROR;
|
||||
}
|
||||
|
||||
+#ifdef BL1_BUILD
|
||||
image_offset = bank_offset + fwu_image[fwu_image_index].image_offset;
|
||||
- if (erase_image(image_offset, fwu_image[fwu_image_index].image_size)) {
|
||||
+ image_size = fwu_image[fwu_image_index].image_size;
|
||||
+#else
|
||||
+ /* Use GPT to find partition instead */
|
||||
+ struct partition_entry_t part;
|
||||
+
|
||||
+ psa_status_t ret = gpt_entry_read_by_type(&(fwu_image[fwu_image_index].image_type), 1, &part);
|
||||
+ if (ret == PSA_ERROR_DOES_NOT_EXIST) {
|
||||
+ /* Create the partition in the expected space */
|
||||
+ struct efi_guid_t new_guid = {0};
|
||||
+ char unicode_name[GPT_ENTRY_NAME_LENGTH] = {'\0'};
|
||||
+ ascii_to_unicode(fwu_image[fwu_image_index].image_names[previous_active_index], unicode_name);
|
||||
+
|
||||
+ ret = gpt_entry_create(&(fwu_image[fwu_image_index].image_type),
|
||||
+ (bank_offset + fwu_image[fwu_image_index].image_offset) / TFM_GPT_BLOCK_SIZE,
|
||||
+ 1 + ((fwu_image[fwu_image_index].image_size - 1) / TFM_GPT_BLOCK_SIZE),
|
||||
+ 0,
|
||||
+ unicode_name,
|
||||
+ &new_guid);
|
||||
+ if (ret == PSA_ERROR_INSUFFICIENT_STORAGE) {
|
||||
+ FWU_LOG_MSG("%s: No space left on device!\r\n", __func__);
|
||||
+ return ret;
|
||||
+ } else if (ret == PSA_ERROR_STORAGE_FAILURE) {
|
||||
+ FWU_LOG_MSG("%s: Flash error whilst creating GPT partition '%s'!\r\n",
|
||||
+ __func__, fwu_image[fwu_image_index].image_names[previous_active_index]);
|
||||
+ return ret;
|
||||
+ } else if (ret < 0) {
|
||||
+ FWU_LOG_MSG("%s: Unable to create GPT partition '%s': %d\r\n", __func__,
|
||||
+ fwu_image[fwu_image_index].image_names[previous_active_index], ret);
|
||||
+ return ret;
|
||||
+ }
|
||||
+
|
||||
+ ret = gpt_entry_read(&new_guid, &part);
|
||||
+ if (ret == PSA_ERROR_STORAGE_FAILURE) {
|
||||
+ FWU_LOG_MSG("%s: Flash error whilst reading GPT partition '%s'\r\n",
|
||||
+ __func__, fwu_image[fwu_image_index].image_names[previous_active_index]);
|
||||
+ return ret;
|
||||
+ } else if (ret < 0) {
|
||||
+ FWU_LOG_MSG("%s: Unable to read GPT partition '%s': %d\r\n", __func__,
|
||||
+ fwu_image[fwu_image_index].image_names[previous_active_index], ret);
|
||||
+ return ret;
|
||||
+ }
|
||||
+ } else if (ret == PSA_ERROR_STORAGE_FAILURE) {
|
||||
+ FWU_LOG_MSG("%s: Flash error whilst reading GPT partition '%s'\r\n",
|
||||
+ __func__, fwu_image[fwu_image_index].image_names[previous_active_index]);
|
||||
+ return ret;
|
||||
+ } else if (ret < 0) {
|
||||
+ FWU_LOG_MSG("%s: Unable to read GPT partition '%s': %d\r\n", __func__,
|
||||
+ fwu_image[fwu_image_index].image_names[previous_active_index], ret);
|
||||
+ return ret;
|
||||
+ }
|
||||
+
|
||||
+ image_offset = part.start * TFM_GPT_BLOCK_SIZE;
|
||||
+ image_size = part.size * TFM_GPT_BLOCK_SIZE;
|
||||
+#endif /* BL1_BUILD */
|
||||
+
|
||||
+ if (erase_image(image_offset, image_size)) {
|
||||
return PSA_ERROR_GENERIC_ERROR;
|
||||
}
|
||||
|
||||
@@ -1924,7 +2078,6 @@ static psa_status_t fwu_update_metadata(const psa_fwu_component_t *candidates, u
|
||||
goto out;
|
||||
}
|
||||
active_index = _metadata.active_index;
|
||||
-
|
||||
if (active_index == BANK_0) {
|
||||
previous_active_index = BANK_1;
|
||||
} else if (active_index == BANK_1) {
|
||||
@@ -1979,15 +2132,89 @@ static psa_status_t copy_image_from_other_bank(int image_index,
|
||||
FWU_LOG_FUNC_ENTER;
|
||||
|
||||
uint32_t bank_offset[NR_OF_FW_BANKS] = {BANK_0_PARTITION_OFFSET, BANK_1_PARTITION_OFFSET};
|
||||
+ psa_status_t ret;
|
||||
+
|
||||
+#ifdef BL1_BUILD
|
||||
+ /* Use offsets directly */
|
||||
size_t remaining_size = fwu_image[image_index].image_size;
|
||||
size_t data_size;
|
||||
size_t offset_read = bank_offset[active_index] + fwu_image[image_index].image_offset;
|
||||
size_t offset_write = bank_offset[previous_active_index] + fwu_image[image_index].image_offset;
|
||||
int data_transferred_count;
|
||||
+#else
|
||||
+ /* Use GPT to find the correct image */
|
||||
+ struct partition_entry_t active_part;
|
||||
+ ret = gpt_entry_read_by_type(
|
||||
+ &(fwu_image[image_index].image_type),
|
||||
+ 0,
|
||||
+ &active_part);
|
||||
+ if (ret == PSA_ERROR_DOES_NOT_EXIST) {
|
||||
+ FWU_LOG_MSG("%s: Unable to find partition '%s'\r\n",
|
||||
+ __func__, fwu_image[image_index].image_names[active_index]);
|
||||
+ return ret;
|
||||
+ } else if (ret == PSA_ERROR_STORAGE_FAILURE) {
|
||||
+ FWU_LOG_MSG("%s: Flash error whilst reading GPT partition '%s'\r\n",
|
||||
+ __func__, fwu_image[image_index].image_names[active_index]);
|
||||
+ return ret;
|
||||
+ } else if (ret < 0) {
|
||||
+ FWU_LOG_MSG("%s: Unable to read partition '%s'\r\n",
|
||||
+ __func__, fwu_image[image_index].image_names[active_index]);
|
||||
+ return ret;
|
||||
+ }
|
||||
|
||||
- FWU_LOG_MSG("%s: Enter \n\r", __func__);
|
||||
+ struct partition_entry_t prev_active_part;
|
||||
+ ret = gpt_entry_read_by_type(
|
||||
+ &(fwu_image[image_index].image_type),
|
||||
+ 1,
|
||||
+ &prev_active_part);
|
||||
|
||||
- psa_status_t ret = erase_image(offset_write, fwu_image[image_index].image_size);
|
||||
+ if (ret == PSA_ERROR_DOES_NOT_EXIST) {
|
||||
+ /* Create the partition in the expected space */
|
||||
+ struct efi_guid_t new_guid = {0};
|
||||
+ char unicode_name[GPT_ENTRY_NAME_LENGTH] = {'\0'};
|
||||
+ ascii_to_unicode(fwu_image[image_index].image_names[previous_active_index], unicode_name);
|
||||
+
|
||||
+ ret = gpt_entry_create(&(fwu_image[image_index].image_type),
|
||||
+ (bank_offset[previous_active_index] + fwu_image[image_index].image_offset) / TFM_GPT_BLOCK_SIZE,
|
||||
+ 1 + ((fwu_image[image_index].image_size - 1) / TFM_GPT_BLOCK_SIZE),
|
||||
+ 0,
|
||||
+ unicode_name,
|
||||
+ &new_guid);
|
||||
+ if (ret == PSA_ERROR_INSUFFICIENT_STORAGE) {
|
||||
+ FWU_LOG_MSG("%s: No space left on device!\r\n", __func__);
|
||||
+ return ret;
|
||||
+ } else if (ret == PSA_ERROR_STORAGE_FAILURE) {
|
||||
+ FWU_LOG_MSG("%s: Flash error whilst creating GPT partition '%s'!\r\n",
|
||||
+ __func__, fwu_image[image_index].image_names[previous_active_index]);
|
||||
+ return ret;
|
||||
+ } else if (ret < 0) {
|
||||
+ return ret;
|
||||
+ }
|
||||
+
|
||||
+ ret = gpt_entry_read(&new_guid, &prev_active_part);
|
||||
+ if (ret == PSA_ERROR_STORAGE_FAILURE) {
|
||||
+ FWU_LOG_MSG("%s: Flash error whilst reading GPT partition '%s'\r\n",
|
||||
+ __func__, fwu_image[image_index].image_names[previous_active_index]);
|
||||
+ return ret;
|
||||
+ } else if (ret < 0) {
|
||||
+ return ret;
|
||||
+ }
|
||||
+ } else if (ret == PSA_ERROR_STORAGE_FAILURE) {
|
||||
+ FWU_LOG_MSG("%s: Flash error whilst reading GPT partition '%s'\r\n",
|
||||
+ __func__, fwu_image[image_index].image_names[previous_active_index]);
|
||||
+ return ret;
|
||||
+ } else if (ret < 0) {
|
||||
+ return ret;
|
||||
+ }
|
||||
+
|
||||
+ size_t remaining_size = prev_active_part.size * TFM_GPT_BLOCK_SIZE;
|
||||
+ size_t data_size;
|
||||
+ size_t offset_read = active_part.start * TFM_GPT_BLOCK_SIZE;
|
||||
+ size_t offset_write = prev_active_part.start * TFM_GPT_BLOCK_SIZE;
|
||||
+ int data_transferred_count;
|
||||
+#endif /* BL1_BUILD */
|
||||
+
|
||||
+ ret = erase_image(offset_write, remaining_size);
|
||||
if (ret != PSA_SUCCESS) {
|
||||
FWU_LOG_MSG("%s: ERROR - Flash erase failed for Image: %d\n\r", __func__, image_index);
|
||||
return ret;
|
||||
@@ -2244,10 +2471,10 @@ psa_status_t fwu_bootloader_reject_staged_image(psa_fwu_component_t component)
|
||||
return PSA_ERROR_BAD_STATE;
|
||||
}
|
||||
|
||||
- int ret;
|
||||
+ psa_status_t ret;
|
||||
uint32_t active_index;;
|
||||
- uint32_t bank_offset;
|
||||
uint32_t image_offset;
|
||||
+ uint32_t image_size;
|
||||
uint8_t image_index = component - FWU_FAKE_IMAGES_INDEX_COUNT; /* Decrement to get the correct fwu image index */
|
||||
|
||||
FWU_LOG_FUNC_ENTER;
|
||||
@@ -2259,6 +2486,8 @@ psa_status_t fwu_bootloader_reject_staged_image(psa_fwu_component_t component)
|
||||
}
|
||||
active_index = _metadata.active_index;
|
||||
|
||||
+#ifdef BL1_BUILD
|
||||
+ uint32_t bank_offset;
|
||||
if (active_index == BANK_0) {
|
||||
bank_offset = BANK_1_PARTITION_OFFSET;
|
||||
} else if (active_index == BANK_1) {
|
||||
@@ -2270,8 +2499,62 @@ psa_status_t fwu_bootloader_reject_staged_image(psa_fwu_component_t component)
|
||||
}
|
||||
|
||||
image_offset = bank_offset + fwu_image[image_index].image_offset;
|
||||
+ image_size = fwu_image[image_index].image_size;
|
||||
+#else
|
||||
+ uint32_t previous_active_index;
|
||||
+ struct partition_entry_t part;
|
||||
+
|
||||
+ if (active_index == BANK_0) {
|
||||
+ previous_active_index = BANK_1;
|
||||
+ } else if (active_index == BANK_1) {
|
||||
+ previous_active_index = BANK_0;
|
||||
+ } else {
|
||||
+ FWU_LOG_MSG("ERROR: %s: active_index %d\n\r",__func__,active_index);
|
||||
+ ret = PSA_ERROR_GENERIC_ERROR;
|
||||
+ goto out;
|
||||
+ }
|
||||
+
|
||||
+ /* The newer entry of the same type is the staged image, as it was created
|
||||
+ * during the fwu process
|
||||
+ */
|
||||
+ ret = gpt_entry_read_by_type(
|
||||
+ &(fwu_image[image_index].image_type),
|
||||
+ 1,
|
||||
+ &part);
|
||||
+
|
||||
+ if (ret == PSA_ERROR_DOES_NOT_EXIST) {
|
||||
+ FWU_LOG_MSG("%s: Partition '%s' not found\n\r",
|
||||
+ __func__, fwu_image[image_index].image_names[previous_active_index]);
|
||||
+ goto out;
|
||||
+ } else if (ret == PSA_ERROR_STORAGE_FAILURE) {
|
||||
+ FWU_LOG_MSG("%s : ERROR - flash failure reading partition '%s'\n\r",
|
||||
+ __func__, fwu_image[image_index].image_names[previous_active_index]);
|
||||
+ goto out;
|
||||
+ } else if (ret < 0) {
|
||||
+ FWU_LOG_MSG("Unable to find partition '%s', ret: %d\n\r",
|
||||
+ fwu_image[image_index].image_names[previous_active_index], ret);
|
||||
+ goto out;
|
||||
+ }
|
||||
+
|
||||
+ /* Remove the partition. This only removes the entry from the header and
|
||||
+ * does not erase the actual data the partition referred to
|
||||
+ */
|
||||
+ ret = gpt_entry_remove(&(part.partition_guid));
|
||||
+ if (ret == PSA_ERROR_STORAGE_FAILURE) {
|
||||
+ FWU_LOG_MSG("%s: Flash error whilst removing GPT partition '%s'\r\n",
|
||||
+ __func__, fwu_image[image_index].image_names[previous_active_index]);
|
||||
+ goto out;
|
||||
+ } else if (ret < 0) {
|
||||
+ FWU_LOG_MSG("%s: Unable to remove partition '%s'\r\n",
|
||||
+ __func__, fwu_image[image_index].image_names[previous_active_index]);
|
||||
+ goto out;
|
||||
+ }
|
||||
+
|
||||
+ image_offset = part.start * TFM_GPT_BLOCK_SIZE;
|
||||
+ image_size = part.size * TFM_GPT_BLOCK_SIZE;
|
||||
+#endif /* BL1_BUILD */
|
||||
|
||||
- if (erase_image(image_offset, fwu_image[image_index].image_size)) {
|
||||
+ if (erase_image(image_offset, image_size)) {
|
||||
return PSA_ERROR_GENERIC_ERROR;
|
||||
}
|
||||
|
||||
+111
@@ -0,0 +1,111 @@
|
||||
From 37cac6c86f10340382ff950e5e0323f2efbe5ed3 Mon Sep 17 00:00:00 2001
|
||||
From: Michael Safwat <michael.safwat@arm.com>
|
||||
Date: Wed, 8 Apr 2026 13:02:47 +0100
|
||||
Subject: [PATCH 1/2] plat: cs1k: Derive host base addresses from offsets
|
||||
|
||||
Define explicit host register offsets and compute base addresses
|
||||
from the common host address space base. This keeps the map
|
||||
consistent, and also makes it easy to relocate all addresses if the
|
||||
base addresses change.
|
||||
|
||||
Define External System Reset Control bitfields and use them to
|
||||
de-assert CPUWAIT when booting the external system, so we can touch
|
||||
only the bit of interest instead of zeroing the whole register.
|
||||
|
||||
Change-Id: Id228351926fc846d28d5bf4e4180a995057154b1
|
||||
Signed-off-by: Michael Safwat <michael.safwat@arm.com>
|
||||
Upstream-Status: Backport [d73cc1dbc2eb72af02de740926f7b3c889bbac4b]
|
||||
---
|
||||
.../Device/Include/platform_base_address.h | 52 ++++++++++++++-----
|
||||
.../arm/corstone1000/tfm_hal_multi_core.c | 5 +-
|
||||
2 files changed, 41 insertions(+), 16 deletions(-)
|
||||
|
||||
diff --git a/platform/ext/target/arm/corstone1000/Device/Include/platform_base_address.h b/platform/ext/target/arm/corstone1000/Device/Include/platform_base_address.h
|
||||
index 3908d69bc..62ee7d049 100644
|
||||
--- a/platform/ext/target/arm/corstone1000/Device/Include/platform_base_address.h
|
||||
+++ b/platform/ext/target/arm/corstone1000/Device/Include/platform_base_address.h
|
||||
@@ -68,23 +68,49 @@
|
||||
/* Host base addresses from the SE perspective - partial list, only the ones
|
||||
* required by the SE are defined here */
|
||||
#define CORSTONE1000_HOST_ADDRESS_SPACE_BASE (0x60000000U) /* Host Address Space */
|
||||
-#define CORSTONE1000_HOST_BIR_BASE (0x60000000U) /* Boot Instruction Register */
|
||||
-#define CORSTONE1000_HOST_TRUSTED_RAM_BASE (0x62000000U) /* Secure RAM */
|
||||
-#define CORSTONE1000_HOST_XNVM_BASE (0x68000000U) /* XNVM */
|
||||
-#define CORSTONE1000_HOST_BASE_SYSTEM_CONTROL_BASE (0x7A010000U) /* Host SCB */
|
||||
-#define CORSTONE1000_EXT_SYS_RESET_REG (0x7A010310U) /* external system (cortex-M3) */
|
||||
-#define CORSTONE1000_HOST_FIREWALL_BASE (0x7A800000U) /* Host Firewall */
|
||||
-#define CORSTONE1000_HOST_INT_APBCOM_BASE (0x7B900000U) /* Internal APBCOM */
|
||||
-#define CORSTONE1000_HOST_FPGA_SCC_REGISTERS (0x80000000U) /* FPGA SCC Registers */
|
||||
-#define CORSTONE1000_HOST_SE_SECURE_FLASH_BASE_FVP (0x80010000U) /* SE Flash */
|
||||
-#define CORSTONE1000_HOST_AXI_QSPI_CTRL_REG_BASE (0x80050000U) /* AXI QSPI Controller */
|
||||
-#define CORSTONE1000_HOST_AXI_QSPI_CTRL_REG_BASE_SE_SECURE_FLASH (0x90010000U) /* AXI QSPI Controller for SE FLash */
|
||||
-#define CORSTONE1000_HOST_DRAM_UEFI_CAPSULE (0xA0000000U) /* 1.5 GB DDR */
|
||||
|
||||
+/* Registers offsets - partial list, only the ones
|
||||
+ * required by the SE are defined here */
|
||||
+#define CORSTONE1000_HOST_BIR_OFFSET (0x00000000U)
|
||||
+#define CORSTONE1000_HOST_CVM_OFFSET (0x02000000U)
|
||||
+#define CORSTONE1000_HOST_XNVM_OFFSET (0x08000000U)
|
||||
+#define CORSTONE1000_HOST_BASE_SYSTEM_CONTROL_BASE_OFFSET (0x1A010000U)
|
||||
+#define CORSTONE1000_HOST_EXT_SYS0_RST_CTRL_OFFSET (0x310U)
|
||||
+#define CORSTONE1000_HOST_FIREWALL_BASE_OFFSET (0x1A800000U)
|
||||
+#define CORSTONE1000_HOST_INT_APBCOM_BASE_OFFSET (0x1B900000U)
|
||||
+/* The below offsets have been derived from the reserved section.*/
|
||||
+#define CORSTONE1000_HOST_FPGA_SCC_REGISTERS_OFFSET (0x20000000U)
|
||||
+#define CORSTONE1000_HOST_SE_SECURE_FLASH_BASE_FVP_OFFSET (0x20010000U)
|
||||
+#define CORSTONE1000_HOST_AXI_QSPI_CTRL_REG_BASE_OFFSET (0x20050000U)
|
||||
+#define CORSTONE1000_HOST_AXI_QSPI_CTRL_REG_BASE_SE_SECURE_FLASH_OFFSET (0x30010000U)
|
||||
+#define CORSTONE1000_HOST_DRAM_UEFI_CAPSULE_OFFSET (0x40000000U)
|
||||
+#define CORSTONE1000_HOST_DSU_120T_BASE_OFFSET (0x60910000U)
|
||||
+
|
||||
+/* Register Addresses */
|
||||
+#define CORSTONE1000_HOST_BIR_BASE (CORSTONE1000_HOST_ADDRESS_SPACE_BASE + CORSTONE1000_HOST_BIR_OFFSET) /* Boot Instruction Register */
|
||||
+#define CORSTONE1000_HOST_TRUSTED_RAM_BASE (CORSTONE1000_HOST_ADDRESS_SPACE_BASE + CORSTONE1000_HOST_CVM_OFFSET) /* On-chip Volatile Memory */
|
||||
+#define CORSTONE1000_HOST_XNVM_BASE (CORSTONE1000_HOST_ADDRESS_SPACE_BASE + CORSTONE1000_HOST_XNVM_OFFSET) /* eXecute-in-place Non-volatile Memory */
|
||||
+#define CORSTONE1000_HOST_BASE_SYSTEM_CONTROL_BASE (CORSTONE1000_HOST_ADDRESS_SPACE_BASE + CORSTONE1000_HOST_BASE_SYSTEM_CONTROL_BASE_OFFSET) /* Security Control Bits */
|
||||
+#define CORSTONE1000_EXT_SYS_RESET_REG (CORSTONE1000_HOST_BASE_SYSTEM_CONTROL_BASE + CORSTONE1000_HOST_EXT_SYS0_RST_CTRL_OFFSET) /* External System (Cortex-M3) */
|
||||
+#define CORSTONE1000_HOST_FIREWALL_BASE (CORSTONE1000_HOST_ADDRESS_SPACE_BASE + CORSTONE1000_HOST_FIREWALL_BASE_OFFSET) /* System Firewall */
|
||||
+#define CORSTONE1000_HOST_INT_APBCOM_BASE (CORSTONE1000_HOST_ADDRESS_SPACE_BASE + CORSTONE1000_HOST_INT_APBCOM_BASE_OFFSET) /* Internal Advanced Peripheral Bus Communication */
|
||||
+#define CORSTONE1000_HOST_FPGA_SCC_REGISTERS (CORSTONE1000_HOST_ADDRESS_SPACE_BASE + CORSTONE1000_HOST_FPGA_SCC_REGISTERS_OFFSET) /* FPGA Serial Communication Controller Registers */
|
||||
+#define CORSTONE1000_HOST_SE_SECURE_FLASH_BASE_FVP (CORSTONE1000_HOST_ADDRESS_SPACE_BASE + CORSTONE1000_HOST_SE_SECURE_FLASH_BASE_FVP_OFFSET) /* Secure Enclave Flash */
|
||||
+#define CORSTONE1000_HOST_AXI_QSPI_CTRL_REG_BASE (CORSTONE1000_HOST_ADDRESS_SPACE_BASE + CORSTONE1000_HOST_AXI_QSPI_CTRL_REG_BASE_OFFSET) /* AXI QSPI Controller */
|
||||
+#define CORSTONE1000_HOST_AXI_QSPI_CTRL_REG_BASE_SE_SECURE_FLASH (CORSTONE1000_HOST_ADDRESS_SPACE_BASE + CORSTONE1000_HOST_AXI_QSPI_CTRL_REG_BASE_SE_SECURE_FLASH_OFFSET) /* AXI QSPI Controller for SE FLash */
|
||||
+#define CORSTONE1000_HOST_DRAM_UEFI_CAPSULE (CORSTONE1000_HOST_ADDRESS_SPACE_BASE + CORSTONE1000_HOST_DRAM_UEFI_CAPSULE_OFFSET) /* DDR RAM (1.5 GB) */
|
||||
#ifdef CORSTONE1000_DSU_120T
|
||||
-#define CORSTONE1000_HOST_DSU_120T_BASE (0xC0910000U) /* DSU-120T PPU */
|
||||
+#define CORSTONE1000_HOST_DSU_120T_BASE (CORSTONE1000_HOST_ADDRESS_SPACE_BASE + CORSTONE1000_HOST_DSU_120T_BASE_OFFSET) /* DynamIQ Shared Unit-120 Power Policy Units */
|
||||
#endif
|
||||
|
||||
+/* Bit definition for External System Reset Control register */
|
||||
+#define CORSTONE1000_EXT_SYS_RESET_REG_CPUWAIT_Pos (0U) // CPU Wait Control. 0b0 - External System's CPUWAIT signal is de-asserted. 0b1 - External System's CPUWAIT signal is asserted.
|
||||
+#define CORSTONE1000_EXT_SYS_RESET_REG_CPUWAIT_Msk (0x1UL << CORSTONE1000_EXT_SYS_RESET_REG_CPUWAIT_Pos) // 1 bit
|
||||
+#define CORSTONE1000_EXT_SYS_RESET_REG_RST_REQ_Pos (1U) // Reset Request for External System. 0b0 - No Reset Requested. 0b1 - Reset Requested.
|
||||
+#define CORSTONE1000_EXT_SYS_RESET_REG_RST_REQ_Msk (0x1UL << CORSTONE1000_EXT_SYS_RESET_REG_RST_REQ_Pos) // 1 bit
|
||||
+#define CORSTONE1000_EXT_SYS_RESET_REG_Reserved_Pos (2U) // Reserved.
|
||||
+#define CORSTONE1000_EXT_SYS_RESET_REG_Reserved_Msk (0x3FFFFFFFUL << CORSTONE1000_EXT_SYS_RESET_REG_Reserved_Pos) // 30 bits
|
||||
+
|
||||
/* Map Component definitions to Corstone definitions */
|
||||
#define CC3XX_BASE_S CORSTONE1000_CRYPTO_ACCELERATOR_BASE
|
||||
|
||||
diff --git a/platform/ext/target/arm/corstone1000/tfm_hal_multi_core.c b/platform/ext/target/arm/corstone1000/tfm_hal_multi_core.c
|
||||
index 9a785bfa0..76360b507 100644
|
||||
--- a/platform/ext/target/arm/corstone1000/tfm_hal_multi_core.c
|
||||
+++ b/platform/ext/target/arm/corstone1000/tfm_hal_multi_core.c
|
||||
@@ -26,12 +26,11 @@
|
||||
#define AA64nAA32_MASK (1 << 3)
|
||||
|
||||
#ifdef EXTERNAL_SYSTEM_SUPPORT
|
||||
-void tfm_external_system_boot()
|
||||
+void tfm_external_system_boot(void)
|
||||
{
|
||||
volatile uint32_t *ext_sys_reset_ctl_reg = (uint32_t *)(CORSTONE1000_EXT_SYS_RESET_REG);
|
||||
|
||||
- /* de-assert CPU_WAIT signal*/
|
||||
- *ext_sys_reset_ctl_reg = 0x0;
|
||||
+ *ext_sys_reset_ctl_reg &= ~(CORSTONE1000_EXT_SYS_RESET_REG_CPUWAIT_Msk);
|
||||
}
|
||||
#endif
|
||||
|
||||
--
|
||||
2.43.0
|
||||
|
||||
+75
@@ -0,0 +1,75 @@
|
||||
From 334e5513db08f6ebdd7e59429849d442b7b43446 Mon Sep 17 00:00:00 2001
|
||||
From: Michael Safwat <michael.safwat@arm.com>
|
||||
Date: Thu, 19 Mar 2026 11:12:19 +0000
|
||||
Subject: [PATCH 2/2] plat: cs1k: Drive NPU via external system reset control
|
||||
|
||||
On Corstone-1000 with Cortex-A320, the NPU reset was previously tied
|
||||
to the host boot flow, so the NPU was powered on when the Secure
|
||||
Enclave powered on the host. Now the NPU is tied to the External
|
||||
System Reset Control register to control the power state.
|
||||
|
||||
Reuse the existing external-system boot control mechanism for NPU.
|
||||
|
||||
Change-Id: I74f9d57e8cbe5cb38db352d706885f9a37db0183
|
||||
Signed-off-by: Michael Safwat <michael.safwat@arm.com>
|
||||
Upstream-Status: Backport [6010d3b509e51cf10a711596e7d6058bde1568dc]
|
||||
---
|
||||
platform/ext/target/arm/corstone1000/CMakeLists.txt | 5 +++++
|
||||
.../arm/corstone1000/Device/Include/platform_base_address.h | 2 +-
|
||||
platform/ext/target/arm/corstone1000/tfm_hal_multi_core.c | 4 ++--
|
||||
3 files changed, 8 insertions(+), 3 deletions(-)
|
||||
|
||||
diff --git a/platform/ext/target/arm/corstone1000/CMakeLists.txt b/platform/ext/target/arm/corstone1000/CMakeLists.txt
|
||||
index e543c4b6b..739a6a086 100644
|
||||
--- a/platform/ext/target/arm/corstone1000/CMakeLists.txt
|
||||
+++ b/platform/ext/target/arm/corstone1000/CMakeLists.txt
|
||||
@@ -484,6 +484,11 @@ if (CORSTONE1000_CORTEX_A320)
|
||||
PUBLIC
|
||||
CORSTONE1000_CORTEX_A320
|
||||
)
|
||||
+
|
||||
+ target_compile_definitions(platform_s
|
||||
+ PUBLIC
|
||||
+ CORSTONE1000_CORTEX_A320
|
||||
+ )
|
||||
endif()
|
||||
|
||||
#========================= tfm_adac ============================================#
|
||||
diff --git a/platform/ext/target/arm/corstone1000/Device/Include/platform_base_address.h b/platform/ext/target/arm/corstone1000/Device/Include/platform_base_address.h
|
||||
index 62ee7d049..631592b34 100644
|
||||
--- a/platform/ext/target/arm/corstone1000/Device/Include/platform_base_address.h
|
||||
+++ b/platform/ext/target/arm/corstone1000/Device/Include/platform_base_address.h
|
||||
@@ -91,7 +91,7 @@
|
||||
#define CORSTONE1000_HOST_TRUSTED_RAM_BASE (CORSTONE1000_HOST_ADDRESS_SPACE_BASE + CORSTONE1000_HOST_CVM_OFFSET) /* On-chip Volatile Memory */
|
||||
#define CORSTONE1000_HOST_XNVM_BASE (CORSTONE1000_HOST_ADDRESS_SPACE_BASE + CORSTONE1000_HOST_XNVM_OFFSET) /* eXecute-in-place Non-volatile Memory */
|
||||
#define CORSTONE1000_HOST_BASE_SYSTEM_CONTROL_BASE (CORSTONE1000_HOST_ADDRESS_SPACE_BASE + CORSTONE1000_HOST_BASE_SYSTEM_CONTROL_BASE_OFFSET) /* Security Control Bits */
|
||||
-#define CORSTONE1000_EXT_SYS_RESET_REG (CORSTONE1000_HOST_BASE_SYSTEM_CONTROL_BASE + CORSTONE1000_HOST_EXT_SYS0_RST_CTRL_OFFSET) /* External System (Cortex-M3) */
|
||||
+#define CORSTONE1000_EXT_SYS_RESET_REG (CORSTONE1000_HOST_BASE_SYSTEM_CONTROL_BASE + CORSTONE1000_HOST_EXT_SYS0_RST_CTRL_OFFSET) /* External System (Cortex-M3/NPU) */
|
||||
#define CORSTONE1000_HOST_FIREWALL_BASE (CORSTONE1000_HOST_ADDRESS_SPACE_BASE + CORSTONE1000_HOST_FIREWALL_BASE_OFFSET) /* System Firewall */
|
||||
#define CORSTONE1000_HOST_INT_APBCOM_BASE (CORSTONE1000_HOST_ADDRESS_SPACE_BASE + CORSTONE1000_HOST_INT_APBCOM_BASE_OFFSET) /* Internal Advanced Peripheral Bus Communication */
|
||||
#define CORSTONE1000_HOST_FPGA_SCC_REGISTERS (CORSTONE1000_HOST_ADDRESS_SPACE_BASE + CORSTONE1000_HOST_FPGA_SCC_REGISTERS_OFFSET) /* FPGA Serial Communication Controller Registers */
|
||||
diff --git a/platform/ext/target/arm/corstone1000/tfm_hal_multi_core.c b/platform/ext/target/arm/corstone1000/tfm_hal_multi_core.c
|
||||
index 76360b507..ff65228bf 100644
|
||||
--- a/platform/ext/target/arm/corstone1000/tfm_hal_multi_core.c
|
||||
+++ b/platform/ext/target/arm/corstone1000/tfm_hal_multi_core.c
|
||||
@@ -25,7 +25,7 @@
|
||||
|
||||
#define AA64nAA32_MASK (1 << 3)
|
||||
|
||||
-#ifdef EXTERNAL_SYSTEM_SUPPORT
|
||||
+#if defined(EXTERNAL_SYSTEM_SUPPORT) || defined(CORSTONE1000_CORTEX_A320)
|
||||
void tfm_external_system_boot(void)
|
||||
{
|
||||
volatile uint32_t *ext_sys_reset_ctl_reg = (uint32_t *)(CORSTONE1000_EXT_SYS_RESET_REG);
|
||||
@@ -123,7 +123,7 @@ void tfm_hal_boot_ns_cpu(uintptr_t start_addr)
|
||||
#endif
|
||||
#endif
|
||||
|
||||
-#ifdef EXTERNAL_SYSTEM_SUPPORT
|
||||
+#if defined(EXTERNAL_SYSTEM_SUPPORT) || defined(CORSTONE1000_CORTEX_A320)
|
||||
/*release EXT SYS out of reset*/
|
||||
tfm_external_system_boot();
|
||||
#endif
|
||||
--
|
||||
2.43.0
|
||||
|
||||
+114
@@ -0,0 +1,114 @@
|
||||
From 4f11567a0152f1ecd98159ca555d8663ee8e5ce0 Mon Sep 17 00:00:00 2001
|
||||
From: Frazer Carsley <frazer.carsley@arm.com>
|
||||
Date: Fri, 10 Apr 2026 17:20:39 +0100
|
||||
Subject: [PATCH] lib: gpt: Fix final entry not being removed
|
||||
|
||||
The final entry would not be removed due to the removals being hidden
|
||||
behind a check on whether the removed entry was not the final entry,
|
||||
causing it to be a no-op. Removal operation is no longer hidden behind
|
||||
that condition.
|
||||
|
||||
Change-Id: Ib264d988d57cb39098f2783c4a001fcf3b004270
|
||||
Signed-off-by: Frazer Carsley <frazer.carsley@arm.com>
|
||||
Upstream-Status: Backport [f3cf6bda1534b8893620c7b7c0d9ff647b44603e]
|
||||
---
|
||||
lib/gpt/src/gpt.c | 64 +++++++++++++++++++++++------------------------
|
||||
1 file changed, 32 insertions(+), 32 deletions(-)
|
||||
|
||||
diff --git a/lib/gpt/src/gpt.c b/lib/gpt/src/gpt.c
|
||||
index a9dbb918e..e4e7fde32 100644
|
||||
--- a/lib/gpt/src/gpt.c
|
||||
+++ b/lib/gpt/src/gpt.c
|
||||
@@ -648,6 +648,7 @@ psa_status_t gpt_entry_remove(const struct efi_guid_t *guid)
|
||||
* to be modified if the last entry in the array was moved or if it is
|
||||
* the only LBA used by the partition array
|
||||
*/
|
||||
+ const uint64_t array_end_lba = partition_array_last_lba(&primary_gpt);;
|
||||
if (cached_index != primary_gpt.num_used_partitions - 1 ||
|
||||
cached_index < gpt_entry_per_lba_count())
|
||||
{
|
||||
@@ -669,7 +670,6 @@ psa_status_t gpt_entry_remove(const struct efi_guid_t *guid)
|
||||
* Use a second buffer to read each consecutive LBA and copy that to
|
||||
* the global LBA buffer to then write afterwards.
|
||||
*/
|
||||
- const uint64_t array_end_lba = partition_array_last_lba(&primary_gpt);
|
||||
for (uint64_t i = partition_entry_lba(&primary_gpt, cached_index) + 1;
|
||||
i <= array_end_lba;
|
||||
++i)
|
||||
@@ -705,45 +705,45 @@ psa_status_t gpt_entry_remove(const struct efi_guid_t *guid)
|
||||
sizeof(array_buf) - primary_gpt.header.entry_size);
|
||||
memcpy(lba_buf, array_buf, TFM_GPT_BLOCK_SIZE);
|
||||
}
|
||||
+ }
|
||||
|
||||
- /* What was the final LBA is now cached and may be empty or partially-filled */
|
||||
- cached_lba = array_end_lba;
|
||||
- write_buffered = false;
|
||||
- uint32_t entries_in_last_lba = (--primary_gpt.num_used_partitions) % gpt_entry_per_lba_count();
|
||||
- if (entries_in_last_lba == 0) {
|
||||
- /* There's nothing left in this LBA, so zero it all and write it out.
|
||||
- * There is also no need to do an erase just to zero afterwards.
|
||||
- */
|
||||
- memset(lba_buf, 0, TFM_GPT_BLOCK_SIZE);
|
||||
- if (backup_gpt_array_lba != 0) {
|
||||
- int write_ret = plat_flash_driver->write(
|
||||
- backup_gpt_array_lba + array_end_lba - PRIMARY_GPT_ARRAY_LBA,
|
||||
- lba_buf);
|
||||
- if (write_ret != TFM_GPT_BLOCK_SIZE) {
|
||||
- return PSA_ERROR_STORAGE_FAILURE;
|
||||
- }
|
||||
- }
|
||||
- int write_ret = plat_flash_driver->write(array_end_lba, lba_buf);
|
||||
+ /* What was the final LBA is now cached and may be empty or partially-filled */
|
||||
+ cached_lba = array_end_lba;
|
||||
+ write_buffered = false;
|
||||
+ uint32_t entries_in_last_lba = (--primary_gpt.num_used_partitions) % gpt_entry_per_lba_count();
|
||||
+ if (entries_in_last_lba == 0) {
|
||||
+ /* There's nothing left in this LBA, so zero it all and write it out.
|
||||
+ * There is also no need to do an erase just to zero afterwards.
|
||||
+ */
|
||||
+ memset(lba_buf, 0, TFM_GPT_BLOCK_SIZE);
|
||||
+ if (backup_gpt_array_lba != 0) {
|
||||
+ int write_ret = plat_flash_driver->write(
|
||||
+ backup_gpt_array_lba + array_end_lba - PRIMARY_GPT_ARRAY_LBA,
|
||||
+ lba_buf);
|
||||
if (write_ret != TFM_GPT_BLOCK_SIZE) {
|
||||
return PSA_ERROR_STORAGE_FAILURE;
|
||||
}
|
||||
- } else {
|
||||
- /* Zero what is not needed anymore */
|
||||
- memset(
|
||||
- lba_buf + primary_gpt.header.entry_size * entries_in_last_lba,
|
||||
- 0,
|
||||
- (gpt_entry_per_lba_count() - entries_in_last_lba) * primary_gpt.header.entry_size);
|
||||
- if (backup_gpt_array_lba != 0) {
|
||||
- ret = write_to_flash(backup_gpt_array_lba + array_end_lba - PRIMARY_GPT_ARRAY_LBA);
|
||||
- if (ret != PSA_SUCCESS) {
|
||||
- return ret;
|
||||
- }
|
||||
- }
|
||||
- ret = write_to_flash(array_end_lba);
|
||||
+ }
|
||||
+ int write_ret = plat_flash_driver->write(array_end_lba, lba_buf);
|
||||
+ if (write_ret != TFM_GPT_BLOCK_SIZE) {
|
||||
+ return PSA_ERROR_STORAGE_FAILURE;
|
||||
+ }
|
||||
+ } else {
|
||||
+ /* Zero what is not needed anymore */
|
||||
+ memset(
|
||||
+ lba_buf + primary_gpt.header.entry_size * entries_in_last_lba,
|
||||
+ 0,
|
||||
+ (gpt_entry_per_lba_count() - entries_in_last_lba) * primary_gpt.header.entry_size);
|
||||
+ if (backup_gpt_array_lba != 0) {
|
||||
+ ret = write_to_flash(backup_gpt_array_lba + array_end_lba - PRIMARY_GPT_ARRAY_LBA);
|
||||
if (ret != PSA_SUCCESS) {
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
+ ret = write_to_flash(array_end_lba);
|
||||
+ if (ret != PSA_SUCCESS) {
|
||||
+ return ret;
|
||||
+ }
|
||||
}
|
||||
|
||||
/* Update the header after flash changes */
|
||||
+37
@@ -0,0 +1,37 @@
|
||||
From 68874e58811c5d4004492f15b3ac46d2cca186c0 Mon Sep 17 00:00:00 2001
|
||||
From: Frazer Carsley <frazer.carsley@arm.com>
|
||||
Date: Thu, 16 Apr 2026 09:54:55 +0100
|
||||
Subject: [PATCH] lib: gpt: Replace warnings with errors
|
||||
|
||||
These warnings return errors, so it makes more sense to output an error
|
||||
message.
|
||||
|
||||
Change-Id: I589e24ba8aba2502a3fc86d2aeb648d125c022bd
|
||||
Signed-off-by: Frazer Carsley <frazer.carsley@arm.com>
|
||||
Upstream-Status: Backport [68874e58811c5d4004492f15b3ac46d2cca186c0]
|
||||
---
|
||||
lib/gpt/src/gpt.c | 4 ++--
|
||||
1 file changed, 2 insertions(+), 2 deletions(-)
|
||||
|
||||
diff --git a/lib/gpt/src/gpt.c b/lib/gpt/src/gpt.c
|
||||
index 16bda8aba..32c7277bd 100644
|
||||
--- a/lib/gpt/src/gpt.c
|
||||
+++ b/lib/gpt/src/gpt.c
|
||||
@@ -830,7 +830,7 @@ psa_status_t gpt_defragment(void)
|
||||
*/
|
||||
psa_status_t ret = sort_partition_array(&primary_gpt);
|
||||
if (ret != PSA_SUCCESS) {
|
||||
- WARN("Unable to defragment flash!\n");
|
||||
+ ERROR("Unable to defragment flash!\n");
|
||||
return ret;
|
||||
}
|
||||
|
||||
@@ -926,7 +926,7 @@ psa_status_t gpt_init(struct gpt_flash_driver_t *flash_driver, uint64_t max_part
|
||||
if (mbr.partitions[0].os_type == MBR_TYPE_GPT) {
|
||||
ret = read_table_from_flash(&primary_gpt, true);
|
||||
} else {
|
||||
- WARN("Unsupported legacy MBR in use\n");
|
||||
+ ERROR("Unsupported legacy MBR in use\n");
|
||||
ret = PSA_ERROR_NOT_SUPPORTED;
|
||||
}
|
||||
|
||||
+268
@@ -0,0 +1,268 @@
|
||||
From ff08a9d998c545a6152789f8ce55bd4200a937cf Mon Sep 17 00:00:00 2001
|
||||
From: Frazer Carsley <frazer.carsley@arm.com>
|
||||
Date: Wed, 15 Apr 2026 10:59:28 +0100
|
||||
Subject: [PATCH] lib: gpt: Enforce entry size of 128 bytes
|
||||
|
||||
Previous to this, the entry size could have been set to any number, even
|
||||
those deemed illegal by the UEFI spec 2.10 [1], as the library did not
|
||||
validate it. 128 bytes is the minimum size for a partition entry and
|
||||
most standard tools that create GPTs will use this.
|
||||
|
||||
[1] https://uefi.org/specs/UEFI/2.10/05_GUID_Partition_Table_Format.html
|
||||
|
||||
Change-Id: Ib6c436353a4b8e00e6c6e63b933a49f11c0a7340
|
||||
Signed-off-by: Frazer Carsley <frazer.carsley@arm.com>
|
||||
Upstream-Status: Backport [ff08a9d998c545a6152789f8ce55bd4200a937cf]
|
||||
---
|
||||
lib/gpt/inc/gpt.h | 2 +
|
||||
lib/gpt/src/gpt.c | 65 +++++++++++++++++++++-----------
|
||||
lib/gpt/unittests/gpt/test_gpt.c | 40 ++++++++++++++++++++
|
||||
3 files changed, 85 insertions(+), 22 deletions(-)
|
||||
|
||||
diff --git a/lib/gpt/inc/gpt.h b/lib/gpt/inc/gpt.h
|
||||
index baf4767f9..34ce67580 100644
|
||||
--- a/lib/gpt/inc/gpt.h
|
||||
+++ b/lib/gpt/inc/gpt.h
|
||||
@@ -214,6 +214,7 @@ psa_status_t gpt_entry_remove(const struct efi_guid_t *guid);
|
||||
*
|
||||
* \retval PSA_SUCCESS GPT is valid.
|
||||
* \retval PSA_ERROR_STORAGE_FAILURE I/O error.
|
||||
+ * \retval PSA_ERROR_NOT_SUPPORTED Entry size is not 128 bytes
|
||||
* \retval PSA_ERROR_INVALID_SIGNATURE GPT is invalid.
|
||||
*/
|
||||
psa_status_t gpt_validate(bool is_primary);
|
||||
@@ -249,6 +250,7 @@ psa_status_t gpt_defragment(void);
|
||||
* functions defined by \p flash_driver is NULL. The init
|
||||
* and uninit functions may be NULL if not required.
|
||||
* \retval PSA_ERROR_NOT_SUPPORTED Legacy MBR is used and not GPT.
|
||||
+ * \retval PSA_ERROR_NOT_SUPPORTED Entry size is not 128 bytes
|
||||
*/
|
||||
__attribute__((nonnull(1)))
|
||||
psa_status_t gpt_init(struct gpt_flash_driver_t *flash_driver,
|
||||
diff --git a/lib/gpt/src/gpt.c b/lib/gpt/src/gpt.c
|
||||
index 32c7277bd..200e21599 100644
|
||||
--- a/lib/gpt/src/gpt.c
|
||||
+++ b/lib/gpt/src/gpt.c
|
||||
@@ -459,7 +459,7 @@ psa_status_t gpt_entry_move(const struct efi_guid_t *guid,
|
||||
|
||||
/* Cached LBA */
|
||||
for (uint32_t i = 0; i < num_entries_in_cached_lba; ++i) {
|
||||
- memcpy(&entry, lba_buf + (i * primary_gpt.header.entry_size), GPT_ENTRY_SIZE);
|
||||
+ memcpy(&entry, lba_buf + (i * GPT_ENTRY_SIZE), GPT_ENTRY_SIZE);
|
||||
|
||||
const struct efi_guid_t ent_guid = entry.unique_guid;
|
||||
if (efi_guid_cmp(&ent_guid, guid) == 0) {
|
||||
@@ -658,9 +658,9 @@ psa_status_t gpt_entry_remove(const struct efi_guid_t *guid)
|
||||
const uint32_t lba_index = cached_index % gpt_entry_per_lba_count();
|
||||
if (lba_index + 1 != gpt_entry_per_lba_count()) {
|
||||
memmove(
|
||||
- lba_buf + lba_index * primary_gpt.header.entry_size,
|
||||
- lba_buf + (lba_index + 1) * primary_gpt.header.entry_size,
|
||||
- (gpt_entry_per_lba_count() - lba_index - 1) * primary_gpt.header.entry_size);
|
||||
+ lba_buf + lba_index * GPT_ENTRY_SIZE,
|
||||
+ lba_buf + (lba_index + 1) * GPT_ENTRY_SIZE,
|
||||
+ (gpt_entry_per_lba_count() - lba_index - 1) * GPT_ENTRY_SIZE);
|
||||
}
|
||||
|
||||
/* If this is not the last LBA, then read the next LBA into memory and
|
||||
@@ -683,7 +683,7 @@ psa_status_t gpt_entry_remove(const struct efi_guid_t *guid)
|
||||
}
|
||||
|
||||
memcpy(
|
||||
- lba_buf + primary_gpt.header.entry_size * (gpt_entry_per_lba_count() - 1),
|
||||
+ lba_buf + GPT_ENTRY_SIZE * (gpt_entry_per_lba_count() - 1),
|
||||
array_buf,
|
||||
GPT_ENTRY_SIZE);
|
||||
|
||||
@@ -701,8 +701,8 @@ psa_status_t gpt_entry_remove(const struct efi_guid_t *guid)
|
||||
|
||||
memmove(
|
||||
array_buf,
|
||||
- array_buf + primary_gpt.header.entry_size,
|
||||
- sizeof(array_buf) - primary_gpt.header.entry_size);
|
||||
+ array_buf + GPT_ENTRY_SIZE,
|
||||
+ sizeof(array_buf) - GPT_ENTRY_SIZE);
|
||||
memcpy(lba_buf, array_buf, TFM_GPT_BLOCK_SIZE);
|
||||
}
|
||||
}
|
||||
@@ -731,9 +731,9 @@ psa_status_t gpt_entry_remove(const struct efi_guid_t *guid)
|
||||
} else {
|
||||
/* Zero what is not needed anymore */
|
||||
memset(
|
||||
- lba_buf + primary_gpt.header.entry_size * entries_in_last_lba,
|
||||
+ lba_buf + GPT_ENTRY_SIZE * entries_in_last_lba,
|
||||
0,
|
||||
- (gpt_entry_per_lba_count() - entries_in_last_lba) * primary_gpt.header.entry_size);
|
||||
+ (gpt_entry_per_lba_count() - entries_in_last_lba) * GPT_ENTRY_SIZE);
|
||||
if (backup_gpt_array_lba != 0) {
|
||||
ret = write_to_flash(backup_gpt_array_lba + array_end_lba - PRIMARY_GPT_ARRAY_LBA);
|
||||
if (ret != PSA_SUCCESS) {
|
||||
@@ -934,6 +934,14 @@ psa_status_t gpt_init(struct gpt_flash_driver_t *flash_driver, uint64_t max_part
|
||||
goto fail_load;
|
||||
}
|
||||
|
||||
+ /* Ensure entry size is supported. */
|
||||
+ if (primary_gpt.header.entry_size != GPT_ENTRY_SIZE) {
|
||||
+ ERROR("Unsupported entry size 0x%08x, must be 0x%08x\n",
|
||||
+ primary_gpt.header.entry_size, GPT_ENTRY_SIZE);
|
||||
+ ret = PSA_ERROR_NOT_SUPPORTED;
|
||||
+ goto fail_load;
|
||||
+ }
|
||||
+
|
||||
/* Count the number of used entries, assuming the array is not sparese */
|
||||
ret = count_used_partitions(&primary_gpt, &primary_gpt.num_used_partitions);
|
||||
if (ret != PSA_SUCCESS) {
|
||||
@@ -948,6 +956,12 @@ psa_status_t gpt_init(struct gpt_flash_driver_t *flash_driver, uint64_t max_part
|
||||
if (ret != PSA_SUCCESS) {
|
||||
goto fail_load;
|
||||
}
|
||||
+ if (backup_gpt.header.entry_size != GPT_ENTRY_SIZE) {
|
||||
+ ERROR("Unsupported entry size 0x%08x, must be 0x%08x\n",
|
||||
+ backup_gpt.header.entry_size, GPT_ENTRY_SIZE);
|
||||
+ ret = PSA_ERROR_NOT_SUPPORTED;
|
||||
+ goto fail_load;
|
||||
+ }
|
||||
backup_gpt_array_lba = backup_gpt.header.array_lba;
|
||||
} else {
|
||||
WARN("Backup GPT location is unknown!\n");
|
||||
@@ -999,11 +1013,7 @@ psa_status_t gpt_uninit(void)
|
||||
/* Returns the number of partition entries in each LBA */
|
||||
static inline uint64_t gpt_entry_per_lba_count(void)
|
||||
{
|
||||
- static uint64_t num_entries = 0;
|
||||
- if (num_entries == 0) {
|
||||
- num_entries = TFM_GPT_BLOCK_SIZE / primary_gpt.header.entry_size;
|
||||
- }
|
||||
- return num_entries;
|
||||
+ return TFM_GPT_BLOCK_SIZE / GPT_ENTRY_SIZE;
|
||||
}
|
||||
|
||||
/* Copies information from the entry to the user visible structure */
|
||||
@@ -1129,15 +1139,15 @@ static psa_status_t update_header(uint32_t num_partitions)
|
||||
/* Take the CRC of the partition array */
|
||||
uint32_t crc = 0;
|
||||
for (uint32_t i = 0; i < header->num_partitions; ++i) {
|
||||
- uint8_t entry_buf[header->entry_size];
|
||||
- memset(entry_buf, 0, header->entry_size);
|
||||
+ uint8_t entry_buf[GPT_ENTRY_SIZE];
|
||||
+ memset(entry_buf, 0, GPT_ENTRY_SIZE);
|
||||
struct gpt_entry_t *entry = (struct gpt_entry_t *)entry_buf;
|
||||
|
||||
psa_status_t ret = read_entry_from_flash(&primary_gpt, i, entry);
|
||||
if (ret != PSA_SUCCESS) {
|
||||
return ret;
|
||||
}
|
||||
- crc = efi_soft_crc32_update(crc, entry_buf, header->entry_size);
|
||||
+ crc = efi_soft_crc32_update(crc, entry_buf, GPT_ENTRY_SIZE);
|
||||
}
|
||||
header->array_crc = crc;
|
||||
|
||||
@@ -1268,7 +1278,7 @@ static psa_status_t read_entry_from_flash(const struct gpt_t *table,
|
||||
|
||||
memcpy(
|
||||
entry,
|
||||
- lba_buf + ((array_index % gpt_entry_per_lba_count()) * table->header.entry_size),
|
||||
+ lba_buf + ((array_index % gpt_entry_per_lba_count()) * GPT_ENTRY_SIZE),
|
||||
GPT_ENTRY_SIZE);
|
||||
|
||||
return PSA_SUCCESS;
|
||||
@@ -1415,7 +1425,7 @@ static psa_status_t write_entry(uint32_t array_index,
|
||||
|
||||
/* Copy into buffer */
|
||||
uint32_t index_in_lba = array_index % gpt_entry_per_lba_count();
|
||||
- memcpy(lba_buf + index_in_lba * primary_gpt.header.entry_size, entry, GPT_ENTRY_SIZE);
|
||||
+ memcpy(lba_buf + index_in_lba * GPT_ENTRY_SIZE, entry, GPT_ENTRY_SIZE);
|
||||
|
||||
/* Write on every nth operation. */
|
||||
if (++num_writes == gpt_entry_per_lba_count()) {
|
||||
@@ -1519,18 +1529,29 @@ static psa_status_t validate_table(struct gpt_t *table, bool is_primary)
|
||||
return PSA_ERROR_INVALID_SIGNATURE;
|
||||
}
|
||||
|
||||
+ /* Check the entry size. This is not a part of the spec but ensures the
|
||||
+ * library only supports entry sizes equal to 128. Otherwise, the backup
|
||||
+ * could be used to restore the primary with an entry size that is different
|
||||
+ * and break that assumption, or vise-versa
|
||||
+ */
|
||||
+ if (header->entry_size != GPT_ENTRY_SIZE) {
|
||||
+ ERROR("Unsupported entry size 0x%08x, must be 0x%08x\n",
|
||||
+ header->entry_size, GPT_ENTRY_SIZE);
|
||||
+ return PSA_ERROR_NOT_SUPPORTED;
|
||||
+ }
|
||||
+
|
||||
/* Check the CRC of the partition array */
|
||||
calc_crc = 0;
|
||||
for (uint32_t i = 0; i < header->num_partitions; ++i) {
|
||||
- uint8_t entry_buf[header->entry_size];
|
||||
- memset(entry_buf, 0, header->entry_size);
|
||||
+ uint8_t entry_buf[GPT_ENTRY_SIZE];
|
||||
+ memset(entry_buf, 0, GPT_ENTRY_SIZE);
|
||||
struct gpt_entry_t *entry = (struct gpt_entry_t *)entry_buf;
|
||||
|
||||
psa_status_t ret = read_entry_from_flash(table, i, entry);
|
||||
if (ret != PSA_SUCCESS) {
|
||||
return ret;
|
||||
}
|
||||
- calc_crc = efi_soft_crc32_update(calc_crc, (uint8_t *)entry, header->entry_size);
|
||||
+ calc_crc = efi_soft_crc32_update(calc_crc, (uint8_t *)entry, GPT_ENTRY_SIZE);
|
||||
}
|
||||
|
||||
if (calc_crc != header->array_crc) {
|
||||
diff --git a/lib/gpt/unittests/gpt/test_gpt.c b/lib/gpt/unittests/gpt/test_gpt.c
|
||||
index 2f05a6b4a..db897b967 100644
|
||||
--- a/lib/gpt/unittests/gpt/test_gpt.c
|
||||
+++ b/lib/gpt/unittests/gpt/test_gpt.c
|
||||
@@ -351,6 +351,30 @@ void test_gpt_init_should_failWhenMbrTypeInvalid(void)
|
||||
TEST_ASSERT_EQUAL(PSA_ERROR_NOT_SUPPORTED, setup_test_gpt());
|
||||
}
|
||||
|
||||
+void test_gpt_init_should_failWhenEntrySizeBad(void)
|
||||
+{
|
||||
+ test_header.entry_size--;
|
||||
+ /* Expect first a valid MBR read */
|
||||
+ register_mocked_read(&test_mbr, sizeof(test_mbr));
|
||||
+
|
||||
+ /* Expect a GPT header read second */
|
||||
+ register_mocked_read(&test_header, sizeof(test_header));
|
||||
+
|
||||
+ TEST_ASSERT_EQUAL(PSA_ERROR_NOT_SUPPORTED, gpt_init(&mock_driver, TEST_MAX_PARTITIONS));
|
||||
+ test_header.entry_size = default_header.entry_size;
|
||||
+
|
||||
+ /* Now do the backup. */
|
||||
+ register_mocked_read(&test_mbr, sizeof(test_mbr));
|
||||
+ register_mocked_read(&test_header, sizeof(test_header));
|
||||
+ register_mocked_read(&test_partition_array, sizeof(test_partition_array));
|
||||
+
|
||||
+ /* Expect fourth the backup to be read. Make the entry size bad */
|
||||
+ test_header.entry_size = 0;
|
||||
+ setup_backup_gpt();
|
||||
+
|
||||
+ TEST_ASSERT_EQUAL(PSA_ERROR_NOT_SUPPORTED, gpt_init(&mock_driver, TEST_MAX_PARTITIONS));
|
||||
+}
|
||||
+
|
||||
void test_gpt_init_should_failWhenFlashDriverNotFullyDefined(void)
|
||||
{
|
||||
gpt_flash_read_t read_fn = mock_driver.read;
|
||||
@@ -433,6 +457,22 @@ void test_gpt_validate_should_failWhenLbaPointerBad(void)
|
||||
TEST_ASSERT_EQUAL(PSA_ERROR_INVALID_SIGNATURE, gpt_validate(false));
|
||||
}
|
||||
|
||||
+void test_gpt_validate_should_failWhenBackupEntrySizeInvalid(void)
|
||||
+{
|
||||
+ /* The entry size for the primary GPT is validated on gpt_init and kept
|
||||
+ * in memory. Therefore, the entry size can only be validated on gpt_validate
|
||||
+ * for the backup table, which is read
|
||||
+ */
|
||||
+ setup_test_gpt();
|
||||
+ struct gpt_header_t backup_header;
|
||||
+ MAKE_BACKUP_HEADER(backup_header, test_header);
|
||||
+ backup_header.entry_size--;
|
||||
+ register_mocked_read(&backup_header, sizeof(backup_header));
|
||||
+ register_mocked_read(&test_partition_array, sizeof(test_partition_array));
|
||||
+
|
||||
+ TEST_ASSERT_EQUAL(PSA_ERROR_NOT_SUPPORTED, gpt_validate(false));
|
||||
+}
|
||||
+
|
||||
void test_gpt_validate_should_failWhenArrayCrcBad(void)
|
||||
{
|
||||
test_header.array_crc--;
|
||||
+38
@@ -0,0 +1,38 @@
|
||||
From c07da31be4551ee9b3ce546a1f6adccb19bc3b59 Mon Sep 17 00:00:00 2001
|
||||
From: Frazer Carsley <frazer.carsley@arm.com>
|
||||
Date: Wed, 15 Apr 2026 11:17:25 +0100
|
||||
Subject: [PATCH] lib: gpt: Ensure block size complies with spec
|
||||
|
||||
The UEFI spec 2.10 [1] implicitly requires a block size of at least 512
|
||||
in order to fit a legacy Master Boot Record.
|
||||
|
||||
[1] https://uefi.org/specs/UEFI/2.10/05_GUID_Partition_Table_Format.html#legacy-master-boot-record-mbr
|
||||
|
||||
Change-Id: I8218ef3d883b51d8fa14835e0ed884139fdebc7d
|
||||
Signed-off-by: Frazer Carsley <frazer.carsley@arm.com>
|
||||
Upstream-Status: Backport [c07da31be4551ee9b3ce546a1f6adccb19bc3b59]
|
||||
---
|
||||
lib/gpt/src/gpt.c | 6 +++++-
|
||||
1 file changed, 5 insertions(+), 1 deletion(-)
|
||||
|
||||
diff --git a/lib/gpt/src/gpt.c b/lib/gpt/src/gpt.c
|
||||
index 200e21599..cda9fe358 100644
|
||||
--- a/lib/gpt/src/gpt.c
|
||||
+++ b/lib/gpt/src/gpt.c
|
||||
@@ -20,11 +20,15 @@
|
||||
#include "efi_soft_crc.h"
|
||||
|
||||
/* This needs to be defined by the platform and is used by the GPT library as
|
||||
- * the number of bytes in a Logical Block Address (LBA)
|
||||
+ * the number of bytes in a Logical Block Address (LBA). It also must be at least
|
||||
+ * 512.
|
||||
*/
|
||||
#ifndef TFM_GPT_BLOCK_SIZE
|
||||
#error "TFM_GPT_BLOCK_SIZE must be defined if using GPT library!"
|
||||
#endif
|
||||
+#if TFM_GPT_BLOCK_SIZE < 512
|
||||
+#error "TFM_GPT_BLOCK_SIZE must be at least 512!"
|
||||
+#endif
|
||||
|
||||
/* Where Master Boot Record (MBR) is on flash */
|
||||
#define MBR_LBA 0ULL
|
||||
+352
@@ -0,0 +1,352 @@
|
||||
From bcce0ce881817b36ad52df550bcbf41b4f0d4938 Mon Sep 17 00:00:00 2001
|
||||
From: Frazer Carsley <frazer.carsley@arm.com>
|
||||
Date: Wed, 15 Apr 2026 15:09:03 +0100
|
||||
Subject: [PATCH] lib: gpt: Expand table validation
|
||||
|
||||
It is implied by the UEFI spec 2.10 [1] that the backup GPT must be
|
||||
located at the end of storage. To this effect, ensure that it is the
|
||||
largest known LBA value.
|
||||
|
||||
Additionally, it is also implied that the partition entry arrays, both
|
||||
primary and backup, must be before or after usable space respectively.
|
||||
|
||||
[1] https://uefi.org/specs/UEFI/2.10/05_GUID_Partition_Table_Format.html
|
||||
|
||||
Change-Id: I5042836822f990a21fbf48b19422879384a844aa
|
||||
Signed-off-by: Frazer Carsley <frazer.carsley@arm.com>
|
||||
Upstream-Status: Backport [bcce0ce881817b36ad52df550bcbf41b4f0d4938]
|
||||
---
|
||||
lib/gpt/src/gpt.c | 115 ++++++++++++++++++++
|
||||
lib/gpt/unittests/gpt/test_gpt.c | 179 +++++++++++++++++++++++++++++++
|
||||
2 files changed, 294 insertions(+)
|
||||
|
||||
diff --git a/lib/gpt/src/gpt.c b/lib/gpt/src/gpt.c
|
||||
index cda9fe358..0335befa7 100644
|
||||
--- a/lib/gpt/src/gpt.c
|
||||
+++ b/lib/gpt/src/gpt.c
|
||||
@@ -229,6 +229,12 @@ static psa_status_t mbr_load(struct mbr_t *mbr);
|
||||
static bool gpt_entry_cmp_guid(const struct gpt_entry_t *entry, const void *guid);
|
||||
static bool gpt_entry_cmp_name(const struct gpt_entry_t *entry, const void *name);
|
||||
static bool gpt_entry_cmp_type(const struct gpt_entry_t *entry, const void *type);
|
||||
+static psa_status_t validate_backup_gpt_lba(const uint64_t backup_lba,
|
||||
+ const uint64_t primary_lba,
|
||||
+ const uint64_t partition_array_end,
|
||||
+ const struct gpt_header_t *header);
|
||||
+static psa_status_t validate_array_lba(const uint64_t partition_array_end,
|
||||
+ const uint64_t usable_lba_start);
|
||||
static psa_status_t validate_table(struct gpt_t *table, bool is_primary);
|
||||
static psa_status_t restore_table(struct gpt_t *restore_from, bool is_primary);
|
||||
static psa_status_t sort_partition_array(const struct gpt_t *table);
|
||||
@@ -1498,6 +1504,73 @@ static inline void swap_headers(const struct gpt_header_t *src, struct gpt_heade
|
||||
primary_gpt.header.array_lba);
|
||||
}
|
||||
|
||||
+/* Validate that the backup GPT LBA is greater than all other LBAs in the header
|
||||
+ */
|
||||
+static psa_status_t validate_backup_gpt_lba(const uint64_t backup_lba,
|
||||
+ const uint64_t primary_lba,
|
||||
+ const uint64_t partition_array_end,
|
||||
+ const struct gpt_header_t *header)
|
||||
+{
|
||||
+ if (backup_lba <= primary_lba) {
|
||||
+ ERROR("Backup LBA (0x%08x%08x) must be final LBA on flash, "
|
||||
+ "primary LBA at 0x%08x%08x\n",
|
||||
+ (uint32_t)(backup_lba >> 32),
|
||||
+ (uint32_t)(backup_lba),
|
||||
+ (uint32_t)(primary_lba >> 32),
|
||||
+ (uint32_t)(primary_lba));
|
||||
+ return PSA_ERROR_INVALID_SIGNATURE;
|
||||
+ }
|
||||
+
|
||||
+ if (backup_lba <= header->first_lba) {
|
||||
+ ERROR("Backup LBA (0x%08x%08x) must be final LBA on flash, "
|
||||
+ "first usable LBA at 0x%08x%08x\n",
|
||||
+ (uint32_t)(backup_lba >> 32),
|
||||
+ (uint32_t)(backup_lba),
|
||||
+ (uint32_t)(header->first_lba >> 32),
|
||||
+ (uint32_t)(header->first_lba));
|
||||
+ return PSA_ERROR_INVALID_SIGNATURE;
|
||||
+ }
|
||||
+
|
||||
+ if (backup_lba <= header->last_lba) {
|
||||
+ ERROR("Backup LBA (0x%08x%08x) must be final LBA on flash, "
|
||||
+ "last usable LBA at 0x%08x%08x\n",
|
||||
+ (uint32_t)(backup_lba >> 32),
|
||||
+ (uint32_t)(backup_lba),
|
||||
+ (uint32_t)(header->last_lba >> 32),
|
||||
+ (uint32_t)(header->last_lba));
|
||||
+ return PSA_ERROR_INVALID_SIGNATURE;
|
||||
+ }
|
||||
+
|
||||
+ if (backup_lba <= partition_array_end) {
|
||||
+ ERROR("Backup LBA (0x%08x%08x) must be final LBA on flash, "
|
||||
+ "partition array ends at LBA at 0x%08x%08x\n",
|
||||
+ (uint32_t)(backup_lba >> 32),
|
||||
+ (uint32_t)(backup_lba),
|
||||
+ (uint32_t)(partition_array_end >> 32),
|
||||
+ (uint32_t)(partition_array_end));
|
||||
+ return PSA_ERROR_INVALID_SIGNATURE;
|
||||
+ }
|
||||
+
|
||||
+ return PSA_SUCCESS;
|
||||
+}
|
||||
+
|
||||
+/* Validate partition array is outside the area of usable flash */
|
||||
+static psa_status_t validate_array_lba(const uint64_t partition_array_end,
|
||||
+ const uint64_t usable_lba_start)
|
||||
+{
|
||||
+ if (partition_array_end >= usable_lba_start) {
|
||||
+ ERROR("GPT partition array must not be in usable space: "
|
||||
+ "0x%08x%08x >= 0x%08x%08x\n",
|
||||
+ (uint32_t)(partition_array_end >> 32),
|
||||
+ (uint32_t)partition_array_end,
|
||||
+ (uint32_t)(usable_lba_start >> 32),
|
||||
+ (uint32_t)usable_lba_start);
|
||||
+ return PSA_ERROR_INVALID_SIGNATURE;
|
||||
+ }
|
||||
+
|
||||
+ return PSA_SUCCESS;
|
||||
+}
|
||||
+
|
||||
/* Validates a specific GPT. */
|
||||
static psa_status_t validate_table(struct gpt_t *table, bool is_primary)
|
||||
{
|
||||
@@ -1564,6 +1637,48 @@ static psa_status_t validate_table(struct gpt_t *table, bool is_primary)
|
||||
return PSA_ERROR_INVALID_SIGNATURE;
|
||||
}
|
||||
|
||||
+ /* Check the backup LBA is greater than all other LBAs. Check also
|
||||
+ * the partition array cannot be overritten by data by ensuring
|
||||
+ * that it is not between the first and last usable LBAs
|
||||
+ */
|
||||
+ if (is_primary) {
|
||||
+ psa_status_t ret = validate_backup_gpt_lba(
|
||||
+ header->backup_lba,
|
||||
+ header->current_lba,
|
||||
+ partition_entry_lba(table, header->num_partitions - 1),
|
||||
+ header);
|
||||
+ if (ret != PSA_SUCCESS) {
|
||||
+ return ret;
|
||||
+ }
|
||||
+
|
||||
+ /* Go to the final LBA of the partition array, including unused entries */
|
||||
+ ret = validate_array_lba(
|
||||
+ partition_entry_lba(table, header->num_partitions - 1),
|
||||
+ header->first_lba);
|
||||
+ if (ret != PSA_SUCCESS) {
|
||||
+ return ret;
|
||||
+ }
|
||||
+ } else {
|
||||
+ psa_status_t ret = validate_backup_gpt_lba(
|
||||
+ header->current_lba,
|
||||
+ header->backup_lba,
|
||||
+ partition_entry_lba(table, header->num_partitions - 1),
|
||||
+ header);
|
||||
+ if (ret != PSA_SUCCESS) {
|
||||
+ return ret;
|
||||
+ }
|
||||
+
|
||||
+ /* To flip the condition, negate the parameters passed: it becomes
|
||||
+ * -array_lba >= -last_lba (equivalent to) array_lba < last_lba
|
||||
+ * (equivalent to) last_lba >= array_lba. This is because the backup array is
|
||||
+ * after the last_lba
|
||||
+ */
|
||||
+ ret = validate_array_lba(~(header->array_lba), ~(header->last_lba));
|
||||
+ if (ret != PSA_SUCCESS) {
|
||||
+ return ret;
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
if (is_primary) {
|
||||
/* Any time the primary table is considered valid, cache the backup
|
||||
* LBA field
|
||||
diff --git a/lib/gpt/unittests/gpt/test_gpt.c b/lib/gpt/unittests/gpt/test_gpt.c
|
||||
index db897b967..bd161ec74 100644
|
||||
--- a/lib/gpt/unittests/gpt/test_gpt.c
|
||||
+++ b/lib/gpt/unittests/gpt/test_gpt.c
|
||||
@@ -493,6 +493,185 @@ void test_gpt_validate_should_failWhenArrayCrcBad(void)
|
||||
TEST_ASSERT_EQUAL(PSA_ERROR_INVALID_SIGNATURE, gpt_validate(false));
|
||||
}
|
||||
|
||||
+void test_gpt_validate_should_failWhenBackupLbaNotAtEndOfDisk(void)
|
||||
+{
|
||||
+ /* First test when the backup lba is before usable disk */
|
||||
+ test_header.backup_lba = test_header.first_lba - 1;
|
||||
+ setup_test_gpt();
|
||||
+
|
||||
+ /* Each entry will be read in order to check the partition array CRC */
|
||||
+ register_mocked_read(&test_partition_array, sizeof(test_partition_array));
|
||||
+ TEST_ASSERT_EQUAL(PSA_ERROR_INVALID_SIGNATURE, gpt_validate(true));
|
||||
+
|
||||
+ /* Then test when the backup is before in usable disk space */
|
||||
+ test_header.backup_lba = test_header.first_lba;
|
||||
+ setup_test_gpt();
|
||||
+ register_mocked_read(&test_partition_array, sizeof(test_partition_array));
|
||||
+ TEST_ASSERT_EQUAL(PSA_ERROR_INVALID_SIGNATURE, gpt_validate(true));
|
||||
+
|
||||
+ test_header.backup_lba = test_header.first_lba + 1;
|
||||
+ setup_test_gpt();
|
||||
+ register_mocked_read(&test_partition_array, sizeof(test_partition_array));
|
||||
+ TEST_ASSERT_EQUAL(PSA_ERROR_INVALID_SIGNATURE, gpt_validate(true));
|
||||
+
|
||||
+ test_header.backup_lba = test_header.last_lba - 1;
|
||||
+ setup_test_gpt();
|
||||
+ register_mocked_read(&test_partition_array, sizeof(test_partition_array));
|
||||
+ TEST_ASSERT_EQUAL(PSA_ERROR_INVALID_SIGNATURE, gpt_validate(true));
|
||||
+
|
||||
+ test_header.backup_lba = test_header.last_lba;
|
||||
+ setup_test_gpt();
|
||||
+ register_mocked_read(&test_partition_array, sizeof(test_partition_array));
|
||||
+ TEST_ASSERT_EQUAL(PSA_ERROR_INVALID_SIGNATURE, gpt_validate(true));
|
||||
+
|
||||
+ /* Finally, test when the backup is before the end of the partition entry array */
|
||||
+ test_header.backup_lba = test_header.array_lba - 1;
|
||||
+ setup_test_gpt();
|
||||
+ register_mocked_read(&test_partition_array, sizeof(test_partition_array));
|
||||
+ TEST_ASSERT_EQUAL(PSA_ERROR_INVALID_SIGNATURE, gpt_validate(true));
|
||||
+
|
||||
+ /* For this scenario, manually setup the backup header so that the array LBA
|
||||
+ * (also the backup header LBA) is valid on init and can then be validated
|
||||
+ * with gpt_validate
|
||||
+ */
|
||||
+ test_header.backup_lba = test_header.array_lba;
|
||||
+
|
||||
+ /* Expect first a valid MBR read */
|
||||
+ register_mocked_read(&test_mbr, sizeof(test_mbr));
|
||||
+
|
||||
+ /* Expect a GPT header read second */
|
||||
+ register_mocked_read(&test_header, sizeof(test_header));
|
||||
+
|
||||
+ /* Expect third each partition is read to find the number in use. This is
|
||||
+ * also the backup header, which will be cached
|
||||
+ */
|
||||
+ setup_backup_gpt();
|
||||
+
|
||||
+ TEST_ASSERT_EQUAL(PSA_SUCCESS, gpt_init(&mock_driver, TEST_MAX_PARTITIONS));
|
||||
+
|
||||
+ /* Backup partition array read for crc */
|
||||
+ register_mocked_read(&test_partition_array, sizeof(test_partition_array));
|
||||
+ TEST_ASSERT_EQUAL(PSA_ERROR_INVALID_SIGNATURE, gpt_validate(true));
|
||||
+
|
||||
+ /* Now do the backup gpt header */
|
||||
+ struct gpt_header_t backup_header;
|
||||
+ test_header.backup_lba = test_header.first_lba - 1;
|
||||
+ MAKE_BACKUP_HEADER(backup_header, test_header);
|
||||
+
|
||||
+ setup_test_gpt();
|
||||
+ register_mocked_read(&backup_header, sizeof(backup_header));
|
||||
+ register_mocked_read(&test_partition_array, sizeof(test_partition_array));
|
||||
+ TEST_ASSERT_EQUAL(PSA_ERROR_INVALID_SIGNATURE, gpt_validate(false));
|
||||
+
|
||||
+ test_header.backup_lba = backup_header.first_lba;
|
||||
+ backup_header.current_lba = backup_header.first_lba;
|
||||
+ setup_test_gpt();
|
||||
+ register_mocked_read(&backup_header, sizeof(backup_header));
|
||||
+ register_mocked_read(&test_partition_array, sizeof(test_partition_array));
|
||||
+ TEST_ASSERT_EQUAL(PSA_ERROR_INVALID_SIGNATURE, gpt_validate(false));
|
||||
+
|
||||
+ test_header.backup_lba = backup_header.first_lba + 1;
|
||||
+ backup_header.current_lba = backup_header.first_lba + 1;
|
||||
+ setup_test_gpt();
|
||||
+ register_mocked_read(&backup_header, sizeof(backup_header));
|
||||
+ register_mocked_read(&test_partition_array, sizeof(test_partition_array));
|
||||
+ TEST_ASSERT_EQUAL(PSA_ERROR_INVALID_SIGNATURE, gpt_validate(false));
|
||||
+
|
||||
+ test_header.backup_lba = backup_header.last_lba - 1;
|
||||
+ backup_header.current_lba = backup_header.last_lba - 1;
|
||||
+ setup_test_gpt();
|
||||
+ register_mocked_read(&backup_header, sizeof(backup_header));
|
||||
+ register_mocked_read(&test_partition_array, sizeof(test_partition_array));
|
||||
+ TEST_ASSERT_EQUAL(PSA_ERROR_INVALID_SIGNATURE, gpt_validate(false));
|
||||
+
|
||||
+ test_header.backup_lba = backup_header.last_lba;
|
||||
+ backup_header.current_lba = backup_header.last_lba;
|
||||
+ setup_test_gpt();
|
||||
+ register_mocked_read(&backup_header, sizeof(backup_header));
|
||||
+ register_mocked_read(&test_partition_array, sizeof(test_partition_array));
|
||||
+ TEST_ASSERT_EQUAL(PSA_ERROR_INVALID_SIGNATURE, gpt_validate(false));
|
||||
+
|
||||
+ test_header.backup_lba = backup_header.array_lba - 1;
|
||||
+ backup_header.current_lba = backup_header.array_lba - 1;
|
||||
+ setup_test_gpt();
|
||||
+ register_mocked_read(&backup_header, sizeof(backup_header));
|
||||
+ register_mocked_read(&test_partition_array, sizeof(test_partition_array));
|
||||
+ TEST_ASSERT_EQUAL(PSA_ERROR_INVALID_SIGNATURE, gpt_validate(false));
|
||||
+
|
||||
+ test_header.backup_lba = backup_header.array_lba;
|
||||
+ backup_header.current_lba = backup_header.array_lba;
|
||||
+ setup_test_gpt();
|
||||
+ register_mocked_read(&backup_header, sizeof(backup_header));
|
||||
+ TEST_ASSERT_EQUAL(PSA_ERROR_INVALID_SIGNATURE, gpt_validate(false));
|
||||
+}
|
||||
+
|
||||
+void test_gpt_validate_should_failWhenPartitionArrayInUsableDiskSpace(void)
|
||||
+{
|
||||
+ /* First test when the primary partition array is in usable disk space */
|
||||
+ test_header.array_lba = test_header.first_lba;
|
||||
+ setup_test_gpt();
|
||||
+
|
||||
+ /* Each entry will be read in order to check the partition array CRC */
|
||||
+ register_mocked_read(&test_partition_array, sizeof(test_partition_array));
|
||||
+ TEST_ASSERT_EQUAL(PSA_ERROR_INVALID_SIGNATURE, gpt_validate(true));
|
||||
+
|
||||
+ test_header.array_lba = test_header.first_lba + 1;
|
||||
+ setup_test_gpt();
|
||||
+ register_mocked_read(&test_partition_array, sizeof(test_partition_array));
|
||||
+ TEST_ASSERT_EQUAL(PSA_ERROR_INVALID_SIGNATURE, gpt_validate(true));
|
||||
+
|
||||
+ test_header.array_lba = test_header.last_lba - 1;
|
||||
+ setup_test_gpt();
|
||||
+ register_mocked_read(&test_partition_array, sizeof(test_partition_array));
|
||||
+ TEST_ASSERT_EQUAL(PSA_ERROR_INVALID_SIGNATURE, gpt_validate(true));
|
||||
+
|
||||
+ test_header.array_lba = test_header.last_lba;
|
||||
+ setup_test_gpt();
|
||||
+ register_mocked_read(&test_partition_array, sizeof(test_partition_array));
|
||||
+ TEST_ASSERT_EQUAL(PSA_ERROR_INVALID_SIGNATURE, gpt_validate(true));
|
||||
+
|
||||
+ /* Then test when the primary partition array is after usable disk space */
|
||||
+ test_header.array_lba = test_header.last_lba + 1;
|
||||
+ setup_test_gpt();
|
||||
+ register_mocked_read(&test_partition_array, sizeof(test_partition_array));
|
||||
+ TEST_ASSERT_EQUAL(PSA_ERROR_INVALID_SIGNATURE, gpt_validate(true));
|
||||
+
|
||||
+ /* Now do the backup gpt header, ensuring it is always after usable space */
|
||||
+ struct gpt_header_t backup_header;
|
||||
+ MAKE_BACKUP_HEADER(backup_header, test_header);
|
||||
+
|
||||
+ backup_header.array_lba = test_header.first_lba - 1;
|
||||
+ setup_test_gpt();
|
||||
+ register_mocked_read(&backup_header, sizeof(backup_header));
|
||||
+ register_mocked_read(&test_partition_array, sizeof(test_partition_array));
|
||||
+ TEST_ASSERT_EQUAL(PSA_ERROR_INVALID_SIGNATURE, gpt_validate(false));
|
||||
+
|
||||
+ /* Then test that the backup partition array is after usable disk space */
|
||||
+ backup_header.array_lba = test_header.first_lba;
|
||||
+ setup_test_gpt();
|
||||
+ register_mocked_read(&backup_header, sizeof(backup_header));
|
||||
+ register_mocked_read(&test_partition_array, sizeof(test_partition_array));
|
||||
+ TEST_ASSERT_EQUAL(PSA_ERROR_INVALID_SIGNATURE, gpt_validate(false));
|
||||
+
|
||||
+ backup_header.array_lba = test_header.first_lba + 1;
|
||||
+ setup_test_gpt();
|
||||
+ register_mocked_read(&backup_header, sizeof(backup_header));
|
||||
+ register_mocked_read(&test_partition_array, sizeof(test_partition_array));
|
||||
+ TEST_ASSERT_EQUAL(PSA_ERROR_INVALID_SIGNATURE, gpt_validate(false));
|
||||
+
|
||||
+ backup_header.array_lba = test_header.last_lba - 1;
|
||||
+ setup_test_gpt();
|
||||
+ register_mocked_read(&backup_header, sizeof(backup_header));
|
||||
+ register_mocked_read(&test_partition_array, sizeof(test_partition_array));
|
||||
+ TEST_ASSERT_EQUAL(PSA_ERROR_INVALID_SIGNATURE, gpt_validate(false));
|
||||
+
|
||||
+ backup_header.array_lba = test_header.last_lba;
|
||||
+ setup_test_gpt();
|
||||
+ register_mocked_read(&backup_header, sizeof(backup_header));
|
||||
+ register_mocked_read(&test_partition_array, sizeof(test_partition_array));
|
||||
+ TEST_ASSERT_EQUAL(PSA_ERROR_INVALID_SIGNATURE, gpt_validate(false));
|
||||
+}
|
||||
+
|
||||
void test_gpt_restore_should_restorePrimaryFromBackup(void)
|
||||
{
|
||||
/* Start with a valid GPT */
|
||||
+151
@@ -0,0 +1,151 @@
|
||||
From 6391a6189ee2024f0ef956f56373f79128576230 Mon Sep 17 00:00:00 2001
|
||||
From: Maulik Patel <maulik.patel@arm.com>
|
||||
Date: Tue, 23 Sep 2025 21:26:44 +0100
|
||||
Subject: [PATCH] Build: Fix compiler warnings
|
||||
|
||||
- Add header crypto_hw for crypto_hw_apply_debug_permissions()
|
||||
- Add header int_com_port_driver.h for IComPortRxIntInit()
|
||||
- Move psa_adac_platform_init() declaration to psa_adac_platform.h
|
||||
- Add include path for psa-adac/transport_layer/transports/sdc-600
|
||||
|
||||
Signed-off-by: Maulik Patel <maulik.patel@arm.com>
|
||||
Change-Id: I34f774a9843f7a3a62ad447fa0ae607184bd800a
|
||||
|
||||
Upstream-Status: Backport [6391a6189ee2024f0ef956f56373f79128576230]
|
||||
Signed-off-by: Jon Mason <jon.mason@arm.com>
|
||||
|
||||
---
|
||||
.../platform/arm/corstone1000/CMakeLists.txt | 2 ++
|
||||
.../platform/arm/corstone1000/corstone1000.c | 7 ++++++-
|
||||
.../platform/arm/corstone1000/include/platform/platform.h | 1 -
|
||||
.../platform/arm/corstone1000/include/psa_adac_platform.h | 6 ++++++
|
||||
.../platform/arm/rse/common/CMakeLists.txt | 1 +
|
||||
.../platform/arm/rse/common/include/platform/platform.h | 1 -
|
||||
.../platform/arm/rse/common/include/psa_adac_platform.h | 7 +++++++
|
||||
.../platform/arm/rse/common/psa_adac_platform.c | 5 +++++
|
||||
8 files changed, 27 insertions(+), 3 deletions(-)
|
||||
|
||||
diff --git a/target/trusted-firmware-m/platform/arm/corstone1000/CMakeLists.txt b/target/trusted-firmware-m/platform/arm/corstone1000/CMakeLists.txt
|
||||
index c36259e0b31f..604c9b72745d 100644
|
||||
--- a/target/trusted-firmware-m/platform/arm/corstone1000/CMakeLists.txt
|
||||
+++ b/target/trusted-firmware-m/platform/arm/corstone1000/CMakeLists.txt
|
||||
@@ -20,6 +20,8 @@ target_include_directories(${PROJECT_NAME}
|
||||
${CMAKE_CURRENT_SOURCE_DIR}
|
||||
${PSA_ADAC_MBEDTLS_INCLUDE}
|
||||
${PSA_ADAC_ROOT}/transport_layer/transports
|
||||
+ ${PSA_ADAC_ROOT}/transport_layer/transports/sdc-600
|
||||
+
|
||||
)
|
||||
|
||||
target_compile_definitions(${PROJECT_NAME}
|
||||
diff --git a/target/trusted-firmware-m/platform/arm/corstone1000/corstone1000.c b/target/trusted-firmware-m/platform/arm/corstone1000/corstone1000.c
|
||||
index e629eed97236..e979b3246e12 100644
|
||||
--- a/target/trusted-firmware-m/platform/arm/corstone1000/corstone1000.c
|
||||
+++ b/target/trusted-firmware-m/platform/arm/corstone1000/corstone1000.c
|
||||
@@ -12,6 +12,11 @@
|
||||
#include "platform/msg_interface.h"
|
||||
#include "demo-anchors.h"
|
||||
#include <string.h>
|
||||
+#include "crypto_hw.h"
|
||||
+
|
||||
+#ifdef PSA_ADAC_AS_TFM_RUNTIME_SERVICE
|
||||
+#include "int_com_port_driver.h"
|
||||
+#endif /* PSA_ADAC_AS_TFM_RUNTIME_SERVICE */
|
||||
|
||||
extern uint8_t discovery_template[];
|
||||
extern size_t discovery_template_len;
|
||||
@@ -70,7 +75,7 @@ int psa_adac_platform_check_certificate(uint8_t *crt, size_t crt_size)
|
||||
|
||||
int psa_adac_to_tfm_apply_permissions(uint8_t permissions_mask[16])
|
||||
{
|
||||
- /* This implementation only support coarse-grained secure debug
|
||||
+ /* This implementation only support coarse-grained secure debug
|
||||
* unlock (closed/open). Fine-grained access-control can be
|
||||
* supported by defining a mapping from permissions_mask to
|
||||
* dcu_reg_values.
|
||||
diff --git a/target/trusted-firmware-m/platform/arm/corstone1000/include/platform/platform.h b/target/trusted-firmware-m/platform/arm/corstone1000/include/platform/platform.h
|
||||
index e99d0d55f624..82b416f5f67f 100644
|
||||
--- a/target/trusted-firmware-m/platform/arm/corstone1000/include/platform/platform.h
|
||||
+++ b/target/trusted-firmware-m/platform/arm/corstone1000/include/platform/platform.h
|
||||
@@ -31,7 +31,6 @@ adac_status_t psa_adac_change_life_cycle_state(uint8_t *input, size_t input_size
|
||||
void psa_adac_close_session(void);
|
||||
void psa_adac_resume(void);
|
||||
void psa_adac_platform_lock(void);
|
||||
-void psa_adac_platform_init(void);
|
||||
int psa_adac_detect_debug_request(void);
|
||||
void psa_adac_acknowledge_debug_request(void);
|
||||
|
||||
diff --git a/target/trusted-firmware-m/platform/arm/corstone1000/include/psa_adac_platform.h b/target/trusted-firmware-m/platform/arm/corstone1000/include/psa_adac_platform.h
|
||||
index 26f10f8999ca..2ae4569f5ff1 100644
|
||||
--- a/target/trusted-firmware-m/platform/arm/corstone1000/include/psa_adac_platform.h
|
||||
+++ b/target/trusted-firmware-m/platform/arm/corstone1000/include/psa_adac_platform.h
|
||||
@@ -30,5 +30,11 @@ int tfm_to_psa_adac_corstone1000_secure_debug(uint8_t *secure_debug_rotpk, uint3
|
||||
*/
|
||||
int psa_adac_to_tfm_apply_permissions(uint8_t permissions_mask[16]);
|
||||
|
||||
+/*
|
||||
+ * Platform initialization function for PSA ADAC.
|
||||
+ * This function should be called during runtime service init to initialize
|
||||
+ * the PSA ADAC platform-specific components.
|
||||
+ */
|
||||
+void psa_adac_platform_init(void);
|
||||
|
||||
#endif /* __PSA_ADAC_PLATFORM_H__ */
|
||||
diff --git a/target/trusted-firmware-m/platform/arm/rse/common/CMakeLists.txt b/target/trusted-firmware-m/platform/arm/rse/common/CMakeLists.txt
|
||||
index 67214bb3f354..d1b9718a8183 100644
|
||||
--- a/target/trusted-firmware-m/platform/arm/rse/common/CMakeLists.txt
|
||||
+++ b/target/trusted-firmware-m/platform/arm/rse/common/CMakeLists.txt
|
||||
@@ -23,6 +23,7 @@ target_include_directories(${PROJECT_NAME}
|
||||
${PSA_ADAC_MBEDTLS_INCLUDE}
|
||||
${PSA_ADAC_ROOT}/transport_layer/transports
|
||||
${TFM_SRC_DIR}/platform/ext/target/arm/rse/common/partition
|
||||
+ ${PSA_ADAC_ROOT}/transport_layer/transports/sdc-600
|
||||
)
|
||||
|
||||
target_compile_definitions(${PROJECT_NAME}
|
||||
diff --git a/target/trusted-firmware-m/platform/arm/rse/common/include/platform/platform.h b/target/trusted-firmware-m/platform/arm/rse/common/include/platform/platform.h
|
||||
index 57044f05a67a..afd4b3033a4b 100644
|
||||
--- a/target/trusted-firmware-m/platform/arm/rse/common/include/platform/platform.h
|
||||
+++ b/target/trusted-firmware-m/platform/arm/rse/common/include/platform/platform.h
|
||||
@@ -32,7 +32,6 @@ void psa_adac_resume(void);
|
||||
void psa_adac_platform_lock(void);
|
||||
int psa_adac_platform_check_token(uint8_t *token, size_t token_size);
|
||||
int psa_adac_platform_check_certificate(uint8_t *crt, size_t crt_size);
|
||||
-void psa_adac_platform_init(void);
|
||||
int psa_adac_detect_debug_request(void);
|
||||
void psa_adac_acknowledge_debug_request(void);
|
||||
int psa_adac_apply_permissions(uint8_t permissions_mask[16]);
|
||||
diff --git a/target/trusted-firmware-m/platform/arm/rse/common/include/psa_adac_platform.h b/target/trusted-firmware-m/platform/arm/rse/common/include/psa_adac_platform.h
|
||||
index a47788566aec..3e1dc73c4e0e 100644
|
||||
--- a/target/trusted-firmware-m/platform/arm/rse/common/include/psa_adac_platform.h
|
||||
+++ b/target/trusted-firmware-m/platform/arm/rse/common/include/psa_adac_platform.h
|
||||
@@ -34,6 +34,13 @@ int tfm_to_psa_adac_rse_secure_debug(uint8_t *secure_debug_rotpk, uint32_t len);
|
||||
*/
|
||||
int psa_adac_to_tfm_apply_permissions(uint8_t permissions_mask[16]);
|
||||
|
||||
+/*
|
||||
+ * Platform initialization function for PSA ADAC.
|
||||
+ * This function should be called during runtime service init to initialize
|
||||
+ * the PSA ADAC platform-specific components.
|
||||
+ */
|
||||
+void psa_adac_platform_init(void);
|
||||
+
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
diff --git a/target/trusted-firmware-m/platform/arm/rse/common/psa_adac_platform.c b/target/trusted-firmware-m/platform/arm/rse/common/psa_adac_platform.c
|
||||
index fa2e7c023ef4..5c5cfd1529a3 100644
|
||||
--- a/target/trusted-firmware-m/platform/arm/rse/common/psa_adac_platform.c
|
||||
+++ b/target/trusted-firmware-m/platform/arm/rse/common/psa_adac_platform.c
|
||||
@@ -21,6 +21,11 @@
|
||||
#include "rse_debug_after_reset.h"
|
||||
#include "lcm_drv.h"
|
||||
#include "device_definition.h"
|
||||
+
|
||||
+#ifdef PSA_ADAC_AS_TFM_RUNTIME_SERVICE
|
||||
+#include "int_com_port_driver.h"
|
||||
+#endif /* PSA_ADAC_AS_TFM_RUNTIME_SERVICE */
|
||||
+
|
||||
#define ROTPK_ANCHOR_ALG PSA_ALG_SHA_512
|
||||
#define UINT8_SIZE_IN_BITS 8
|
||||
|
||||
+32
@@ -0,0 +1,32 @@
|
||||
From 972bf711ad884607409c225f9338bf25206e29e8 Mon Sep 17 00:00:00 2001
|
||||
From: Bence Balogh <bence.balogh@arm.com>
|
||||
Date: Wed, 31 Jul 2024 15:56:51 +0200
|
||||
Subject: [PATCH] Fix psa_key_handle_t initialization
|
||||
|
||||
If the MBEDTLS_PSA_CRYPTO_KEY_ID_ENCODES_OWNER macro is defined in the
|
||||
mbedcrypto configuration header file then the psa_key_handle_t is a
|
||||
struct. In this case, it is defined in the used configuration header
|
||||
so the struct cannot be initialized with -1.
|
||||
|
||||
Signed-off-by: Bence Balogh <bence.balogh@arm.com>
|
||||
Upstream-Status: Inappropriate [mbedcrypto configs have to be fixed to build secure-debug mps3 without this patch]
|
||||
---
|
||||
psa_crypto/adac_crypto_psa_mac.c | 2 +-
|
||||
1 file changed, 1 insertion(+), 1 deletion(-)
|
||||
|
||||
diff --git a/psa_crypto/adac_crypto_psa_mac.c b/psa_crypto/adac_crypto_psa_mac.c
|
||||
index 046fef7..93ab8f9 100644
|
||||
--- a/psa_crypto/adac_crypto_psa_mac.c
|
||||
+++ b/psa_crypto/adac_crypto_psa_mac.c
|
||||
@@ -198,7 +198,7 @@ psa_status_t psa_adac_verify_mac(uint8_t key_type,
|
||||
size_t mac_size)
|
||||
{
|
||||
psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT;
|
||||
- psa_key_handle_t handle = -1;
|
||||
+ psa_key_handle_t handle = {0};
|
||||
psa_status_t ret = PSA_ERROR_NOT_SUPPORTED;
|
||||
psa_key_type_t type = 0;
|
||||
size_t bits = 0;
|
||||
--
|
||||
2.25.1
|
||||
|
||||
@@ -28,35 +28,78 @@ EXTRA_OECMAKE += "-DPLATFORM_IS_FVP=${TFM_PLATFORM_IS_FVP}"
|
||||
EXTRA_OECMAKE += "-DCC312_LEGACY_DRIVER_API_ENABLED=OFF"
|
||||
EXTRA_OECMAKE:append = " -DENABLE_MULTICORE=${@bb.utils.contains('MACHINE_FEATURES', 'corstone1000_smp', 'TRUE', 'FALSE', d)}"
|
||||
EXTRA_OECMAKE:append:corstone1000-mps3 = " -DPLATFORM_PSA_ADAC_SECURE_DEBUG=${@bb.utils.contains('MACHINE_FEATURES', 'secure-debug', 'ON', 'OFF', d)}"
|
||||
# Keep the device in CM until authenticated DCU_EN can be preserved across
|
||||
# reset and applied from BL2.
|
||||
EXTRA_OECMAKE:append:corstone1000-mps3 = " -DCORSTONE1000_SKIP_PROVISIONING_FOR_DEBUG=${@bb.utils.contains('MACHINE_FEATURES', 'secure-debug', 'ON', 'OFF', d)}"
|
||||
EXTRA_OECMAKE:append:corstone1000-mps3 = " -DPLATFORM_PSA_ADAC_SOURCE_PATH=${S}/external/tfm-psa-adac -DPLATFORM_PSA_ADAC_BUILD_PATH=${B}/tfm-psa-adac-build"
|
||||
|
||||
FILESEXTRAPATHS:prepend := "${THISDIR}/files:"
|
||||
SRC_URI:append:corstone1000 = " \
|
||||
file://0001-CC312-alignment-of-cc312-differences-between-fvp-and.patch \
|
||||
file://0002-Corstone-1000-Enable-different-DRBG-configurations.patch \
|
||||
file://0003-bl2-corstone-1000-secure-debug-waiting-in-CM-LCS.patch \
|
||||
file://0004-Workaround-compile-errors-in-AES.patch \
|
||||
file://0005-plat-cs1k-Removed-unused-variables.patch \
|
||||
file://0006-lib-gpt-Show-intent-of-GUIDs-in-unittests-more-clear.patch \
|
||||
file://0007-lib-gpt-Provide-macro-identifying-free-space.patch \
|
||||
file://0008-lib-gpt-Add-operation-to-duplicate-entries.patch \
|
||||
file://0009-lib-gpt-Consecutively-erase-blocks-when-moving-parti.patch \
|
||||
file://0010-lib-gpt-Clarify-API-operation.patch \
|
||||
file://0011-lib-gpt-Add-metadata-only-API-operations.patch \
|
||||
file://0012-plat-cs1k-Add-flash-erase-protection.patch \
|
||||
file://0013-plat-cs1k-Remove-unused-FWU-partitions-upon-version-.patch \
|
||||
file://0014-plat-cs1k-Duplicate-old-images-in-FWU.patch \
|
||||
file://0015-platform-corstone1000-Increase-FIP-partition-size.patch \
|
||||
file://0016-platform-corstone1000-Optionally-skip-provisioning.patch \
|
||||
file://0001-arm-trusted-firmware-m-disable-address-warnings-into.patch \
|
||||
file://0002-Platform-CS1000-Remove-unused-BL1-files.patch \
|
||||
file://0003-Platform-Corstone1000-Fix-BL1-compiler-switch-and-re.patch \
|
||||
file://0004-CC312-alignment-of-cc312-differences-between-fvp-and.patch \
|
||||
file://0005-Platform-Corstone1000-Enable-FWU-partition.patch \
|
||||
file://0006-Platform-Corstone1000-Implement-Bootloader-Abstracti.patch \
|
||||
file://0007-Platform-Corstone1000-Increase-buffer-sizes.patch \
|
||||
file://0008-Platform-Corstone1000-Remove-duplicate-configuration.patch \
|
||||
file://0009-plat-corstone1000-Add-support-for-Cortex-A320-varian.patch \
|
||||
file://0010-Corstone-1000-Enable-different-DRBG-configurations.patch \
|
||||
file://0011-bl2-corstone-1000-Remove-psa_adac_to_tfm_apply_permi.patch \
|
||||
file://0012-bl2-corstone-1000-secure-debug-waiting-in-CM-LCS.patch \
|
||||
file://0013-Build-adjust-CS1000-platform-for-GCC-v14.2.patch \
|
||||
file://0014-Workaround-compile-errors-in-AES.patch \
|
||||
file://0015-CC312-Add-barrier-before-first-AO-lock-write.patch \
|
||||
file://0016-Platform-CS1K-make-mutlicore-support-platform-generi.patch \
|
||||
file://0017-lib-efi_guid-Added-EFI-GUID-library.patch \
|
||||
file://0018-lib-efi_soft_crc-Added-EFI-CRC-library.patch \
|
||||
file://0019-lib-gpt-Implemented-generic-GPT-parser-for-flash.patch \
|
||||
file://0020-lib-gpt-Expanded-how-GPT-partition-can-be-identified.patch \
|
||||
file://0021-lib-gpt-Added-operations-to-modify-partitions.patch \
|
||||
file://0022-lib-gpt-Added-operation-to-move-entry.patch \
|
||||
file://0023-lib-gpt-Added-ability-to-create-and-remove-partition.patch \
|
||||
file://0024-lib-gpt-Added-table-validation-operations.patch \
|
||||
file://0025-lib-gpt-Added-defragmentation-operation.patch \
|
||||
file://0026-lib-GPT-Fix-cppcheck-warnings.patch \
|
||||
file://0027-lib-efi_guid-Remove-unecessary-include-folder.patch \
|
||||
file://0028-lib-efi_guid-Correct-included-folder.patch \
|
||||
file://0029-lib-efi_soft_crc-Correct-include-directory.patch \
|
||||
file://0030-lib-gpt-Add-missing-link-library.patch \
|
||||
file://0031-lib-gpt-Correct-variable-name-used.patch \
|
||||
file://0032-lib-gpt-Correct-include-directory.patch \
|
||||
file://0033-lib-gpt-Move-contents-of-CMake-config-file.patch \
|
||||
file://0034-plat-cs1k-Fixed-formatting-errors.patch \
|
||||
file://0035-plat-cs1k-Removed-unused-variables.patch \
|
||||
file://0036-plat-cs1k-Fixed-bad-function-returns.patch \
|
||||
file://0037-plat-cs1k-Improved-logging-in-function.patch \
|
||||
file://0038-plat-cs1k-Remove-unused-function.patch \
|
||||
file://0039-plat-cs1k-Reduce-BL1-binary-size.patch \
|
||||
file://0040-plat-cs1k-Update-license-identifier.patch \
|
||||
file://0041-plat-cs1k-Changed-to-use-new-GPT-library.patch \
|
||||
file://0042-plat-cs1k-Move-variable-from-stack-to-data.patch \
|
||||
file://0043-plat-cs1k-Create-and-remove-FWU-image-partitions.patch \
|
||||
file://0044-plat-cs1k-Derive-host-base-addresses-from-offsets.patch \
|
||||
file://0045-plat-cs1k-Drive-NPU-via-external-system-reset-contro.patch \
|
||||
file://0046-lib-gpt-Fix-final-entry-not-being-removed.patch \
|
||||
file://0047-lib-gpt-Replace-warnings-with-errors.patch \
|
||||
file://0048-lib-gpt-Enforce-entry-size-of-128-bytes.patch \
|
||||
file://0049-lib-gpt-Ensure-block-size-complies-with-spec.patch \
|
||||
file://0050-lib-gpt-Expand-table-validation.patch \
|
||||
file://0051-lib-gpt-Show-intent-of-GUIDs-in-unittests-more-clear.patch \
|
||||
file://0052-lib-gpt-Provide-macro-identifying-free-space.patch \
|
||||
file://0053-lib-gpt-Add-operation-to-duplicate-entries.patch \
|
||||
file://0054-lib-gpt-Consecutively-erase-blocks-when-moving-parti.patch \
|
||||
file://0055-lib-gpt-Clarify-API-operation.patch \
|
||||
file://0056-lib-gpt-Add-metadata-only-API-operations.patch \
|
||||
file://0057-plat-cs1k-Add-flash-erase-protection.patch \
|
||||
file://0058-plat-cs1k-Remove-unused-FWU-partitions-upon-version-.patch \
|
||||
file://0059-plat-cs1k-Duplicate-old-images-in-FWU.patch \
|
||||
"
|
||||
|
||||
SRCREV_tfm-psa-adac:corstone1000 = "f2809ae231be33a1afcd7714f40756c67d846c88"
|
||||
FILESEXTRAPATHS:prepend:corstone1000-mps3 := "${THISDIR}/files/corstone1000/psa-adac:"
|
||||
SRC_URI:append:corstone1000-mps3 = " \
|
||||
file://0001-PSA-revert-header-versions.patch;patchdir=external/tfm-psa-adac \
|
||||
file://0002-cmake-Update-psa_adac_psa_crypto-dependencies.patch;patchdir=external/tfm-psa-adac \
|
||||
file://0002-Fix-psa_key_handle_t-initialization.patch;patchdir=external/tfm-psa-adac \
|
||||
file://0003-cmake-Update-psa_adac_psa_crypto-dependencies.patch;patchdir=external/tfm-psa-adac \
|
||||
file://0001-Build-Fix-compiler-warnings.patch;patchdir=external/tfm-psa-adac \
|
||||
"
|
||||
|
||||
create_bl1_image(){
|
||||
|
||||
@@ -86,23 +86,6 @@ SRC_URI:append = " \
|
||||
file://0040-configs-corstone1000-disable-EFI-debug-support.patch \
|
||||
"
|
||||
|
||||
# Add FF-A bus runtime support
|
||||
SRC_URI:append = " \
|
||||
file://0041-efi_loader-add-runtime-memset-helper.patch \
|
||||
file://0042-arm-ffa-add-FF-A-bus-runtime-support.patch \
|
||||
file://0043-efi_loader-add-FF-A-runtime-support-in-EFI-variable-.patch \
|
||||
file://0044-efi_loader-enable-EFI-runtime-SetVariable-GetVariabl.patch \
|
||||
file://0045-efi_loader-move-runtime-GetVariable-helpers-to-efi_v.patch \
|
||||
file://0046-corstone1000-enable-bootefi-selftest.patch \
|
||||
file://0047-efi-selftest-add-runtime-variable-tests-with-non-vol.patch \
|
||||
file://0048-test-dm-add-sandbox-FF-A-runtime-transport-tests.patch \
|
||||
file://0049-sandbox-ffa-share-synthetic-partition-metadata-via-m.patch \
|
||||
file://0050-doc-arm64-document-FF-A-runtime-path-for-EFI-variabl.patch \
|
||||
file://0051-doc-bootefi-note-two-phase-runtime-variables-selftes.patch \
|
||||
file://0052-efi_loader-align-FF-A-cache-maintenance-with-runtime.patch \
|
||||
file://0053-corstone1000-a320-enable-bootefi-selftest.patch \
|
||||
"
|
||||
|
||||
uboot_configure_config:append() {
|
||||
openssl req -x509 -sha256 -newkey rsa:2048 -subj /CN=CRT/ -keyout ${B}/CRT.key -out ${S}/CRT.crt -nodes -days 365
|
||||
}
|
||||
|
||||
+5
-5
@@ -1,4 +1,4 @@
|
||||
From 8113805be420994a67bde766f0100fc3c39e985e Mon Sep 17 00:00:00 2001
|
||||
From 891cef3c87081d0b719213c98cb2a50ecb601332 Mon Sep 17 00:00:00 2001
|
||||
From: Abdellatif El Khlifi <abdellatif.elkhlifi@arm.com>
|
||||
Date: Wed, 30 Oct 2024 14:10:43 +0000
|
||||
Subject: [PATCH] arm_ffa: Add NULL pointer check to the uclass driver
|
||||
@@ -18,7 +18,7 @@ Upstream-Status: Submitted [cover letter: https://lore.kernel.org/all/2025070215
|
||||
1 file changed, 10 insertions(+), 1 deletion(-)
|
||||
|
||||
diff --git a/drivers/firmware/arm-ffa/arm-ffa-uclass.c b/drivers/firmware/arm-ffa/arm-ffa-uclass.c
|
||||
index 76a8775e911..2f5fc879ff4 100644
|
||||
index 96c64964bb7..f8d231204db 100644
|
||||
--- a/drivers/firmware/arm-ffa/arm-ffa-uclass.c
|
||||
+++ b/drivers/firmware/arm-ffa/arm-ffa-uclass.c
|
||||
@@ -1,6 +1,6 @@
|
||||
@@ -29,7 +29,7 @@ index 76a8775e911..2f5fc879ff4 100644
|
||||
*
|
||||
* Authors:
|
||||
* Abdellatif El Khlifi <abdellatif.elkhlifi@arm.com>
|
||||
@@ -951,6 +951,9 @@ int ffa_partition_info_get(struct udevice *dev, const char *uuid_str,
|
||||
@@ -954,6 +954,9 @@ int ffa_partition_info_get(struct udevice *dev, const char *uuid_str,
|
||||
{
|
||||
struct ffa_bus_ops *ops = ffa_get_ops(dev);
|
||||
|
||||
@@ -39,7 +39,7 @@ index 76a8775e911..2f5fc879ff4 100644
|
||||
if (!ops->partition_info_get)
|
||||
return -ENOSYS;
|
||||
|
||||
@@ -976,6 +979,9 @@ int ffa_sync_send_receive(struct udevice *dev, u16 dst_part_id,
|
||||
@@ -979,6 +982,9 @@ int ffa_sync_send_receive(struct udevice *dev, u16 dst_part_id,
|
||||
{
|
||||
struct ffa_bus_ops *ops = ffa_get_ops(dev);
|
||||
|
||||
@@ -49,7 +49,7 @@ index 76a8775e911..2f5fc879ff4 100644
|
||||
if (!ops->sync_send_receive)
|
||||
return -ENOSYS;
|
||||
|
||||
@@ -997,6 +1003,9 @@ int ffa_rxtx_unmap(struct udevice *dev)
|
||||
@@ -1000,6 +1006,9 @@ int ffa_rxtx_unmap(struct udevice *dev)
|
||||
{
|
||||
struct ffa_bus_ops *ops = ffa_get_ops(dev);
|
||||
|
||||
|
||||
+7
-7
@@ -1,4 +1,4 @@
|
||||
From 05e6d6b8949eb00a1a22f75a53e005a8d9e3c87e Mon Sep 17 00:00:00 2001
|
||||
From d4dc79029ab883a5baa33fbecd5db20a93716172 Mon Sep 17 00:00:00 2001
|
||||
From: Abdellatif El Khlifi <abdellatif.elkhlifi@arm.com>
|
||||
Date: Tue, 29 Oct 2024 17:22:35 +0000
|
||||
Subject: [PATCH] arm_ffa: Add FFA_MEM_SHARE support
|
||||
@@ -48,10 +48,10 @@ index f966f8ba6af..3eec735d741 100644
|
||||
- FF-A bus discovery makes sure FF-A framework is responsive and compatible
|
||||
with the driver
|
||||
diff --git a/drivers/firmware/arm-ffa/arm-ffa-uclass.c b/drivers/firmware/arm-ffa/arm-ffa-uclass.c
|
||||
index 2f5fc879ff4..d09e31177d7 100644
|
||||
index f8d231204db..2ba0b925fa6 100644
|
||||
--- a/drivers/firmware/arm-ffa/arm-ffa-uclass.c
|
||||
+++ b/drivers/firmware/arm-ffa/arm-ffa-uclass.c
|
||||
@@ -92,6 +92,20 @@ static struct ffa_abi_errmap err_msg_map[FFA_ERRMAP_COUNT] = {
|
||||
@@ -95,6 +95,20 @@ static struct ffa_abi_errmap err_msg_map[FFA_ERRMAP_COUNT] = {
|
||||
"DENIED: Buffer pair already registered",
|
||||
},
|
||||
},
|
||||
@@ -72,7 +72,7 @@ index 2f5fc879ff4..d09e31177d7 100644
|
||||
};
|
||||
|
||||
/**
|
||||
@@ -926,6 +940,177 @@ int ffa_msg_send_direct_req_hdlr(struct udevice *dev, u16 dst_part_id,
|
||||
@@ -929,6 +943,177 @@ int ffa_msg_send_direct_req_hdlr(struct udevice *dev, u16 dst_part_id,
|
||||
return ffa_to_std_errno(ffa_errno);
|
||||
}
|
||||
|
||||
@@ -250,7 +250,7 @@ index 2f5fc879ff4..d09e31177d7 100644
|
||||
/* FF-A driver operations (used by clients for communicating with FF-A)*/
|
||||
|
||||
/**
|
||||
@@ -1012,6 +1197,31 @@ int ffa_rxtx_unmap(struct udevice *dev)
|
||||
@@ -1015,6 +1200,31 @@ int ffa_rxtx_unmap(struct udevice *dev)
|
||||
return ops->rxtx_unmap(dev);
|
||||
}
|
||||
|
||||
@@ -283,7 +283,7 @@ index 2f5fc879ff4..d09e31177d7 100644
|
||||
* ffa_do_probe() - probing FF-A framework
|
||||
* @dev: the FF-A bus device (arm_ffa)
|
||||
diff --git a/drivers/firmware/arm-ffa/arm-ffa.c b/drivers/firmware/arm-ffa/arm-ffa.c
|
||||
index 9e6b5dcc542..8f7c5794f95 100644
|
||||
index 94e6105cb38..df904cae412 100644
|
||||
--- a/drivers/firmware/arm-ffa/arm-ffa.c
|
||||
+++ b/drivers/firmware/arm-ffa/arm-ffa.c
|
||||
@@ -1,6 +1,6 @@
|
||||
@@ -294,7 +294,7 @@ index 9e6b5dcc542..8f7c5794f95 100644
|
||||
*
|
||||
* Authors:
|
||||
* Abdellatif El Khlifi <abdellatif.elkhlifi@arm.com>
|
||||
@@ -81,6 +81,7 @@ static const struct ffa_bus_ops ffa_ops = {
|
||||
@@ -84,6 +84,7 @@ static const struct ffa_bus_ops ffa_ops = {
|
||||
.partition_info_get = ffa_get_partitions_info_hdlr,
|
||||
.sync_send_receive = ffa_msg_send_direct_req_hdlr,
|
||||
.rxtx_unmap = ffa_unmap_rxtx_buffers_hdlr,
|
||||
|
||||
+7
-7
@@ -1,4 +1,4 @@
|
||||
From c26404d7403748b60e61205b68b08912c34f436d Mon Sep 17 00:00:00 2001
|
||||
From 4a608633474b545eac07c3e4dd27bdad7bdfb005 Mon Sep 17 00:00:00 2001
|
||||
From: Abdellatif El Khlifi <abdellatif.elkhlifi@arm.com>
|
||||
Date: Tue, 29 Oct 2024 17:24:43 +0000
|
||||
Subject: [PATCH] arm_ffa: Add FFA_MEM_RECLAIM support
|
||||
@@ -47,10 +47,10 @@ index 3eec735d741..d2c4fb49f79 100644
|
||||
- FF-A bus discovery makes sure FF-A framework is responsive and compatible
|
||||
with the driver
|
||||
diff --git a/drivers/firmware/arm-ffa/arm-ffa-uclass.c b/drivers/firmware/arm-ffa/arm-ffa-uclass.c
|
||||
index d09e31177d7..84023f6a94c 100644
|
||||
index 2ba0b925fa6..597b4e994b4 100644
|
||||
--- a/drivers/firmware/arm-ffa/arm-ffa-uclass.c
|
||||
+++ b/drivers/firmware/arm-ffa/arm-ffa-uclass.c
|
||||
@@ -106,6 +106,18 @@ static struct ffa_abi_errmap err_msg_map[FFA_ERRMAP_COUNT] = {
|
||||
@@ -109,6 +109,18 @@ static struct ffa_abi_errmap err_msg_map[FFA_ERRMAP_COUNT] = {
|
||||
"DENIED: Memory region ownership, permission, access or attributes error",
|
||||
},
|
||||
},
|
||||
@@ -69,7 +69,7 @@ index d09e31177d7..84023f6a94c 100644
|
||||
};
|
||||
|
||||
/**
|
||||
@@ -1111,6 +1123,44 @@ int ffa_memory_share_hdlr(struct udevice *dev, struct ffa_mem_ops_args *args)
|
||||
@@ -1114,6 +1126,44 @@ int ffa_memory_share_hdlr(struct udevice *dev, struct ffa_mem_ops_args *args)
|
||||
return ffa_memory_ops(dev, FFA_MEM_SHARE, args);
|
||||
}
|
||||
|
||||
@@ -114,7 +114,7 @@ index d09e31177d7..84023f6a94c 100644
|
||||
/* FF-A driver operations (used by clients for communicating with FF-A)*/
|
||||
|
||||
/**
|
||||
@@ -1222,6 +1272,32 @@ int ffa_memory_share(struct udevice *dev, struct ffa_mem_ops_args *args)
|
||||
@@ -1225,6 +1275,32 @@ int ffa_memory_share(struct udevice *dev, struct ffa_mem_ops_args *args)
|
||||
return ops->memory_share(dev, args);
|
||||
}
|
||||
|
||||
@@ -148,10 +148,10 @@ index d09e31177d7..84023f6a94c 100644
|
||||
* ffa_do_probe() - probing FF-A framework
|
||||
* @dev: the FF-A bus device (arm_ffa)
|
||||
diff --git a/drivers/firmware/arm-ffa/arm-ffa.c b/drivers/firmware/arm-ffa/arm-ffa.c
|
||||
index 8f7c5794f95..863dc7e5cac 100644
|
||||
index df904cae412..de36f5647d2 100644
|
||||
--- a/drivers/firmware/arm-ffa/arm-ffa.c
|
||||
+++ b/drivers/firmware/arm-ffa/arm-ffa.c
|
||||
@@ -82,6 +82,7 @@ static const struct ffa_bus_ops ffa_ops = {
|
||||
@@ -85,6 +85,7 @@ static const struct ffa_bus_ops ffa_ops = {
|
||||
.sync_send_receive = ffa_msg_send_direct_req_hdlr,
|
||||
.rxtx_unmap = ffa_unmap_rxtx_buffers_hdlr,
|
||||
.memory_share = ffa_memory_share_hdlr,
|
||||
|
||||
+3
-3
@@ -1,4 +1,4 @@
|
||||
From 1c41fc705dc986935000ecb49a167ab823b11116 Mon Sep 17 00:00:00 2001
|
||||
From 28ecd80dd073448b1ec200f1bf4b6c2c4659af16 Mon Sep 17 00:00:00 2001
|
||||
From: Abdellatif El Khlifi <abdellatif.elkhlifi@arm.com>
|
||||
Date: Thu, 17 Oct 2024 22:11:22 +0100
|
||||
Subject: [PATCH] arm_ffa: sandbox: Replace the emulator error log with debug
|
||||
@@ -17,7 +17,7 @@ Upstream-Status: Submitted [cover letter: https://lore.kernel.org/all/2025070215
|
||||
1 file changed, 2 insertions(+), 3 deletions(-)
|
||||
|
||||
diff --git a/drivers/firmware/arm-ffa/ffa-emul-uclass.c b/drivers/firmware/arm-ffa/ffa-emul-uclass.c
|
||||
index 6198d687354..954cada27ce 100644
|
||||
index 1521d9b66ac..d2f051f7e2a 100644
|
||||
--- a/drivers/firmware/arm-ffa/ffa-emul-uclass.c
|
||||
+++ b/drivers/firmware/arm-ffa/ffa-emul-uclass.c
|
||||
@@ -1,6 +1,6 @@
|
||||
@@ -28,7 +28,7 @@ index 6198d687354..954cada27ce 100644
|
||||
*
|
||||
* Authors:
|
||||
* Abdellatif El Khlifi <abdellatif.elkhlifi@arm.com>
|
||||
@@ -655,8 +655,7 @@ void sandbox_arm_ffa_smccc_smc(ffa_value_t *args, ffa_value_t *res)
|
||||
@@ -658,8 +658,7 @@ void sandbox_arm_ffa_smccc_smc(ffa_value_t *args, ffa_value_t *res)
|
||||
args->a0);
|
||||
}
|
||||
|
||||
|
||||
+10
-10
@@ -1,4 +1,4 @@
|
||||
From eaa2884eef6015b530ea66317b908f035ce73124 Mon Sep 17 00:00:00 2001
|
||||
From 962b8b4f2baf4a84de1fc76382ef7aa240ec1534 Mon Sep 17 00:00:00 2001
|
||||
From: Abdellatif El Khlifi <abdellatif.elkhlifi@arm.com>
|
||||
Date: Tue, 11 Feb 2025 17:54:45 +0000
|
||||
Subject: [PATCH] arm_ffa: sandbox: Improve the readability of clearing the X
|
||||
@@ -40,10 +40,10 @@ index b0881822d78..5c46547beab 100644
|
||||
/* number of emulated FF-A secure partitions (SPs) */
|
||||
#define SANDBOX_PARTITIONS_CNT (4)
|
||||
diff --git a/drivers/firmware/arm-ffa/ffa-emul-uclass.c b/drivers/firmware/arm-ffa/ffa-emul-uclass.c
|
||||
index 954cada27ce..48b6d1fec2e 100644
|
||||
index d2f051f7e2a..dcf5bce9435 100644
|
||||
--- a/drivers/firmware/arm-ffa/ffa-emul-uclass.c
|
||||
+++ b/drivers/firmware/arm-ffa/ffa-emul-uclass.c
|
||||
@@ -80,7 +80,7 @@ static int sandbox_ffa_version(struct udevice *emul, ffa_value_t *pargs, ffa_val
|
||||
@@ -83,7 +83,7 @@ static int sandbox_ffa_version(struct udevice *emul, ffa_value_t *pargs, ffa_val
|
||||
res->a0 = priv->fwk_version;
|
||||
|
||||
/* x1-x7 MBZ */
|
||||
@@ -52,7 +52,7 @@ index 954cada27ce..48b6d1fec2e 100644
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -108,7 +108,7 @@ static int sandbox_ffa_id_get(struct udevice *emul, ffa_value_t *pargs, ffa_valu
|
||||
@@ -111,7 +111,7 @@ static int sandbox_ffa_id_get(struct udevice *emul, ffa_value_t *pargs, ffa_valu
|
||||
res->a2 = priv->id;
|
||||
|
||||
/* x3-x7 MBZ */
|
||||
@@ -61,7 +61,7 @@ index 954cada27ce..48b6d1fec2e 100644
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -133,14 +133,14 @@ static int sandbox_ffa_features(ffa_value_t *pargs, ffa_value_t *res)
|
||||
@@ -136,14 +136,14 @@ static int sandbox_ffa_features(ffa_value_t *pargs, ffa_value_t *res)
|
||||
res->a2 = RXTX_BUFFERS_MIN_SIZE;
|
||||
res->a3 = 0;
|
||||
/* x4-x7 MBZ */
|
||||
@@ -78,7 +78,7 @@ index 954cada27ce..48b6d1fec2e 100644
|
||||
log_err("FF-A interface %lx not implemented\n", pargs->a1);
|
||||
|
||||
return ffa_to_std_errmap[NOT_SUPPORTED];
|
||||
@@ -245,7 +245,7 @@ cleanup:
|
||||
@@ -248,7 +248,7 @@ cleanup:
|
||||
res->a1 = 0;
|
||||
|
||||
/* x3-x7 MBZ */
|
||||
@@ -87,7 +87,7 @@ index 954cada27ce..48b6d1fec2e 100644
|
||||
|
||||
return ret;
|
||||
}
|
||||
@@ -302,7 +302,7 @@ feedback:
|
||||
@@ -305,7 +305,7 @@ feedback:
|
||||
res->a1 = 0;
|
||||
|
||||
/* x3-x7 MBZ */
|
||||
@@ -96,7 +96,7 @@ index 954cada27ce..48b6d1fec2e 100644
|
||||
|
||||
return ret;
|
||||
}
|
||||
@@ -349,7 +349,7 @@ feedback:
|
||||
@@ -352,7 +352,7 @@ feedback:
|
||||
res->a1 = 0;
|
||||
|
||||
/* x3-x7 MBZ */
|
||||
@@ -105,7 +105,7 @@ index 954cada27ce..48b6d1fec2e 100644
|
||||
|
||||
return ret;
|
||||
}
|
||||
@@ -385,7 +385,7 @@ static int sandbox_ffa_rx_release(struct udevice *emul, ffa_value_t *pargs, ffa_
|
||||
@@ -388,7 +388,7 @@ static int sandbox_ffa_rx_release(struct udevice *emul, ffa_value_t *pargs, ffa_
|
||||
res->a1 = 0;
|
||||
|
||||
/* x3-x7 MBZ */
|
||||
@@ -114,7 +114,7 @@ index 954cada27ce..48b6d1fec2e 100644
|
||||
|
||||
return ret;
|
||||
}
|
||||
@@ -445,7 +445,7 @@ static int sandbox_ffa_msg_send_direct_req(struct udevice *emul,
|
||||
@@ -448,7 +448,7 @@ static int sandbox_ffa_msg_send_direct_req(struct udevice *emul,
|
||||
res->a2 = -INVALID_PARAMETERS;
|
||||
|
||||
/* x3-x7 MBZ */
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user