Compare commits

..
Author SHA1 Message Date
Ross Burton 49a410f6d2 CI: move meta-oe to use blacksail branch
This now has a blacksail branch.

Signed-off-by: Ross Burton <ross.burton@arm.com>
Signed-off-by: Jon Mason <jon.mason@arm.com>
2026-10-12 09:45:50 -04:00
Jon Mason 52a0a3656d edk2: update to edk2-stable202608
Update edk2 and edk2-platforms from edk2-stable202605 to edk2-stable202608 tags.

Add a backport for the SmbiosType2Generator clang build failure
introduced by the newer edk2 release.

Remove the same patch from RDN2 and RDV2, where it is not
applicable because those platforms use an older SHA-based edk2
release.

Update SBSA-ACS to use the new edk2 release.

Signed-off-by: Jon Mason <jon.mason@arm.com>
2026-10-06 16:16:45 -04:00
Jon Mason 231cfdefd2 arm/trusted-firmware-m: update to 2.3.1
Update Trusted Firmware-M from 2.3.0 to the 2.3.1 release.
This requires rebasing corstone1000 patches

Signed-off-by: Jon Mason <jon.mason@arm.com>
2026-10-05 09:12:01 -04:00
Clement Faure c0a3d1ab0e arm-bsp/trusted-services: conditionally require platforms configuration file
Guard the inclusion of platform configuration files behind an override.
This prevents unwanted platform overrides from leaking in
DEVTOOL_EXTRA_OVERRIDES of other platform builds.

Signed-off-by: Clement Faure <clement.faure@arm.com>
Signed-off-by: Ross Burton <ross.burton@arm.com>
2026-10-02 12:07:38 +01:00
Jon Mason 7ad49af445 arm/trusted-firmware-a: update LTS to 2.14.9
Update the TF-A LTS recipes to the lts-v2.14.9 tag.

This release adds mbedTLS as a submodule, matching how newer TF-A releases
provide this dependency.  This is a change from earlier releases in the
2.14 LTS series and requires the mbedTLS sources to be fetched as part of
the TF-A source tree.

Also update fiptool-native to use the corresponding TF-A 2.14.9 revision.

Signed-off-by: Jon Mason <jon.mason@arm.com>
Signed-off-by: Ross Burton <ross.burton@arm.com>
2026-10-02 11:53:47 +01:00
Harsimran Singh Tungal a5bc7b39ec arm-bsp/trusted-firmware-m: corstone1000: backport Corstone-1000 security fixes
Backport two TF-M security fixes for the Corstone-1000 platform.

The fixes address vulnerabilities in the TF-M firmware and keep the
platform aligned with upstream TF-M security updates.

Signed-off-by: Harsimran Singh Tungal <harsimransingh.tungal@arm.com>
Signed-off-by: Ross Burton <ross.burton@arm.com>
2026-09-30 10:45:00 +01:00
Oscar Belshaw 3a97808a24 arm-bsp/corstone1000: update TF-A to 2.15.0
Select the TF-A and TF-A Tests 2.15 release series for Corstone1000 and
update the FPGA and Cortex-A320 FVP documentation to reference the
2.15.0 recipe.

Remove the TF-A Cortex-A320 and multicore patches and the TF-A Tests
Cortex-A320 patch, as these changes are included upstream. Drop the
obsolete TFA_MBEDTLS workaround.

Add a patch to align the BL configuration mapping with the enclosing
shared RAM page. ARM_FW_CONFIG_BASE follows the meminfo_t structure and
is not page aligned, causing mmap_add_region_check() to reject the
mapping with -EINVAL. Base the mapping at ARM_SHARED_RAM_BASE while
preserving the firmware configuration load address and reserved space.

Add a Corstone1000 BL2 hook that waits 25 ms after arm_io_setup() and
before common GPT initialization when RESET_TO_BL2 and ARM_GPT_SUPPORT
are enabled. Enable the system counter and initialize the delay timer
before waiting, since their common initialization occurs later. Apply
the hook to FPGA, Cortex-A35 FVP and Cortex-A320 FVP builds.

The delay works around invalid MBR signatures observed during early
flash access on MPS3 with TF-A 2.15. It retains the common GPT-before-MMU
ordering and existing reset handling. This is a temporary timing
workaround: the underlying cause remains under investigation, and
25 ms is a tested delay rather than a documented hardware requirement.

Change-Id: Ic57f6474c6019edd58caeca8e2751d05d17678c7
Signed-off-by: Oscar Belshaw <Oscar.Belshaw@arm.com>
Signed-off-by: Ross Burton <ross.burton@arm.com>
2026-09-30 10:44:33 +01:00
Harsimran Singh Tungal 02a2fa9662 arm/trusted-firmware-a: fix cot-dt2c parser failure
Provide a TF-A fix to normalise CoT DTS cell expressions before cot-dt2c
parses the generated descriptor.

This avoids build failures where cot-dt2c reports "not a valid CoT DT file"
when parsing arithmetic expressions in generated CoT descriptors.

Signed-off-by: Harsimran Singh Tungal <harsimransingh.tungal@arm.com>
Signed-off-by: Ross Burton <ross.burton@arm.com>
2026-09-29 14:38:01 +01:00
Ross Burton b8f83d0670 CI: use blacksail branches
OpenEmbedded Core is preparing to release and master has diverged. Until
we have also diverged, stick to the stable branches for oe-core and
bitbake.

meta-oe and meta-secure-core have not yet diverged, so they need to stay
on master for now.

Signed-off-by: Ross Burton <ross.burton@arm.com>
2026-09-25 09:23:56 +01:00
Ahmed Gomaa 954c8d5fee arm-bsp/trusted-firmware-m: corstone1000: avoid provisioning reset
Corstone-1000 performs PSA ADAC authentication while the device is
in CM. TF-M runtime provisioning then changes the lifecycle state and
resets the platform, which loses the authenticated debug permissions.

Add a Secure Debug build option that skips TF-M runtime provisioning.
This keeps the device in CM and avoids the provisioning reset until a
reset-safe design can preserve DCU_EN across reset and apply it from
BL2.

Update the Secure Debug guide to use Arm Development Studio's built-in
PSA-ADAC manager and obtain test credentials without building the
external SDM library. Document the connection setup and verify that
the system boots after authentication.

Signed-off-by: Ahmed Gomaa <ahmed.gomaa@arm.com>
2026-09-24 08:46:49 -04:00
Ahmed Gomaa 130e764b78 arm-bsp/trusted-firmware-m: corstone1000: bump to 2.3.0
Select TF-M and its native scripts at version 2.3 for both
Corstone-1000 and Corstone-1000-A320.

Remove 45 obsolete TF-M patches and two obsolete PSA-ADAC patches,
47 in total. Refresh three retained TF-M patches and renumber the
remaining series: 15 TF-M patches and two PSA-ADAC patches.

Drop the Corstone-specific PSA-ADAC revision override to use the
revision pinned by the generic TF-M 2.3 recipe, which includes the
required Corstone-1000 Secure Debug fixes.

Configure Corstone-1000 image signing with the TF-M default non-secure
PSA key ID required by TF-M 2.3 image verification. Without this
metadata, BL2 cannot select the expected built-in verification key.

Update the user guide recipe references to TF-M 2.3.0.

Signed-off-by: Ahmed Gomaa <ahmed.gomaa@arm.com>
2026-09-24 08:46:49 -04:00
Ahmed Gomaa dc85142cae arm/trusted-firmware-m: add TF-M 2.3 signing support
TF-M 2.3 packages its image-signing wrapper as the
mcuboot_imagesign_wrapper console command. Add the required native
Python runtime dependencies and install the bundled MCUboot PEM
signing keys in the native sysroot.

Install TF-M's patched MCUboot imgtool package, including its
imgtool.keys Python modules for loading and handling cryptographic
keys. These modules are part of the signing tool implementation,
separate from the PEM signing-key files installed above.

Prefer this patched package through PYTHONPATH because it supports
PSA key IDs and writes them into signed image metadata.

Update tfm_sign_image.bbclass to invoke the console command when
available, retaining wrapper.py as a fallback for older TF-M versions.
Add optional PSA key ID arguments so platforms can provide the
identifier expected by BL2 during image verification.

Signed-off-by: Ahmed Gomaa <ahmed.gomaa@arm.com>
2026-09-24 08:46:49 -04:00
Ross Burton 77efb76ff2 meta-*: change layer compatibility to blacksail
The upcoming 6.1 release is codenamed blacksail, so set that as the
layer compatibility.  We can't also claim to be compatible with wrynose
as apart from potential dependency issues, the LICENSE changes mean this
layer will not parse successfully.

Signed-off-by: Ross Burton <ross.burton@arm.com>
2026-09-23 14:26:16 +01:00
Harsimran Singh Tungal 7f9ee424de arm-bsp/u-boot: Remove u-boot recipe u-boot_2025.10.bb
Remove the u-boot recipe u-boot_2025.10.bb as new u-boot version
2026.07 is available in core.

Signed-off-by: Alex Chapman <alex.chapman@arm.com>
Signed-off-by: Harsimran Singh Tungal <harsimransingh.tungal@arm.com>
Signed-off-by: Jon Mason <jon.mason@arm.com>
2026-09-17 08:00:05 -04:00
Harsimran Singh Tungal 57d9235d97 arm-bsp/u-boot: corstone1000: Upgrade to v2026.07
- Bump CS1K and CS1K-A320 to U-Boot v2026.07.
- Refactor patches 0001->0006, 0008, 0010, 0012->0017,
  0020->0022, 0024->0030, 0034, 0037, 0039->0042, 0045->0050.
- Remove patch 0053 and renumber patch 0054 as 0053.
- Use the upstream recipe and update the documentation.

Wrynose provides v2026.07, replacing the custom v2025.10 recipe.

Signed-off-by: Alex Chapman <alex.chapman@arm.com>
Signed-off-by: Harsimran Singh Tungal <harsimransingh.tungal@arm.com>
Signed-off-by: Jon Mason <jon.mason@arm.com>
2026-09-17 08:00:05 -04:00
Jon Mason 5e9a3230e7 arm-bsp: ignore benign parselogs error on rdn2 and rdv2
The latest kernel produces the following ACPI message on rdn2 and
rdv2:

ACPI: PNP0A08:03: _OSC: platform retains control of PCIe features (AE_ERROR)

This message is benign, but causes the parselogs test in testimage to
fail. Add it to the list of ignored errors for both platforms.

Signed-off-by: Jon Mason <jon.mason@arm.com>
2026-09-16 13:00:05 -04:00
Jon Mason 351ba71364 arm-bsp/sbsa-ref: add e1000e to kernel config
Recent changes to the arm64 kernel defconfig changed CONFIG_E1000E from
built-in to a module. This breaks testimage networking on the SBSA
Reference platform.

testimage provides the target network configuration through the kernel
“ip=” command-line option. The kernel needs the network driver to be
built-in in order to configure the interface from this option during
boot. With e1000e built as a module, the interface is not available at
that point and testimage is unable to establish an SSH connection to the
target.

Set CONFIG_E1000E=y in the sbsa-ref kernel configuration to make the
driver built-in again and restore testimage SSH testing.

Signed-off-by: Jon Mason <jon.mason@arm.com>
2026-09-14 18:00:03 -04:00
Gianluca Andreotti 063652ff6a arm/uefi_capsule: Generate signing PEMs in WORKDIR
GenerateCapsule expects a PEM that contains both the private key and the
matching certificate. The current capsule flow appends the certificate
to PAYLOAD_PRIVATE_KEY_PATH in place, which mutates the deployed key
file and adds another certificate block every time do_image_uefi_capsule
runs.

Prepare per-component signing PEMs under WORKDIR instead and pass those
files to the capsule JSON generator. This keeps the configured private
key unchanged, makes repeated capsule builds idempotent, and provides
GenerateCapsule with the combined key and certificate input it requires.

Rename the helper's primary signing input from --private_keys to
--signing_pems to reflect the actual input format, while keeping
--private_keys as a compatibility alias.

Generating the signing PEMs per component also allows each capsule
payload to use its own private key and matching certificate instead of
relying on a single mutated key file.

Use expr for the signing PEM counter because the BitBake shell parser
does not support arithmetic expansion.

Signed-off-by: Gianluca Andreotti <gianluca.andreotti@arm.com>
Signed-off-by: Jon Mason <jon.mason@arm.com>
2026-09-10 00:53:12 -04:00
Oscar Belshaw 629d62bcaa arm-bsp/corstone1000: update OP-TEE to 4.10.0
Update Corstone-1000 to OP-TEE 4.10.0.

Removed the local 4.9.0 recipes and patches that are included
upstream in 4.10.0.

Tested on the Corstone-1000 Cortex-A35 and Cortex-A320 FVPs.

Signed-off-by: Oscar Belshaw <Oscar.Belshaw@arm.com>
Signed-off-by: Jon Mason <jon.mason@arm.com>
2026-09-10 00:53:12 -04:00
Rasmus Villemoes 9cbedaf381 optee-ftpm: rewrite its optee-os bbappend to use EARLY_TA_PATHS bitbake variable
If anything else in the BSP also wants or needs to add an early TA to
optee, that will conflict with this .bbappend adding its own
EARLY_TA_PATHS="..." argument to EXTRA_OEMAKE.

Instead, add the path to the ftpm TA to the newly introduced
EARLY_TA_PATHS bitbake variable, which the main recipe will use to
produce the make argument.

Passing CFG_EARLY_TA=y explicitly is not needed, as optee-os' build
system sets that automatically if the EARLY_TA_PATHS list is
non-empty.

CFG_CORE_HEAP_SIZE is somewhat harder to make play along nicely with
other .bbappends that might have an opinion on its proper (minimum)
value. For now, keep adding it explicitly to EXTRA_OEMAKE.

Signed-off-by: Rasmus Villemoes <ravi@prevas.dk>
Signed-off-by: Jon Mason <jon.mason@arm.com>
2026-09-10 00:53:12 -04:00
Rasmus Villemoes 9414135734 optee-os: make early TAs more convenient to add for .bbappends
If two different .bbappends both try to add an "early TA" by appending
an EARLY_TA_PATHS="..." to EXTRA_OEMAKE, only one of them will
actually take effect.

For example, meta-arm itself has a .bbappend in optee-ftpm which adds
the ftpm TA if optee-ftpm is in MACHINE_FEATURES. If the BSP developer
wants to add another early TA, he has to take that into account and
very carefully ensure to create an EARLY_TA_PATHS="..." argument which
contains both the ftpm value as well as his desired extra TA.

Instead, let the main recipe define a variable which can simply be
appended to in the normal way, and which is used for deriving the
single EARLY_TA_PATHS="" argument in the make command line.

Handle the in-tree TAs similarly.

Signed-off-by: Rasmus Villemoes <ravi@prevas.dk>
Signed-off-by: Jon Mason <jon.mason@arm.com>
2026-09-10 00:53:12 -04:00
Ross Burton ade09d3a60 arm/fiptool: fix native linkage
The Makefiles in TF-A have changed since this recipe was last altered,
and our BUILD_LDFLAGS are no longer being respected. This means the built
objects don't have the correct RPATH, so they fail to run if the host
doesn't have libcrypto.so.4 (from OpenSSL 4) installed.

Pass all of our BUILD_* flags via HOSTCC*, and delete the now redundant
sed operations.

Signed-off-by: Ross Burton <ross.burton@arm.com>
Signed-off-by: Jon Mason <jon.mason@arm.com>
2026-09-09 20:29:19 -04:00
Ross Burton fede80de4c arm/trusted-firmware-a: enable OpenSSL stub engine API
The cert_create tool uses the OpenSSL engine API, which has been removed
from OpenSSL 4.  Enable the engine stubs to fix the build until this is
resolved upstream.

Also shoe-horn BUILD_CFLAGS into cert_create/Makefile, so the define is
passed to the build.

Signed-off-by: Ross Burton <ross.burton@arm.com>
Signed-off-by: Jon Mason <jon.mason@arm.com>
2026-09-09 20:29:19 -04:00
Ross Burton e54d151854 arm-bsp/u-boot: enable OpenSSL engine stub API
u-boot/lib/rsa/rsa-sign.c uses the OpenSSL engine API, but this has been
removed from OpenSSL 4. Patches are being worked on upstream and the
recipe in oe-core has those patches, but for ease we can simply enable
the stub API to fix the build until this old recipe is removed.

Signed-off-by: Ross Burton <ross.burton@arm.com>
Signed-off-by: Jon Mason <jon.mason@arm.com>
2026-09-09 20:29:19 -04:00
Jon Mason b0ff16aba4 arm/uefi-secureboot: fix race with secureboot keys
gen-sbkeys creates and installs the secure boot signing keys, certificates,
and database used by U-Boot and systemd-boot.  Both recipes require these
files during do_compile, but there was no dependency ensuring that
gen-sbkeys:do_install completed first.

Add an explicit do_compile dependency on gen-sbkeys:do_install for both
U-Boot and systemd-boot to prevent the race, which was causing intermittent
CI failures.

The uki.bbclass also requires the secure boot keys and certificates, but
depends on systemd-boot:do_deploy, which ensures the keys are available before
they are needed.

Issues being tracked in meta-secure-core
https://github.com/Wind-River/meta-secure-core/issues/145
https://github.com/Wind-River/meta-secure-core/issues/146

Signed-off-by: Jon Mason <jon.mason@arm.com>
2026-08-25 14:00:04 -04:00
Jaipaul Cheernam c6f7492f4a meta-arm: fix trailing whitespace
Bitbake now warns about trailing whitespace in parsed metadata lines.
Fix the affected files to silence the warnings during parsing.

Reported on:
https://autobuilder.yoctoproject.org/valkyrie/#/builders/75/builds/4317/steps/16/logs/warnings

Signed-off-by: Jaipaul Cheernam <jaipaul.cheernam@est.tech>
Signed-off-by: Jon Mason <jon.mason@arm.com>
2026-08-25 12:00:13 -04:00
Harsimran Singh Tungal 86b180b091 arm-bsp/linux: corstone1000: Enable CMA for Ethos-U
Enable CMA in the Corstone-1000 Ethos-U kernel configuration. Larger
Teflon model tests require reliable contiguous buffer allocation and
relies on kernel CMA support.

Signed-off-by: Harsimran Singh Tungal <harsimransingh.tungal@arm.com>
Signed-off-by: Jon Mason <jon.mason@arm.com>
2026-08-20 11:00:03 -04:00
Jon Mason 170b7e2a1c arm/fvps: change COMPATIBLE_HOST default
Make the COMPATIBLE_HOST in fvp-common.inc be both x86 and arm64, since
that is the large majority of the FVPs available.

