Platform: RSE: Rename RSE platform files
Renames all 'rss' files to 'rse'. Avoids changes unrelated to moving
files in this commit to keep to commit history clearer.
Signed-off-by: Jamie Fox <jamie.fox@arm.com>
Change-Id: I321aa2cdff6117c869a7128d2866207efd9b3309
diff --git a/docs/platform/arm/rse/index.rst b/docs/platform/arm/rse/index.rst
new file mode 100644
index 0000000..73dc11b
--- /dev/null
+++ b/docs/platform/arm/rse/index.rst
@@ -0,0 +1,22 @@
+#############################
+Runtime Security Engine (RSE)
+#############################
+
+Previously known as Runtime Security Subsystem (RSS).
+
+.. toctree::
+ :maxdepth: 1
+
+ RSE introduction <readme.rst>
+ RSE communication design <rse_comms.rst>
+ RSE hardware key management <rse_key_management.rst>
+ RSE provisioning <rse_provisioning.rst>
+
+RSE also includes the following extra partitions:
+
+- `Measured boot partition <https://git.trustedfirmware.org/TF-M/tf-m-extras.git/tree/partitions/measured_boot/measured_boot_integration_guide.rst>`_
+- `Delegated attestation partition <https://git.trustedfirmware.org/TF-M/tf-m-extras.git/tree/partitions/delegated_attestation/delegated_attest_integration_guide.rst>`_
+
+--------------
+
+*Copyright (c) 2022-2023, Arm Limited. All rights reserved.*
diff --git a/docs/platform/arm/rse/readme.rst b/docs/platform/arm/rse/readme.rst
new file mode 100644
index 0000000..0052f4d
--- /dev/null
+++ b/docs/platform/arm/rse/readme.rst
@@ -0,0 +1,189 @@
+Runtime Security Engine (RSE)
+=============================
+
+Introduction
+------------
+
+Runtime Security Engine (RSE) is an Arm subsystem that provides a reference
+implementation of the HES Host in the
+`Arm Confidential Compute Architecture (CCA) <https://www.arm.com/architecture/security-features/arm-confidential-compute-architecture>`_.
+It is designed to be integrated into A-profile compute subsystems that implement
+Arm CCA, where it serves as the Root of Trust.
+
+RSE initially boots from immutable code (BL1_1) in its internal ROM, before
+jumping to BL1_2, which is provisioned and hash-locked in RSE OTP. The updatable
+MCUBoot BL2 boot stage is loaded from host system flash into RSE SRAM, where it
+is authenticated. BL2 loads and authenticates the TF-M runtime into RSE SRAM
+from host flash. BL2 is also responsible for loading initial boot code into
+other subsystems within the host.
+
+The RSE platform port supports the TF-M Crypto, TF-M Initial Attestation,
+Measured Boot and TF-M Platform services along with the corresponding
+regression tests. It supports the IPC model in multi-core topology with
+Isolation Level 1 and 2.
+
+Building TF-M
+-------------
+
+Follow the instructions in :doc:`Build instructions </building/tfm_build_instruction>`.
+Build TF-M with platform name: `arm/rse/<rse platform name>`
+
+For example for building RSE for Total Compute platforms:
+``-DTFM_PLATFORM=arm/rse/tc``
+
+Signing host images
+-------------------
+
+RSE BL2 can load boot images into other subsystems within the host system. It
+expects images to be signed, with the signatures attached to the images in the
+MCUBoot metadata format.
+
+The `imgtool Python package <https://pypi.org/project/imgtool/>`_ can be used to
+sign images in the required format. To sign a host image using the development
+key distributed with TF-M, use the following command::
+
+ imgtool sign \
+ -k <TF-M base directory>/bl2/ext/mcuboot/root-RSA-3072.pem \
+ --public-key-format full \
+ --max-align 8 \
+ --align 1 \
+ -v "0.0.1" \
+ -s 1 \
+ -H 0x2000 \
+ --pad-header \
+ -S 0x80000 \
+ --pad \
+ -L <load address> \
+ <binary infile> \
+ <signed binary outfile>
+
+The ``load address`` is the logical address in the RSE memory map to which BL2
+will load the image. RSE FW expects the first host image to be loaded to address
+``0x70000000`` (the beginning of the RSE ATU host access region), and each
+subsequent host image to be loaded at an offset of ``0x1000000`` from the
+previous image. The RSE ATU should be configured to map these logical addresses
+to the physical addresses in the host system that the images need to be loaded
+to.
+
+For more information on the ``imgtool`` parameters, see the MCUBoot
+`imgtool documentation <https://docs.mcuboot.com/imgtool.html>`_.
+
+.. warning::
+
+ The TF-M development key must never be used in production. To generate a
+ production key, follow the imgtool documentation.
+
+Running the code
+----------------
+
+To run the built images, first the ROM image must be created from the bl1_1
+binary and the ROM DMA Initial Command Sequence (ICS).::
+
+ srec_cat \
+ bl1_1.bin -Binary -offset 0x0 \
+ rom_dma_ics.bin -Binary -offset 0x1F000 \
+ -o rom.bin -Binary
+
+Then, the flash image must be created by concatenating the images that are
+output from the build. To create the flash image, the following ``fiptool``
+command should be run. ``fiptool`` documentation can be found `here
+<https://trustedfirmware-a.readthedocs.io/en/latest/getting_started/tools-build.html?highlight=fiptool#building-and-using-the-fip-tool>`_.
+Note that an up-to-date fiptool that supports the RSE UUIDs must be used.::
+
+ fiptool create \
+ --align 8192 --rss-bl2 bl2_signed.bin \
+ --align 8192 --rss-ns tfm_ns_signed.bin \
+ --align 8192 --rss-s tfm_s_signed.bin \
+ --align 8192 --rss-scp-bl1 <signed Host SCP BL1 image> \
+ --align 8192 --rss-ap-bl1 <signed Host AP BL1 image> \
+ fip.bin
+
+If you already have a ``fip.bin`` containing host firmware images, RSE FIP
+images can be patched in::
+
+ fiptool update --align 8192 --rss-bl2 bl2_signed.bin fip.bin
+ fiptool update --align 8192 --rss-ns tfm_ns.bin fip.bin
+ fiptool update --align 8192 --rss-s tfm_s.bin fip.bin
+
+If XIP mode is enabled, the following ``fiptool`` command should be run to
+create the flash image::
+
+ fiptool create \
+ --align 8192 --rss-bl2 bl2_signed.bin \
+ --align 8192 --rss-ns tfm_ns_encrypted.bin \
+ --align 8192 --rss-s tfm_s_encrypted.bin \
+ --align 8192 --rss-sic-tables-ns tfm_ns_sic_tables_signed.bin \
+ --align 8192 --rss-sic-tables-s tfm_s_sic_tables_signed.bin \
+ --align 8192 --rss-scp-bl1 <signed Host SCP BL1 image> \
+ --align 8192 --rss-ap-bl1 <signed Host AP BL1 image> \
+ fip.bin
+
+Once the FIP is prepared, a host flash image can be created using ``srec_cat``::
+
+ srec_cat \
+ fip.bin -Binary -offset 0x0 \
+ -o host_flash.bin -Binary
+
+If GPT support is enabled, and a host ``fip.bin`` and ``fip_gpt.bin`` has been
+obtained, RSE images can be inserted by first patching the host FIP and then
+inserting that patched FIP into the GPT image::
+
+ sector_size=$(gdisk -l fip_gpt.bin | grep -i "sector size (logical):" | \
+ sed 's/.*logical): \([0-9]*\) bytes/\1/')
+
+ fip_label=" FIP_A$"
+ fip_start_sector=$(gdisk -l fip_gpt.bin | grep "$fip_label" | awk '{print $2}')
+ fip_sector_am=$(gdisk -l fip_gpt.bin | grep "$fip_label" | awk '{print $3 - $2}')
+
+ dd if=fip.bin of=fip_gpt.bin bs=$sector_size seek=$fip_start_sector \
+ count=$fip_sector_am conv=notrunc
+
+ fip_label = " FIP_B$"
+ fip_start_sector = $(gdisk -l fip_gpt.bin | grep "$fip_label" | awk '{print $2}')
+ fip_sector_am = $(gdisk -l fip_gpt.bin | grep "$fip_label" | awk '{print $3 - $2}')
+
+ dd if=fip.bin of=fip_gpt.bin bs=$sector_size seek=$fip_start_sector \
+ count=$fip_sector_am conv=notrunc
+
+To patch a ``fip_gpt.bin`` without having an initial ``fip.bin``, the FIP can be
+extracted from the GPT image using the following commands (and can then be
+patched and reinserted using the above commands)::
+
+ sector_size=$(gdisk -l fip_gpt.bin | grep -i "sector size (logical):" | \
+ sed 's/.*logical): \([0-9]*\) bytes/\1/')
+
+ fip_label=" FIP_A$"
+ fip_start_sector=$(gdisk -l fip_gpt.bin | grep "$fip_label" | awk '{print $2}')
+ fip_sector_am=$(gdisk -l fip_gpt.bin | grep "$fip_label" | awk '{print $3 - $2}')
+
+ dd if=fip_gpt.bin of=fip.bin bs=$sector_size skip=$fip_start_sector \
+ count=$fip_sector_am conv=notrunc
+
+Once the ``fip_gpt.bin`` is prepared, it is placed at the base of the host flash
+image::
+
+ srec_cat \
+ fip_gpt.bin -Binary -offset 0x0 \
+ -o host_flash.bin -Binary
+
+The RSE ROM binary should be placed in RSE ROM at ``0x11000000`` and the host
+flash binary should be placed at the base of the host flash. For the TC
+platform, this is at ``0x80000000``.
+
+The RSE OTP must be provisioned. On a development platform with
+``TFM_DUMMY_PROVISIONING`` enabled, BL1_1 expects provisioning bundles to be
+preloaded into SRAM. Preload ``encrypted_cm_provisioning_bundle_0.bin`` to the
+base of VM0, and ``encrypted_dm_provisioning_bundle.bin`` to the base of VM1.
+
+If ``TFM_DUMMY_PROVISIONING`` is disabled and provisioning is required, then
+BL1_1 will first wait for the TP mode to be set by a debugger (setting the
+``tp_mode`` variable in the current stack frame is easiest). BL1_1 will then
+wait for provisioning bundles to be loaded to VM0 and VM1 in the same way as
+when ``TFM_DUMMY_PROVISIONING`` is enabled, except that it will not
+automatically perform the reset once each provisioning state is complete. For
+more details about provisioning flows, see
+:doc:`RSE provisioning </platform/arm/rse/rse_provisioning>`.
+
+--------------
+
+*Copyright (c) 2022-2023, Arm Limited. All rights reserved.*
diff --git a/docs/platform/arm/rse/rse_comms.rst b/docs/platform/arm/rse/rse_comms.rst
new file mode 100644
index 0000000..14b0b13
--- /dev/null
+++ b/docs/platform/arm/rse/rse_comms.rst
@@ -0,0 +1,156 @@
+########################
+RSE communication design
+########################
+
+The RSE communication protocol is designed to be a lightweight serialization of
+the psa_call() API through a combination of in-band MHU (Message Handling Unit)
+transport and parameter-passing through shared memory.
+
+**************
+Message format
+**************
+
+To call an RSE service, the client must send a message in-band over the MHU
+sender link to RSE and wait for a reply message on the MHU receiver (either by
+polling the MHU or waiting for interrupt). The messages are defined as packed C
+structs, which are serialized in byte-order over the MHU links.
+
+Messages encoding a psa_call() to RSE take the form::
+
+ __PACKED_STRUCT serialized_psa_msg_t {
+ struct serialized_rss_comms_header_t header;
+ __PACKED_UNION {
+ struct rss_embed_msg_t embed;
+ struct rss_pointer_access_msg_t pointer_access;
+ } msg;
+ };
+
+Replies from RSE take the form::
+
+ __PACKED_STRUCT serialized_psa_reply_t {
+ struct serialized_rss_comms_header_t header;
+ __PACKED_UNION {
+ struct rss_embed_reply_t embed;
+ struct rss_pointer_access_reply_t pointer_access;
+ } reply;
+ };
+
+All messages (calls and replies), in all protocols carry the following header::
+
+ __PACKED_STRUCT serialized_rss_comms_header_t {
+ uint8_t protocol_ver;
+ uint8_t seq_num;
+ uint16_t client_id;
+ };
+
+The ``client_id`` can be used by the caller to identify different clients at the
+endpoint for access control purposes. It is combined with an RSE-internal
+identifier for the endpoint to create the PSA Client ID for the call.
+
+The sequence number, ``seq_num``, is returned in the reply message to allow the
+client to identify which message is being responded to, since replies may be
+out-of-order. The sender is free to assign sequence numbers using a scheme of
+its choice, and it is the sender's responsibility to ensure that two messages
+with the same sequence number are not in simultaneous flight.
+
+The ``protocol_ver`` identifies which message protocol is being used. There are
+two protocols currently supported, "embed" (``protocol_ver=0``) and "pointer
+access" (``protocol_ver=1``).
+
+Embed protocol
+==============
+
+The embed protocol embeds the psa_call iovecs into the message sent over the
+MHU. It has the following format::
+
+ __PACKED_STRUCT rss_embed_msg_t {
+ psa_handle_t handle;
+ uint32_t ctrl_param;
+ uint16_t io_size[PSA_MAX_IOVEC];
+ uint8_t payload[RSS_COMMS_PAYLOAD_MAX_SIZE];
+ };
+
+The ``handle`` is the psa_call handle parameter and the ``ctrl_param`` packs the
+type, in_len and out_len parameters of psa_call into one parameter.
+
+The ``io_size`` array contains the sizes of the up to ``PSA_MAX_IOVEC`` (4)
+iovecs, in order, with the invec sizes before the outvec sizes.
+
+The ``payload`` array then contains the invec data packed contiguously in order.
+The length of this parameter is variable, equal to the sum of the invec lengths
+in io_size. The caller does not need to pad the payload to the maximum size. The
+maximum payload size for this protocol, ``RSS_COMMS_PAYLOAD_MAX_SIZE``, is a
+build-time option.
+
+Replies in the embed protocol take the form::
+
+ __PACKED_STRUCT rss_embed_reply_t {
+ int32_t return_val;
+ uint16_t out_size[PSA_MAX_IOVEC];
+ uint8_t payload[RSS_COMMS_PAYLOAD_MAX_SIZE];
+ };
+
+The ``return_val`` is the return value of the psa_call() invocation, the
+``out_size`` is the (potentially updated) sizes of the outvecs and the
+``payload`` buffer contains the outvec data serialized contiguously in outvec
+order.
+
+Pointer access protocol
+=======================
+
+The pointer access protocol passes the psa_call iovecs as pointers to shared
+memory using the following MHU message format::
+
+ __PACKED_STRUCT rss_pointer_access_msg_t {
+ psa_handle_t handle;
+ uint32_t ctrl_param;
+ uint32_t io_sizes[PSA_MAX_IOVEC];
+ uint64_t host_ptrs[PSA_MAX_IOVEC];
+ };
+
+The ``handle``, ``ctrl_param`` and ``io_sizes`` have the same definition as in
+the embed protocol.
+
+The ``host_ptrs`` point to each of the up to ``PSA_MAX_IOVEC`` iovec buffers in
+host system memory. It is the caller's responsibility to write the invec data to
+the invec pointers before sending the message, and ensure that the memory
+pointed-to remains valid for the duration of the call.
+
+The reply message has the form::
+
+ __PACKED_STRUCT rss_pointer_access_reply_t {
+ int32_t return_val;
+ uint32_t out_size[PSA_MAX_IOVEC];
+ };
+
+The ``return_val`` and ``out_size`` have the same meaning as in the embed
+protocol.
+
+RSE writes the outvec data to the pointers supplied in the call message prior to
+sending the MHU reply message, so no further payload is sent in the reply
+message.
+
+************************
+Implementation structure
+************************
+
+The RSE side of the communication implementation is located in
+``platform/ext/target/arm/rse/common/rse_comms``. The implementation is
+structured as follows:
+
+- ``rse_comms.c``: Implements the TF-M RPC layer using RSE comms implementation.
+- ``rse_comms_hal.c``: Abstracts MHU message sending and receiving.
+
+- ``rse_comms_protocol.c``: The common part of the RSE comms protocol.
+- ``rse_comms_protocol_embed.c``: The embed RSE comms protocol.
+- ``rse_comms_protocol_protocol_access.c``: The pointer access RSE comms protocol.
+
+- ``rse_comms_atu.c``: Allocates and frees ATU regions for host pointer access.
+- ``rse_comms_permissions_hal.c``: Checks service access permissions and pointer validity.
+
+A reference implementation of the client side of the RSE comms is available in
+the Trusted Firmware-A repository.
+
+--------------
+
+*Copyright (c) 2022-2023, Arm Limited. All rights reserved.*
diff --git a/docs/platform/arm/rse/rse_key_management.rst b/docs/platform/arm/rse/rse_key_management.rst
new file mode 100644
index 0000000..8ce261b
--- /dev/null
+++ b/docs/platform/arm/rse/rse_key_management.rst
@@ -0,0 +1,53 @@
+RSE key management
+==================
+
+The RSE has a set of hardware components that act together to prevent hardware
+protected keys being disclosed to compromised software. This chain involves the
+LifeCycle Manager "LCM", the Key Management Unit "KMU", and the cryptographic
+accelerator in the integration layer of the RSE (which in reference RSE builds
+is a CryptoCell-3XX series accelerator).
+
+Hardware protected keys (henceforth "Hardware Keys") are stored in the LCM, in
+protected keyslots. On production-mode "PCI" chips these slots are write-only.
+They are protected during provisioning from disclosure by Secure Provisioning
+"SP" mode disabling debug, and the encryption with either the RTL key or the CM
+provisioning key. On boot, the LCM checks the integrity of the stored hardware
+keys by comparing the amount of zeroes with a stored zero-count which, because
+of the property of the OTP that does not allow 1-bits to be set to 0-bits,
+allows detection of any changes in the keys. If the check succeeds it exports
+the keys to the KMU over a private memory bus (one that is not accessible
+programs running on the RSE' CPU or other controllers on the main bus such as
+the DMA).
+
+The KMU has between 2 and 32 hardware keyslots, which are 256 bit (32 byte) in
+size. Between 0 and 8 of these are hardware keyslots, and correspond to the
+hardware keyslots in the LCM. These slots are filled by the key export from the
+LCM, and have their permissions preconfigured so they are not readable or
+writable by software. Software KMU keyslots (keyslots that are not defined in
+hardware as hardware keyslots) can be read and written, and then subsequently
+locked to prevent reading and writing, so that they behave like hardware
+keyslots. This allows trusted immutable firmware to set up keys for less-trusted
+later stage code, which can be used but cannot be read. KMU keyslots can be
+exported over another private bus to the cryptographic accelerator. Hardware
+keyslots can be invalidated, making them unusable until a hard reset.
+
+The cryptographic accelerator receives the key into a write-only key register,
+and then can use it to perform cryptographic operations. For the CryptoCell-3XX
+series, this is limited to AES. As with the previous stages, software cannot
+retrieve the key, only use it. Note that currently this can only be used with
+the cc3xx_rom_lib driver, not the cryptocell-312-runtime driver, as the latter
+requires modification. Note that this path is the only way to use hardware
+protected keys on the RSE, they cannot be used by software cryptographic
+libraries that require key material to be accessible by software.
+
+The RSE uses this functionality to allow key derivation (based on NIST SP800-108
+with an RSA-based PRF that can utilise the hardware keys as described above)
+from the HUK and GUK. This allows the derivation of the CCA platform attestation
+key / delegated attestation root key without allowing access to the GUK
+directly. As a further security measure, these keys are derived by ROM/OTP code,
+and the HUK and GUK are then invalidated so they cannot be used by the runtime
+firmware and BL2.
+
+--------------
+
+*Copyright (c) 2022-2023, Arm Limited. All rights reserved.*
diff --git a/docs/platform/arm/rse/rse_provisioning.rst b/docs/platform/arm/rse/rse_provisioning.rst
new file mode 100644
index 0000000..3a4ee43
--- /dev/null
+++ b/docs/platform/arm/rse/rse_provisioning.rst
@@ -0,0 +1,147 @@
+RSE provisioning
+================
+
+Provisioning theory
+-------------------
+
+The LifeCycle Manager (LCM) controls access to the RSE OTP, and includes a
+state-machine that controls Lifecycle-state (LCS) transitions. The LCM is
+derived from the OTP management and state machine subsystems of the
+CryptoCell-3XX series accelerators, and will be familiar to those who have
+worked with them.
+
+When the chip hasn't been provisioned, the OTP is blank, which means the LCM is
+in "Virgin" Test/Production mode "TP mode" state. The first step for
+provisioning must be to set the LCM to either test-chip mode "TCI" or
+production-chip mode "PCI". In TCI mode the RTL key is masked to avoid
+disclosure, several OTP fields are changed from write-only to read-write, to aid
+in debugging, and debugging is not limited in secure provisioning mode (though
+the RTL key reads as zero). If ``TFM_DUMMY_PROVISIONING`` is enabled in cmake
+(which it is by default) then the chip will be set to TCI mode. If this option
+is not enabled, execution will pause to allow the setting to be set by a
+debugger.
+
+Once the TP mode has been set, the chip is then is Chip Manufacturer
+provisioning state "CM". This mode is intended for the provisioning of the HUK,
+GUK, CM provisioning key, CM code-encryption key, the root-of-trust public key
+and the CM config. To provision these fields, The firmware must first receive a
+provisioning bundle via a debugger. This bundle must be placed at the start of
+VM0 + an offset the size of the OTP DMA ICS (usually 0x400). This bundle
+contains the keys and also code to perform the provisioning such as a driver for
+the LCM, and a function to randomly generate the HUK via the CryptoCell TRNG.
+The chip must then enter secure provisioning mode by setting the SP_ENABLE
+register. This causes a reset (but does not clear the RSE SRAMs), and allows
+access to the RTL key by exporting it to the KMU, though in secure provisioning
+mode the ability to debug the RSE is disabled, to prevent disclosure of the
+decrypted provisioning bundle values. The RSE will then decrypt and authenticate
+the bundle using the RTL key. Under TCI mode the RTL key is zeroed, the bundle
+generation tool must use a zeroed key to encrypt and sign the bundle. Once the
+CM provisioning bundle has been unpacked, the RSE will execute the code which
+will provision the CM provisioning data into OTP. The RSE must be cold-reset,
+which will disable secure provisioning mode. If ``TFM_DUMMY_PROVISIONING`` is
+enabled the reset will happen automatically, else the external provisioning
+device should read the provisioning state from the GPIO/PSI (which is set via
+the ``rss_sysctrl`` register) and perform the reset.
+
+After the cold reset, the RSE will automatically transition to Device
+Manufacturer provisioning state "DM" as the LCM hardware state-machine reads the
+values of the cm_config_1 and cm_config_2 fields as non-zero. This state is
+designed to provision the DM provisioning key, the DM code-encryption key and
+the DM config. The procedure follows the same steps as the CM provisioning flow,
+with the exception that the bundle will now be encrypted and signed using the CM
+provisioning key and must be placed at the base of VM1. As before, once the
+provisioning bundle has been unpacked/run, the RSE must either be cold-reset or
+will perform this automatically.
+
+After the cold reset, the device will now be in Secure Enable "SE" mode, due to
+the dm_config_1 field being non-zero. Debug may be limited based on the hardware
+DCU mask for SE state. Provisioning will not be run on boot.
+
+Practical RSE provisioning
+--------------------------
+
+The RSE buildsystem produces two provisioning bundles (containing both code and
+data), and then encrypts and signs them with the RTL key to produce
+``encrypted_cm_provisioning_bundle.bin`` and
+``encrypted_dm_provisioning_bundle.bin``.
+
+.. Note::
+ Currently encrypted provisioning bundles are not supported due to a lack of
+ AEAD encryption support in the cc312-rom-lib driver. The
+ encrypted_*_provisioning_bundle.bin files should still be used, but note that
+ their contents are not encrypted.
+
+On first boot, the RSE is in Virgin state. If the RSE firmware was built with
+``TFM_DUMMY_PROVISIONING`` enabled then it will automatically set the chip to
+TCI mode and cold-reset. Production ROM implementations must disable
+``TFM_DUMMY_PROVISIONING``, which will cause RSE to loop in the ROM until either
+TCI or PCI mode is set with a debugger. It is possible to set the TP mode in the
+LCS registers directly, however it may be easier to set the ``tp_mode`` variable
+in the frame where RSE is looping, at which point the loop will exit and the TP
+mode will be set by the ROM code.
+
+On non-virgin boot in CM lifecycle state, RSE checks the start of VM0 for the
+magic constant ``0xC0DEFEED``, which is required to be the first word in the CM
+provisioning bundle. There is also a second check for a constant at the end of
+the bundle to ensure the bundle has finished writing. The RSE will perform this
+check in a loop until a bundle is found.
+
+This procedure is repeated for DM LCS, except that the magic constant is
+``0xBEEFFEED`` and the bundle must be loaded to the base of VM1. Note that the
+size of RSE memory may vary depending on implementation, so the load address of
+the DM bundle may change.
+
+In production systems it is intended that these bundles are loaded by a
+debugger, but for development systems it may be too onerous to perform this
+procedure, particularly if the system is one that has ephemeral OTP such as an
+FVP. The preferred solution is to preload to the provisioning bundles into VM0
+and VM1 as part of the image loading, which is supported on FVPs but may not be
+on other systems. An alternative solution is to perform provisioning manually
+once, and then to save the state of the OTP in SE LCS and then preload that on
+subsequent boots.
+
+RSE provisioning GPIO signalling
+--------------------------------
+The state of the RSE ROM boot/provisioning flow is signalled outside of the RSE
+subsystem via the GPIOs as part of the Persistent State Interface (PSI). The PSI
+signals the lifecycle state as a hardware signal, but additionally the software
+can signal over the PSI by setting the ``rss_sysctrl`` register.
+
+The boot state is encoded in the lowest 4 bits of the ``rss_sysctrl`` register,
+and has meaning as follows:
+
++--------+------------------------------------------------------------------+
+| Signal | State |
++========+==================================================================+
+| 0x0 | RSE cold boot default |
++--------+------------------------------------------------------------------+
+| 0x1 | Virgin chip idle, ready to set PCI/TCI mode |
++--------+------------------------------------------------------------------+
+| 0x2 | CM LCS idle, waiting for CM provisioning bundle |
++--------+------------------------------------------------------------------+
+| 0x3 | RMA LCS idle |
++--------+------------------------------------------------------------------+
+| 0x4 | CM secure provisioning started, secure provisioning mode enabled |
++--------+------------------------------------------------------------------+
+| 0x5 | CM secure provisioning failed due to bundle authentication error |
++--------+------------------------------------------------------------------+
+| 0x6 | CM secure provisioning failed due to other error |
++--------+------------------------------------------------------------------+
+| 0x7 | CM secure provisioning succeeded |
++--------+------------------------------------------------------------------+
+| 0x8 | DM LCS idle, waiting for CM provisioning bundle |
++--------+------------------------------------------------------------------+
+| 0x9 | DM secure provisioning started, secure provisioning mode enabled |
++--------+------------------------------------------------------------------+
+| 0xa | DM secure provisioning failed due to bundle authentication error |
++--------+------------------------------------------------------------------+
+| 0xb | DM secure provisioning failed due to other error |
++--------+------------------------------------------------------------------+
+| 0xc | DM secure provisioning succeeded |
++--------+------------------------------------------------------------------+
+| 0xd | SE LCS standard boot |
++--------+------------------------------------------------------------------+
+
+--------------
+
+*Copyright (c) 2022-2024, Arm Limited. All rights reserved.*