Signed-off-by: Jon Mason <jon.mason@arm.com>
2026-08-10 14:00:04 -04:00
Jon Mason 683f9680f8 arm/fvps: remove unused files
fvp-envelope is no longer used and fvp-rdv1 and fvp-sgi575 no longer
have anything referencing them.

Signed-off-by: Jon Mason <jon.mason@arm.com>
2026-08-10 14:00:04 -04:00
Jon Mason c9b21728ab arm/fvp: Update FVP Base to 11.32.19
Update the fvp-base model recipe to version 11.32.19.

The new release changes the package layout and installation process,
requiring updates to the license checksums, source checksums, install
procedure, and FVP binary linking.

Signed-off-by: Jon Mason <jon.mason@arm.com>
2026-08-10 14:00:04 -04:00
Alex Chapman b08f6b0b5e arm-bsp/docs:corstone1000: Clarify secure debug setup
Replace the incomplete Arm Development Studio steps with the configuration database and hardware connection flow.

Initialize the required submodules and document that the Secure Debug Manager library must be built before importing the configuration.

Signed-off-by: Alex Chapman <alex.chapman@arm.com>
Signed-off-by: Jon Mason <jon.mason@arm.com>
2026-08-03 07:00:04 -04:00
Alex Chapman fba4a2d12b arm-bsp/docs:corstone1000/a320: Use kas shell for capsule generation
- Replace manual partial and rollback capsule generation with a kas
shell command
- Remove incorrect MPS3 capsule transfer instructions
- Fix broken MPS3 section header
- Update incorrect capsule amount in instructions

Shortens documentation and improves clarity in capsule generation,
making it easier to see how the partial and rollback capsules differ.

Also correct the capsule count in the test setup instructions.

Signed-off-by: Alex Chapman <alex.chapman@arm.com>
Signed-off-by: Jon Mason <jon.mason@arm.com>
2026-08-03 07:00:04 -04:00
Jon Mason fd397fc751 arm-bsp/firmware-image-juno: remove dependency on Linaro firmware archive
The Juno firmware recipe currently depends on the
juno-latest-oe-uboot.zip archive hosted on Linaro. That archive is no
longer available, making the recipe impossible to build from scratch.

Replace the archive dependency with the individual firmware files
required to recreate the original directory layout. The recipe now
assembles the firmware tree during do_install(), generating the small
board-specific differences where appropriate.

The original archive contained duplicate copies of mbb_v151.ebf,
io_b118.bit, and tapid.arm under the HBI0262B/C/D directories. The only
meaningful differences between those directories are the PMS firmware
filename and references to it, so the recipe generates the board-specific
files with sed rather than storing duplicate copies.

Similarly, the SITE1 images.txt files only differ in the referenced DTB,
so those are generated from a common template.

Signed-off-by: Jon Mason <jon.mason@arm.com>
2026-07-27 09:50:21 -04:00
Jon Mason 5ff5de465a arm-bsp/external-system: update HOMEPAGE
The HOMEPAGE variable was not updated when the SRC_URI was and it no
longer points to a valid webpage.

Signed-off-by: Jon Mason <jon.mason@arm.com>
2026-07-26 15:00:04 -04:00
Jon Mason 3f9a9c8c38 arm-bsp/corstone1000-external-sys-tests: update HOMEPAGE
The HOMEPAGE variable was not updated when the SRC_URI was and it no
longer points to a valid webpage.

Signed-off-by: Jon Mason <jon.mason@arm.com>
2026-07-26 15:00:04 -04:00
Ross Burton 167661762b arm/fvp-common: refresh LICENSE statement
Extract the full list of licenses from third_party_licenses.txt.

Signed-off-by: Ross Burton <ross.burton@arm.com>
Signed-off-by: Jon Mason <jon.mason@arm.com>
2026-07-22 11:00:02 -04:00
Ross Burton 0bb23ce40d arm-toolchain/external-arm-toolchain: fix license
Part of the GCC license is -only, not -or-later.  Thanks to Denys
Dmytriyenko and Joshua Watt for their diligent review.

Signed-off-by: Ross Burton <ross.burton@arm.com>
Signed-off-by: Jon Mason <jon.mason@arm.com>
2026-07-22 11:00:02 -04:00
Ross Burton dc8a847b6b recipes: port LICENSE to SPDX
openembedded-core now parses the LICENSE field as a SPDX license
expression[1], so convert the license statements.

This is mostly replacing "&" with "AND", but we can also use "WITH" in
the GCC recipes.

[1] oe-core e9d424738d6 ("classes/conf/lib: Parse LICENSE as SPDX Expression")

Signed-off-by: Ross Burton <ross.burton@arm.com>
Signed-off-by: Jon Mason <jon.mason@arm.com>
2026-07-21 10:08:22 -04:00
Jon Mason 28606c7215 CI: fix sstate-mirror
We should be using OE_FRAGMENTS for the upstream sstate mirror, and
BB_HASHSERVE is in base.yml

Signed-off-by: Jon Mason <jon.mason@arm.com>
2026-07-14 12:00:03 -04:00
Jon Mason b4fbbaf196 arm/optee-ftpm: update recipe name
optee-ftpm tagged the 4.10 release, but had no functional changes (that
is, they tagged the same commit of 4.9.0 with 4.10.0).  Update the
recipe name to match the latest version, and not have people think that
one package was held back.

Also, modify the version checking to be less incorrect

Signed-off-by: Jon Mason <jon.mason@arm.com>
2026-07-14 10:00:08 -04:00
Jon Mason c2a169b18e arm/opencsd: update to 1.8.3
Signed-off-by: Jon Mason <jon.mason@arm.com>
2026-07-14 10:00:08 -04:00
Jon Mason ea93de35ae arm-bsp/external-system: update to the latest commit
The source tree is question is not tagged or branched with any version.
Update to the latest commit, change the recipe name to denote it is
'git' and not versioned, and fix the upgrade-status.  Also, update the
git URL.

Signed-off-by: Jon Mason <jon.mason@arm.com>
2026-07-14 10:00:05 -04:00
Jon Mason 82711f1a48 arm-bsp/corstone1000-external-sys-tests: update to the latest commit
The source tree is question is not tagged or branched with any version.
Update to the latest commit, change the recipe name to denote it is
'git' and not versioned, and fix the upgrade-status.  Also, update the
git URL.

Signed-off-by: Jon Mason <jon.mason@arm.com>
2026-07-14 10:00:05 -04:00
Jon Mason 451dfc3712 arm-toolchain: Update to new toolchain version
Update the recipes to the newest release.  Also, Arm Binary Toolchains
have moved to https://gitlab.arm.com/tooling/gnu-toolchains-for-arm

The new location has a new layout, which means the upstream version
check needs to change.  Unfortunately, they are not using tags, but do
seem to use branch names like a tag.  So, using that for the version
check.

Signed-off-by: Jon Mason <jon.mason@arm.com>
2026-07-14 10:00:03 -04:00
Jon Mason 9607ed4eee arm-bsp: Lengthen Boot timeout for rdv2/rdn2
CI is seeing intermittent boot test timeout errors, where the FVP is
almost to shell but times out before getting there.  To get around this,
lengthen the timeout to allow for more opportunity to complete
successfully.

By default, the timeout is 600 seconds.  Increase this by 50% to 900.

Signed-off-by: Jon Mason <jon.mason@arm.com>
2026-07-07 10:00:04 -04:00
Harsimran Singh Tungal 94e19cb2b9 ci: enable testimage coverage for Corstone-1000 A320 FVP
Update the Corstone-1000 A320 FVP CI matrix to run testimage jobs.

This enables testimage coverage for both the firmware-only and no-firmware
entries.

Signed-off-by: Harsimran Singh Tungal <harsimransingh.tungal@arm.com>
Signed-off-by: Jon Mason <jon.mason@arm.com>
2026-06-30 09:00:03 -04:00
Harsimran Singh Tungal 589e16aebc fvp:corstone1000-a320: update Corstone-1000 A320 FVP to 11.31
Update the Corstone-1000 with Cortex-A320 FVP recipe to use the
11.31.cs1000_a320_2 release from Arm Developer.

Switch the source URL to the new package layout, add the architecture-specific
download tokens, and update the x86_64 and aarch64 SHA256 checksums.

The new package extracts directly into the FVP install directory, so update the
install step and license paths accordingly.

Signed-off-by: Harsimran Singh Tungal <harsimransingh.tungal@arm.com>
Signed-off-by: Jon Mason <jon.mason@arm.com>
2026-06-30 09:00:03 -04:00
Harsimran Singh Tungal 793354dbf2 arm-bsp/documentation: corstone1000-a320: update 2026.05 wrynose release documentation
Update the Corstone-1000 with Cortex-A320 changelog, release notes,
user guide, tests documentation and metadata for the 2026.05 release.

Add the new 2026.05 changelog entry for the Corstone-1000 with
Cortex-A320 specific updates and align the component version tables and
Yocto distribution component versions with the current release content.

Refresh the user guide and tests documentation to align with the
2026.05 release state, including release tag references, recipe version
references, report links

Signed-off-by: Harsimran Singh Tungal <harsimransingh.tungal@arm.com>
Signed-off-by: Jon Mason <jon.mason@arm.com>
2026-06-30 09:00:03 -04:00
Harsimran Singh Tungal c6febbdd02 arm-bsp/documentation: corstone1000: update 2026.05 wrynose release documentation
Update the Corstone-1000 changelog, release notes and user guide for
the 2026.05 wrynose release.

Add the new 2026.05 changelog entry and capture the main release work,
including the component upgrades, TF-M GPT and PSA FWU changes, and the
updated SSH-enabled build flow.
Refresh the component version tables and Yocto distribution component
versions in changelog for the new release.

Update the user guide to align with the 2026.05 release branch and
documentation state, including the Yocto release name, recipe version
references, release tag references, and related asset and report links.

Signed-off-by: Harsimran Singh Tungal <harsimransingh.tungal@arm.com>
Signed-off-by: Jon Mason <jon.mason@arm.com>
2026-06-30 09:00:03 -04:00
Jon Mason 847af9c082 arm/u-boot: fix uefi-secureboot on u-boot v2026.04
u-boot v2026.04 changed to kbuild 6.1, which broke how ubootefi.var is
used.  Apply patch from u-boot mailing list to address the issue.

Signed-off-by: Jon Mason <jon.mason@arm.com>
2026-06-25 18:00:03 -04:00
Jon Mason 3681201897 arm/optee: update to 4.10.0
Update the recipes to 4.10.0 and update the git recipes to 4.10.0
Since corstone1000 is still using 4.9.0, move that to meta-arm-bsp

Signed-off-by: Jon Mason <jon.mason@arm.com>
2026-06-18 09:50:49 -04:00
Jon Mason 9014a4e935 arm/opencsd: upgrade to v1.8.2
Signed-off-by: Jon Mason <jon.mason@arm.com>
2026-06-18 09:50:49 -04:00
Jon Mason 200ccaa637 arm/uefi: update edk2-firmware to 202605
Update edk2-firmware to the latest release.
Of note, GCC5 make variable has been removed.  Use the GCC make variable
instead.  Also, these changes caused the need to modify the sbsa-acs
patches.

Signed-off-by: Jon Mason <jon.mason@arm.com>
2026-06-18 09:50:49 -04:00
Jon Mason cef3e3a22c arm/trusted-firmware-a: Update git recipe to the latest commit
Signed-off-by: Jon Mason <jon.mason@arm.com>
2026-06-18 09:50:49 -04:00
Jon Mason dd460eb29d arm/trusted-firmware-a: Update LTS to 2.14.2
Signed-off-by: Jon Mason <jon.mason@arm.com>
2026-06-18 09:50:49 -04:00
Jon Mason 66c46946f5 arm/trusted-firmware-a: remove older LTS versions
The policy in meta-arm is to only have the latest version and the
latest LTS version.  Remove all of the older LTS versions to comply with
this policy.

Signed-off-by: Jon Mason <jon.mason@arm.com>
2026-06-18 09:50:46 -04:00
Jon Mason f1098681f4 arm/trusted-firmware-a: Add support for v2.15.0
Add support for the newest release of TF-A.
mnedtls was made a git submodule, and moved location.  Given that this
will be the location going forward, I thought it best to change inc file
to point by default to the new location, and have the LTS versions to
point to the old location in their recipes.

Also, seeing some weird behavior with CPUs not coming on line in
sbsa-ref and qemuarm-secureboot.  So, pinning those back to the LTS
until they can be sorted out.

Signed-off-by: Jon Mason <jon.mason@arm.com>
2026-06-18 09:50:03 -04:00
Arthur Cassegrain 8df56513d9 arm/trusted-services: enable devtool modify for ts-psa-api-test
Place psa-arch-tests under ${S}/ts-external/psatest and update the
recipe paths to match.

This keeps the external source layout aligned with trusted-services,
updates the Corstone-1000 patch locations, and lets devtool modify work
against the same psa-arch-tests tree that CMake and
apply_local_src_patches use.

Signed-off-by: Arthur Cassegrain <arthur.cassegrain@arm.com>
Signed-off-by: Jon Mason <jon.mason@arm.com>
2026-06-17 09:13:31 -04:00
Jon Mason d718d02774 arm/trusted-firmware-m: remove 2.1.4
Remove the older LTS, since there is a policy of the most recent release
and the previous LTS.

Signed-off-by: Jon Mason <jon.mason@arm.com>
2026-06-17 09:13:31 -04:00
Jon Mason c5df984862 arm/trusted-firmware-m: Add 2.3.0 Support
Add recipes for newest version of tf-m.  Of note, mbedtls has been
removed in favor of the TF-PSA-Crypto library.  This is having a cascade
into the other recipes, with a removal from the core inc file and add of
the individual lines to the specific versions.

TF-PSA-Crypto is Apache 2.0 licensed.  So, no need to change the recipe
license field.

Signed-off-by: Jon Mason <jon.mason@arm.com>
2026-06-17 09:13:31 -04:00
Jon Mason 22de042eaf CI: use Musca S1 for LTS testing
In TF-M 2.3.0, Musca S1 was removed, but B1 is still present.  In an
effort to keep coverage, swapping S1 and B1.

Signed-off-by: Jon Mason <jon.mason@arm.com>
2026-06-17 09:13:31 -04:00
Ross Burton fe60f0804e CI: add option to control whether warnings should be fatal or not
Warnings being always fatal is quite anti-social because sometimes there
are temporary warnings that we don't want to break the CI.

Signed-off-by: Ross Burton <ross.burton@arm.com>
2026-06-16 16:51:12 +01:00
Ross Burton dea9d913d8 CI: use a single multiline script statement in .build
No change to the script, just formatting.

Signed-off-by: Ross Burton <ross.burton@arm.com>
2026-06-16 16:48:01 +01:00
Ross Burton c53fcf76e2 CI: default CACHE_DIR to CI_PROJECT_DIR
Set the default cache directory to be the build tree so we don't assume
anything about the runner environment by default.

After this change, runners that don't set CACHE_DIR will need to set it
explicltly in their variables.

Signed-off-by: Ross Burton <ross.burton@arm.com>
2026-06-16 16:42:24 +01:00
Ross Burton ab0930aa96 CI: remove cve.yml and NVDCVE_API_KEY
This yml fragment wasn't actually used by our CI, and the cve-check class
no longer exists.

Signed-off-by: Ross Burton <ross.burton@arm.com>
2026-06-16 16:39:25 +01:00
Jon Mason 9aaee17adb arm/scp-firmware: add CVE_PRODUCT
Per https://nvd.nist.gov/products/cpe/detail/593B1385-F4BE-452B-AE3B-51627F6CAE45
add CVE_PRODUCT entry.  Since there wasn't one existing, there is no
need to remove anything.

Signed-off-by: Jon Mason <jon.mason@arm.com>
2026-06-11 10:12:32 -04:00
Jon Mason d0b93e582c arm/trusted-firmware-m: add CVE_PRODUCT
Per https://nvd.nist.gov/products/cpe/detail/C0F7CF14-9ACD-42C5-A1F8-839937F8C4DC
add CVE_PRODUCT entry.  Since there wasn't one existing, there is no
need to remove anything.

Signed-off-by: Jon Mason <jon.mason@arm.com>
2026-06-11 10:12:32 -04:00
Jon Mason e2e63f20b5 arm/trusted-firmware-a: modify CVE_PRODUCT
Per https://nvd.nist.gov/products/cpe/detail/2E1BD3E8-DF65-42E3-A0BA-747137D6DEF2
Adding "trustedfirmware:trusted_firmware-a"

We can probably remove "arm:trusted_firmware-a", since it has been
depreciated.  Fearing unintended issues, leaving it in for now.

Signed-off-by: Jon Mason <jon.mason@arm.com>
2026-06-11 10:12:32 -04:00
Jon Mason 81f5a92193 arm/optee: modify CVE_PRODUCT
Per https://nvd.nist.gov/products/cpe/detail/EB42962B-24FD-4716-B3E2-69F3258A57CF
adding "trustedfirmware:op-tee"

We can probably remove "linaro:op-tee", since it has been depreciated.
Fearing unintended issues, leaving it in for now.

Signed-off-by: Jon Mason <jon.mason@arm.com>
2026-06-11 10:12:32 -04:00
Jon Mason 02d361b435 arm/ts-sp-common: Workaround unused-but-set-variable errors
With the new GCC, we're seeing the following error:
| In file included from /builder/meta-arm/build/tmp/work/armv8-5a-poky-linux/ts-sp-smm-gateway/git/sources/ts/components/common/dlmalloc/malloc_wrapper.c:62:
| /builder/meta-arm/build/tmp/work/armv8-5a-poky-linux/ts-sp-smm-gateway/git/sources/ts/components/common/dlmalloc/malloc.c: In function 'add_segment':
| /builder/meta-arm/build/tmp/work/armv8-5a-poky-linux/ts-sp-smm-gateway/git/sources/ts/components/common/dlmalloc/malloc.c:4002:7: error: variable 'nfences' set but not used [-Werror=unused-but-set-variable=]
|  4002 |   int nfences = 0;
|       |       ^~~~~~~

To workaround this issue, add "-Wno-error=unused-but-set-variable" to TARGET_CFLAGS

Signed-off-by: Jon Mason <jon.mason@arm.com>
2026-06-02 09:00:04 -04:00
Jon Mason f23b86a59c arm/tf-a-tests: Workaround GCC errors for 'unused-but-set-variable'
New GCC is logging errors for unused-but-set-variable in
tftf/tests/runtime_services/standard_service/psci/api_tests/psci_stat/test_psci_stat.c

Workaround this by adding -Wno-unused-but-set-variable to the Makefile
Refer to https://github.com/TrustedFirmware-A/tf-a-tests/issues/4
For the upstream resolution, if/when that arrives.

Signed-off-by: Jon Mason <jon.mason@arm.com>
2026-06-02 09:00:04 -04:00
Michael Safwat 6e6567869f arm-bsp/docs: corstone1000-a320: Add standalone A320 documentation
Add a separate Corstone-1000 Armv9-A Edge-AI documentation
set for the Cortex-A320 platform.

Populate the new documentation tree with the initial index,
user guide, software architecture, release notes, change log,
and supporting images.

Keep common Corstone-1000 material in the existing documentation
set and move A320-specific content into the new standalone
document set.

Signed-off-by: Michael Safwat <michael.safwat@arm.com>
Signed-off-by: Lisa Durbin <lisa.durbin@arm.com>
Signed-off-by: Alex Chapman <alex.chapman@arm.com>
Signed-off-by: Hugues KAMBA MPIANA <hugues.kambampiana@arm.com>
2026-05-28 09:47:59 -04:00
Michael Safwat 6ab14ea640 runfvp: add --dry-run option
Add a --dry-run option to scripts/runfvp to print the constructed
FVP command line and exit without launching the model.

This is useful for checking parameters and reusing them with different
FVP binaries.

Signed-off-by: Michael Safwat <michael.safwat@arm.com>
Signed-off-by: Jon Mason <jon.mason@arm.com>
2026-05-28 05:00:03 -04:00
Gyorgy Sarvari 3c07303388 arm/trusted-firmware-a: don't set LD if LTO is enabled
Some platforms (like Allwinner A64/sun50i_a64) have LTO enabled
in the Makefiles, which causes a linking error when using ld:

| [...]/aarch64-oe-linux/aarch64-oe-linux-ld: -f may not be used without -shared

Add an option to be able to indicate in the recipe if the plaform has LTO enabled,
and only pass LD to make in case LTO is disabled, otherwise let it use $CC (as set by the Makefile).

The option is disabled by default to keep the existing behavior.

Signed-off-by: Gyorgy Sarvari <skandigraun@gmail.com>
Signed-off-by: Jon Mason <jon.mason@arm.com>
2026-05-24 07:00:05 -04:00
Alex Chapman ce5b4c4b0a arm/edk2-basetools-native: Add missing libuuid dependency
GenFv requires libuuid in the native sysroot.

Add util-linux-libuuid-native and pass required flags through to the
BaseTools makefiles. This can be missed on machines with libuuid
headers installed, as the build may find the host copy instead.

Signed-off-by: Alex Chapman <alex.chapman@arm.com>
Signed-off-by: Jon Mason <jon.mason@arm.com>
2026-05-20 10:00:03 -04:00
Marek Bykowski e04ac672d5 arm-bsp: use IMAGE_LINK_NAME for FVP disk image path
${IMAGE_NAME} expands to a timestamped filename which gets written into
the .fvpconf. A mismatch occurs when do_image reruns (regenerating the
.fvpconf with a new timestamp) but do_image_wic hits sstate (leaving the
old .wic on disk), causing the FVP to fail at startup with:

  Can't stat <image>-<timestamp>.wic! (error 2)

Use IMAGE_LINK_NAME instead, which is the stable symlink that always
points to the most recently built .wic.

Signed-off-by: Marek Bykowski <marek.bykowski@gmail.com>
Signed-off-by: Jon Mason <jon.mason@arm.com>
2026-05-19 12:00:03 -04:00
Michael Safwat 33cc743536 arm-bsp/docs: corstone1000: Drop A320 content from base documentation
Remove Cortex-A320-specific content from the base Corstone-1000
documentation.

Drop the A320-only sections, commands, notes, and subsystem image from
the shared Corstone-1000 software architecture and user guide now that
the platform is documented in its own standalone document set.

Signed-off-by: Michael Safwat <michael.safwat@arm.com>
Signed-off-by: Jon Mason <jon.mason@arm.com>
2026-05-18 15:00:03 -04:00
Hugues KAMBA MPIANA dd2437f8d6 ci: Add Corstone-1000 with Cortex-A320 builds
Add CI coverage for the Corstone-1000 with Cortex-A320 FVP machine.

Build the Corstone-1000 with Cortex-A320 FVP with the firmware-only
configuration and run both `none` and `tftf`.
Also run `none` for the no-firmware build.

Signed-off-by: Alex Chapman <alex.chapman@arm.com>
Signed-off-by: Hugues KAMBA MPIANA <hugues.kambampiana@arm.com>
Signed-off-by: Jon Mason <jon.mason@arm.com>
2026-05-18 15:00:03 -04:00
Alex Chapman 7ea8654517 arm-bsp:corstone1000: Create a standalone corstone1000-a320-fvp machine
Add `corstone1000-a320-fvp` as a dedicated machine instead of enabling
the Cortex-A320 variant through a kas overlay on `corstone1000-fvp`.

Move the A320-specific machine features, overrides, FVP executable
selection, and Ethos-U85 configuration into the new machine
configuration. Keep the generic `corstone1000-fvp` machine focused on
the base FVP platform.

Update the A320 kas to use `corstone1000-a320-fvp` directly, and
allow pregenerated SSH host keys for the new virtual machine.

Signed-off-by: Alex Chapman <alex.chapman@arm.com>
Signed-off-by: Hugues KAMBA MPIANA <hugues.kambampiana@arm.com>
Signed-off-by: Jon Mason <jon.mason@arm.com>
2026-05-18 15:00:03 -04:00
Alex Chapman faaa3b84a4 arm-bsp/docs,kas:corstone1000: Add SSH image build support
Add a shared Corstone-1000 kas configuration for building SSH-enabled
mass storage images across the supported Corstone-1000 machines.

Enable Dropbear SSH in the mass storage OS image, add pregenerated SSH
host keys for FVP builds, and document the SSH image build flow in the
user guides.

SSH support is too large for the flash OS image, so provide a dedicated
`core-image-minimal` kas configuration for SSH-enabled mass storage
images instead.

Signed-off-by: Alex Chapman <alex.chapman@arm.com>
Signed-off-by: Hugues KAMBA MPIANA <hugues.kambampiana@arm.com>
Signed-off-by: Jon Mason <jon.mason@arm.com>
2026-05-18 15:00:03 -04:00
Alex Chapman 3f14fc635c arm-bsp/tf-a: corstone1000: Fix Cortex-A320 errata override
Fix the Corstone-1000 with Cortex-A320 override for the
Trusted Firmware-A errata list.
The override was misspelled as
`ENABLE_CORTEX_A35_ERRATA:cortexta320` instead of
`ENABLE_CORTEX_A35_ERRATA:cortexa320`.

Rename the list to `ENABLE_CORTEX_A_ERRATA`, since it is shared by
the Cortex-A35 and Cortex-A320 variants.

Signed-off-by: Alex Chapman <alex.chapman@arm.com>
Signed-off-by: Hugues KAMBA MPIANA <hugues.kambampiana@arm.com>
Signed-off-by: Jon Mason <jon.mason@arm.com>
2026-05-18 15:00:03 -04:00
Ross Burton 120782d5fe CI: use kas 5.2
Upgrade to the latest version of Kas.

Signed-off-by: Ross Burton <ross.burton@arm.com>
Signed-off-by: Jon Mason <jon.mason@arm.com>
2026-05-18 12:00:03 -04:00
Harsimran Singh Tungal 1843e9e2eb arm-bsp: corstone1000: Enable FF-A-backed EFI runtime variables and selftests
This series wires up Arm FF-A support for EFI runtime services by
factoring runtime-safe helpers into the FF-A bus, layer the EFI
variable TEE transport on top, and then rehome the helper exports
so there’s a single implementation shared between boot and
runtime paths. Corstone1000 enables the self-test command and
expands the runtime variable selftest so it exercises non-volatile
storage across reboots.

Key Changes
===========
 - Add the FF-A runtime transport patch stack to the corstone1000
   U-Boot recipe.

 - Enable EFI runtime variable handling over FF-A and include the
   bootefi selftests and sandbox FF-A runtime transport test.

 - Increase the FIP partition sizes from 2MiB to 2.5MiB
   and update TFA_FIP_RE_SIGN_BIN_SIZE from 0x00200000 to 0x00280000
   to reflect the new allocation. The size of u-boot-EFI-2025.10-r0.bin
   has increased from ~707KB to ~944KB following the FF-A/EFI runtime
   related changes. As this binary is packaged within the FIP, the
   overall signed FIP size has grown accordingly.

 - Add a Yocto patch to increase the FIP partition size from
   2MB to 2.5MB in the TF-M flash layout for Corstone-1000.

Signed-off-by: Harsimran Singh Tungal <harsimransingh.tungal@arm.com>
Signed-off-by: Jon Mason <jon.mason@arm.com>
2026-05-12 12:00:04 -04:00
David Hu da39013db9 arm/trusted-firmware-m: Enable regression test build
TF-M build system has introduced a ground-breaking change since v2.0.0.
Enable TF-M regression test build, following build instructions in TF-M
document [1].

Add the BUILD_REGRESSION_TESTS variable to enable regression test
builds. Individual regression test suites can be selected by
passing the appropriate TF-M CMake options through EXTRA_OECMAKE.
If regression test is enabled, build TF-M and tests from tf-m-tests
directory.

The build files for Normal World build will be installed.

[1]: https://trustedfirmware-m.readthedocs.io/en/latest/building/tests_build_instruction.html

Signed-off-by: David Hu <david.hu2@arm.com>
Signed-off-by: Gergely Kovacs <Gergely.Kovacs2@arm.com>
Signed-off-by: Jon Mason <jon.mason@arm.com>
2026-05-11 08:00:04 -04:00
Jon Mason 4112fda50b arm-bsp/edk2-firmware: workaround apcica changes
With the latest version of acpica (20260408), the following error is
being encountered in edk2 platforms for Arm SGI

| "iasl"  -p/builder/meta-arm/build/tmp/work/rdn2-poky-linux/edk2-firmware/202602/build/Build/RdN2/DEBUG_GCC5/AARCH64/Platform/ARM/SgiPkg/AcpiTables/RdN2AcpiTables/OUTPUT/./SsdtEvents.aml /builder/meta-arm/build/tmp/work/rdn2-poky-linux/edk2-firmware/202602/build/Build/RdN2/DEBUG_GCC5/AARCH64/Platform/ARM/SgiPkg/AcpiTables/RdN2AcpiTables/OUTPUT/./SsdtEvents.iiii
| /builder/meta-arm/build/tmp/work/rdn2-poky-linux/edk2-firmware/202602/build/Build/RdN2/DEBUG_GCC5/AARCH64/Platform/ARM/SgiPkg/AcpiTables/RdN2AcpiTables/OUTPUT/./SsdtEvents.iiii     61:       Printf ("GPIO0 Pin0 Toggled")
| Error    6010 -                                                                                                                                                                                  Internal compiler error ^  (Invalid parse opcode in OpcGenerateAmlOpcode)

Since this appears to be a debug message, and the relevant platforms are
a work in progress.  Work around this issue by removing the printf.

Signed-off-by: Jon Mason <jon.mason@arm.com>
2026-05-05 13:11:15 -04:00
Jon Mason f3a2db0561 arm-bsp/u-boot: Update fvp-base, juno, corstone1000 patches
Fuzz detected when applying patch.  Use devtool to update and clean-up
the relevant patches.

Signed-off-by: Jon Mason <jon.mason@arm.com>
2026-05-01 10:00:10 -04:00
Alex Chapman 3aa085566e arm-bsp/docs:corstone1000: Reduce sudo dependency in OOB tests
- Add `wic`` image manipulation requirement, `mtools`, to prerequisites
- switch the `kas` install step to a user-local virtual environment
  removing `sudo` requirement
- Add `wic` install step
- replaced the mount/unmount acs_results and capsule staging steps
  with non-`sudo` wic-based image manipulation.
- Adds guidance for using serial-console without `sudo`
- Standardise capsule transfer to the root of the BOOT partition
- Update docs to align with new non-`sudo` requirement for
  `create_keys_and_sign.sh` interactive script.

These updates remove several unnecessary `sudo`` dependencies when
running OOB CS1K testing.

Signed-off-by: Jon Mason <jon.mason@arm.com>
2026-05-01 10:00:03 -04:00
Alex Chapman 85bd24f7b0 arm-bsp/docs:corstone1000: Fix secure boot script path
- Use the correct `${WORKSPACE}` script path without the stray `./` prefix.

This avoids an invalid command path.

Signed-off-by: Jon Mason <jon.mason@arm.com>
2026-05-01 10:00:03 -04:00
271 changed files with 4912 additions and 22422 deletions

No files matched your search

+1 -1
View File
@@ -1,4 +1,4 @@
image: ${MIRROR_GHCR}/siemens/kas/kas:4.7
image: ${MIRROR_GHCR}/siemens/kas/kas:5.2
variables:
# These are needed as the k8s executor doesn't respect the container
+2 -2
View File
@@ -7,12 +7,12 @@ distro: poky
defaults:
repos:
branch: wrynose
branch: blacksail
repos:
bitbake:
url: https://git.openembedded.org/bitbake
branch: "2.18"
branch: "2.20"
layers:
bitbake: disabled
+4 -3
View File
@@ -5,6 +5,7 @@ header:
local_conf_header:
latest_revisions: |
PREFERRED_VERSION_trusted-firmware-a ?= "2.10.%"
PREFERRED_VERSION_tf-a-tests ?= "2.10.%"
PREFERRED_VERSION_trusted-firmware-m ?= "2.1.%"
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.%"
+1
View File
@@ -6,6 +6,7 @@ header:
repos:
meta-secure-core:
url: https://github.com/Wind-River/meta-secure-core.git
branch: master
layers:
meta-secure-core-common:
meta-signing-key:
-5
View File
@@ -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.1.%"
machine: musca-b1
target:
+5
View File
@@ -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.2.%"
machine: musca-s1
target:
+1 -3
View File
@@ -5,7 +5,5 @@ 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"
+3 -7
View File
@@ -5,25 +5,21 @@ distro: poky
defaults:
repos:
branch: wrynose
branch: master
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:
@@ -35,7 +31,7 @@ repos:
meta-openembedded:
url: https://git.openembedded.org/meta-openembedded
commit: 9af4488d46cb4fd4c0d2d64820c86225ebd6ac71
# commit: 461d85a1831318747af5abe86da193bcde3fd9b4
layers:
meta-oe:
meta-python:
@@ -43,7 +39,7 @@ repos:
meta-secure-core:
url: https://github.com/wind-river/meta-secure-core.git
commit: 07a99ae241acd488a2feda1ededf87dc70dfde80
# commit: 59d7e90542947c342098863b9998693ac79352b0
layers:
meta-secure-core-common:
meta-signing-key:
+1 -1
View File
@@ -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 = "wrynose"
LAYERSERIES_COMPAT_meta-arm-bsp = "blacksail"
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_NAME}.wic"
FVP_CONFIG[board.msd_mmc.p_mmc_file] ?= "${IMAGE_LINK_NAME}.wic"
# MMC2 card configuration
FVP_CONFIG[board.msd_mmc_2.card_type] ?= "SDHC"
+1 -1
View File
@@ -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_NAME}.wic"
FVP_CONFIG[bp.virtioblockdevice.image_path] ?= "${IMAGE_LINK_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,19 +5,20 @@ require ${TUNE_FILE}
MACHINEOVERRIDES =. "corstone1000:"
# TF-M
PREFERRED_VERSION_trusted-firmware-m ?= "2.2.%"
PREFERRED_VERSION_trusted-firmware-m ?= "2.3.%"
PREFERRED_VERSION_trusted-firmware-m-scripts-native ?= "2.3.%"
# TF-A
TFA_PLATFORM = "corstone1000"
PREFERRED_VERSION_trusted-firmware-a ?= "2.14.%"
PREFERRED_VERSION_tf-a-tests ?= "2.14.%"
PREFERRED_VERSION_trusted-firmware-a ?= "2.15.%"
PREFERRED_VERSION_tf-a-tests ?= "2.15.%"
TFA_BL2_BINARY = "bl2-corstone1000.bin"
TFA_FIP_BINARY = "fip-corstone1000.bin"
# optee
PREFERRED_VERSION_optee-os ?= "4.9.%"
PREFERRED_VERSION_optee-client ?= "4.9.%"
PREFERRED_VERSION_optee-os ?= "4.10.%"
PREFERRED_VERSION_optee-client ?= "4.10.%"
# Trusted Services
TS_PLATFORM = "arm/corstone1000"
@@ -26,7 +27,7 @@ TS_SP_SE_PROXY_CONFIG = "corstone1000"
MACHINE_FEATURES += "ts-smm-gateway ts-se-proxy"
# U-Boot
PREFERRED_VERSION_u-boot ?= "2025.10"
PREFERRED_VERSION_u-boot ?= "2026.07"
MACHINE_FEATURES += "efi"
EFI_PROVIDER ?= "grub-efi"
+6 -1
View File
@@ -49,10 +49,15 @@ 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_NAME}.wic"
FVP_CONFIG[board.virtioblockdevice.image_path] ?= "${IMAGE_LINK_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"
+6 -1
View File
@@ -51,10 +51,15 @@ 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_NAME}.wic"
FVP_CONFIG[board.virtioblockdevice.image_path] ?= "${IMAGE_LINK_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"
+2
View File
@@ -26,6 +26,8 @@ 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,20 +192,11 @@ The following payloads can be individually updated:
### Generate capsules {.reference}
[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`.
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.
:::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`
The capsule's default metadata 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}
@@ -222,116 +213,39 @@ 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:
```
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_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
```
Run the command below to generate the partial 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-partial-v7.uefi.capsule
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
'
```
The partial capsule will be located in the `${WORKSPACE}` directory.
The partial capsule will be located at
`${WORKSPACE}/build/tmp/deploy/images/corstone1000-a320-fvp/corstone1000-a320-fvp-v7.uefi.capsule`.
#### Invalid capsule {.reference}
#### Rollback 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.
Use the following commands to generate the `capsule_config.json` file, which is required by the EDK2 tool for capsule creation:
Run the command below to generate the rollback capsule:
```
cd ${WORKSPACE}
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
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
'
```
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.
The rollback capsule will be located at
`${WORKSPACE}/build/tmp/deploy/images/corstone1000-a320-fvp/corstone1000-a320-fvp-v5.uefi.capsule`.
### Transfer capsules to target {.reference}
@@ -369,8 +283,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}/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/
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/
sync
```
@@ -401,7 +315,7 @@ To run the test:
cd ${WORKSPACE} && tmux
```
2. Run the FVP within `tmux` with the IR prebuilt image which now also contains the two capsules:
2. Run the FVP within `tmux` with the IR prebuilt image which now also contains the three capsules:
```
kas shell meta-arm/kas/corstone1000-a320-fvp.yml:meta-arm/ci/debug.yml \
@@ -526,7 +440,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-partial-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-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.
@@ -57,7 +57,7 @@ Table: Trusted Firmware-A components
| Type | Path |
| --------- | ---------------------------------------------------------------------------------------------------------------- |
| bbappend | `${WORKSPACE}/meta-arm/meta-arm-bsp/recipes-bsp/trusted-firmware-a/trusted-firmware-a_%.bbappend` |
| Recipe | `${WORKSPACE}/meta-arm/meta-arm/recipes-bsp/trusted-firmware-a/trusted-firmware-a_2.14.1.bb` |
| Recipe | `${WORKSPACE}/meta-arm/meta-arm/recipes-bsp/trusted-firmware-a/trusted-firmware-a_2.15.0.bb` |
#### Trusted Services {.reference}
@@ -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.9.0.bb` |
| Recipe | `${WORKSPACE}/meta-arm/meta-arm/recipes-security/optee/optee-os_4.10.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}/meta-arm/meta-arm-bsp/recipes-bsp/u-boot/u-boot_2025.10.bb` |
| Recipe | `${WORKSPACE}/core/meta/recipes-bsp/u-boot/u-boot_2026.07.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.2.2.bb` |
| Recipe | `${WORKSPACE}/meta-arm/meta-arm/recipes-bsp/trusted-firmware-m/trusted-firmware-m_2.3.0.bb` |
## Build {.reference}
@@ -28,6 +28,7 @@ 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:
@@ -91,7 +92,7 @@ Host Processor Components
+----------+-------------------------------------------------------------------------------------------------------+
| bbappend | ``${WORKSPACE}/meta-arm/meta-arm-bsp/recipes-bsp/trusted-firmware-a/trusted-firmware-a_%.bbappend`` |
+----------+-------------------------------------------------------------------------------------------------------+
| Recipe | ``${WORKSPACE}/meta-arm/meta-arm/recipes-bsp/trusted-firmware-a/trusted-firmware-a_2.14.1.bb`` |
| Recipe | ``${WORKSPACE}/meta-arm/meta-arm/recipes-bsp/trusted-firmware-a/trusted-firmware-a_2.15.0.bb`` |
+----------+-------------------------------------------------------------------------------------------------------+
`Trusted Services <https://trusted-services.readthedocs.io/en/latest/index.html>`__
@@ -130,11 +131,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.9.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.10.0.bb`` |
+----------+-------------------------------------------------------------------------------------------+
`U-Boot <https://github.com/u-boot/u-boot.git>`__
=================================================
@@ -144,7 +145,7 @@ Host Processor Components
+----------+----------------------------------------------------------------------------------+
| bbappend | ``${WORKSPACE}/meta-arm/meta-arm-bsp/recipes-bsp/u-boot/u-boot_%.bbappend`` |
+----------+----------------------------------------------------------------------------------+
| Recipe | ``${WORKSPACE}/meta-arm/meta-arm-bsp/recipes-bsp/u-boot/u-boot_2025.10.bb`` |
| Recipe | ``${WORKSPACE}/core/meta/recipes-bsp/u-boot/u-boot_2026.07.bb`` |
+----------+----------------------------------------------------------------------------------+
Linux
@@ -172,7 +173,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.2.2.bb`` |
| Recipe | ``${WORKSPACE}/meta-arm/meta-arm/recipes-bsp/trusted-firmware-m/trusted-firmware-m_2.3.0.bb`` |
+----------+-------------------------------------------------------------------------------------------------------+
************************************
@@ -210,13 +211,22 @@ Build
mkdir ${WORKSPACE}
cd ${WORKSPACE}
#. Install kas version 4.4 with ``sudo`` rights.
#. Create a Python virtual environment and activate it.
.. code-block:: console
sudo pip3 install kas==4.4
python3 -m venv ${WORKSPACE}/venv_cs1k
source ${WORKSPACE}/venv_cs1k/bin/activate
Ensure the kas installation directory is visible on the ``$PATH`` environment variable.
#. 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.
#. Clone the `meta-arm` Yocto layer in the workspace ``${WORKSPACE}``.
@@ -439,6 +449,10 @@ 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
@@ -864,14 +878,15 @@ The results can be fetched from the `acs_results` folder in the ``BOOT`` partiti
.. note::
Access the `acs_results` folder in FVP by running the following commands:
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.
.. code-block:: console
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
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}
#####################################################
@@ -927,20 +942,11 @@ The following payloads can be individually updated:
Generate Capsules
*****************
`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``.
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.
.. 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``
The capsule's default metadata 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
@@ -959,118 +965,40 @@ 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
./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
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
'
The partial capsule will be located in the ``${WORKSPACE}`` directory.
The partial capsule will be located at
``${WORKSPACE}/build/tmp/deploy/images/corstone1000-${TARGET}/corstone1000-${TARGET}-v7.uefi.capsule``.
Invalid Capsule
===============
Rollback 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.
Use the following commands to generate the `capsule_config.json` file, which is required by the EDK2 tool for capsule creation:
Run the command below to generate the rollback capsule:
.. 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
'
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.
The rollback capsule will be located at
``${WORKSPACE}/build/tmp/deploy/images/corstone1000-${TARGET}/corstone1000-${TARGET}-v5.uefi.capsule``.
***************************
Transfer Capsules to Target
@@ -1079,76 +1007,48 @@ 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::
``/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.
The staging steps below are shared between ``mps3`` and ``fvp``.
#. 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.
FVP
===
MPS3
====
#. 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
#. 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}``.
************************
Run Capsule Update Tests
@@ -1172,7 +1072,7 @@ Positive Full Capsule Update Test
- MPS3:
#. Plug the prepared USB drive which has the IR prebuilt image and two capsules to the MPS3.
#. Plug the prepared USB drive which has the IR prebuilt image and three capsules to the MPS3.
#. Power cycle the MPS3.
- FVP:
@@ -1183,17 +1083,18 @@ Positive Full Capsule Update Test
cd ${WORKSPACE} && tmux
#. Run the FVP within ``tmux`` with the IR prebuilt image which now also contains the two capsules:
#. Run the FVP within ``tmux`` with the IR prebuilt image which now also contains the three 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_IMAGE_PATH}/ir-acs-live-image-generic-arm64.wic"
-- -C board.msd_mmc.p_mmc_file=${ACS_STAGED_IMAGE}"
.. warning::
``${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.
``${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.
#. 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).
@@ -1214,7 +1115,7 @@ Positive Full Capsule Update Test
.. code-block:: console
EFI/BOOT/app/CapsuleApp.efi EFI/BOOT/corstone1000-mps3-v6.uefi.capsule
EFI/BOOT/app/CapsuleApp.efi corstone1000-mps3-v6.uefi.capsule
- FVP:
@@ -1327,7 +1228,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}-partial-v7.uefi.capsule`` instead of ``corstone1000-${TARGET}-v6.uefi.capsule``.
``corstone1000-${TARGET}-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.
@@ -1368,7 +1269,7 @@ Rollback Protection Capsule Update Test
.. code-block:: console
EFI/BOOT/app/CapsuleApp.efi EFI/BOOT/corstone1000-mps3-v5.uefi.capsule
EFI/BOOT/app/CapsuleApp.efi corstone1000-mps3-v5.uefi.capsule
- FVP:
@@ -1683,6 +1584,10 @@ 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.
@@ -1903,19 +1808,17 @@ 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
****************************
@@ -2226,33 +2129,75 @@ 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/>`__
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_>`__.
#. 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 (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.
#. Clone the `Secure Debug Manager
<https://github.com/ARM-software/secure-debug-manager>`__
repository to obtain the dummy test credentials.
.. code-block:: console
cd ${WORKSPACE}
git clone https://github.com/ARM-software/secure-debug-manager.git
#. Navigate into the repository directory and checkout the specific commit in the listing below.
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``:
.. code-block:: console
cd ${WORKSPACE}/secure-debug-manager
git checkout b30d6496ca749123e86b39b161b9f70ef76106d6
export ARMDS_INSTALL_DIR=/opt/arm/developmentstudio_platinum-2026.b
export CS1000_ADAC_DB=${WORKSPACE}/armds-cs1000-adac611
#. Follow the instructions in the `Secure Debug Manager (PSA-ADAC / SDC-600)'s README <secure-debug-manager-repo-readme_>`__ for the development machine setup.
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"/>
#. Rebuild the software stack with Secure Debug.
@@ -2272,11 +2217,60 @@ and `Arm Development Studio <arm-ds-website_>`__ versions 2022.2, 2022.c, or 202
IComPortInit : 383 : warn : init : IComPortInit: Blocked reading LPH2RA
#. Connect the debug probe to the MPS3 using the 20-pin 1.27mm connector with the ``CS_20W_1.27MM silkscreen`` label.
#. Open a new Arm Development Studio IDE window and add the user configuration
database.
#. 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_>`__.
#. 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``.
#. Connect the debuger to the target using the debug configuration.
#. 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.
#. Provide the paths to the private key and trust chain certificate when asked by Arm Development Studio Console.
@@ -2285,21 +2279,21 @@ and `Arm Development Studio <arm-ds-website_>`__ versions 2022.2, 2022.c, or 202
...
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
...
#. 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``):
#. 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:
.. code-block:: console
...
boot_platform_init: Corstone-1000 Secure Debug is a success.
...
corstone1000-mps3 login:
--------------
@@ -2307,9 +2301,8 @@ and `Arm Development Studio <arm-ds-website_>`__ versions 2022.2, 2022.c, or 202
*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 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
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
# 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,2 +1,3 @@
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,2 +1,3 @@
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,17 +1,18 @@
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://git.linaro.org/landing-teams/working/arm/external-system.git"
HOMEPAGE = "https://gitlab.arm.com/arm-reference-solutions/corstone1000/external_system/rtx"
DEPENDS = "gcc-arm-none-eabi-native"
INHIBIT_DEFAULT_DEPS = "1"
LICENSE = "BSD-3-Clause & Apache-2.0"
LIC_FILES_CHKSUM = "file://license.md;md5=e44b2531cd6ffe9dece394dbe988d9a0 \
LICENSE = "Apache-2.0 AND BSD-3-Clause"
LIC_FILES_CHKSUM = "file://LICENSE;md5=e44b2531cd6ffe9dece394dbe988d9a0 \
file://cmsis/LICENSE.txt;md5=e3fc50a88d0a364313df4b21ef20c29e"
SRC_URI = "gitsm://git.gitlab.arm.com/arm-reference-solutions/corstone1000/external_system/rtx.git;protocol=https;branch=master \
SRC_URI = "gitsm://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 = "8c9dca74b104ff6c9722fb0738ba93dd3719c080"
PV .= "+git"
SRCREV = "3a38cef6e9582907ad6f79950e3d54330c9ab42c"
UPSTREAM_CHECK_COMMITS = "1"
COMPATIBLE_MACHINE = "(corstone1000)"
PACKAGE_ARCH = "${MACHINE_ARCH}"
@@ -160,9 +160,10 @@ 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 = "0x00200000"
TFA_FIP_RE_SIGN_BIN_SIZE = "0x00280000"
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() {
@@ -12,19 +12,27 @@ PACKAGE_ARCH = "${MACHINE_ARCH}"
COMPATIBLE_MACHINE = "juno"
LINARO_RELEASE = "19.06"
SRC_URI = "http://releases.linaro.org/members/arm/platforms/${LINARO_RELEASE}/juno-latest-oe-uboot.zip;subdir=${S} \
file://images-r0.txt \
file://images-r1.txt \
file://images-r2.txt \
SRC_URI = " \
file://mbb_v151.ebf \
file://io_b118.bit \
file://tapid.arm \
file://pms_v103.bin \
file://pms_v104.bin \
file://pms_v105.bin \
file://mb-board.txt \
file://site1-HBI0262B-board.txt \
file://site1-HBI0262C-board.txt \
file://site1-HBI0262D-board.txt \
file://site1-images.txt \
file://hdlcdclk.dat \
file://startup.nsh \
file://selftest \
file://config.txt \
file://uEnv.txt \
"
SRC_URI[md5sum] = "01b662b81fa409d55ff298238ad24003"
SRC_URI[sha256sum] = "b8a3909bb3bc4350a8771b863193a3e33b358e2a727624a77c9ecf13516cec82"
FIRMWARE_DIR = "juno-firmware-${LINARO_RELEASE}"
S = "${UNPACKDIR}/${FIRMWARE_DIR}"
FIRMWARE_DIR = "juno-firmware"
S = "${UNPACKDIR}"
inherit deploy nopackages
@@ -34,23 +42,63 @@ do_compile[noexec] = "1"
# The ${D} is used as a temporary directory and we don't generate any
# packages for this recipe.
do_install() {
cp -a ${S} ${D}/
install -d ${D}/${FIRMWARE_DIR}/
cp -f ${UNPACKDIR}/config.txt ${D}/${FIRMWARE_DIR}/
# Files in the MB directory are mostly the same, except for the PMS file and references to the PMS file by name
install -d ${D}/${FIRMWARE_DIR}/MB/HBI0262B/
cp -f ${UNPACKDIR}/mbb_v151.ebf ${D}/${FIRMWARE_DIR}/MB/HBI0262B/
cp -f ${UNPACKDIR}/io_b118.bit ${D}/${FIRMWARE_DIR}/MB/HBI0262B/
cp -f ${UNPACKDIR}/tapid.arm ${D}/${FIRMWARE_DIR}/MB/HBI0262B/
cp -f ${UNPACKDIR}/pms_v103.bin ${D}/${FIRMWARE_DIR}/MB/HBI0262B/
cp -f ${UNPACKDIR}/mb-board.txt ${D}/${FIRMWARE_DIR}/MB/HBI0262B/board.txt
install -d ${D}/${FIRMWARE_DIR}/MB/HBI0262C/
cp -f ${UNPACKDIR}/mbb_v151.ebf ${D}/${FIRMWARE_DIR}/MB/HBI0262C/
cp -f ${UNPACKDIR}/io_b118.bit ${D}/${FIRMWARE_DIR}/MB/HBI0262C/
cp -f ${UNPACKDIR}/tapid.arm ${D}/${FIRMWARE_DIR}/MB/HBI0262C/
cp -f ${UNPACKDIR}/pms_v104.bin ${D}/${FIRMWARE_DIR}/MB/HBI0262C/
sed 's/pms_v103/pms_v104/g' ${UNPACKDIR}/mb-board.txt > ${D}/${FIRMWARE_DIR}/MB/HBI0262C/board.txt
install -d ${D}/${FIRMWARE_DIR}/MB/HBI0262D/
cp -f ${UNPACKDIR}/mbb_v151.ebf ${D}/${FIRMWARE_DIR}/MB/HBI0262D/
cp -f ${UNPACKDIR}/io_b118.bit ${D}/${FIRMWARE_DIR}/MB/HBI0262D/
cp -f ${UNPACKDIR}/tapid.arm ${D}/${FIRMWARE_DIR}/MB/HBI0262D/
cp -f ${UNPACKDIR}/pms_v105.bin ${D}/${FIRMWARE_DIR}/MB/HBI0262D/
sed 's/pms_v103/pms_v105/g' ${UNPACKDIR}/mb-board.txt > ${D}/${FIRMWARE_DIR}/MB/HBI0262D/board.txt
# The SITE1 image files are mostly the same except for the DTB they reference
install -d ${D}/${FIRMWARE_DIR}/SITE1/HBI0262B/
cp -f ${UNPACKDIR}/site1-HBI0262B-board.txt ${D}/${FIRMWARE_DIR}/SITE1/HBI0262B/board.txt
cp -f ${UNPACKDIR}/site1-images.txt ${D}/${FIRMWARE_DIR}/SITE1/HBI0262B/images.txt
install -d ${D}/${FIRMWARE_DIR}/SITE1/HBI0262C/
cp -f ${UNPACKDIR}/site1-HBI0262C-board.txt ${D}/${FIRMWARE_DIR}/SITE1/HBI0262C/board.txt
sed 's/juno\.dtb/juno-r1.dtb/g' ${UNPACKDIR}/site1-images.txt > ${D}/${FIRMWARE_DIR}/SITE1/HBI0262C/images.txt
install -d ${D}/${FIRMWARE_DIR}/SITE1/HBI0262D/
cp -f ${UNPACKDIR}/site1-HBI0262D-board.txt ${D}/${FIRMWARE_DIR}/SITE1/HBI0262D/board.txt
sed 's/juno\.dtb/juno-r2.dtb/g' ${UNPACKDIR}/site1-images.txt > ${D}/${FIRMWARE_DIR}/SITE1/HBI0262D/images.txt
# The files in SOFTWARE are listed in the SITE1 board.txt file by name
install -d ${D}/${FIRMWARE_DIR}/SOFTWARE/
cp -f ${RECIPE_SYSROOT}/firmware/trusted-firmware-a/fip.bin \
${D}/${FIRMWARE_DIR}/SOFTWARE/fip.bin
cp -f ${RECIPE_SYSROOT}/firmware/trusted-firmware-a/bl1.bin \
${D}/${FIRMWARE_DIR}/SOFTWARE/bl1.bin
cp -f ${RECIPE_SYSROOT}/firmware/trusted-firmware-a/fip.bin \
${D}/${FIRMWARE_DIR}/SOFTWARE/fip.bin
cp -f ${UNPACKDIR}/hdlcdclk.dat ${D}/${FIRMWARE_DIR}/SOFTWARE/
cp -f ${RECIPE_SYSROOT}/firmware/scp-firmware/scp_romfw_bypass.bin \
${D}/${FIRMWARE_DIR}/SOFTWARE/scp_bl1.bin
cp -f ${UNPACKDIR}/startup.nsh ${D}/${FIRMWARE_DIR}/SOFTWARE/
cp -f ${UNPACKDIR}/selftest ${D}/${FIRMWARE_DIR}/SOFTWARE/
dd if=/dev/zero of="${D}/${FIRMWARE_DIR}/SOFTWARE/blank.img" bs=1024 count=192 status=none
# u-boot environment file
cp -f ${UNPACKDIR}/uEnv.txt ${D}/${FIRMWARE_DIR}/SOFTWARE/
# Juno images list file
cp -f ${UNPACKDIR}/images-r0.txt ${D}/${FIRMWARE_DIR}/SITE1/HBI0262B/images.txt
cp -f ${UNPACKDIR}/images-r1.txt ${D}/${FIRMWARE_DIR}/SITE1/HBI0262C/images.txt
cp -f ${UNPACKDIR}/images-r2.txt ${D}/${FIRMWARE_DIR}/SITE1/HBI0262D/images.txt
}
do_deploy() {
@@ -0,0 +1,28 @@
TITLE: V2M-Juno Configuration File
[CONFIGURATION]
AUTORUN: TRUE ;Auto Run from power on
TESTMENU: FALSE ;MB Peripheral Test Menu
UPDATE: FALSE ;Force JTAG and FPGA update to DBs
VERIFY: FALSE ;Force FPGA verify to DBs
DVIMODE: VGA ;VGA or SVGA or XGA or SXGA or UXGA
MBLOG: FALSE ;LOG MB MICRO in run mode FALSE/UART0/UART1
DBLOG: FALSE ;LOG DB MICRO in run mode FALSE/UART1 (when MBLOG is not UART1)
USERSWITCH: 00000000 ;UserSwitch[7:0] in binary
CONFSWITCH: 00000000 ;Configuration Switch[7:0] in binary, Core[0:1] Cluster[2]
ASSERTNPOR: TRUE ;External resets assert nPOR
WDTRESET: RESETMB ;Watchdog reset options NONE/RESETMB/RESETDB
PCIMASTER: DB1 ;Port Failover DB1/SL3
MASTERSITE: DB1 ;Boot Master DB1/SL3
REMOTE: NONE ;Selects remote command via USB or FTP NONE/USB/FTP
MCCMACADDRESS: 0xFFFFFFFFFFFF ;MCC MAC Address (must be even MAC address)
SMCMACADDRESS: 0xFFFFFFFFFFFF ;SMC MAC Address
HOSTNAME: V2M-JUNO-A2 ;Host name for FTP [15 characters max]
@@ -1,71 +0,0 @@
TITLE: Versatile Express Images Configuration File
[IMAGES]
TOTALIMAGES: 10 ;Number of Images (Max: 32)
NOR0UPDATE: AUTO ;Image Update:NONE/AUTO/FORCE
NOR0ADDRESS: 0x00000000 ;Image Flash Address
NOR0FILE: \SOFTWARE\fip.bin ;Image File Name
NOR0LOAD: 00000000 ;Image Load Address
NOR0ENTRY: 00000000 ;Image Entry Point
NOR1UPDATE: AUTO ;Image Update:NONE/AUTO/FORCE
NOR1ADDRESS: 0x03EC0000 ;Image Flash Address
NOR1FILE: \SOFTWARE\bl1.bin ;Image File Name
NOR1LOAD: 00000000 ;Image Load Address
NOR1ENTRY: 00000000 ;Image Entry Point
NOR2UPDATE: AUTO ;Image Update:NONE/AUTO/FORCE
NOR2ADDRESS: 0x00500000 ;Image Flash Address
NOR2FILE: \SOFTWARE\Image ;Image File Name
NOR2NAME: norkern ;Rename kernel to norkern
NOR2LOAD: 00000000 ;Image Load Address
NOR2ENTRY: 00000000 ;Image Entry Point
NOR3UPDATE: AUTO ;Image Update:NONE/AUTO/FORCE
NOR3ADDRESS: 0x03000000 ;Image Flash Address
NOR3FILE: \SOFTWARE\juno-r1.dtb ;Image File Name
NOR3NAME: board.dtb ;Specify target filename to preserve file extension
NOR3LOAD: 00000000 ;Image Load Address
NOR3ENTRY: 00000000 ;Image Entry Point
NOR4UPDATE: AUTO ;Image Update:NONE/AUTO/FORCE
NOR4ADDRESS: 0x030C0000 ;Image Flash Address
NOR4FILE: \SOFTWARE\hdlcdclk.dat ;Image File Name
NOR4LOAD: 00000000 ;Image Load Address
NOR4ENTRY: 00000000 ;Image Entry Point
NOR5UPDATE: AUTO ;Image Update:NONE/AUTO/FORCE
NOR5ADDRESS: 0x03E40000 ;Image Flash Address
NOR5FILE: \SOFTWARE\scp_bl1.bin ;Image File Name
NOR5LOAD: 00000000 ;Image Load Address
NOR5ENTRY: 00000000 ;Image Entry Point
NOR6UPDATE: AUTO ;Image Update:NONE/AUTO/FORCE
NOR6ADDRESS: 0x0BF00000 ;Image Flash Address
NOR6FILE: \SOFTWARE\startup.nsh ;Image File Name
NOR6NAME: startup.nsh
NOR6LOAD: 00000000 ;Image Load Address
NOR6ENTRY: 00000000 ;Image Entry Point
NOR7UPDATE: AUTO ;Image Update:NONE/AUTO/FORCE
NOR7ADDRESS: 0x0BFC0000 ;Image Flash Address
NOR7FILE: \SOFTWARE\blank.img ;Image File Name
NOR7NAME: BOOTENV
NOR7LOAD: 00000000 ;Image Load Address
NOR7ENTRY: 00000000 ;Image Entry Point
NOR8UPDATE: AUTO ;Image Update:NONE/AUTO/FORCE
NOR8ADDRESS: 0x03100000 ;Image Flash Address
NOR8FILE: \SOFTWARE\selftest ;Image File Name
NOR8LOAD: 00000000 ;Image Load Address
NOR8ENTRY: 00000000 ;Image Entry Point
NOR9UPDATE: AUTO ;Image Update:NONE/AUTO/FORCE
NOR9ADDRESS: 0x03180000 ;Image Flash Address
NOR9NAME: uEnv.txt
NOR9FILE: \SOFTWARE\uEnv.txt ;Image File Name
NOR9LOAD: 00000000 ;Image Load Address
NOR9ENTRY: 00000000 ;Image Entry Point
@@ -1,71 +0,0 @@
TITLE: Versatile Express Images Configuration File
[IMAGES]
TOTALIMAGES: 10 ;Number of Images (Max: 32)
NOR0UPDATE: AUTO ;Image Update:NONE/AUTO/FORCE
NOR0ADDRESS: 0x00000000 ;Image Flash Address
NOR0FILE: \SOFTWARE\fip.bin ;Image File Name
NOR0LOAD: 00000000 ;Image Load Address
NOR0ENTRY: 00000000 ;Image Entry Point
NOR1UPDATE: AUTO ;Image Update:NONE/AUTO/FORCE
NOR1ADDRESS: 0x03EC0000 ;Image Flash Address
NOR1FILE: \SOFTWARE\bl1.bin ;Image File Name
NOR1LOAD: 00000000 ;Image Load Address
NOR1ENTRY: 00000000 ;Image Entry Point
NOR2UPDATE: AUTO ;Image Update:NONE/AUTO/FORCE
NOR2ADDRESS: 0x00500000 ;Image Flash Address
NOR2FILE: \SOFTWARE\Image ;Image File Name
NOR2NAME: norkern ;Rename kernel to norkern
NOR2LOAD: 00000000 ;Image Load Address
NOR2ENTRY: 00000000 ;Image Entry Point
NOR3UPDATE: AUTO ;Image Update:NONE/AUTO/FORCE
NOR3ADDRESS: 0x03000000 ;Image Flash Address
NOR3FILE: \SOFTWARE\juno-r2.dtb ;Image File Name
NOR3NAME: board.dtb ;Specify target filename to preserve file extension
NOR3LOAD: 00000000 ;Image Load Address
NOR3ENTRY: 00000000 ;Image Entry Point
NOR4UPDATE: AUTO ;Image Update:NONE/AUTO/FORCE
NOR4ADDRESS: 0x030C0000 ;Image Flash Address
NOR4FILE: \SOFTWARE\hdlcdclk.dat ;Image File Name
NOR4LOAD: 00000000 ;Image Load Address
NOR4ENTRY: 00000000 ;Image Entry Point
NOR5UPDATE: AUTO ;Image Update:NONE/AUTO/FORCE
NOR5ADDRESS: 0x03E40000 ;Image Flash Address
NOR5FILE: \SOFTWARE\scp_bl1.bin ;Image File Name
NOR5LOAD: 00000000 ;Image Load Address
NOR5ENTRY: 00000000 ;Image Entry Point
NOR6UPDATE: AUTO ;Image Update:NONE/AUTO/FORCE
NOR6ADDRESS: 0x0BF00000 ;Image Flash Address
NOR6FILE: \SOFTWARE\startup.nsh ;Image File Name
NOR6NAME: startup.nsh
NOR6LOAD: 00000000 ;Image Load Address
NOR6ENTRY: 00000000 ;Image Entry Point
NOR7UPDATE: AUTO ;Image Update:NONE/AUTO/FORCE
NOR7ADDRESS: 0x0BFC0000 ;Image Flash Address
NOR7FILE: \SOFTWARE\blank.img ;Image File Name
NOR7NAME: BOOTENV
NOR7LOAD: 00000000 ;Image Load Address
NOR7ENTRY: 00000000 ;Image Entry Point
NOR8UPDATE: AUTO ;Image Update:NONE/AUTO/FORCE
NOR8ADDRESS: 0x03100000 ;Image Flash Address
NOR8FILE: \SOFTWARE\selftest ;Image File Name
NOR8LOAD: 00000000 ;Image Load Address
NOR8ENTRY: 00000000 ;Image Entry Point
NOR9UPDATE: AUTO ;Image Update:NONE/AUTO/FORCE
NOR9ADDRESS: 0x03180000 ;Image Flash Address
NOR9NAME: uEnv.txt
NOR9FILE: \SOFTWARE\uEnv.txt ;Image File Name
NOR9LOAD: 00000000 ;Image Load Address
NOR9ENTRY: 00000000 ;Image Entry Point
Binary file not shown.
@@ -0,0 +1,26 @@
BOARD: HBI0262
TITLE: MotherBoard Configuration File
[MCCS]
MBBIOS: mbb_v151.ebf ;MB BIOS IMAGE
[FPGAS]
MBIOFPGA: io_b118.bit ;MB IOFPGA
[PMIC]
MBPMIC: pms_v103.bin ;MB PMIC
[OSCCLKS]
TOTALOSCCLKS: 11
OSC0: 50.0 ;OSC0 Juno SYSREFCLK (System clock)
OSC1: 50.0 ;OSC1 Juno AONREFCLK (Always On)
OSC2: 50.0 ;OSC2 Juno PXLREFCLK (HS pixel clock)
OSC3: 47.5 ;OSC3 Juno PXCLKIN (LS pixel clock)
OSC4: 2.11 ;OSC4 Juno I2SCLK (Audio)
OSC5: 50.0 ;OSC5 Juno SMCMCLK (Static memory)
OSC6: 50.0 ;OSC6 Juno CA53 REF_CLK (RSVD)
OSC7: 50.0 ;OSC7 Juno CA57 REF_CLK (RSVD)
OSC8: 50.0 ;OSC8 Juno GPU REF_CLK (RSVD)
OSC9: 30.0 ;OSC9 IOFPGA BOOT (RSVD)
OSC10: 24.0 ;OSC10 IOFPGA UART (RSVD)
OSC11: 7.37 ;OSC11 Juno UARTCLK (UART clock)
Binary file not shown.
Binary file not shown.
Binary file not shown.
@@ -0,0 +1,22 @@
BOARD: HBI0262
TITLE: V2M-Juno DevChip Configuration File
[SCC REGISTERS]
TOTALSCCS: 12 ;Total Number of SCC registers
SCC: 0x054 0x0007FFFE ;Enable non-secure DMA operations
SCC: 0x05C 0x00FE001E ;Enable default GPU Texture Formats
SCC: 0x100 0x003F1000 ;A57 PLL Register 0 (800MHz)
SCC: 0x104 0x0001F300 ;A57 PLL Register 1
SCC: 0x108 0x00371000 ;A53 PLL Register 0 (700MHz)
SCC: 0x10C 0x0001B300 ;A53 PLL Register 1
SCC: 0x118 0x003F1000 ;SYS PLL Register 0 (1600MHz)
SCC: 0x11C 0x0001F100 ;SYS PLL Register 1
SCC: 0x0F8 0x0BEC0000 ;BL1 entry point
SCC: 0x0FC 0xABE40000 ;BL0 entry point
SCC: 0x00C 0x000000C2 ;Clock Control, TMIF2XCLK, Register 0xC1 = default
;[3:0] CLKSEL : 0 Output gated, 1 AON_REF_CLK, 2 SYSCLK
;[7:4] CLKDIV : Clock divider -1 (0 give a division of 1)
SCC: 0x010 0x000000C2 ;Clock Control, TSIF2XCLK, Register 0xC1 = default
;[3:0] CLKSEL : 0 Output gated, 1 AON_REF_CLK, 2 SYSCLK
;[7:4] CLKDIV : Clock divider -1 (0 give a division of 1)
@@ -0,0 +1,24 @@
BOARD: HBI0262
TITLE: V2M-Juno DevChip Configuration File
[SCC REGISTERS]
TOTALSCCS: 13 ;Total Number of SCC registers
SCC: 0x054 0x0007FFFE ;Enable non-secure DMA operations
SCC: 0x05C 0x00FE001E ;Enable default GPU Texture Formats
SCC: 0x100 0x003F1000 ;A57 PLL Register 0 (800MHz)
SCC: 0x104 0x0001F300 ;A57 PLL Register 1
SCC: 0x108 0x00331000 ;A53 PLL Register 0 (650MHz)
SCC: 0x10C 0x00019300 ;A53 PLL Register 1
SCC: 0x118 0x003F1000 ;SYS PLL Register 0 (1600MHz)
SCC: 0x11C 0x0001F100 ;SYS PLL Register 1
SCC: 0x0F8 0x0BEC0000 ;BL1 entry point
SCC: 0x0FC 0xABE40000 ;BL0 entry point
SCC: 0xA14 0x00000000 ;PCLKDBG_CONTROL DIV=1
SCC: 0x00C 0x000000C2 ;Clock Control, TMIF2XCLK, Register 0xC1 = default
;[3:0] CLKSEL : 0 Output gated, 1 AON_REF_CLK, 2 SYSCLK
;[7:4] CLKDIV : Clock divider -1 (0 give a division of 1)
SCC: 0x010 0x000000C2 ;Clock Control, TSIF2XCLK, Register 0xC1 = default
;[3:0] CLKSEL : 0 Output gated, 1 AON_REF_CLK, 2 SYSCLK
;[7:4] CLKDIV : Clock divider -1 (0 give a division of 1)
@@ -0,0 +1,24 @@
BOARD: HBI0262
TITLE: V2M-Juno DevChip Configuration File
[SCC REGISTERS]
TOTALSCCS: 13 ;Total Number of SCC registers
SCC: 0x054 0x0007FFFE ;Enable non-secure DMA operations
SCC: 0x05C 0x00FE001E ;Enable default GPU Texture Formats
SCC: 0x100 0x00271000 ;A72 PLL Register 0 (1000MHz)
SCC: 0x104 0x00013100 ;A72 PLL Register 1
SCC: 0x108 0x003F1000 ;A53 PLL Register 0 (800MHz)
SCC: 0x10C 0x0001F300 ;A53 PLL Register 1
SCC: 0x118 0x003F1000 ;SYS PLL Register 0 (1600MHz)
SCC: 0x11C 0x0001F100 ;SYS PLL Register 1
SCC: 0x0F8 0x0BEC0000 ;BL1 entry point
SCC: 0x0FC 0xABE40000 ;BL0 entry point
SCC: 0xA14 0x00000000 ;PCLKDBG_CONTROL DIV=1
SCC: 0x00C 0x000000C2 ;Clock Control, TMIF2XCLK, Register 0xC1 = default
;[3:0] CLKSEL : 0 Output gated, 1 AON_REF_CLK, 2 SYSCLK
;[7:4] CLKDIV : Clock divider -1 (0 give a division of 1)
SCC: 0x010 0x000000C2 ;Clock Control, TSIF2XCLK, Register 0xC1 = default
;[3:0] CLKSEL : 0 Output gated, 1 AON_REF_CLK, 2 SYSCLK
;[7:4] CLKDIV : Clock divider -1 (0 give a division of 1)
@@ -0,0 +1,4 @@
echo -off
echo Juno startup.nsh from NOR flash
echo Example command to start the kernel:
echo norkern dtb=board.dtb initrd=ramdisk.img console=ttyAMA0,115200n8 root=/dev/sda2 rw rootwait earlyprintk=pl011,0x7ff80000 debug user_debug=31 androidboot.hardware=juno loglevel=9 sky2.mac_address=0xAA,0xBB,0xCC,0xDD,0xEE,0xFF
@@ -0,0 +1,97 @@
# ARM TAP controller IR register lengths file
#
# Copyright (C) 2008 ARM Limited. All rights reserved.
#
# This file contains a definition of the devices names, ID codes, ID code mask
# and IR lengths for devices used on ARM boards. This file is read by the
# progcards_usb.exe program and used to determine if a device ID is valid and
# the corresponding IR length. A device that is not recognized will be display
# as 'UNKOWN' and device details should be added to this file.
#
# DEVICE NAME ID CODE ID MASK IR LENGTH
# ------------- ---------- ---------- ---------
# XILINX PLDs
XC9572 0x09504093 0x0FFFFFFF 8
XC9536XL 0x29602093 0x0FFFFFFF 8
XC9572XL 0x09604093 0x0FFFFFFF 8
XC95288XL 0x09616093 0x0FFFFFFF 8
XCR3256XL 0xF494FFFF 0x0FFF8001 4
XC4036XLA 0x00224093 0x00FFFFFF 3
XC4062XLA 0x00230093 0x00FFFFFF 3
XC4085XLA 0x00238093 0x00FFFFFF 3
XC2C32A 0x06E1C093 0x0FFF0FFF 8
XC2C64A 0x06E5D093 0x0FFF0FFF 8
XC2C128 0x06D8A093 0x0FFF0FFF 8
XC2C256 0x16D4c093 0x0FFF0FFF 8
XC2C384 0x06D5C093 0x0FFF0FFF 8
# XILINX FPGAs
XCV600 0x10630093 0x00FFFFFF 5
XCV600E 0x90A30093 0x00FFFFFF 5
XCV1000 0x40640093 0x0FFFFFFF 5
XCV2000E 0xF0A50093 0x0FFFFFFF 5
XC2V2000 0x01038093 0x0FFFFFFF 6
XC2V6000 0x31060093 0x0FFFFFFF 6
XC2V8000 0x01070093 0x0FFFFFFF 6
XC4VLX40 0x316A4093 0x0FFFFFFF 10
XC4VLX160 0x01718093 0x0FFFFFFF 10
XC4VLX200 0x01734093 0x0FFFFFFF 10
XC5VLX50T 0x02A96093 0x0FFFFFFF 10
XC5VLX110 0x228D6093 0x0FFFFFFF 10
XC5VLX330 0x2295C093 0x0FFFFFFF 10
XC2S200E 0x20A1C093 0x0FFFFFFF 5
XC2S300E 0x90A20093 0x0FFFFFFF 5
XC3S200A 0x02218093 0x0FFFFFFF 6
XC3S4000 0x01448093 0x0FFFFFFF 6
XC6SLX45 0x04008093 0x0FFFFFFF 6
# ARM
ARM7TDMI 0x3F0F0F0F 0xFFFFFFFF 4
ARM7TDMI-r4 0x40700F0F 0xFFFFFFFF 4
ARM720T 0x0F0F0F0F 0xFFFFFFFF 4
ARM920T 0x10920F0F 0xFFFFFFFF 4
ARM926EJ-S 0x07926F0F 0xFFFFFFFF 4
ARM940T 0x1F0F0F0F 0xFFFFFFFF 4
ARM10200 0x00A20F0F 0xFFFFFFFF 4
ARMFLASH 0x0F0E5F2F 0xFFFFFFFF 5
ARMDBT 0x00000F0F 0xFFFFFFFF 5
PWP926EJ-S_BS2 0x0F21FF0F 0xFFFFFFFF 2
ARM_BS2_ 0x0F203F0F 0xFFFFFFFF 2
ARM1136J-Sr0_BS2 0x0F21DF0F 0xFFFFFFFF 2
ARM11MPCore_BS5 0x17536021 0xFFFFFFFF 5
PXP1176JZF_BS2 0x0F2258EF 0xFFFFFFFF 2
CORTEXA8 0x0F423477 0xFFFFFFFF 4
CORTEXA9 0x08226021 0xFFFFFFFF 4
# ALTERA
EPM3032A 0x170320DD 0xFFFFFFFF 10
EPM7256AE 0x172560DD 0xFFFFFFFF 10
EPM7512AE 0x175120DD 0xFFFFFFFF 10
EPM1270 0x020A30DD 0xFFFFFFFF 10
EP20K1000E 0x090000DD 0xFFFFFFFF 10
EP2S180F 0x020960DD 0xFFFFFFFF 10
# Misc
ispClock5520 0x00150043 0xFFFFFFFF 8
ispClock5620 0x00160043 0xFFFFFFFF 8
ispClock5610V 0x00161043 0xFFFFFFFF 8
ispClock5610AV 0x00166043 0xFFFFFFFF 8
ISSP 0x0F0F0F0F 0x0FFFFFFF 5
Mali200 0x10400477 0xFFFFFFFF 2
PLX6520 0x3197839B 0xFFFFFFFF 5
PLX8114 0x21FB239B 0xFFFFFFFF 5
PLX8518 0x1214639B 0xFFFFFFFF 5
PLX8518 0x4214639B 0xFFFFFFFF 5
STM32TMC 0x16410041 0x0FFF0FFF 5
STM32CM3 0x3BA00477 0x0FFFFFFF 4
IDT89HPES32H8 0x08035067 0xFFFFFFFF 6
IDT89H16NT16 0x28090067 0xFFFFFFFF 6
NX5000_BYPASS 0x14951185 0xFFFFFFFF 4
NX5000_FC1152 0x03387589 0xFFFFFFFF 4
@@ -1,231 +0,0 @@
From 4e23e72e65481fe917d8a0af355b3b7669d5acb6 Mon Sep 17 00:00:00 2001
From: Harsimran Singh Tungal <harsimransingh.tungal@arm.com>
Date: Thu, 7 Aug 2025 10:05:02 +0000
Subject: [PATCH] plat: corstone1000: add Cortex-A320 support
Introduce `CORSTONE1000_CORTEX_A320` to enable Cortex-A320 on
Corstone-1000 while keeping Cortex-A35 as the default. When the
define is enabled, the build switches from `cortex_a35.S` to
`cortex_a320.S`, maintaining compatibility with existing A35-based
designs.
Also add Normal-World mappings for the Ethos-U85 NPU and its SRAM
on Cortex-A320 platforms so U-Boot and other non-secure software
can safely access these regions:
* **Ethos-U85 registers**: base `0x1A050000`, size `0x00004000` (16 KB),
attrs `MT_DEVICE | MT_RW | MT_NS`
* **Non-secure SRAM**: base `0x02400000`, size `0x00400000` (4 MB),
attrs `MT_MEMORY | MT_RW | MT_NS`
Enable GICv3 with GIC-600 when building for Cortex-A320 (retain
GICv2/GIC-400 for Cortex-A35):
* Update `plat_my_core_pos()` and `plat_arm_calc_core_pos()` to use
the Cortex-A320 MPIDR_EL1 affinity layout.
* Add an A320-specific core-position routine in assembly guarded by
`CORSTONE1000_CORTEX_A320`.
* Switch to the GICv3 driver with GIC-600 extensions: update GIC base
addresses, use GICv3 APIs, and set `USE_GIC_DRIVER=3`,
`GICV3_SUPPORT_GIC600=1`, `GIC_ENABLE_V4_EXTN=1`.
These changes prepare the platform for Cortex-A320 integration and
ensure correct GIC configuration and secondary-core bring-up, while
preserving A35 behavior.
Upstream-Status: Submitted (https://review.trustedfirmware.org/c/TF-A/trusted-firmware-a/+/45729)
Signed-off-by: Harsimran Singh Tungal <harsimransingh.tungal@arm.com>
Signed-off-by: Frazer Carsley <frazer.carsley@arm.com>
Signed-off-by: Michael Safwat <michael.safwat@arm.com>
---
.../common/corstone1000_helpers.S | 35 ++++++++++++++++++-
.../corstone1000/common/corstone1000_plat.c | 4 +++
.../corstone1000/common/corstone1000_pm.c | 8 +++++
.../common/include/platform_def.h | 26 ++++++++++++++
plat/arm/board/corstone1000/platform.mk | 11 ++++++
5 files changed, 83 insertions(+), 1 deletion(-)
diff --git a/plat/arm/board/corstone1000/common/corstone1000_helpers.S b/plat/arm/board/corstone1000/common/corstone1000_helpers.S
index a4ca9fe98223..665dbc61a92e 100644
--- a/plat/arm/board/corstone1000/common/corstone1000_helpers.S
+++ b/plat/arm/board/corstone1000/common/corstone1000_helpers.S
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2021-2024 Arm Limited and Contributors. All rights reserved.
+ * Copyright (c) 2021-2025 Arm Limited and Contributors. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
@@ -13,6 +13,39 @@
.globl plat_is_my_cpu_primary
.globl plat_arm_calc_core_pos
+#ifdef CORSTONE1000_CORTEX_A320
+ .globl plat_my_core_pos
+
+func plat_my_core_pos
+ mrs x0, mpidr_el1
+ b plat_arm_calc_core_pos
+endfunc plat_my_core_pos
+
+func plat_arm_calc_core_pos
+ /* Aff0 is always 0 for Cortex-A320
+ MPIDR format: https://developer.arm.com/documentation/109551/0001/AArch64-registers/AArch64-Identification-registers-summary/MPIDR-EL1--Multiprocessor-Affinity-Register?lang=en
+ */
+ /* Extract Aff1 (core ID) */
+ ubfx x1, x0, #MPIDR_AFF1_SHIFT, #MPIDR_AFFINITY_BITS
+
+ /* Extract Aff2 (cluster lower bits) */
+ ubfx x2, x0, #MPIDR_AFF2_SHIFT, #MPIDR_AFFINITY_BITS
+
+ /* Extract Aff3 (cluster upper bits) */
+ ubfx x3, x0, #MPIDR_AFF3_SHIFT, #MPIDR_AFFINITY_BITS
+
+ /* cluster_id = (Aff3 << 8) | Aff2 */
+ lsl x3, x3, #MPIDR_AFFINITY_BITS
+ orr x3, x3, x2
+
+ /* core_pos = core_id + (cluster_id * FVP_MAX_CPUS_PER_CLUSTER) */
+ mov x4, #CORSTONE1000_MAX_CPUS_PER_CLUSTER
+ madd x0, x3, x4, x1
+
+ ret
+endfunc plat_arm_calc_core_pos
+#endif
+
/* --------------------------------------------------------------------
* void plat_secondary_cold_boot_setup (void);
*
diff --git a/plat/arm/board/corstone1000/common/corstone1000_plat.c b/plat/arm/board/corstone1000/common/corstone1000_plat.c
index e388c82f311b..d34e80b29bb0 100644
--- a/plat/arm/board/corstone1000/common/corstone1000_plat.c
+++ b/plat/arm/board/corstone1000/common/corstone1000_plat.c
@@ -26,6 +26,10 @@ const mmap_region_t plat_arm_mmap[] = {
ARM_MAP_NS_DRAM1,
CORSTONE1000_MAP_DEVICE,
CORSTONE1000_EXTERNAL_FLASH,
+#ifdef CORSTONE1000_CORTEX_A320
+ ARM_MAP_ETHOS_U85,
+ ARM_MAP_NONSECURE_SRAM,
+#endif
{0}
};
diff --git a/plat/arm/board/corstone1000/common/corstone1000_pm.c b/plat/arm/board/corstone1000/common/corstone1000_pm.c
index ac808873b9e7..a87697e97f11 100644
--- a/plat/arm/board/corstone1000/common/corstone1000_pm.c
+++ b/plat/arm/board/corstone1000/common/corstone1000_pm.c
@@ -8,7 +8,11 @@
#include <plat/arm/common/plat_arm.h>
#include <platform_def.h>
#include <plat/common/platform.h>
+#ifdef CORSTONE1000_CORTEX_A320
+#include <drivers/arm/gicv3.h>
+#else
#include <drivers/arm/gicv2.h>
+#endif
/*******************************************************************************
* Export the platform handlers via plat_arm_psci_pm_ops. The ARM Standard
* platform layer will take care of registering the handlers with PSCI.
@@ -24,7 +28,11 @@ static void corstone1000_system_reset(void)
* Disable GIC CPU interface to prevent pending interrupt
* from waking up the AP from WFI.
*/
+#ifdef CORSTONE1000_CORTEX_A320
+ gicv3_cpuif_disable(plat_my_core_pos());
+#else
gicv2_cpuif_disable();
+#endif
/* Flush and invalidate data cache */
dcsw_op_all(DCCISW);
diff --git a/plat/arm/board/corstone1000/common/include/platform_def.h b/plat/arm/board/corstone1000/common/include/platform_def.h
index 200383475c80..ffb1e2dec0e1 100644
--- a/plat/arm/board/corstone1000/common/include/platform_def.h
+++ b/plat/arm/board/corstone1000/common/include/platform_def.h
@@ -112,12 +112,19 @@
#define ARM_SHARED_RAM_SIZE (SZ_8K) /* 8 KB */
#define ARM_SHARED_RAM_BASE ARM_TRUSTED_SRAM_BASE
+#ifdef CORSTONE1000_CORTEX_A320
+#define TOTAL_SECURE_SRAM_SIZE (SZ_4M)
+#define TOTAL_NONSECURE_SRAM_SIZE (SZ_4M)
+#define PLAT_ARM_TRUSTED_SRAM_SIZE (TOTAL_SECURE_SRAM_SIZE - \
+ ARM_SHARED_RAM_SIZE)
+#else
/* The remaining Trusted SRAM is used to load the BL images */
#define TOTAL_SRAM_SIZE (SZ_4M) /* 4 MB */
#define PLAT_ARM_TRUSTED_SRAM_SIZE (TOTAL_SRAM_SIZE - \
ARM_SHARED_RAM_SIZE)
+#endif
#define PLAT_ARM_MAX_BL2_SIZE (180 * SZ_1K) /* 180 KB */
@@ -208,8 +215,13 @@
#define MAX_IO_BLOCK_DEVICES 1
/* GIC related constants */
+#ifdef CORSTONE1000_CORTEX_A320
+#define PLAT_ARM_GICD_BASE 0x1C000000
+#define PLAT_ARM_GICR_BASE 0x1C040000
+#else
#define PLAT_ARM_GICD_BASE 0x1C010000
#define PLAT_ARM_GICC_BASE 0x1C02F000
+#endif
/* MHUv2 Secure Channel receiver and sender */
#define PLAT_SDK700_MHU0_SEND 0x1B800000
@@ -334,6 +346,20 @@
CORSTONE1000_DEVICE_BASE, \
CORSTONE1000_DEVICE_SIZE, \
MT_DEVICE | MT_RW | MT_SECURE)
+#ifdef CORSTONE1000_CORTEX_A320
+#define ARM_ETHOS_U85_BASE UL(0x1A050000)
+#define ARM_ETHOS_U85_SIZE UL(0x4000)
+#define ARM_MAP_ETHOS_U85 MAP_REGION_FLAT( \
+ ARM_ETHOS_U85_BASE, \
+ ARM_ETHOS_U85_SIZE, \
+ MT_DEVICE | MT_RW | MT_NS)
+
+#define ARM_NONSECURE_SRAM_BASE (ARM_TRUSTED_SRAM_BASE + TOTAL_SECURE_SRAM_SIZE)
+#define ARM_MAP_NONSECURE_SRAM MAP_REGION_FLAT( \
+ ARM_NONSECURE_SRAM_BASE, \
+ TOTAL_NONSECURE_SRAM_SIZE, \
+ MT_MEMORY | MT_RW | MT_NS)
+#endif
#define ARM_IRQ_SEC_PHY_TIMER 29
diff --git a/plat/arm/board/corstone1000/platform.mk b/plat/arm/board/corstone1000/platform.mk
index 65be9c1f5ad7..fe3e94865fca 100644
--- a/plat/arm/board/corstone1000/platform.mk
+++ b/plat/arm/board/corstone1000/platform.mk
@@ -9,7 +9,14 @@ ifeq ($(filter ${TARGET_PLATFORM}, fpga fvp),)
$(error TARGET_PLATFORM must be fpga or fvp)
endif
+ifdef CORSTONE1000_CORTEX_A320
+CORSTONE1000_CPU_LIBS +=lib/cpus/aarch64/cortex_a320.S
+$(eval $(call add_define,CORSTONE1000_CORTEX_A320))
+GIC_ENABLE_V4_EXTN := 1
+GICV3_SUPPORT_GIC600 := 1
+else
CORSTONE1000_CPU_LIBS +=lib/cpus/aarch64/cortex_a35.S
+endif
PLAT_INCLUDES := -Iplat/arm/board/corstone1000/common/include \
-Iplat/arm/board/corstone1000/include \
@@ -43,7 +50,11 @@ $(eval $(call add_define,CORSTONE1000_FVP_MULTICORE))
endif
endif
+ifdef CORSTONE1000_CORTEX_A320
+USE_GIC_DRIVER := 3
+else
USE_GIC_DRIVER := 2
+endif
BL2_SOURCES += plat/arm/board/corstone1000/common/corstone1000_security.c \
plat/arm/board/corstone1000/common/corstone1000_err.c \
@@ -0,0 +1,45 @@
From f05f9b75f60697be84217d0957e8864d58ee71bb Mon Sep 17 00:00:00 2001
From: Oscar Belshaw <Oscar.Belshaw@arm.com>
Date: Tue, 11 Aug 2026 15:40:27 +0100
Subject: [PATCH] plat: corstone1000: align BL config mapping
ARM_FW_CONFIG_BASE starts after the meminfo_t structure and is therefore
not page aligned. Translation table mappings require page-aligned base
addresses and sizes.
Map the enclosing page from ARM_SHARED_RAM_BASE while retaining
ARM_FW_CONFIG_BASE as the configuration load address. This prevents
mmap_add_region_check() from returning -EINVAL during BL2 initialization.
Only the mapping is widened: the reserved meminfo_t space at the start of
shared RAM and the firmware configuration load addresses are unchanged.
Upstream-Status: Submitted [https://review.trustedfirmware.org/c/TF-A/trusted-firmware-a/+/54909]
Signed-off-by: Oscar Belshaw <Oscar.Belshaw@arm.com>
---
.../arm/board/corstone1000/common/include/platform_def.h | 10 +++++-----
1 file changed, 5 insertions(+), 5 deletions(-)
diff --git a/plat/arm/board/corstone1000/common/include/platform_def.h b/plat/arm/board/corstone1000/common/include/platform_def.h
index 382426869b..6673010d2f 100644
--- a/plat/arm/board/corstone1000/common/include/platform_def.h
+++ b/plat/arm/board/corstone1000/common/include/platform_def.h
@@ -334,11 +334,11 @@
* Map the region for the optional device tree configuration with read and
* write permissions
*/
-#define ARM_MAP_BL_CONFIG_REGION MAP_REGION_FLAT( \
- ARM_FW_CONFIG_BASE, \
- (ARM_FW_CONFIG_LIMIT \
- - ARM_FW_CONFIG_BASE), \
- MT_MEMORY | MT_RW | MT_SECURE)
+#define ARM_MAP_BL_CONFIG_REGION MAP_REGION_FLAT( \
+ ARM_SHARED_RAM_BASE, \
+ (ARM_FW_CONFIG_LIMIT \
+ - ARM_SHARED_RAM_BASE), \
+ MT_MEMORY | MT_RW | MT_SECURE)
#define CORSTONE1000_DEVICE_BASE (0x1A000000)
#define CORSTONE1000_DEVICE_SIZE (0x26000000)
@@ -1,113 +0,0 @@
From a9801643d9d4d3f24960c5f24d5f5c3fd4889cc1 Mon Sep 17 00:00:00 2001
From: Alex Chapman <alecha05@e142473.arm.com>
Date: Tue, 3 Mar 2026 17:00:58 +0000
Subject: [PATCH] feat(corestone-1000): make mutlicore support platform generic
To improve portability, testing coverage, and future platform enablement.
- Replace FVP-only multicore checks with platform-generic checks.
- Add the corresponding TF-M patch to the Corstone-1000 recipe.
Upstream-Status: Submitted [https://review.trustedfirmware.org/c/TF-A/trusted-firmware-a/+/49092]
Signed-off-by: Alex Chapman <alex.chapman@arm.com>
---
plat/arm/board/corstone1000/common/corstone1000_helpers.S | 4 ++--
plat/arm/board/corstone1000/common/corstone1000_pm.c | 6 +++---
plat/arm/board/corstone1000/common/include/platform_def.h | 4 ++--
plat/arm/board/corstone1000/platform.mk | 6 ++----
4 files changed, 9 insertions(+), 11 deletions(-)
diff --git a/plat/arm/board/corstone1000/common/corstone1000_helpers.S b/plat/arm/board/corstone1000/common/corstone1000_helpers.S
index 665dbc61a..d41df4ebe 100644
--- a/plat/arm/board/corstone1000/common/corstone1000_helpers.S
+++ b/plat/arm/board/corstone1000/common/corstone1000_helpers.S
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2021-2025 Arm Limited and Contributors. All rights reserved.
+ * Copyright (c) 2021-2026 Arm Limited and Contributors. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
@@ -54,7 +54,7 @@ endfunc plat_arm_calc_core_pos
* --------------------------------------------------------------------
*/
func plat_secondary_cold_boot_setup
-#if defined(CORSTONE1000_FVP_MULTICORE)
+#if defined(CORSTONE1000_MULTICORE)
/* Calculate the address of our hold entry */
bl plat_my_core_pos
diff --git a/plat/arm/board/corstone1000/common/corstone1000_pm.c b/plat/arm/board/corstone1000/common/corstone1000_pm.c
index a87697e97..2c7a2c67b 100644
--- a/plat/arm/board/corstone1000/common/corstone1000_pm.c
+++ b/plat/arm/board/corstone1000/common/corstone1000_pm.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2021-2025, Arm Limited and Contributors. All rights reserved.
+ * Copyright (c) 2021-2026, Arm Limited and Contributors. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
@@ -41,7 +41,7 @@ static void corstone1000_system_reset(void)
*watchdog_ctrl_reg = SECURE_WATCHDOG_MASK_ENABLE;
}
-#if defined(CORSTONE1000_FVP_MULTICORE)
+#if defined(CORSTONE1000_MULTICORE)
int corstone1000_validate_ns_entrypoint(uintptr_t entrypoint)
{
/*
@@ -77,7 +77,7 @@ void corstone1000_pwr_domain_on_finish(const psci_power_state_t *target_state)
#endif
plat_psci_ops_t plat_arm_psci_pm_ops = {
-#if defined(CORSTONE1000_FVP_MULTICORE)
+#if defined(CORSTONE1000_MULTICORE)
.pwr_domain_on = corstone1000_pwr_domain_on,
.pwr_domain_on_finish = corstone1000_pwr_domain_on_finish,
.validate_ns_entrypoint = corstone1000_validate_ns_entrypoint,
diff --git a/plat/arm/board/corstone1000/common/include/platform_def.h b/plat/arm/board/corstone1000/common/include/platform_def.h
index ffb1e2dec..4682b8b5d 100644
--- a/plat/arm/board/corstone1000/common/include/platform_def.h
+++ b/plat/arm/board/corstone1000/common/include/platform_def.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2021-2025, Arm Limited and Contributors. All rights reserved.
+ * Copyright (c) 2021-2026, Arm Limited and Contributors. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
@@ -266,7 +266,7 @@
#define PLAT_ARM_TRUSTED_MAILBOX_BASE ARM_TRUSTED_SRAM_BASE
-#if defined(CORSTONE1000_FVP_MULTICORE)
+#if defined(CORSTONE1000_MULTICORE)
/* The secondary core entrypoint address points to bl31_warm_entrypoint
* and the address size is 8 bytes */
#define CORSTONE1000_SECONDARY_CORE_ENTRYPOINT_ADDRESS_SIZE UL(0x8)
diff --git a/plat/arm/board/corstone1000/platform.mk b/plat/arm/board/corstone1000/platform.mk
index fe3e94865..dee40f3b3 100644
--- a/plat/arm/board/corstone1000/platform.mk
+++ b/plat/arm/board/corstone1000/platform.mk
@@ -1,5 +1,5 @@
#
-# Copyright (c) 2021-2025 Arm Limited and Contributors. All rights reserved.
+# Copyright (c) 2021-2026 Arm Limited and Contributors. All rights reserved.
#
# SPDX-License-Identifier: BSD-3-Clause
#
@@ -44,10 +44,8 @@ $(eval $(call add_define,CORSTONE1000_WITH_BL32))
endif
ENABLE_MULTICORE := 0
-ifneq ($(filter ${TARGET_PLATFORM}, fvp),)
ifeq (${ENABLE_MULTICORE},1)
-$(eval $(call add_define,CORSTONE1000_FVP_MULTICORE))
-endif
+$(eval $(call add_define,CORSTONE1000_MULTICORE))
endif
ifdef CORSTONE1000_CORTEX_A320
--
2.43.0
@@ -0,0 +1,83 @@
From: Oscar Belshaw <Oscar.Belshaw@arm.com>
Subject: [PATCH] fix(corstone1000): delay early GPT access
TF-A 2.15 initializes GPT before MMU setup in the common BL2 boot path.
On Corstone1000 MPS3, early memory-mapped flash reads have returned an
invalid MBR signature, preventing boot. A 25 ms delay before GPT access
has allowed boot and reset tests to complete on the tested configurations.
Override the weak plat_arm_io_setup hook for Corstone1000 BL2 with
RESET_TO_BL2 and ARM_GPT_SUPPORT enabled. Preserve arm_io_setup and its
error handling, then wait 25 ms before returning to common GPT setup.
The common system-counter enable occurs in arm_bl31_platform_setup, and
common generic_delay_timer_init occurs after GPT initialization. Enable
the system counter here with the same CNTCR configuration used by BL31,
then initialize the delay driver before calling mdelay. Driver initialization
alone does not enable the hardware counter. Do not reset the counter value;
leave the later common initialization unchanged.
Use the same hook for FPGA, A35 FVP and A320 FVP. Keep the common GPT-before-
MMU ordering and reset handling unchanged, without diagnostic flash reads
or console output.
This is a timing workaround, not a hardware readiness check. The underlying
cause and any required hardware settling interval remain under investigation;
25 ms is the tested delay, not a documented minimum platform requirement.
Upstream-Status: Submitted [https://review.trustedfirmware.org/c/TF-A/trusted-firmware-a/+/54910]
Signed-off-by: Oscar Belshaw <Oscar.Belshaw@arm.com>
---
.../corstone1000/common/corstone1000_plat.c | 28 ++++++++++++++++++++
1 file changed, 28 insertions(+)
diff --git a/plat/arm/board/corstone1000/common/corstone1000_plat.c b/plat/arm/board/corstone1000/common/corstone1000_plat.c
index d34e80b..1c51145 100644
--- a/plat/arm/board/corstone1000/common/corstone1000_plat.c
+++ b/plat/arm/board/corstone1000/common/corstone1000_plat.c
@@ -6,10 +6,14 @@
#include <assert.h>
+#include <arch.h>
#include <common/bl_common.h>
+#include <common/debug.h>
+#include <drivers/delay_timer.h>
#include <drivers/generic_delay_timer.h>
#include <drivers/io/io_storage.h>
+#include <lib/mmio.h>
#include <plat/common/platform.h>
#include <plat/arm/common/arm_fconf_getter.h>
#include <plat/arm/common/arm_fconf_io_storage.h>
@@ -33,6 +37,30 @@ const mmap_region_t plat_arm_mmap[] = {
{0}
};
+#define CS1K_GPT_DELAY 25U /* GPT initialization delay in milliseconds. */
+
+#if defined(IMAGE_BL2) && RESET_TO_BL2 && ARM_GPT_SUPPORT
+void plat_arm_io_setup(void)
+{
+ int err;
+
+ err = arm_io_setup();
+ if (err < 0) {
+ panic();
+ }
+
+ /*
+ * Allow time before early memory-mapped flash reads. This is a
+ * workaround for invalid GPT reads observed on MPS3; the underlying
+ * readiness requirement still needs investigation.
+ */
+ mmio_write_32(ARM_SYS_CNTCTL_BASE + CNTCR_OFF,
+ CNTCR_FCREQ(0U) | CNTCR_EN);
+ generic_delay_timer_init();
+ mdelay(CS1K_GPT_DELAY);
+}
+#endif
+
static void set_fip_image_source(void)
{
const struct plat_io_policy *policy;
@@ -1,157 +0,0 @@
From ff4bb404474a3310654827c36c4ac882eb0344b5 Mon Sep 17 00:00:00 2001
From: Michael Safwat <michael.safwat@arm.com>
Date: Tue, 26 Aug 2025 11:20:01 +0000
Subject: [PATCH] plat: corstone1000: Add Cortex-A320 support
Switch platform to GICv3 (GIC-600) for Corstone-1000 with Cortex-A320
depending on CORSTONE1000_CORTEX_A320:
- Define GICD and GICR bases.
- Update the platform sources to include the GIC-V3 files.
Move the NVM offset to prevent overlap with the TFTF firmware,
which starts at 0x80000000 (TFTF_BASE).
Introduce a new skip file tests_to_skip_cortex_a320 to be used when building
TF-A-Tests with CORSTONE1000_CORTEX_A320=1. This ensures that tests which
are not supported or cause traps on Corstone-1000 with Cortex-A320 are
consistently skipped during execution.
Skipped entries:
CPU extensions/AMUv1 suspend/resume
CPU extensions/Use trace buffer control Registers
Signed-off-by: Michael Safwat <michael.safwat@arm.com>
Signed-off-by: Harsimran Singh Tungal <harsimransingh.tungal@arm.com>
Upstream-Status: Submitted (https://review.trustedfirmware.org/c/TF-A/tf-a-tests/+/42352)
---
plat/arm/corstone1000/corstone1000_def.h | 12 ++++++++++-
plat/arm/corstone1000/include/platform_def.h | 11 +++++-----
plat/arm/corstone1000/platform.mk | 20 ++++++++++++++++++
.../tests_to_skip_cortex_a320.txt | 21 +++++++++++++++++++
4 files changed, 58 insertions(+), 6 deletions(-)
create mode 100644 plat/arm/corstone1000/tests_to_skip_cortex_a320.txt
diff --git a/plat/arm/corstone1000/corstone1000_def.h b/plat/arm/corstone1000/corstone1000_def.h
index 3e6f036acc9a..c4fa9a3b5f68 100644
--- a/plat/arm/corstone1000/corstone1000_def.h
+++ b/plat/arm/corstone1000/corstone1000_def.h
@@ -26,13 +26,23 @@
* GIC-400 & interrupt handling related constants
******************************************************************************/
/* GIC memory map */
+#ifdef CORSTONE1000_CORTEX_A320
+#define GICD_BASE 0x1C000000
+#define GICR_BASE 0x1C040000
+
+/* GIC re-distributor doesn't exits on gic-600, but we still need to
+ * provide GICC_BASE as the gic driver needs it
+ */
+#define GICC_BASE 0x0
+#else
+
#define GICD_BASE 0x1C010000
#define GICC_BASE 0x1C02F000
/* GIC re-distributor doesn't exits on gic-400, but we still need to
* provide GICR_BASE as the gic driver needs it
*/
#define GICR_BASE 0x0
-
+#endif
/*******************************************************************************
* PL011 related constants
******************************************************************************/
diff --git a/plat/arm/corstone1000/include/platform_def.h b/plat/arm/corstone1000/include/platform_def.h
index 91f4cda19a90..2a9e5c4c35bb 100644
--- a/plat/arm/corstone1000/include/platform_def.h
+++ b/plat/arm/corstone1000/include/platform_def.h
@@ -98,12 +98,13 @@
#endif
/*
- * USE 0x200000 DRAM offset to store TFTF data
- *
- * Please note that this won't be suitable for all test scenarios and
- * for this reason some tests will be disabled in this configuration.
+ * When USE_NVM = 0, TFTF_NVM_OFFSET marks the DRAM region
+ * used as NVM. This region must not overlap the memory where
+ * the TFTF image is loaded. The load address is given by
+ * the TFTF_BASE macro. Set TFTF_NVM_OFFSET to leave enough
+ * space for the TFTF image.
*/
-#define TFTF_NVM_OFFSET 0x40000
+#define TFTF_NVM_OFFSET 0x80000
#define TFTF_NVM_SIZE (128 * SZ_1M) /* 128 MB */
/*******************************************************************************
diff --git a/plat/arm/corstone1000/platform.mk b/plat/arm/corstone1000/platform.mk
index cd7a19162bcf..dfdd27abd897 100644
--- a/plat/arm/corstone1000/platform.mk
+++ b/plat/arm/corstone1000/platform.mk
@@ -6,6 +6,16 @@
PLAT_INCLUDES := -Iplat/arm/corstone1000/include/
+CORSTONE1000_CORTEX_A320 := 0
+ifeq (${CORSTONE1000_CORTEX_A320},1)
+PLAT_SOURCES := drivers/arm/timer/private_timer.c \
+ drivers/arm/timer/system_timer.c \
+ plat/arm/corstone1000/plat_helpers.S \
+ plat/arm/corstone1000/corstone1000_pwr_state.c \
+ plat/arm/corstone1000/corstone1000_topology.c \
+ plat/arm/corstone1000/corstone1000_mem_prot.c \
+ plat/arm/corstone1000/plat_setup.c
+else
PLAT_SOURCES := drivers/arm/timer/private_timer.c \
drivers/arm/timer/system_timer.c \
plat/arm/corstone1000/plat_helpers.S \
@@ -13,6 +23,7 @@ PLAT_SOURCES := drivers/arm/timer/private_timer.c \
plat/arm/corstone1000/corstone1000_topology.c \
plat/arm/corstone1000/corstone1000_mem_prot.c \
plat/arm/corstone1000/plat_setup.c
+endif
PLAT_SUPPORTS_NS_RESET := 1
@@ -21,6 +32,15 @@ $(eval $(call assert_boolean,PLAT_SUPPORTS_NS_RESET))
$(eval $(call add_define,TFTF_DEFINES,PLAT_SUPPORTS_NS_RESET))
FIRMWARE_UPDATE := 0
+
+ifeq ($(CORSTONE1000_CORTEX_A320),1)
+$(eval $(call add_define,TFTF_DEFINES,CORSTONE1000_CORTEX_A320))
+endif
+
+ifeq (${CORSTONE1000_CORTEX_A320},1)
+PLAT_TESTS_SKIP_LIST := plat/arm/corstone1000/tests_to_skip_cortex_a320.txt
+else
PLAT_TESTS_SKIP_LIST := plat/arm/corstone1000/tests_to_skip.txt
+endif
include plat/arm/common/arm_common.mk
diff --git a/plat/arm/corstone1000/tests_to_skip_cortex_a320.txt b/plat/arm/corstone1000/tests_to_skip_cortex_a320.txt
new file mode 100644
index 000000000000..87b9241daba0
--- /dev/null
+++ b/plat/arm/corstone1000/tests_to_skip_cortex_a320.txt
@@ -0,0 +1,21 @@
+Realm payload tests
+Realm payload boot
+Realm payload multi CPU request
+Realm payload Delegate and Undelegate
+Multi CPU Realm payload Delegate and Undelegate
+Testing delegation fails
+Realm testing with SPM tests
+PSCI System Suspend Validation
+PSCI STAT/Stats test cases after system suspend
+IRQ support in TSP/Resume preempted STD SMC after PSCI SYSTEM SUSPEND
+PSCI SYSTEM SUSPEND stress tests
+Timer framework Validation/Verify the timer interrupt generation
+CPU Hotplug/CPU hotplug
+PSCI CPU Suspend
+PSCI CPU Suspend in OSI mode
+PSCI STAT/for valid composite state CPU suspend
+FF-A Setup and Discovery/FF-A RXTX remap unmapped region success
+FF-A Memory Sharing/Normal World VM retrieve request into SPMC
+Boot requirement tests
+CPU extensions/AMUv1 suspend/resume
+CPU extensions/Use trace buffer control Registers
@@ -9,8 +9,3 @@ EXTRA_OEMAKE:append:cortexa320 = " \
CORSTONE1000_CORTEX_A320=1 \
"
TFTF_MODE:corstone1000 = "release"
FILESEXTRAPATHS:prepend:corstone1000 := "${THISDIR}/files/corstone1000/tf-a-tests:"
SRC_URI:append:corstone1000 = " \
file://0001-plat-corstone1000-Add-Cortex-A320-support.patch \
"
@@ -5,13 +5,12 @@ COMPATIBLE_MACHINE = "(corstone1000)"
FILESEXTRAPATHS:prepend := "${THISDIR}/files/corstone1000:"
SRC_URI:append = " \
file://0001-Fix-FF-A-version-in-SPMC-manifest.patch \
file://0002-plat-corstone1000-add-Cortex-A320-support.patch \
file://0003-feat-corestone-1000-make-mutlicore-support-platform-.patch \
file://0002-plat-corstone1000-align-BL-config-region.patch \
file://0003-plat-corstone1000-delay-early-GPT-access.patch \
"
TFA_DEBUG = "1"
TFA_UBOOT ?= "1"
TFA_MBEDTLS = "1"
TFA_BUILD_TARGET = "bl2 bl31 fip"
# Enabling Secure-EL1 Payload Dispatcher (SPD)
@@ -55,9 +55,6 @@ 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,7 +3,6 @@
COMPATIBLE_MACHINE = "juno"
TFA_PLATFORM = "juno"
TFA_DEBUG = "1"
TFA_MBEDTLS = "1"
TFA_UBOOT ?= "1"
TFA_BUILD_TARGET = "bl1 bl2 bl31 dtbs fip"
@@ -27,3 +27,29 @@ 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,3 +27,29 @@ 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"
@@ -1,8 +1,8 @@
From 4274b94aa0af175e31b8883ec6f2113133608e24 Mon Sep 17 00:00:00 2001
From 4cfcc1af5dd1a9aaadcf42a46d5dc769977b4fed Mon Sep 17 00:00:00 2001
From: Ali Can Ozaslan <ali.oezaslan@arm.com>
Date: Wed, 15 May 2024 12:12:15 +0000
Subject: [PATCH] CC312: alignment of cc312 differences between fvp and mps3
corstone1000 platforms
Subject: [PATCH 01/14] CC312: alignment of cc312 differences between fvp and
mps3 corstone1000 platforms
Configures CC312 mps3 model same as predefined cc312 FVP
configuration while keeping debug ports closed.
@@ -15,10 +15,10 @@ Upstream-Status: Inappropriate [Requires an aligment cc3xx with mps3 hw and fvp
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 31e4332bed64..4b08c02526d3 100644
index b43e86988a41..af8181ca815a 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
@@ -207,6 +207,9 @@ CClibRetCode_t CC_LibInit(CCRndContext_t *rndContext_ptr, CCRndWorkBuff_t *rndW
@@ -209,6 +209,9 @@ CClibRetCode_t CC_LibInit(CCRndContext_t *rndContext_ptr, CCRndWorkBuff_t *rndW
goto InitErr2;
}
@@ -28,3 +28,6 @@ index 31e4332bed64..4b08c02526d3 100644
/* 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);
--
2.39.5
@@ -1,25 +0,0 @@
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
@@ -1,7 +1,7 @@
From dae5f3d1ec85e29f44d3f19bec2312607751ec22 Mon Sep 17 00:00:00 2001
From a02970f522567169fa1851ab1b5431793e365cb0 Mon Sep 17 00:00:00 2001
From: Devaraj Ranganna <devaraj.ranganna@arm.com>
Date: Thu, 18 Sep 2025 22:07:38 +0100
Subject: [PATCH] Corstone-1000: Enable different DRBG configurations
Subject: [PATCH 02/14] Corstone-1000: Enable different DRBG configurations
The following DRBG configurations are enabled:
@@ -18,10 +18,10 @@ Signed-off-by: Devaraj Ranganna <devaraj.ranganna@arm.com>
1 file changed, 7 insertions(+)
diff --git a/platform/ext/target/arm/corstone1000/cc3xx_config.h b/platform/ext/target/arm/corstone1000/cc3xx_config.h
index ac034b17982a..e3f78439861f 100644
index 68707f3a2194..8c53cace937c 100644
--- a/platform/ext/target/arm/corstone1000/cc3xx_config.h
+++ b/platform/ext/target/arm/corstone1000/cc3xx_config.h
@@ -90,6 +90,13 @@
@@ -100,6 +100,13 @@
#error "cc3xx_config: RNG config must select a single DRBG"
#endif /* CC3XX_CONFIG_RNG_DRBG_HMAC + CC3XX_CONFIG_RNG_DRBG_CTR + CC3XX_CONFIG_RNG_DRBG_HASH */
@@ -35,3 +35,6 @@ index ac034b17982a..e3f78439861f 100644
/* Whether an external TRNG should be used in place of the standard CC3XX TRNG */
/* #define CC3XX_CONFIG_RNG_EXTERNAL_TRNG */
--
2.39.5
@@ -1,449 +0,0 @@
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;
-}
@@ -1,43 +0,0 @@
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
@@ -0,0 +1,93 @@
From d8141d0d445bc5117b21dc684410b115e82d5568 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 03/14] 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 9bc0f20e1045..d034efe59f5d 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;
--
2.39.5
@@ -0,0 +1,33 @@
From 8a30545506d8a7f58f0ad30130593e0f78e8b219 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 04/14] 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 6bc89fe1155c..2008e9641b49 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;
}
--
2.39.5
@@ -1,33 +0,0 @@
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.")
@@ -1,20 +1,21 @@
From c579565c25937ae9455efe9cc3fbcace84c3e580 Mon Sep 17 00:00:00 2001
From 9192041a3e6eec6b9e63dbdbe7fa49581aafa5b2 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
Subject: [PATCH 05/14] 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 cff80b755..83b0bd27d 100644
index deb14a9215b5..ed4a9f6804c9 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
@@ -1511,7 +1511,6 @@ static psa_status_t fwu_accept_image(struct fwu_metadata *metadata,
@@ -1614,7 +1614,6 @@ static psa_status_t fwu_accept_image(struct fwu_metadata *metadata,
uint8_t number)
{
uint8_t current_state;
@@ -22,7 +23,7 @@ index cff80b755..83b0bd27d 100644
uint32_t active_bank_index;
uint32_t fwu_image_index;
psa_status_t ret;
@@ -1848,7 +1847,6 @@ static psa_status_t fwu_update_metadata(const psa_fwu_component_t *candidates, u
@@ -2160,7 +2159,6 @@ static psa_status_t fwu_update_metadata(const psa_fwu_component_t *candidates, u
{
int ret;
uint32_t active_index;
@@ -30,8 +31,8 @@ index cff80b755..83b0bd27d 100644
uint32_t previous_active_index;
uint8_t fwu_image_index;
@@ -1864,10 +1862,8 @@ static psa_status_t fwu_update_metadata(const psa_fwu_component_t *candidates, u
@@ -2175,10 +2173,8 @@ static psa_status_t fwu_update_metadata(const psa_fwu_component_t *candidates, u
active_index = _metadata.active_index;
if (active_index == BANK_0) {
previous_active_index = BANK_1;
- bank_offset = BANK_1_PARTITION_OFFSET;
@@ -41,3 +42,6 @@ index cff80b755..83b0bd27d 100644
} else {
FWU_LOG_MSG("ERROR: %s: active_index %d\n\r",__func__,active_index);
ret = PSA_ERROR_DATA_INVALID;
--
2.39.5
@@ -1,7 +1,8 @@
From ca0d50fc1abbfe165941dc0bd674bb117f236f87 Mon Sep 17 00:00:00 2001
From 81813176251a37995390338914f309d8ca72549d Mon Sep 17 00:00:00 2001
From: Frazer Carsley <frazer.carsley@arm.com>
Date: Mon, 30 Mar 2026 14:06:20 +0100
Subject: [PATCH] lib: gpt: Show intent of GUIDs in unittests more clearly
Subject: [PATCH 06/14] lib: gpt: Show intent of GUIDs in unittests more
clearly
The standard EFI_GUID macros used in the unittests do not convey the
full meaning of the why that particular GUID is used. The new macros can
@@ -16,7 +17,7 @@ Upstream-Status: Submitted [https://review.trustedfirmware.org/c/TF-M/trusted-fi
1 file changed, 31 insertions(+), 24 deletions(-)
diff --git a/lib/gpt/unittests/gpt/test_gpt.c b/lib/gpt/unittests/gpt/test_gpt.c
index bd161ec74..32dfb8fb2 100644
index bd161ec7445b..32dfb8fb2757 100644
--- a/lib/gpt/unittests/gpt/test_gpt.c
+++ b/lib/gpt/unittests/gpt/test_gpt.c
@@ -69,6 +69,13 @@
@@ -214,3 +215,6 @@ index bd161ec74..32dfb8fb2 100644
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 */
--
2.39.5
@@ -1,46 +0,0 @@
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
@@ -1,7 +1,7 @@
From 229313778bae6ca16d6e3b25437c8e87eddf3084 Mon Sep 17 00:00:00 2001
From 02ce1958e127f0bec9bfb86cd3a3e406644e1fce Mon Sep 17 00:00:00 2001
From: Frazer Carsley <frazer.carsley@arm.com>
Date: Mon, 30 Mar 2026 14:35:45 +0100
Subject: [PATCH] lib: gpt: Provide macro identifying free space
Subject: [PATCH 07/14] lib: gpt: Provide macro identifying free space
In the unit tests, it is often required to know where free space on the
mocked disk is in order to determine where it is valid to create or move
@@ -15,7 +15,7 @@ Upstream-Status: Submitted [https://review.trustedfirmware.org/c/TF-M/trusted-fi
1 file changed, 23 insertions(+), 19 deletions(-)
diff --git a/lib/gpt/unittests/gpt/test_gpt.c b/lib/gpt/unittests/gpt/test_gpt.c
index 32dfb8fb2..0ae660336 100644
index 32dfb8fb2757..0ae6603368e8 100644
--- a/lib/gpt/unittests/gpt/test_gpt.c
+++ b/lib/gpt/unittests/gpt/test_gpt.c
@@ -58,6 +58,7 @@
@@ -155,3 +155,6 @@ index 32dfb8fb2..0ae660336 100644
/* Fourth, start in the backup header area */
TEST_ASSERT_EQUAL(PSA_ERROR_INVALID_ARGUMENT, gpt_entry_move(
--
2.39.5
@@ -1,31 +0,0 @@
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]")
@@ -1,7 +1,7 @@
From 38daa61f876a6becb3968f1360d403f496634131 Mon Sep 17 00:00:00 2001
From 69ee51ca58f8b1460a9ce4649c0e07f21201ff0a Mon Sep 17 00:00:00 2001
From: Frazer Carsley <frazer.carsley@arm.com>
Date: Mon, 16 Mar 2026 16:46:43 +0000
Subject: [PATCH] lib: gpt: Add operation to duplicate entries
Subject: [PATCH 08/14] lib: gpt: Add operation to duplicate entries
Without this new function, callers of the library would have to first
read the entry they want to duplicate, then attempt to create a new
@@ -20,7 +20,7 @@ Upstream-Status: Submitted [https://review.trustedfirmware.org/c/TF-M/trusted-fi
3 files changed, 201 insertions(+)
diff --git a/lib/gpt/inc/gpt.h b/lib/gpt/inc/gpt.h
index 34ce67580..334a08f41 100644
index 34ce675801b3..334a08f41abe 100644
--- a/lib/gpt/inc/gpt.h
+++ b/lib/gpt/inc/gpt.h
@@ -170,6 +170,25 @@ psa_status_t gpt_entry_move(const struct efi_guid_t *guid,
@@ -50,7 +50,7 @@ index 34ce67580..334a08f41 100644
* \brief Creates a partition entry in the table.
*
diff --git a/lib/gpt/src/gpt.c b/lib/gpt/src/gpt.c
index 0335befa7..920c4ccca 100644
index 0335befa7770..920c4ccca78e 100644
--- a/lib/gpt/src/gpt.c
+++ b/lib/gpt/src/gpt.c
@@ -516,6 +516,29 @@ psa_status_t gpt_entry_move(const struct efi_guid_t *guid,
@@ -84,7 +84,7 @@ index 0335befa7..920c4ccca 100644
const uint64_t start,
const uint64_t size,
diff --git a/lib/gpt/unittests/gpt/test_gpt.c b/lib/gpt/unittests/gpt/test_gpt.c
index 0ae660336..5d2c4243f 100644
index 0ae6603368e8..5d2c4243f607 100644
--- a/lib/gpt/unittests/gpt/test_gpt.c
+++ b/lib/gpt/unittests/gpt/test_gpt.c
@@ -738,6 +738,165 @@ void test_gpt_defragment_should_succeedWhenNoIOFailure(void)
@@ -253,3 +253,6 @@ index 0ae660336..5d2c4243f 100644
void test_gpt_entry_create_should_createNewEntry(void)
{
/* Add an entry. It must not overlap with an existing entry and must also
--
2.39.5
@@ -1,7 +1,8 @@
From 0dcbef3a0800a2a610b32935a54762d4b42203f1 Mon Sep 17 00:00:00 2001
From 4dab128d0da86be6ca09b861dfb157a11345e0e7 Mon Sep 17 00:00:00 2001
From: Frazer Carsley <frazer.carsley@arm.com>
Date: Tue, 17 Mar 2026 11:44:14 +0000
Subject: [PATCH] lib: gpt: Consecutively erase blocks when moving partitions
Subject: [PATCH 09/14] lib: gpt: Consecutively erase blocks when moving
partitions
An LBA is typically smaller than a flash sector size, so it becomes
inefficient to erase block by block and also erases the same sector
@@ -21,7 +22,7 @@ Upstream-Status: Submitted [https://review.trustedfirmware.org/c/TF-M/trusted-fi
1 file changed, 75 insertions(+), 27 deletions(-)
diff --git a/lib/gpt/src/gpt.c b/lib/gpt/src/gpt.c
index 920c4ccca..984c8f821 100644
index 920c4ccca78e..984c8f82146c 100644
--- a/lib/gpt/src/gpt.c
+++ b/lib/gpt/src/gpt.c
@@ -207,7 +207,7 @@ static psa_status_t read_entry_from_flash(const struct gpt_t *table,
@@ -238,3 +239,6 @@ index 920c4ccca..984c8f821 100644
memcpy(lba_buf, temp_buf, GPT_HEADER_SIZE);
return ret;
--
2.39.5
@@ -1,487 +0,0 @@
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();
@@ -1,7 +1,7 @@
From 7e2ae2fc4f8ae8a16a24b87d0650c6b4b28fc870 Mon Sep 17 00:00:00 2001
From 60608602c55f92c82263775cbe42b221f3ea5f09 Mon Sep 17 00:00:00 2001
From: Frazer Carsley <frazer.carsley@arm.com>
Date: Wed, 8 Apr 2026 17:39:13 +0100
Subject: [PATCH] lib: gpt: Clarify API operation
Subject: [PATCH 10/14] lib: gpt: Clarify API operation
The move and duplicate operations both also move or copy (respectively)
the partition data, which is not immediately obvious.
@@ -14,7 +14,7 @@ Upstream-Status: Submitted [https://review.trustedfirmware.org/c/TF-M/trusted-fi
1 file changed, 3 insertions(+), 2 deletions(-)
diff --git a/lib/gpt/inc/gpt.h b/lib/gpt/inc/gpt.h
index 334a08f41..c11ecbff2 100644
index 334a08f41abe..c11ecbff2619 100644
--- a/lib/gpt/inc/gpt.h
+++ b/lib/gpt/inc/gpt.h
@@ -152,7 +152,7 @@ __attribute__((nonnull(1)))
@@ -36,3 +36,6 @@ index 334a08f41..c11ecbff2 100644
*
* \param[in] old_guid Entry to duplicate.
* \param[in] start Starting LBA (0 uses the lowest free LBA possible).
--
2.39.5
@@ -1,48 +0,0 @@
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 */
@@ -1,7 +1,7 @@
From f9badce3570bbc89b141c86a6b8a988d90d81f0c Mon Sep 17 00:00:00 2001
From b10d50f554745f2f9a2e43c24e1020c4da15a098 Mon Sep 17 00:00:00 2001
From: Frazer Carsley <frazer.carsley@arm.com>
Date: Wed, 8 Apr 2026 17:51:18 +0100
Subject: [PATCH] lib: gpt: Add metadata-only API operations
Subject: [PATCH 11/14] lib: gpt: Add metadata-only API operations
Both move and duplicate functions also move or copy (respectively) the
partition data. This is not always required, for example if the
@@ -17,7 +17,7 @@ Upstream-Status: Submitted [https://review.trustedfirmware.org/c/TF-M/trusted-fi
3 files changed, 473 insertions(+), 120 deletions(-)
diff --git a/lib/gpt/inc/gpt.h b/lib/gpt/inc/gpt.h
index c11ecbff2..c5bddb470 100644
index c11ecbff2619..c5bddb4704e7 100644
--- a/lib/gpt/inc/gpt.h
+++ b/lib/gpt/inc/gpt.h
@@ -170,6 +170,25 @@ psa_status_t gpt_entry_move(const struct efi_guid_t *guid,
@@ -74,7 +74,7 @@ index c11ecbff2..c5bddb470 100644
* \brief Creates a partition entry in the table.
*
diff --git a/lib/gpt/src/gpt.c b/lib/gpt/src/gpt.c
index 984c8f821..d6528f6a5 100644
index 984c8f82146c..d6528f6a50ef 100644
--- a/lib/gpt/src/gpt.c
+++ b/lib/gpt/src/gpt.c
@@ -222,9 +222,17 @@ static psa_status_t find_gpt_entry(const struct gpt_t *table,
@@ -413,7 +413,7 @@ index 984c8f821..d6528f6a5 100644
restore_to.header.array_lba,
(restore_from->header.num_partitions +
diff --git a/lib/gpt/unittests/gpt/test_gpt.c b/lib/gpt/unittests/gpt/test_gpt.c
index 5d2c4243f..bd9eb8ba1 100644
index 5d2c4243f607..bd9eb8ba1da5 100644
--- a/lib/gpt/unittests/gpt/test_gpt.c
+++ b/lib/gpt/unittests/gpt/test_gpt.c
@@ -897,6 +897,153 @@ void test_gpt_entry_duplicate_should_failWhenTableFull(void)
@@ -699,3 +699,6 @@ index 5d2c4243f..bd9eb8ba1 100644
void test_gpt_attr_set_should_setAttributes(void)
{
/* Start with a populated GPT */
--
2.39.5
@@ -1,53 +0,0 @@
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;
@@ -1,7 +1,7 @@
From 60277832aa6d4a205a5b1180f0513de0eb7c84c6 Mon Sep 17 00:00:00 2001
From 857a18c00ca3301ed6136333732d4c35e838e51f Mon Sep 17 00:00:00 2001
From: Frazer Carsley <frazer.carsley@arm.com>
Date: Tue, 17 Mar 2026 11:05:45 +0000
Subject: [PATCH] plat: cs1k: Add flash erase protection
Subject: [PATCH 12/14] plat: cs1k: Add flash erase protection
The GPT library deals in blocks, whereas flash deals in sectors. On
cs1k, eight blocks make up a sector. So, when the GPT library requests a
@@ -23,7 +23,7 @@ Upstream-Status: Submitted [https://review.trustedfirmware.org/c/TF-M/trusted-fi
1 file changed, 39 insertions(+), 3 deletions(-)
diff --git a/platform/ext/target/arm/corstone1000/io/io_gpt.c b/platform/ext/target/arm/corstone1000/io/io_gpt.c
index 513c77016..f7c3d79d2 100644
index 513c770166cc..f7c3d79d272f 100644
--- a/platform/ext/target/arm/corstone1000/io/io_gpt.c
+++ b/platform/ext/target/arm/corstone1000/io/io_gpt.c
@@ -53,6 +53,32 @@ static uint8_t sector_buf[FLASH_SECTOR_SIZE];
@@ -96,3 +96,6 @@ index 513c77016..f7c3d79d2 100644
}
} else {
/* Partial erase of final sector */
--
2.39.5
@@ -1,147 +0,0 @@
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
@@ -0,0 +1,35 @@
From e7fb39d0124f60b624f535bc78745fbf4aac678c 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 13/14] 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 e2219d80a75c..b7282beb232e 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 */
--
2.39.5
@@ -1,48 +0,0 @@
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;
}
@@ -0,0 +1,70 @@
From 3b01281520036b621166d409634dab9b46d01f70 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 14/14] 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 | 9 +++++++++
2 files changed, 10 insertions(+)
diff --git a/secure_fw/spm/CMakeLists.txt b/secure_fw/spm/CMakeLists.txt
index bf0ab6e99c16..6741c52089de 100644
--- a/secure_fw/spm/CMakeLists.txt
+++ b/secure_fw/spm/CMakeLists.txt
@@ -110,6 +110,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
index 2bafac0c980e..22090c34efc4 100644
--- 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.39.5
@@ -1,41 +0,0 @@
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
@@ -1,90 +0,0 @@
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
@@ -1,217 +0,0 @@
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;
+}
@@ -1,136 +0,0 @@
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;
+}
@@ -1,308 +0,0 @@
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));
+}
@@ -1,961 +0,0 @@
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)
@@ -1,374 +0,0 @@
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 */
@@ -1,713 +0,0 @@
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
@@ -1,412 +0,0 @@
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
@@ -1,280 +0,0 @@
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
@@ -1,74 +0,0 @@
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
*/
@@ -1,28 +0,0 @@
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
@@ -1,28 +0,0 @@
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
@@ -1,25 +0,0 @@
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
)
@@ -1,27 +0,0 @@
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
@@ -1,24 +0,0 @@
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)
@@ -1,27 +0,0 @@
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>
)
@@ -1,51 +0,0 @@
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")
@@ -1,261 +0,0 @@
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;
}
}
@@ -1,40 +0,0 @@
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 =
@@ -1,48 +0,0 @@
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);
Loaded 100 of 271 files, more files were not shown because too many files have changed in this diff. Show more