Merge changes from topic "rss/mboot-attest" into integration
* changes:
docs(maintainers): add PSA, MHU, RSS comms code owners
feat(plat/arm/fvp): enable RSS backend based measured boot
feat(lib/psa): mock PSA APIs
feat(drivers/measured_boot): add RSS backend
feat(drivers/arm/rss): add RSS communication driver
feat(lib/psa): add initial attestation API
feat(lib/psa): add measured boot API
feat(drivers/arm/mhu): add MHU driver
diff --git a/Makefile b/Makefile
index 16c85bc..b42bdc5 100644
--- a/Makefile
+++ b/Makefile
@@ -1011,6 +1011,7 @@
NS_TIMER_SWITCH \
OVERRIDE_LIBC \
PL011_GENERIC_UART \
+ PLAT_RSS_NOT_SUPPORTED \
PROGRAMMABLE_RESET_ADDRESS \
PSCI_EXTENDED_STATE_ID \
RESET_TO_BL31 \
@@ -1146,6 +1147,7 @@
NS_TIMER_SWITCH \
PL011_GENERIC_UART \
PLAT_${PLAT} \
+ PLAT_RSS_NOT_SUPPORTED \
PROGRAMMABLE_RESET_ADDRESS \
PSCI_EXTENDED_STATE_ID \
RAS_EXTENSION \
diff --git a/docs/about/maintainers.rst b/docs/about/maintainers.rst
index b9b5878..c62a6be 100644
--- a/docs/about/maintainers.rst
+++ b/docs/about/maintainers.rst
@@ -293,6 +293,20 @@
:|G|: `odeprez`_
:|F|: drivers/arm/gic/
+Message Handling Unit (MHU) driver
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+:|M|: David Vincze <david.vincze@arm.com>
+:|G|: `davidvincze`_
+:|F|: include/drivers/arm/mhu.h
+:|F|: drivers/arm/mhu
+
+Runtime Security Subsystem (RSS) comms driver
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+:|M|: David Vincze <david.vincze@arm.com>
+:|G|: `davidvincze`_
+:|F|: include/drivers/arm/rss_comms.h
+:|F|: drivers/arm/rss
+
Libfdt wrappers
^^^^^^^^^^^^^^^
:|M|: Madhukar Pappireddy <Madhukar.Pappireddy@arm.com>
@@ -331,6 +345,13 @@
:|F|: drivers/fwu
:|F|: include/drivers/fwu
+Platform Security Architecture (PSA) APIs
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+:|M|: Sandrine Bailleux <sandrine.bailleux@arm.com>
+:|G|: `sandrine-bailleux-arm`_
+:|F|: include/lib/psa
+:|F|: lib/psa
+
System Control and Management Interface (SCMI) Server
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
:|M|: Etienne Carriere <etienne.carriere@st.com>
@@ -821,6 +842,7 @@
.. _b49020: https://github.com/b49020
.. _carlocaione: https://github.com/carlocaione
.. _danh-arm: https://github.com/danh-arm
+.. _davidvincze: https://github.com/davidvincze
.. _etienne-lms: https://github.com/etienne-lms
.. _glneo: https://github.com/glneo
.. _grandpaul: https://github.com/grandpaul
diff --git a/docs/getting_started/build-options.rst b/docs/getting_started/build-options.rst
index d2cda4d..742b6b5 100644
--- a/docs/getting_started/build-options.rst
+++ b/docs/getting_started/build-options.rst
@@ -994,6 +994,11 @@
if FEAT_TRF is implemented. This flag can take the values 0 to 2, to align
with the ``FEATURE_DETECTION`` mechanism. This flag is disabled by default.
+- ``PLAT_RSS_NOT_SUPPORTED``: Boolean option to enable the usage of the PSA
+ APIs on platforms that doesn't support RSS (providing Arm CCA HES
+ functionalities). When enabled (``1``), a mocked version of the APIs are used.
+ The default value is 0.
+
GICv3 driver options
--------------------
diff --git a/drivers/arm/mhu/mhu_v2_x.c b/drivers/arm/mhu/mhu_v2_x.c
new file mode 100644
index 0000000..3103b92
--- /dev/null
+++ b/drivers/arm/mhu/mhu_v2_x.c
@@ -0,0 +1,379 @@
+/*
+ * Copyright (c) 2020-2022, Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <assert.h>
+#include <stdbool.h>
+#include <stdint.h>
+
+#include "mhu_v2_x.h"
+
+#define MHU_V2_X_MAX_CHANNELS 124
+#define MHU_V2_1_MAX_CHCOMB_INT 4
+#define ENABLE 0x1
+#define DISABLE 0x0
+#define CLEAR_INTR 0x1
+#define CH_PER_CH_COMB 0x20
+#define SEND_FRAME(p_mhu) ((struct mhu_v2_x_send_frame_t *)p_mhu)
+#define RECV_FRAME(p_mhu) ((struct mhu_v2_x_recv_frame_t *)p_mhu)
+
+#define MHU_MAJOR_REV_V2 0x1u
+#define MHU_MINOR_REV_2_0 0x0u
+#define MHU_MINOR_REV_2_1 0x1u
+
+struct mhu_v2_x_send_ch_window_t {
+ /* Offset: 0x00 (R/ ) Channel Status */
+ volatile uint32_t ch_st;
+ /* Offset: 0x04 (R/ ) Reserved */
+ volatile uint32_t reserved_0;
+ /* Offset: 0x08 (R/ ) Reserved */
+ volatile uint32_t reserved_1;
+ /* Offset: 0x0C ( /W) Channel Set */
+ volatile uint32_t ch_set;
+ /* Offset: 0x10 (R/ ) Channel Interrupt Status (Reserved in 2.0) */
+ volatile uint32_t ch_int_st;
+ /* Offset: 0x14 ( /W) Channel Interrupt Clear (Reserved in 2.0) */
+ volatile uint32_t ch_int_clr;
+ /* Offset: 0x18 (R/W) Channel Interrupt Enable (Reserved in 2.0) */
+ volatile uint32_t ch_int_en;
+ /* Offset: 0x1C (R/ ) Reserved */
+ volatile uint32_t reserved_2;
+};
+
+struct mhu_v2_x_send_frame_t {
+ /* Offset: 0x000 ( / ) Sender Channel Window 0 -123 */
+ struct mhu_v2_x_send_ch_window_t send_ch_window[MHU_V2_X_MAX_CHANNELS];
+ /* Offset: 0xF80 (R/ ) Message Handling Unit Configuration */
+ volatile uint32_t mhu_cfg;
+ /* Offset: 0xF84 (R/W) Response Configuration */
+ volatile uint32_t resp_cfg;
+ /* Offset: 0xF88 (R/W) Access Request */
+ volatile uint32_t access_request;
+ /* Offset: 0xF8C (R/ ) Access Ready */
+ volatile uint32_t access_ready;
+ /* Offset: 0xF90 (R/ ) Interrupt Status */
+ volatile uint32_t int_st;
+ /* Offset: 0xF94 ( /W) Interrupt Clear */
+ volatile uint32_t int_clr;
+ /* Offset: 0xF98 (R/W) Interrupt Enable */
+ volatile uint32_t int_en;
+ /* Offset: 0xF9C (R/ ) Reserved */
+ volatile uint32_t reserved_0;
+ /* Offset: 0xFA0 (R/W) Channel Combined IRQ Stat (Reserved in 2.0) */
+ volatile uint32_t ch_comb_int_st[MHU_V2_1_MAX_CHCOMB_INT];
+ /* Offset: 0xFC4 (R/ ) Reserved */
+ volatile uint32_t reserved_1[6];
+ /* Offset: 0xFC8 (R/ ) Implementer Identification Register */
+ volatile uint32_t iidr;
+ /* Offset: 0xFCC (R/ ) Architecture Identification Register */
+ volatile uint32_t aidr;
+ /* Offset: 0xFD0 (R/ ) */
+ volatile uint32_t pid_1[4];
+ /* Offset: 0xFE0 (R/ ) */
+ volatile uint32_t pid_0[4];
+ /* Offset: 0xFF0 (R/ ) */
+ volatile uint32_t cid[4];
+};
+
+struct mhu_v2_x_rec_ch_window_t {
+ /* Offset: 0x00 (R/ ) Channel Status */
+ volatile uint32_t ch_st;
+ /* Offset: 0x04 (R/ ) Channel Status Masked */
+ volatile uint32_t ch_st_msk;
+ /* Offset: 0x08 ( /W) Channel Clear */
+ volatile uint32_t ch_clr;
+ /* Offset: 0x0C (R/ ) Reserved */
+ volatile uint32_t reserved_0;
+ /* Offset: 0x10 (R/ ) Channel Mask Status */
+ volatile uint32_t ch_msk_st;
+ /* Offset: 0x14 ( /W) Channel Mask Set */
+ volatile uint32_t ch_msk_set;
+ /* Offset: 0x18 ( /W) Channel Mask Clear */
+ volatile uint32_t ch_msk_clr;
+ /* Offset: 0x1C (R/ ) Reserved */
+ volatile uint32_t reserved_1;
+};
+
+struct mhu_v2_x_recv_frame_t {
+ /* Offset: 0x000 ( / ) Receiver Channel Window 0 -123 */
+ struct mhu_v2_x_rec_ch_window_t rec_ch_window[MHU_V2_X_MAX_CHANNELS];
+ /* Offset: 0xF80 (R/ ) Message Handling Unit Configuration */
+ volatile uint32_t mhu_cfg;
+ /* Offset: 0xF84 (R/ ) Reserved */
+ volatile uint32_t reserved_0[3];
+ /* Offset: 0xF90 (R/ ) Interrupt Status (Reserved in 2.0) */
+ volatile uint32_t int_st;
+ /* Offset: 0xF94 (R/ ) Interrupt Clear (Reserved in 2.0) */
+ volatile uint32_t int_clr;
+ /* Offset: 0xF98 (R/W) Interrupt Enable (Reserved in 2.0) */
+ volatile uint32_t int_en;
+ /* Offset: 0xF9C (R/ ) Reserved */
+ volatile uint32_t reserved_1;
+ /* Offset: 0xFA0 (R/ ) Channel Combined IRQ Stat (Reserved in 2.0) */
+ volatile uint32_t ch_comb_int_st[MHU_V2_1_MAX_CHCOMB_INT];
+ /* Offset: 0xFB0 (R/ ) Reserved */
+ volatile uint32_t reserved_2[6];
+ /* Offset: 0xFC8 (R/ ) Implementer Identification Register */
+ volatile uint32_t iidr;
+ /* Offset: 0xFCC (R/ ) Architecture Identification Register */
+ volatile uint32_t aidr;
+ /* Offset: 0xFD0 (R/ ) */
+ volatile uint32_t pid_1[4];
+ /* Offset: 0xFE0 (R/ ) */
+ volatile uint32_t pid_0[4];
+ /* Offset: 0xFF0 (R/ ) */
+ volatile uint32_t cid[4];
+};
+
+union mhu_v2_x_frame {
+ struct mhu_v2_x_send_frame_t send_frame;
+ struct mhu_v2_x_recv_frame_t recv_frame;
+};
+
+enum mhu_v2_x_error_t mhu_v2_x_driver_init(struct mhu_v2_x_dev_t *dev,
+ enum mhu_v2_x_supported_revisions rev)
+{
+ uint32_t AIDR = 0;
+ union mhu_v2_x_frame *p_mhu;
+
+ assert(dev != NULL);
+
+ p_mhu = (union mhu_v2_x_frame *)dev->base;
+
+ if (dev->is_initialized) {
+ return MHU_V_2_X_ERR_ALREADY_INIT;
+ }
+
+ if (rev == MHU_REV_READ_FROM_HW) {
+ /* Read revision from HW */
+ if (dev->frame == MHU_V2_X_RECEIVER_FRAME) {
+ AIDR = p_mhu->recv_frame.aidr;
+ } else {
+ AIDR = p_mhu->send_frame.aidr;
+ }
+
+ /* Get bits 7:4 to read major revision */
+ if (((AIDR >> 4) & 0b1111) != MHU_MAJOR_REV_V2) {
+ /* Unsupported MHU version */
+ return MHU_V_2_X_ERR_UNSUPPORTED_VERSION;
+ } /* No need to save major version, driver only supports MHUv2 */
+
+ /* Get bits 3:0 to read minor revision */
+ dev->subversion = AIDR & 0b1111;
+
+ if (dev->subversion != MHU_MINOR_REV_2_0 &&
+ dev->subversion != MHU_MINOR_REV_2_1) {
+ /* Unsupported subversion */
+ return MHU_V_2_X_ERR_UNSUPPORTED_VERSION;
+ }
+ } else {
+ /* Revisions were provided by caller */
+ if (rev == MHU_REV_2_0) {
+ dev->subversion = MHU_MINOR_REV_2_0;
+ } else if (rev == MHU_REV_2_1) {
+ dev->subversion = MHU_MINOR_REV_2_1;
+ } else {
+ /* Unsupported subversion */
+ return MHU_V_2_X_ERR_UNSUPPORTED_VERSION;
+ } /* No need to save major version, driver only supports MHUv2 */
+ }
+
+ dev->is_initialized = true;
+
+ return MHU_V_2_X_ERR_NONE;
+}
+
+uint32_t mhu_v2_x_get_num_channel_implemented(const struct mhu_v2_x_dev_t *dev)
+{
+ union mhu_v2_x_frame *p_mhu;
+
+ assert(dev != NULL);
+
+ p_mhu = (union mhu_v2_x_frame *)dev->base;
+
+ if (!(dev->is_initialized)) {
+ return MHU_V_2_X_ERR_NOT_INIT;
+ }
+
+ if (dev->frame == MHU_V2_X_SENDER_FRAME) {
+ return (SEND_FRAME(p_mhu))->mhu_cfg;
+ } else {
+ assert(dev->frame == MHU_V2_X_RECEIVER_FRAME);
+ return (RECV_FRAME(p_mhu))->mhu_cfg;
+ }
+}
+
+enum mhu_v2_x_error_t mhu_v2_x_channel_send(const struct mhu_v2_x_dev_t *dev,
+ uint32_t channel, uint32_t val)
+{
+ union mhu_v2_x_frame *p_mhu;
+
+ assert(dev != NULL);
+
+ p_mhu = (union mhu_v2_x_frame *)dev->base;
+
+ if (!(dev->is_initialized)) {
+ return MHU_V_2_X_ERR_NOT_INIT;
+ }
+
+ if (dev->frame == MHU_V2_X_SENDER_FRAME) {
+ (SEND_FRAME(p_mhu))->send_ch_window[channel].ch_set = val;
+ return MHU_V_2_X_ERR_NONE;
+ } else {
+ return MHU_V_2_X_ERR_INVALID_ARG;
+ }
+}
+
+enum mhu_v2_x_error_t mhu_v2_x_channel_poll(const struct mhu_v2_x_dev_t *dev,
+ uint32_t channel, uint32_t *value)
+{
+ union mhu_v2_x_frame *p_mhu;
+
+ assert(dev != NULL);
+
+ p_mhu = (union mhu_v2_x_frame *)dev->base;
+
+ if (!(dev->is_initialized)) {
+ return MHU_V_2_X_ERR_NOT_INIT;
+ }
+
+ if (dev->frame == MHU_V2_X_SENDER_FRAME) {
+ *value = (SEND_FRAME(p_mhu))->send_ch_window[channel].ch_st;
+ return MHU_V_2_X_ERR_NONE;
+ } else {
+ return MHU_V_2_X_ERR_INVALID_ARG;
+ }
+}
+
+enum mhu_v2_x_error_t mhu_v2_x_channel_clear(const struct mhu_v2_x_dev_t *dev,
+ uint32_t channel)
+{
+ union mhu_v2_x_frame *p_mhu;
+
+ assert(dev != NULL);
+
+ p_mhu = (union mhu_v2_x_frame *)dev->base;
+
+ if (!(dev->is_initialized)) {
+ return MHU_V_2_X_ERR_NOT_INIT;
+ }
+
+ if (dev->frame == MHU_V2_X_RECEIVER_FRAME) {
+ (RECV_FRAME(p_mhu))->rec_ch_window[channel].ch_clr = UINT32_MAX;
+ return MHU_V_2_X_ERR_NONE;
+ } else {
+ return MHU_V_2_X_ERR_INVALID_ARG;
+ }
+}
+
+enum mhu_v2_x_error_t mhu_v2_x_channel_receive(
+ const struct mhu_v2_x_dev_t *dev, uint32_t channel, uint32_t *value)
+{
+ union mhu_v2_x_frame *p_mhu;
+
+ assert(dev != NULL);
+
+ p_mhu = (union mhu_v2_x_frame *)dev->base;
+
+ if (!(dev->is_initialized)) {
+ return MHU_V_2_X_ERR_NOT_INIT;
+ }
+
+ if (dev->frame == MHU_V2_X_RECEIVER_FRAME) {
+ *value = (RECV_FRAME(p_mhu))->rec_ch_window[channel].ch_st;
+ return MHU_V_2_X_ERR_NONE;
+ } else {
+ return MHU_V_2_X_ERR_INVALID_ARG;
+ }
+}
+
+enum mhu_v2_x_error_t mhu_v2_x_channel_mask_set(
+ const struct mhu_v2_x_dev_t *dev, uint32_t channel, uint32_t mask)
+{
+ union mhu_v2_x_frame *p_mhu;
+
+ assert(dev != NULL);
+
+ p_mhu = (union mhu_v2_x_frame *)dev->base;
+
+ if (!(dev->is_initialized)) {
+ return MHU_V_2_X_ERR_NOT_INIT;
+ }
+
+ if (dev->frame == MHU_V2_X_RECEIVER_FRAME) {
+ (RECV_FRAME(p_mhu))->rec_ch_window[channel].ch_msk_set = mask;
+ return MHU_V_2_X_ERR_NONE;
+ } else {
+ return MHU_V_2_X_ERR_INVALID_ARG;
+ }
+}
+
+enum mhu_v2_x_error_t mhu_v2_x_channel_mask_clear(
+ const struct mhu_v2_x_dev_t *dev, uint32_t channel, uint32_t mask)
+{
+ union mhu_v2_x_frame *p_mhu;
+
+ assert(dev != NULL);
+
+ p_mhu = (union mhu_v2_x_frame *)dev->base;
+
+ if (!(dev->is_initialized)) {
+ return MHU_V_2_X_ERR_NOT_INIT;
+ }
+
+ if (dev->frame == MHU_V2_X_RECEIVER_FRAME) {
+ (RECV_FRAME(p_mhu))->rec_ch_window[channel].ch_msk_clr = mask;
+ return MHU_V_2_X_ERR_NONE;
+ } else {
+ return MHU_V_2_X_ERR_INVALID_ARG;
+ }
+}
+enum mhu_v2_x_error_t mhu_v2_x_initiate_transfer(
+ const struct mhu_v2_x_dev_t *dev)
+{
+ union mhu_v2_x_frame *p_mhu;
+
+ assert(dev != NULL);
+
+ p_mhu = (union mhu_v2_x_frame *)dev->base;
+
+ if (!(dev->is_initialized)) {
+ return MHU_V_2_X_ERR_NOT_INIT;
+ }
+
+ if (dev->frame != MHU_V2_X_SENDER_FRAME) {
+ return MHU_V_2_X_ERR_INVALID_ARG;
+ }
+
+ (SEND_FRAME(p_mhu))->access_request = ENABLE;
+
+ while (!((SEND_FRAME(p_mhu))->access_ready)) {
+ /* Wait in a loop for access ready signal to be high */
+ ;
+ }
+
+ return MHU_V_2_X_ERR_NONE;
+}
+
+enum mhu_v2_x_error_t mhu_v2_x_close_transfer(const struct mhu_v2_x_dev_t *dev)
+{
+ union mhu_v2_x_frame *p_mhu;
+
+ assert(dev != NULL);
+
+ p_mhu = (union mhu_v2_x_frame *)dev->base;
+
+ if (!(dev->is_initialized)) {
+ return MHU_V_2_X_ERR_NOT_INIT;
+ }
+
+ if (dev->frame != MHU_V2_X_SENDER_FRAME) {
+ return MHU_V_2_X_ERR_INVALID_ARG;
+ }
+
+ (SEND_FRAME(p_mhu))->access_request = DISABLE;
+
+ return MHU_V_2_X_ERR_NONE;
+}
diff --git a/drivers/arm/mhu/mhu_v2_x.h b/drivers/arm/mhu/mhu_v2_x.h
new file mode 100644
index 0000000..10247d2
--- /dev/null
+++ b/drivers/arm/mhu/mhu_v2_x.h
@@ -0,0 +1,210 @@
+/*
+ * Copyright (c) 2020-2022, Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef MHU_V2_X_H
+#define MHU_V2_X_H
+
+#include <stdbool.h>
+#include <stdint.h>
+
+#define MHU_2_X_INTR_NR2R_OFF (0x0u)
+#define MHU_2_X_INTR_R2NR_OFF (0x1u)
+#define MHU_2_1_INTR_CHCOMB_OFF (0x2u)
+
+#define MHU_2_X_INTR_NR2R_MASK (0x1u << MHU_2_X_INTR_NR2R_OFF)
+#define MHU_2_X_INTR_R2NR_MASK (0x1u << MHU_2_X_INTR_R2NR_OFF)
+#define MHU_2_1_INTR_CHCOMB_MASK (0x1u << MHU_2_1_INTR_CHCOMB_OFF)
+
+enum mhu_v2_x_frame_t {
+ MHU_V2_X_SENDER_FRAME = 0x0u,
+ MHU_V2_X_RECEIVER_FRAME = 0x1u,
+};
+
+enum mhu_v2_x_supported_revisions {
+ MHU_REV_READ_FROM_HW = 0,
+ MHU_REV_2_0,
+ MHU_REV_2_1,
+};
+
+struct mhu_v2_x_dev_t {
+ uintptr_t base;
+ enum mhu_v2_x_frame_t frame;
+ uint32_t subversion; /*!< Hardware subversion: v2.X */
+ bool is_initialized; /*!< Indicates if the MHU driver
+ * is initialized and enabled
+ */
+};
+
+/**
+ * MHU v2 error enumeration types.
+ */
+enum mhu_v2_x_error_t {
+ MHU_V_2_X_ERR_NONE = 0,
+ MHU_V_2_X_ERR_NOT_INIT = -1,
+ MHU_V_2_X_ERR_ALREADY_INIT = -2,
+ MHU_V_2_X_ERR_UNSUPPORTED_VERSION = -3,
+ MHU_V_2_X_ERR_INVALID_ARG = -4,
+ MHU_V_2_X_ERR_GENERAL = -5
+};
+
+/**
+ * Initializes the driver.
+ *
+ * dev MHU device struct mhu_v2_x_dev_t.
+ * rev MHU revision (if can't be identified from HW).
+ *
+ * Reads the MHU hardware version.
+ *
+ * Returns mhu_v2_x_error_t error code.
+ *
+ * MHU revision only has to be specified when versions can't be read
+ * from HW (ARCH_MAJOR_REV reg reads as 0x0).
+ *
+ * This function doesn't check if dev is NULL.
+ */
+enum mhu_v2_x_error_t mhu_v2_x_driver_init(struct mhu_v2_x_dev_t *dev,
+ enum mhu_v2_x_supported_revisions rev);
+
+/**
+ * Returns the number of channels implemented.
+ *
+ * dev MHU device struct mhu_v2_x_dev_t.
+ *
+ * This function doesn't check if dev is NULL.
+ */
+uint32_t mhu_v2_x_get_num_channel_implemented(
+ const struct mhu_v2_x_dev_t *dev);
+
+/**
+ * Sends the value over a channel.
+ *
+ * dev MHU device struct mhu_v2_x_dev_t.
+ * channel Channel to send the value over.
+ * val Value to send.
+ *
+ * Sends the value over a channel.
+ *
+ * Returns mhu_v2_x_error_t error code.
+ *
+ * This function doesn't check if dev is NULL.
+ * This function doesn't check if channel is implemented.
+ */
+enum mhu_v2_x_error_t mhu_v2_x_channel_send(const struct mhu_v2_x_dev_t *dev,
+ uint32_t channel, uint32_t val);
+
+/**
+ * Polls sender channel status.
+ *
+ * dev MHU device struct mhu_v2_x_dev_t.
+ * channel Channel to poll the status of.
+ * value Pointer to variable that will store the value.
+ *
+ * Polls sender channel status.
+ *
+ * Returns mhu_v2_x_error_t error code.
+ *
+ * This function doesn't check if dev is NULL.
+ * This function doesn't check if channel is implemented.
+ */
+enum mhu_v2_x_error_t mhu_v2_x_channel_poll(const struct mhu_v2_x_dev_t *dev,
+ uint32_t channel, uint32_t *value);
+
+/**
+ * Clears the channel after the value is send over it.
+ *
+ * dev MHU device struct mhu_v2_x_dev_t.
+ * channel Channel to clear.
+ *
+ * Clears the channel after the value is send over it.
+ *
+ * Returns mhu_v2_x_error_t error code..
+ *
+ * This function doesn't check if dev is NULL.
+ * This function doesn't check if channel is implemented.
+ */
+enum mhu_v2_x_error_t mhu_v2_x_channel_clear(const struct mhu_v2_x_dev_t *dev,
+ uint32_t channel);
+
+/**
+ * Receives the value over a channel.
+ *
+ * dev MHU device struct mhu_v2_x_dev_t.
+ * channel Channel to receive the value from.
+ * value Pointer to variable that will store the value.
+ *
+ * Receives the value over a channel.
+ *
+ * Returns mhu_v2_x_error_t error code.
+ *
+ * This function doesn't check if dev is NULL.
+ * This function doesn't check if channel is implemented.
+ */
+enum mhu_v2_x_error_t mhu_v2_x_channel_receive(
+ const struct mhu_v2_x_dev_t *dev, uint32_t channel, uint32_t *value);
+
+/**
+ * Sets bits in the Channel Mask.
+ *
+ * dev MHU device struct mhu_v2_x_dev_t.
+ * channel Which channel's mask to set.
+ * mask Mask to be set over a receiver frame.
+ *
+ * Sets bits in the Channel Mask.
+ *
+ * Returns mhu_v2_x_error_t error code..
+ *
+ * This function doesn't check if dev is NULL.
+ * This function doesn't check if channel is implemented.
+ */
+enum mhu_v2_x_error_t mhu_v2_x_channel_mask_set(
+ const struct mhu_v2_x_dev_t *dev, uint32_t channel, uint32_t mask);
+
+/**
+ * Clears bits in the Channel Mask.
+ *
+ * dev MHU device struct mhu_v2_x_dev_t.
+ * channel Which channel's mask to clear.
+ * mask Mask to be clear over a receiver frame.
+ *
+ * Clears bits in the Channel Mask.
+ *
+ * Returns mhu_v2_x_error_t error code.
+ *
+ * This function doesn't check if dev is NULL.
+ * This function doesn't check if channel is implemented.
+ */
+enum mhu_v2_x_error_t mhu_v2_x_channel_mask_clear(
+ const struct mhu_v2_x_dev_t *dev, uint32_t channel, uint32_t mask);
+
+/**
+ * Initiates a MHU transfer with the handshake signals.
+ *
+ * dev MHU device struct mhu_v2_x_dev_t.
+ *
+ * Initiates a MHU transfer with the handshake signals in a blocking mode.
+ *
+ * Returns mhu_v2_x_error_t error code.
+ *
+ * This function doesn't check if dev is NULL.
+ */
+enum mhu_v2_x_error_t mhu_v2_x_initiate_transfer(
+ const struct mhu_v2_x_dev_t *dev);
+
+/**
+ * Closes a MHU transfer with the handshake signals.
+ *
+ * dev MHU device struct mhu_v2_x_dev_t.
+ *
+ * Closes a MHU transfer with the handshake signals in a blocking mode.
+ *
+ * Returns mhu_v2_x_error_t error code.
+ *
+ * This function doesn't check if dev is NULL.
+ */
+enum mhu_v2_x_error_t mhu_v2_x_close_transfer(
+ const struct mhu_v2_x_dev_t *dev);
+
+#endif /* MHU_V2_X_H */
diff --git a/drivers/arm/mhu/mhu_wrapper_v2_x.c b/drivers/arm/mhu/mhu_wrapper_v2_x.c
new file mode 100644
index 0000000..d8b7cfd
--- /dev/null
+++ b/drivers/arm/mhu/mhu_wrapper_v2_x.c
@@ -0,0 +1,302 @@
+/*
+ * Copyright (c) 2022, Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <assert.h>
+#include <stddef.h>
+#include <stdint.h>
+#include <string.h>
+
+#include <drivers/arm/mhu.h>
+
+#include "mhu_v2_x.h"
+
+#define MHU_NOTIFY_VALUE (1234u)
+
+/*
+ * MHU devices for host:
+ * HSE: Host to Secure Enclave (sender device)
+ * SEH: Secure Enclave to Host (receiver device)
+ */
+struct mhu_v2_x_dev_t MHU1_HSE_DEV = {0, MHU_V2_X_SENDER_FRAME};
+struct mhu_v2_x_dev_t MHU1_SEH_DEV = {0, MHU_V2_X_RECEIVER_FRAME};
+
+static enum mhu_error_t error_mapping_to_mhu_error_t(enum mhu_v2_x_error_t err)
+{
+ switch (err) {
+ case MHU_V_2_X_ERR_NONE:
+ return MHU_ERR_NONE;
+ case MHU_V_2_X_ERR_NOT_INIT:
+ return MHU_ERR_NOT_INIT;
+ case MHU_V_2_X_ERR_ALREADY_INIT:
+ return MHU_ERR_ALREADY_INIT;
+ case MHU_V_2_X_ERR_UNSUPPORTED_VERSION:
+ return MHU_ERR_UNSUPPORTED_VERSION;
+ case MHU_V_2_X_ERR_INVALID_ARG:
+ return MHU_ERR_INVALID_ARG;
+ case MHU_V_2_X_ERR_GENERAL:
+ return MHU_ERR_GENERAL;
+ default:
+ return MHU_ERR_GENERAL;
+ }
+}
+
+static enum mhu_v2_x_error_t signal_and_wait_for_clear(void)
+{
+ enum mhu_v2_x_error_t err;
+ struct mhu_v2_x_dev_t *dev = &MHU1_HSE_DEV;
+ uint32_t val = MHU_NOTIFY_VALUE;
+ /* Using the last channel for notifications */
+ uint32_t channel_notify = mhu_v2_x_get_num_channel_implemented(dev) - 1;
+
+ err = mhu_v2_x_channel_send(dev, channel_notify, val);
+ if (err != MHU_V_2_X_ERR_NONE) {
+ return err;
+ }
+
+ do {
+ err = mhu_v2_x_channel_poll(dev, channel_notify, &val);
+ if (err != MHU_V_2_X_ERR_NONE) {
+ break;
+ }
+ } while (val != 0);
+
+ return err;
+}
+
+static enum mhu_v2_x_error_t wait_for_signal(void)
+{
+ enum mhu_v2_x_error_t err;
+ struct mhu_v2_x_dev_t *dev = &MHU1_SEH_DEV;
+ uint32_t val = 0;
+ /* Using the last channel for notifications */
+ uint32_t channel_notify = mhu_v2_x_get_num_channel_implemented(dev) - 1;
+
+ do {
+ err = mhu_v2_x_channel_receive(dev, channel_notify, &val);
+ if (err != MHU_V_2_X_ERR_NONE) {
+ break;
+ }
+ } while (val != MHU_NOTIFY_VALUE);
+
+ return err;
+}
+
+static enum mhu_v2_x_error_t clear_and_wait_for_next_signal(void)
+{
+ enum mhu_v2_x_error_t err;
+ struct mhu_v2_x_dev_t *dev = &MHU1_SEH_DEV;
+ uint32_t num_channels = mhu_v2_x_get_num_channel_implemented(dev);
+ uint32_t i;
+
+ /* Clear all channels */
+ for (i = 0; i < num_channels; ++i) {
+ err = mhu_v2_x_channel_clear(dev, i);
+ if (err != MHU_V_2_X_ERR_NONE) {
+ return err;
+ }
+ }
+
+ return wait_for_signal();
+}
+
+enum mhu_error_t mhu_init_sender(uintptr_t mhu_sender_base)
+{
+ enum mhu_v2_x_error_t err;
+
+ assert(mhu_sender_base != (uintptr_t)NULL);
+
+ MHU1_HSE_DEV.base = mhu_sender_base;
+
+ err = mhu_v2_x_driver_init(&MHU1_HSE_DEV, MHU_REV_READ_FROM_HW);
+ return error_mapping_to_mhu_error_t(err);
+}
+
+enum mhu_error_t mhu_init_receiver(uintptr_t mhu_receiver_base)
+{
+ enum mhu_v2_x_error_t err;
+ uint32_t num_channels, i;
+
+ assert(mhu_receiver_base != (uintptr_t)NULL);
+
+ MHU1_SEH_DEV.base = mhu_receiver_base;
+
+ err = mhu_v2_x_driver_init(&MHU1_SEH_DEV, MHU_REV_READ_FROM_HW);
+ if (err != MHU_V_2_X_ERR_NONE) {
+ return error_mapping_to_mhu_error_t(err);
+ }
+
+ num_channels = mhu_v2_x_get_num_channel_implemented(&MHU1_SEH_DEV);
+
+ /* Mask all channels except the notifying channel */
+ for (i = 0; i < (num_channels - 1); ++i) {
+ err = mhu_v2_x_channel_mask_set(&MHU1_SEH_DEV, i, UINT32_MAX);
+ if (err != MHU_V_2_X_ERR_NONE) {
+ return error_mapping_to_mhu_error_t(err);
+ }
+ }
+
+ /* The last channel is used for notifications */
+ err = mhu_v2_x_channel_mask_clear(
+ &MHU1_SEH_DEV, (num_channels - 1), UINT32_MAX);
+ return error_mapping_to_mhu_error_t(err);
+}
+
+/*
+ * Public function. See mhu.h
+ *
+ * The basic steps of transferring a message:
+ * 1. Initiate MHU transfer.
+ * 2. Send over the size of the payload on Channel 1. It is the very first
+ * 4 Bytes of the transfer. Continue with Channel 2.
+ * 3. Send over the payload, writing the channels one after the other
+ * (4 Bytes each). The last available channel is reserved for controlling
+ * the transfer.
+ * When the last channel is reached or no more data is left, STOP.
+ * 4. Notify the receiver using the last channel and wait for acknowledge.
+ * If there is still data to transfer, jump to step 3. Otherwise, proceed.
+ * 5. Close MHU transfer.
+ *
+ */
+enum mhu_error_t mhu_send_data(const uint8_t *send_buffer, size_t size)
+{
+ enum mhu_v2_x_error_t err;
+ struct mhu_v2_x_dev_t *dev = &MHU1_HSE_DEV;
+ uint32_t num_channels = mhu_v2_x_get_num_channel_implemented(dev);
+ uint32_t chan = 0;
+ uint32_t i;
+ uint32_t *p;
+
+ /* For simplicity, require the send_buffer to be 4-byte aligned */
+ if ((uintptr_t)send_buffer & 0x3U) {
+ return MHU_ERR_INVALID_ARG;
+ }
+
+ err = mhu_v2_x_initiate_transfer(dev);
+ if (err != MHU_V_2_X_ERR_NONE) {
+ return error_mapping_to_mhu_error_t(err);
+ }
+
+ /* First send over the size of the actual message */
+ err = mhu_v2_x_channel_send(dev, chan, (uint32_t)size);
+ if (err != MHU_V_2_X_ERR_NONE) {
+ return error_mapping_to_mhu_error_t(err);
+ }
+ chan++;
+
+ p = (uint32_t *)send_buffer;
+ for (i = 0; i < size; i += 4) {
+ err = mhu_v2_x_channel_send(dev, chan, *p++);
+ if (err != MHU_V_2_X_ERR_NONE) {
+ return error_mapping_to_mhu_error_t(err);
+ }
+ if (++chan == (num_channels - 1)) {
+ err = signal_and_wait_for_clear();
+ if (err != MHU_V_2_X_ERR_NONE) {
+ return error_mapping_to_mhu_error_t(err);
+ }
+ chan = 0;
+ }
+ }
+
+ /* Signal the end of transfer.
+ * It's not required to send a signal when the message was
+ * perfectly-aligned (num_channels - 1 channels were used in the last
+ * round) preventing it from signaling twice at the end of transfer.
+ */
+ if (chan != 0) {
+ err = signal_and_wait_for_clear();
+ if (err != MHU_V_2_X_ERR_NONE) {
+ return error_mapping_to_mhu_error_t(err);
+ }
+ }
+
+ err = mhu_v2_x_close_transfer(dev);
+ return error_mapping_to_mhu_error_t(err);
+}
+
+/*
+ * Public function. See mhu.h
+ *
+ * The basic steps of receiving a message:
+ * 1. Read the size of the payload from Channel 1. It is the very first
+ * 4 Bytes of the transfer. Continue with Channel 2.
+ * 2. Receive the payload, read the channels one after the other
+ * (4 Bytes each). The last available channel is reserved for controlling
+ * the transfer.
+ * When the last channel is reached clear all the channels
+ * (also sending an acknowledge on the last channel).
+ * 3. If there is still data to receive wait for a notification on the last
+ * channel and jump to step 2 as soon as it arrived. Otherwise, proceed.
+ * 4. End of transfer.
+ *
+ */
+enum mhu_error_t mhu_receive_data(uint8_t *receive_buffer, size_t *size)
+{
+ enum mhu_v2_x_error_t err;
+ struct mhu_v2_x_dev_t *dev = &MHU1_SEH_DEV;
+ uint32_t num_channels = mhu_v2_x_get_num_channel_implemented(dev);
+ uint32_t chan = 0;
+ uint32_t message_len;
+ uint32_t i;
+ uint32_t *p;
+
+ /* For simplicity, require:
+ * - the receive_buffer to be 4-byte aligned,
+ * - the buffer size to be a multiple of 4.
+ */
+ if (((uintptr_t)receive_buffer & 0x3U) || (*size & 0x3U)) {
+ return MHU_ERR_INVALID_ARG;
+ }
+
+ /* Busy wait for incoming reply */
+ err = wait_for_signal();
+ if (err != MHU_V_2_X_ERR_NONE) {
+ return error_mapping_to_mhu_error_t(err);
+ }
+
+ /* The first word is the length of the actual message */
+ err = mhu_v2_x_channel_receive(dev, chan, &message_len);
+ if (err != MHU_V_2_X_ERR_NONE) {
+ return error_mapping_to_mhu_error_t(err);
+ }
+ chan++;
+
+ if (message_len > *size) {
+ /* Message buffer too small */
+ *size = message_len;
+ return MHU_ERR_BUFFER_TOO_SMALL;
+ }
+
+ p = (uint32_t *)receive_buffer;
+ for (i = 0; i < message_len; i += 4) {
+ err = mhu_v2_x_channel_receive(dev, chan, p++);
+ if (err != MHU_V_2_X_ERR_NONE) {
+ return error_mapping_to_mhu_error_t(err);
+ }
+
+ /* Only wait for next transfer if there is still missing data */
+ if (++chan == (num_channels - 1) && (message_len - i) > 4) {
+ /* Busy wait for next transfer */
+ err = clear_and_wait_for_next_signal();
+ if (err != MHU_V_2_X_ERR_NONE) {
+ return error_mapping_to_mhu_error_t(err);
+ }
+ chan = 0;
+ }
+ }
+
+ /* Clear all channels */
+ for (i = 0; i < num_channels; ++i) {
+ err = mhu_v2_x_channel_clear(dev, i);
+ if (err != MHU_V_2_X_ERR_NONE) {
+ return error_mapping_to_mhu_error_t(err);
+ }
+ }
+
+ *size = message_len;
+
+ return MHU_ERR_NONE;
+}
diff --git a/drivers/arm/rss/rss_comms.c b/drivers/arm/rss/rss_comms.c
new file mode 100644
index 0000000..28a4925
--- /dev/null
+++ b/drivers/arm/rss/rss_comms.c
@@ -0,0 +1,225 @@
+/*
+ * Copyright (c) 2022, Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <stdint.h>
+#include <string.h>
+
+#include <common/debug.h>
+#include <drivers/arm/mhu.h>
+#include <drivers/arm/rss_comms.h>
+#include <initial_attestation.h>
+#include <psa/client.h>
+
+#include <platform_def.h>
+
+#define TYPE_OFFSET U(16)
+#define TYPE_MASK (0xFFFFUL << TYPE_OFFSET)
+#define IN_LEN_OFFSET U(8)
+#define IN_LEN_MASK (0xFFUL << IN_LEN_OFFSET)
+#define OUT_LEN_OFFSET U(0)
+#define OUT_LEN_MASK (0xFFUL << OUT_LEN_OFFSET)
+
+#define PARAM_PACK(type, in_len, out_len) \
+ (((((uint32_t)type) << TYPE_OFFSET) & TYPE_MASK) | \
+ ((((uint32_t)in_len) << IN_LEN_OFFSET) & IN_LEN_MASK) | \
+ ((((uint32_t)out_len) << OUT_LEN_OFFSET) & OUT_LEN_MASK))
+
+#define PARAM_UNPACK_IN_LEN(ctrl_param) \
+ ((size_t)(((ctrl_param) & IN_LEN_MASK) >> IN_LEN_OFFSET))
+
+/* Message types */
+struct __packed packed_psa_call_t {
+ uint8_t protocol_ver;
+ uint8_t seq_num;
+ uint16_t client_id;
+ psa_handle_t handle;
+ uint32_t ctrl_param; /* type, in_len, out_len */
+ uint16_t io_size[4];
+};
+
+struct __packed packed_psa_reply_t {
+ uint8_t protocol_ver;
+ uint8_t seq_num;
+ uint16_t client_id;
+ int32_t return_val;
+ uint16_t out_size[4];
+};
+
+/*
+ * In the current implementation the RoT Service request that requires the
+ * biggest message buffer is the RSS_ATTEST_GET_TOKEN. The maximum required
+ * buffer size is calculated based on the platform-specific needs of
+ * this request.
+ */
+#define MAX_REQUEST_PAYLOAD_SIZE (PSA_INITIAL_ATTEST_CHALLENGE_SIZE_64 \
+ + PLAT_ATTEST_TOKEN_MAX_SIZE)
+
+/* Buffer to store the messages to be sent/received. */
+static uint8_t message_buf[MAX_REQUEST_PAYLOAD_SIZE] __aligned(4);
+
+static int32_t pack_params(const psa_invec *invecs,
+ size_t in_len,
+ uint8_t *buf,
+ size_t *buf_len)
+{
+ uint32_t i;
+ size_t payload_size = 0U;
+
+ for (i = 0U; i < in_len; ++i) {
+ if (invecs[i].len > *buf_len - payload_size) {
+ return -1;
+ }
+ memcpy(buf + payload_size, invecs[i].base, invecs[i].len);
+ payload_size += invecs[i].len;
+ }
+
+ *buf_len = payload_size;
+ return 0;
+}
+
+static int serialise_message(const struct packed_psa_call_t *msg,
+ const psa_invec *invecs,
+ uint8_t *payload_buf,
+ size_t *payload_len)
+{
+ size_t message_len = 0U;
+ size_t len;
+
+ /* Copy the message header into the payload buffer. */
+ len = sizeof(*msg);
+ if (len > *payload_len) {
+ ERROR("[RSS-COMMS] Message buffer too small.\n");
+ return -1;
+ }
+ memcpy(payload_buf, (const void *)msg, len);
+ message_len += len;
+
+ /* The input data will follow the message header in the payload buffer. */
+ len = *payload_len - message_len;
+ if (pack_params(invecs, PARAM_UNPACK_IN_LEN(msg->ctrl_param),
+ payload_buf + message_len, &len) != 0) {
+ ERROR("[RSS-COMMS] Message buffer too small.\n");
+ return -1;
+ }
+ message_len += len;
+
+ *payload_len = message_len;
+ return 0;
+}
+
+static void unpack_params(const uint8_t *buf,
+ psa_outvec *outvecs,
+ size_t out_len)
+{
+ size_t i;
+
+ for (i = 0U; i < out_len; ++i) {
+ memcpy(outvecs[i].base, buf, outvecs[i].len);
+ buf += outvecs[i].len;
+ }
+}
+
+static void deserialise_reply(struct packed_psa_reply_t *reply,
+ psa_outvec *outvecs,
+ size_t outlen,
+ const uint8_t *message,
+ size_t message_len)
+{
+ uint32_t i;
+
+ memcpy(reply, message, sizeof(*reply));
+
+ /* Outvecs */
+ for (i = 0U; i < outlen; ++i) {
+ outvecs[i].len = reply->out_size[i];
+ }
+
+ unpack_params(message + sizeof(*reply), outvecs, outlen);
+}
+
+psa_status_t psa_call(psa_handle_t handle, int32_t type,
+ const psa_invec *in_vec, size_t in_len,
+ psa_outvec *out_vec, size_t out_len)
+{
+ enum mhu_error_t err;
+ static uint32_t seq_num = 1U;
+ struct packed_psa_call_t msg = {
+ .protocol_ver = 0U,
+ .seq_num = seq_num,
+ /* No need to distinguish callers (currently concurrent calls are not supported). */
+ .client_id = 1U,
+ .handle = handle,
+ .ctrl_param = PARAM_PACK(type, in_len, out_len),
+ };
+
+ struct packed_psa_reply_t reply = {0};
+ size_t message_size;
+ uint32_t i;
+
+ /* Fill msg iovec lengths */
+ for (i = 0U; i < in_len; ++i) {
+ msg.io_size[i] = in_vec[i].len;
+ }
+ for (i = 0U; i < out_len; ++i) {
+ msg.io_size[in_len + i] = out_vec[i].len;
+ }
+
+ message_size = sizeof(message_buf);
+ if (serialise_message(&msg, in_vec, message_buf, &message_size)) {
+ /* Local buffer is probably too small. */
+ return PSA_ERROR_INSUFFICIENT_MEMORY;
+ }
+
+ err = mhu_send_data(message_buf, message_size);
+ if (err != MHU_ERR_NONE) {
+ return PSA_ERROR_COMMUNICATION_FAILURE;
+ }
+
+ message_size = sizeof(message_buf);
+#if DEBUG
+ /*
+ * Poisoning the message buffer (with a known pattern).
+ * Helps in detecting hypothetical RSS communication bugs.
+ */
+ memset(message_buf, 0xA5, message_size);
+#endif
+ err = mhu_receive_data(message_buf, &message_size);
+ if (err != MHU_ERR_NONE) {
+ return PSA_ERROR_COMMUNICATION_FAILURE;
+ }
+
+ deserialise_reply(&reply, out_vec, out_len, message_buf, message_size);
+
+ seq_num++;
+
+ VERBOSE("[RSS-COMMS] Received reply\n");
+ VERBOSE("protocol_ver=%d\n", reply.protocol_ver);
+ VERBOSE("seq_num=%d\n", reply.seq_num);
+ VERBOSE("client_id=%d\n", reply.client_id);
+ VERBOSE("return_val=%d\n", reply.return_val);
+ VERBOSE("out_size[0]=%d\n", reply.out_size[0]);
+
+ return reply.return_val;
+}
+
+int rss_comms_init(uintptr_t mhu_sender_base, uintptr_t mhu_receiver_base)
+{
+ enum mhu_error_t err;
+
+ err = mhu_init_sender(mhu_sender_base);
+ if (err != MHU_ERR_NONE) {
+ ERROR("[RSS-COMMS] Host to RSS MHU driver initialization failed: %d\n", err);
+ return -1;
+ }
+
+ err = mhu_init_receiver(mhu_receiver_base);
+ if (err != MHU_ERR_NONE) {
+ ERROR("[RSS-COMMS] RSS to Host MHU driver initialization failed: %d\n", err);
+ return -1;
+ }
+
+ return 0;
+}
diff --git a/drivers/measured_boot/rss/rss_measured_boot.c b/drivers/measured_boot/rss/rss_measured_boot.c
new file mode 100644
index 0000000..fe2baf0
--- /dev/null
+++ b/drivers/measured_boot/rss/rss_measured_boot.c
@@ -0,0 +1,125 @@
+/*
+ * Copyright (c) 2022, Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+#include <assert.h>
+#include <stdint.h>
+
+#include <common/debug.h>
+#include <drivers/auth/crypto_mod.h>
+#include <drivers/measured_boot/rss/rss_measured_boot.h>
+#include <lib/psa/measured_boot.h>
+#include <psa/crypto_types.h>
+#include <psa/crypto_values.h>
+#include <psa/error.h>
+
+#define MBOOT_ALG_SHA512 0
+#define MBOOT_ALG_SHA384 1
+#define MBOOT_ALG_SHA256 2
+
+#if MBOOT_ALG_ID == MBOOT_ALG_SHA512
+#define CRYPTO_MD_ID CRYPTO_MD_SHA512
+#define PSA_CRYPTO_MD_ID PSA_ALG_SHA_512
+#elif MBOOT_ALG_ID == MBOOT_ALG_SHA384
+#define CRYPTO_MD_ID CRYPTO_MD_SHA384
+#define PSA_CRYPTO_MD_ID PSA_ALG_SHA_384
+#elif MBOOT_ALG_ID == MBOOT_ALG_SHA256
+#define CRYPTO_MD_ID CRYPTO_MD_SHA256
+#define PSA_CRYPTO_MD_ID PSA_ALG_SHA_256
+#else
+# error Invalid Measured Boot algorithm.
+#endif /* MBOOT_ALG_ID */
+
+/* Pointer to struct rss_mboot_metadata */
+static struct rss_mboot_metadata *plat_metadata_ptr;
+
+/* Functions' declarations */
+void rss_measured_boot_init(void)
+{
+ /* At this point it is expected that communication channel over MHU
+ * is already initialised by platform init.
+ */
+
+ /* Get pointer to platform's struct rss_mboot_metadata structure */
+ plat_metadata_ptr = plat_rss_mboot_get_metadata();
+ assert(plat_metadata_ptr != NULL);
+}
+
+int rss_mboot_measure_and_record(uintptr_t data_base, uint32_t data_size,
+ uint32_t data_id)
+{
+ unsigned char hash_data[CRYPTO_MD_MAX_SIZE];
+ int rc;
+ psa_status_t ret;
+ const struct rss_mboot_metadata *metadata_ptr = plat_metadata_ptr;
+
+ /* Get the metadata associated with this image. */
+ while ((metadata_ptr->id != RSS_MBOOT_INVALID_ID) &&
+ (metadata_ptr->id != data_id)) {
+ metadata_ptr++;
+ }
+
+ /* If image is not present in metadata array then skip */
+ if (metadata_ptr->id == RSS_MBOOT_INVALID_ID) {
+ return 0;
+ }
+
+ /* Calculate hash */
+ rc = crypto_mod_calc_hash(CRYPTO_MD_ID,
+ (void *)data_base, data_size, hash_data);
+ if (rc != 0) {
+ return rc;
+ }
+
+ ret = rss_measured_boot_extend_measurement(
+ metadata_ptr->slot,
+ metadata_ptr->signer_id,
+ metadata_ptr->signer_id_size,
+ metadata_ptr->version,
+ metadata_ptr->version_size,
+ PSA_CRYPTO_MD_ID,
+ metadata_ptr->sw_type,
+ metadata_ptr->sw_type_size,
+ hash_data,
+ MBOOT_DIGEST_SIZE,
+ metadata_ptr->lock_measurement);
+ if (ret != PSA_SUCCESS) {
+ return ret;
+ }
+
+ return 0;
+}
+
+int rss_mboot_set_signer_id(unsigned int img_id,
+ const void *pk_ptr,
+ size_t pk_len)
+{
+ unsigned char hash_data[CRYPTO_MD_MAX_SIZE];
+ struct rss_mboot_metadata *metadata_ptr = plat_metadata_ptr;
+ int rc;
+
+ /* Get the metadata associated with this image. */
+ while ((metadata_ptr->id != RSS_MBOOT_INVALID_ID) &&
+ (metadata_ptr->id != img_id)) {
+ metadata_ptr++;
+ }
+
+ /* If image is not present in metadata array then skip */
+ if (metadata_ptr->id == RSS_MBOOT_INVALID_ID) {
+ return 0;
+ }
+
+ /* Calculate public key hash */
+ rc = crypto_mod_calc_hash(CRYPTO_MD_ID, (void *)pk_ptr,
+ pk_len, hash_data);
+ if (rc != 0) {
+ return rc;
+ }
+
+ /* Update metadata struct with the received signer_id */
+ (void)memcpy(metadata_ptr->signer_id, hash_data, MBOOT_DIGEST_SIZE);
+ metadata_ptr->signer_id_size = MBOOT_DIGEST_SIZE;
+
+ return 0;
+}
diff --git a/drivers/measured_boot/rss/rss_measured_boot.mk b/drivers/measured_boot/rss/rss_measured_boot.mk
new file mode 100644
index 0000000..01545af
--- /dev/null
+++ b/drivers/measured_boot/rss/rss_measured_boot.mk
@@ -0,0 +1,35 @@
+#
+# Copyright (c) 2022, Arm Limited. All rights reserved.
+#
+# SPDX-License-Identifier: BSD-3-Clause
+#
+
+# Hash algorithm for measured boot
+# SHA-256 (or stronger) is required.
+# TODO: The measurement algorithm incorrectly suggests that the TPM backend
+# is used which may not be the case. It is currently being worked on and
+# soon TPM_HASH_ALG will be replaced by a more generic name.
+TPM_HASH_ALG := sha256
+
+ifeq (${TPM_HASH_ALG}, sha512)
+ MBOOT_ALG_ID := MBOOT_ALG_SHA512
+ MBOOT_DIGEST_SIZE := 64U
+else ifeq (${TPM_HASH_ALG}, sha384)
+ MBOOT_ALG_ID := MBOOT_ALG_SHA384
+ MBOOT_DIGEST_SIZE := 48U
+else
+ MBOOT_ALG_ID := MBOOT_ALG_SHA256
+ MBOOT_DIGEST_SIZE := 32U
+endif #TPM_HASH_ALG
+
+# Set definitions for Measured Boot driver.
+$(eval $(call add_defines,\
+ $(sort \
+ MBOOT_ALG_ID \
+ MBOOT_DIGEST_SIZE \
+ MBOOT_RSS_BACKEND \
+)))
+
+MEASURED_BOOT_SRC_DIR := drivers/measured_boot/rss/
+
+MEASURED_BOOT_SOURCES += ${MEASURED_BOOT_SRC_DIR}rss_measured_boot.c
diff --git a/include/drivers/arm/mhu.h b/include/drivers/arm/mhu.h
new file mode 100644
index 0000000..7745bd9
--- /dev/null
+++ b/include/drivers/arm/mhu.h
@@ -0,0 +1,79 @@
+/*
+ * Copyright (c) 2022, Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef MHU_H
+#define MHU_H
+
+#include <stddef.h>
+#include <stdint.h>
+
+/**
+ * Generic MHU error enumeration types.
+ */
+enum mhu_error_t {
+ MHU_ERR_NONE = 0,
+ MHU_ERR_NOT_INIT = -1,
+ MHU_ERR_ALREADY_INIT = -2,
+ MHU_ERR_UNSUPPORTED_VERSION = -3,
+ MHU_ERR_UNSUPPORTED = -4,
+ MHU_ERR_INVALID_ARG = -5,
+ MHU_ERR_BUFFER_TOO_SMALL = -6,
+ MHU_ERR_GENERAL = -7,
+};
+
+/**
+ * Initializes sender MHU.
+ *
+ * mhu_sender_base Base address of sender MHU.
+ *
+ * Returns mhu_error_t error code.
+ *
+ * This function must be called before mhu_send_data().
+ */
+enum mhu_error_t mhu_init_sender(uintptr_t mhu_sender_base);
+
+
+/**
+ * Initializes receiver MHU.
+ *
+ * mhu_receiver_base Base address of receiver MHU.
+ *
+ * Returns mhu_error_t error code.
+ *
+ * This function must be called before mhu_receive_data().
+ */
+enum mhu_error_t mhu_init_receiver(uintptr_t mhu_receiver_base);
+
+/**
+ * Sends data over MHU.
+ *
+ * send_buffer Pointer to buffer containing the data to be transmitted.
+ * size Size of the data to be transmitted in bytes.
+ *
+ * Returns mhu_error_t error code.
+ *
+ * The send_buffer must be 4-byte aligned and its length must be at least
+ * (4 - (size % 4)) bytes bigger than the data size to prevent buffer
+ * over-reading.
+ */
+enum mhu_error_t mhu_send_data(const uint8_t *send_buffer, size_t size);
+
+/**
+ * Receives data from MHU.
+ *
+ * receive_buffer Pointer the buffer where to store the received data.
+ * size As input the size of the receive_buffer, as output the
+ * number of bytes received. As a limitation,
+ * the size of the buffer must be a multiple of 4.
+ *
+ * Returns mhu_error_t error code.
+ *
+ * The receive_buffer must be 4-byte aligned and its length must be a
+ * multiple of 4.
+ */
+enum mhu_error_t mhu_receive_data(uint8_t *receive_buffer, size_t *size);
+
+#endif /* MHU_H */
diff --git a/include/drivers/arm/rss_comms.h b/include/drivers/arm/rss_comms.h
new file mode 100644
index 0000000..b96c79f
--- /dev/null
+++ b/include/drivers/arm/rss_comms.h
@@ -0,0 +1,15 @@
+/*
+ * Copyright (c) 2022, Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ */
+
+#ifndef RSS_COMMS_H
+#define RSS_COMMS_H
+
+#include <stdint.h>
+
+int rss_comms_init(uintptr_t mhu_sender_base, uintptr_t mhu_receiver_base);
+
+#endif /* RSS_COMMS_H */
diff --git a/include/drivers/measured_boot/rss/rss_measured_boot.h b/include/drivers/measured_boot/rss/rss_measured_boot.h
new file mode 100644
index 0000000..fe88576
--- /dev/null
+++ b/include/drivers/measured_boot/rss/rss_measured_boot.h
@@ -0,0 +1,55 @@
+/*
+ * Copyright (c) 2022, Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef RSS_MEASURED_BOOT_H
+#define RSS_MEASURED_BOOT_H
+
+#include <stdint.h>
+
+#include <common/debug.h>
+#include <measured_boot.h>
+
+#define RSS_MBOOT_INVALID_ID UINT32_MAX
+
+/*
+ * Each boot measurement has some metadata (i.e. a string) that identifies
+ * what was measured and how. The sw_type field of the rss_mboot_metadata
+ * structure represents the role of the software component that was measured.
+ * The below macros define strings suitable for the sw_type.
+ * The key thing is to choose meaningful strings so that when the attestation
+ * token is verified, then the different components can be identified.
+ */
+#define RSS_MBOOT_BL2_STRING "BL_2"
+#define RSS_MBOOT_BL31_STRING "SECURE_RT_EL3"
+#define RSS_MBOOT_HW_CONFIG_STRING "HW_CONFIG"
+#define RSS_MBOOT_FW_CONFIG_STRING "FW_CONFIG"
+#define RSS_MBOOT_TB_FW_CONFIG_STRING "TB_FW_CONFIG"
+#define RSS_MBOOT_SOC_FW_CONFIG_STRING "SOC_FW_CONFIG"
+#define RSS_MBOOT_RMM_STRING "RMM"
+
+
+struct rss_mboot_metadata {
+ unsigned int id;
+ uint8_t slot;
+ uint8_t signer_id[SIGNER_ID_MAX_SIZE];
+ size_t signer_id_size;
+ uint8_t version[VERSION_MAX_SIZE];
+ size_t version_size;
+ uint8_t sw_type[SW_TYPE_MAX_SIZE];
+ size_t sw_type_size;
+ bool lock_measurement;
+};
+
+/* Functions' declarations */
+void rss_measured_boot_init(void);
+struct rss_mboot_metadata *plat_rss_mboot_get_metadata(void);
+int rss_mboot_measure_and_record(uintptr_t data_base, uint32_t data_size,
+ uint32_t data_id);
+
+/* TODO: These metadata are currently not available during TF-A boot */
+int rss_mboot_set_signer_id(unsigned int img_id, const void *pk_ptr, size_t pk_len);
+
+#endif /* RSS_MEASURED_BOOT_H */
diff --git a/include/lib/psa/initial_attestation.h b/include/lib/psa/initial_attestation.h
new file mode 100644
index 0000000..93169f0
--- /dev/null
+++ b/include/lib/psa/initial_attestation.h
@@ -0,0 +1,54 @@
+/*
+ * Copyright (c) 2018-2022, Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ */
+
+#ifndef PSA_INITIAL_ATTESTATION_H
+#define PSA_INITIAL_ATTESTATION_H
+
+#include <limits.h>
+#include <stddef.h>
+#include <stdint.h>
+
+#include "psa/error.h"
+
+/*
+ * Initial attestation API version is: 1.0.0
+ */
+#define PSA_INITIAL_ATTEST_API_VERSION_MAJOR (1)
+#define PSA_INITIAL_ATTEST_API_VERSION_MINOR (0)
+
+/* The allowed size of input challenge in bytes. */
+#define PSA_INITIAL_ATTEST_CHALLENGE_SIZE_32 32U
+#define PSA_INITIAL_ATTEST_CHALLENGE_SIZE_48 48U
+#define PSA_INITIAL_ATTEST_CHALLENGE_SIZE_64 64U
+
+/* Initial Attestation message types that distinguish Attest services. */
+#define RSS_ATTEST_GET_TOKEN 1001U
+#define RSS_ATTEST_GET_TOKEN_SIZE 1002U
+#define RSS_ATTEST_GET_DELEGATED_KEY 1003U
+
+/**
+ * Get the platform attestation token.
+ *
+ * auth_challenge Pointer to buffer where challenge input is stored. This
+ * must be the hash of the public part of the delegated
+ * attestation key.
+ * challenge_size Size of challenge object in bytes.
+ * token_buf Pointer to the buffer where attestation token will be
+ * stored.
+ * token_buf_size Size of allocated buffer for token, in bytes.
+ * token_size Size of the token that has been returned, in bytes.
+ *
+ * Returns error code as specified in psa_status_t.
+ */
+psa_status_t
+psa_initial_attest_get_token(const uint8_t *auth_challenge,
+ size_t challenge_size,
+ uint8_t *token_buf,
+ size_t token_buf_size,
+ size_t *token_size);
+
+#endif /* PSA_INITIAL_ATTESTATION_H */
diff --git a/include/lib/psa/measured_boot.h b/include/lib/psa/measured_boot.h
new file mode 100644
index 0000000..bdb79d5
--- /dev/null
+++ b/include/lib/psa/measured_boot.h
@@ -0,0 +1,77 @@
+/*
+ * Copyright (c) 2022, Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ */
+
+#ifndef PSA_MEASURED_BOOT_H
+#define PSA_MEASURED_BOOT_H
+
+#include <stdbool.h>
+#include <stddef.h>
+#include <stdint.h>
+
+#include "psa/error.h"
+
+/* Minimum measurement value size that can be requested to store */
+#define MEASUREMENT_VALUE_MIN_SIZE 32U
+/* Maximum measurement value size that can be requested to store */
+#define MEASUREMENT_VALUE_MAX_SIZE 64U
+/* Minimum signer id size that can be requested to store */
+#define SIGNER_ID_MIN_SIZE MEASUREMENT_VALUE_MIN_SIZE
+/* Maximum signer id size that can be requested to store */
+#define SIGNER_ID_MAX_SIZE MEASUREMENT_VALUE_MAX_SIZE
+/* The theoretical maximum image version is: "255.255.65535\0" */
+#define VERSION_MAX_SIZE 14U
+/* Example sw_type: "BL_2, BL_33, etc." */
+#define SW_TYPE_MAX_SIZE 20U
+#define NUM_OF_MEASUREMENT_SLOTS 32U
+
+
+/**
+ * Extends and stores a measurement to the requested slot.
+ *
+ * index Slot number in which measurement is to be stored
+ * signer_id Pointer to signer_id buffer.
+ * signer_id_size Size of the signer_id buffer in bytes.
+ * version Pointer to version buffer.
+ * version_size Size of the version buffer in bytes.
+ * measurement_algo Algorithm identifier used for measurement.
+ * sw_type Pointer to sw_type buffer.
+ * sw_type_size Size of the sw_type buffer in bytes.
+ * measurement_value Pointer to measurement_value buffer.
+ * measurement_value_size Size of the measurement_value buffer in bytes.
+ * lock_measurement Boolean flag requesting whether the measurement
+ * is to be locked.
+ *
+ * PSA_SUCCESS:
+ * - Success.
+ * PSA_ERROR_INVALID_ARGUMENT:
+ * - The size of any argument is invalid OR
+ * - Input Measurement value is NULL OR
+ * - Input Signer ID is NULL OR
+ * - Requested slot index is invalid.
+ * PSA_ERROR_BAD_STATE:
+ * - Request to lock, when slot is already locked.
+ * PSA_ERROR_NOT_PERMITTED:
+ * - When the requested slot is not accessible to the caller.
+ */
+
+/* Not a standard PSA API, just an extension therefore use the 'rss_' prefix
+ * rather than the usual 'psa_'.
+ */
+psa_status_t
+rss_measured_boot_extend_measurement(uint8_t index,
+ const uint8_t *signer_id,
+ size_t signer_id_size,
+ const uint8_t *version,
+ size_t version_size,
+ uint32_t measurement_algo,
+ const uint8_t *sw_type,
+ size_t sw_type_size,
+ const uint8_t *measurement_value,
+ size_t measurement_value_size,
+ bool lock_measurement);
+
+#endif /* PSA_MEASURED_BOOT_H */
diff --git a/include/lib/psa/psa/client.h b/include/lib/psa/psa/client.h
new file mode 100644
index 0000000..56fe028
--- /dev/null
+++ b/include/lib/psa/psa/client.h
@@ -0,0 +1,102 @@
+
+/*
+ * Copyright (c) 2018-2021, Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ */
+
+#ifndef PSA_CLIENT_H
+#define PSA_CLIENT_H
+
+#include <stddef.h>
+#include <stdint.h>
+
+#include <psa/error.h>
+
+#ifndef IOVEC_LEN
+#define IOVEC_LEN(arr) ((uint32_t)(sizeof(arr)/sizeof(arr[0])))
+#endif
+/*********************** PSA Client Macros and Types *************************/
+/**
+ * The version of the PSA Framework API that is being used to build the calling
+ * firmware. Only part of features of FF-M v1.1 have been implemented. FF-M v1.1
+ * is compatible with v1.0.
+ */
+#define PSA_FRAMEWORK_VERSION (0x0101u)
+/**
+ * Return value from psa_version() if the requested RoT Service is not present
+ * in the system.
+ */
+#define PSA_VERSION_NONE (0u)
+/**
+ * The zero-value null handle can be assigned to variables used in clients and
+ * RoT Services, indicating that there is no current connection or message.
+ */
+#define PSA_NULL_HANDLE ((psa_handle_t)0)
+/**
+ * Tests whether a handle value returned by psa_connect() is valid.
+ */
+#define PSA_HANDLE_IS_VALID(handle) ((psa_handle_t)(handle) > 0)
+/**
+ * Converts the handle value returned from a failed call psa_connect() into
+ * an error code.
+ */
+#define PSA_HANDLE_TO_ERROR(handle) ((psa_status_t)(handle))
+/**
+ * Maximum number of input and output vectors for a request to psa_call().
+ */
+#define PSA_MAX_IOVEC (4u)
+/**
+ * An IPC message type that indicates a generic client request.
+ */
+#define PSA_IPC_CALL (0)
+typedef int32_t psa_handle_t;
+/**
+ * A read-only input memory region provided to an RoT Service.
+ */
+typedef struct psa_invec {
+ const void *base; /*!< the start address of the memory buffer */
+ size_t len; /*!< the size in bytes */
+} psa_invec;
+/**
+ * A writable output memory region provided to an RoT Service.
+ */
+typedef struct psa_outvec {
+ void *base; /*!< the start address of the memory buffer */
+ size_t len; /*!< the size in bytes */
+} psa_outvec;
+
+/**
+ * Call an RoT Service on an established connection.
+ *
+ * handle A handle to an established connection.
+ * type The request type. Must be zero(PSA_IPC_CALL) or positive.
+ * in_vec Array of input psa_invec structures.
+ * in_len Number of input psa_invec structures.
+ * out_vec Array of output psa_outvec structures.
+ * out_len Number of output psa_outvec structures.
+ *
+ * Return value >=0 RoT Service-specific status value.
+ * Return value <0 RoT Service-specific error code.
+ *
+ * PSA_ERROR_PROGRAMMER_ERROR:
+ * - The connection has been terminated by the RoT Service.
+ *
+ * The call is a PROGRAMMER ERROR if one or more of the following are true:
+ * - An invalid handle was passed.
+ * - The connection is already handling a request.
+ * - type < 0.
+ * - An invalid memory reference was provided.
+ * - in_len + out_len > PSA_MAX_IOVEC.
+ * - The message is unrecognized by the RoT.
+ * - Service or incorrectly formatted.
+ */
+psa_status_t psa_call(psa_handle_t handle,
+ int32_t type,
+ const psa_invec *in_vec,
+ size_t in_len,
+ psa_outvec *out_vec,
+ size_t out_len);
+
+#endif /* PSA_CLIENT_H */
diff --git a/include/lib/psa/psa/error.h b/include/lib/psa/psa/error.h
new file mode 100644
index 0000000..8a6eb7b
--- /dev/null
+++ b/include/lib/psa/psa/error.h
@@ -0,0 +1,42 @@
+
+/*
+ * Copyright (c) 2019-2021, Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ */
+
+#ifndef PSA_ERROR_H
+#define PSA_ERROR_H
+
+#include <stdint.h>
+
+typedef int32_t psa_status_t;
+
+#define PSA_SUCCESS ((psa_status_t)0)
+#define PSA_SUCCESS_REBOOT ((psa_status_t)1)
+#define PSA_SUCCESS_RESTART ((psa_status_t)2)
+#define PSA_ERROR_PROGRAMMER_ERROR ((psa_status_t)-129)
+#define PSA_ERROR_CONNECTION_REFUSED ((psa_status_t)-130)
+#define PSA_ERROR_CONNECTION_BUSY ((psa_status_t)-131)
+#define PSA_ERROR_GENERIC_ERROR ((psa_status_t)-132)
+#define PSA_ERROR_NOT_PERMITTED ((psa_status_t)-133)
+#define PSA_ERROR_NOT_SUPPORTED ((psa_status_t)-134)
+#define PSA_ERROR_INVALID_ARGUMENT ((psa_status_t)-135)
+#define PSA_ERROR_INVALID_HANDLE ((psa_status_t)-136)
+#define PSA_ERROR_BAD_STATE ((psa_status_t)-137)
+#define PSA_ERROR_BUFFER_TOO_SMALL ((psa_status_t)-138)
+#define PSA_ERROR_ALREADY_EXISTS ((psa_status_t)-139)
+#define PSA_ERROR_DOES_NOT_EXIST ((psa_status_t)-140)
+#define PSA_ERROR_INSUFFICIENT_MEMORY ((psa_status_t)-141)
+#define PSA_ERROR_INSUFFICIENT_STORAGE ((psa_status_t)-142)
+#define PSA_ERROR_INSUFFICIENT_DATA ((psa_status_t)-143)
+#define PSA_ERROR_SERVICE_FAILURE ((psa_status_t)-144)
+#define PSA_ERROR_COMMUNICATION_FAILURE ((psa_status_t)-145)
+#define PSA_ERROR_STORAGE_FAILURE ((psa_status_t)-146)
+#define PSA_ERROR_HARDWARE_FAILURE ((psa_status_t)-147)
+#define PSA_ERROR_INVALID_SIGNATURE ((psa_status_t)-149)
+#define PSA_ERROR_DEPENDENCY_NEEDED ((psa_status_t)-156)
+#define PSA_ERROR_CURRENTLY_INSTALLING ((psa_status_t)-157)
+
+#endif /* PSA_ERROR_H */
diff --git a/include/lib/psa/psa_manifest/sid.h b/include/lib/psa/psa_manifest/sid.h
new file mode 100644
index 0000000..947e58f
--- /dev/null
+++ b/include/lib/psa/psa_manifest/sid.h
@@ -0,0 +1,21 @@
+/*
+ * Copyright (c) 2019-2022, Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ */
+
+#ifndef PSA_MANIFEST_SID_H
+#define PSA_MANIFEST_SID_H
+
+/******** PSA_SP_INITIAL_ATTESTATION ********/
+#define RSS_ATTESTATION_SERVICE_SID (0x00000020U)
+#define RSS_ATTESTATION_SERVICE_VERSION (1U)
+#define RSS_ATTESTATION_SERVICE_HANDLE (0x40000103U)
+
+/******** PSA_SP_MEASURED_BOOT ********/
+#define RSS_MEASURED_BOOT_SID (0x000000E0U)
+#define RSS_MEASURED_BOOT_VERSION (1U)
+#define RSS_MEASURED_BOOT_HANDLE (0x40000104U)
+
+#endif /* PSA_MANIFEST_SID_H */
diff --git a/lib/psa/initial_attestation.c b/lib/psa/initial_attestation.c
new file mode 100644
index 0000000..44498a8
--- /dev/null
+++ b/lib/psa/initial_attestation.c
@@ -0,0 +1,163 @@
+/*
+ * Copyright (c) 2018-2022, Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ */
+
+#include <initial_attestation.h>
+#include <psa/client.h>
+#include <psa_manifest/sid.h>
+
+#if !PLAT_RSS_NOT_SUPPORTED
+psa_status_t
+psa_initial_attest_get_token(const uint8_t *auth_challenge,
+ size_t challenge_size,
+ uint8_t *token_buf,
+ size_t token_buf_size,
+ size_t *token_size)
+{
+ psa_status_t status;
+ psa_invec in_vec[] = {
+ {auth_challenge, challenge_size}
+ };
+ psa_outvec out_vec[] = {
+ {token_buf, token_buf_size},
+ };
+
+ status = psa_call(RSS_ATTESTATION_SERVICE_HANDLE, RSS_ATTEST_GET_TOKEN,
+ in_vec, IOVEC_LEN(in_vec),
+ out_vec, IOVEC_LEN(out_vec));
+
+ if (status == PSA_SUCCESS) {
+ *token_size = out_vec[0].len;
+ }
+
+ return status;
+}
+
+#else /* !PLAT_RSS_NOT_SUPPORTED */
+
+#include <string.h>
+
+static const uint8_t platform_token[] = {
+ 0xD2, 0x84, 0x43, 0xA1, 0x01, 0x26, 0xA0, 0x59,
+ 0x02, 0xBE, 0xAA, 0x3A, 0x00, 0x01, 0x24, 0xFF,
+ 0x58, 0x20, 0xAB, 0xAB, 0xAB, 0xAB, 0xAB, 0xAB,
+ 0xAB, 0xAB, 0xAB, 0xAB, 0xAB, 0xAB, 0xAB, 0xAB,
+ 0xAB, 0xAB, 0xAB, 0xAB, 0xAB, 0xAB, 0xAB, 0xAB,
+ 0xAB, 0xAB, 0xAB, 0xAB, 0xAB, 0xAB, 0xAB, 0xAB,
+ 0xAB, 0xAB, 0x3A, 0x00, 0x01, 0x24, 0xFB, 0x58,
+ 0x20, 0xA0, 0xA1, 0xA2, 0xA3, 0xA4, 0xA5, 0xA6,
+ 0xA7, 0xA8, 0xA9, 0xAA, 0xAB, 0xAC, 0xAD, 0xAE,
+ 0xAF, 0xB0, 0xB1, 0xB2, 0xB3, 0xB4, 0xB5, 0xB6,
+ 0xB7, 0xB8, 0xB9, 0xBA, 0xBB, 0xBC, 0xBD, 0xBE,
+ 0xBF, 0x3A, 0x00, 0x01, 0x25, 0x00, 0x58, 0x21,
+ 0x01, 0xFA, 0x58, 0x75, 0x5F, 0x65, 0x86, 0x27,
+ 0xCE, 0x54, 0x60, 0xF2, 0x9B, 0x75, 0x29, 0x67,
+ 0x13, 0x24, 0x8C, 0xAE, 0x7A, 0xD9, 0xE2, 0x98,
+ 0x4B, 0x90, 0x28, 0x0E, 0xFC, 0xBC, 0xB5, 0x02,
+ 0x48, 0x3A, 0x00, 0x01, 0x24, 0xFA, 0x58, 0x20,
+ 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA,
+ 0xBB, 0xBB, 0xBB, 0xBB, 0xBB, 0xBB, 0xBB, 0xBB,
+ 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC,
+ 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD,
+ 0x3A, 0x00, 0x01, 0x24, 0xF8, 0x20, 0x3A, 0x00,
+ 0x01, 0x24, 0xF9, 0x00, 0x3A, 0x00, 0x01, 0x24,
+ 0xFD, 0x85, 0xA5, 0x05, 0x58, 0x20, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x60,
+ 0x01, 0x65, 0x42, 0x4C, 0x31, 0x5F, 0x32, 0x06,
+ 0x66, 0x53, 0x48, 0x41, 0x32, 0x35, 0x36, 0x02,
+ 0x58, 0x20, 0xF8, 0xB7, 0xCE, 0xAD, 0x9B, 0xE4,
+ 0x5A, 0x8F, 0x5C, 0x52, 0x6F, 0x0C, 0x05, 0x25,
+ 0x8F, 0xF3, 0xE9, 0x81, 0xDC, 0xBC, 0xF2, 0x05,
+ 0x7F, 0x33, 0xF6, 0xBB, 0xDC, 0xD9, 0x4D, 0xA2,
+ 0x34, 0x3A, 0xA5, 0x05, 0x58, 0x20, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x67,
+ 0x31, 0x2E, 0x37, 0x2E, 0x32, 0x2B, 0x30, 0x01,
+ 0x63, 0x42, 0x4C, 0x32, 0x06, 0x66, 0x53, 0x48,
+ 0x41, 0x32, 0x35, 0x36, 0x02, 0x58, 0x20, 0x3A,
+ 0xE5, 0x9E, 0x40, 0xA9, 0x6B, 0xD5, 0x29, 0x1C,
+ 0xAB, 0x7A, 0x5F, 0xBD, 0x1F, 0x9A, 0xA6, 0x52,
+ 0xFB, 0x77, 0x7D, 0xA3, 0xEC, 0x9C, 0x29, 0xBC,
+ 0xE6, 0x5B, 0x3B, 0x43, 0xFC, 0x9D, 0x26, 0xA5,
+ 0x05, 0x58, 0x20, 0xBF, 0xE6, 0xD8, 0x6F, 0x88,
+ 0x26, 0xF4, 0xFF, 0x97, 0xFB, 0x96, 0xC4, 0xE6,
+ 0xFB, 0xC4, 0x99, 0x3E, 0x46, 0x19, 0xFC, 0x56,
+ 0x5D, 0xA2, 0x6A, 0xDF, 0x34, 0xC3, 0x29, 0x48,
+ 0x9A, 0xDC, 0x38, 0x04, 0x67, 0x31, 0x2E, 0x35,
+ 0x2E, 0x30, 0x2B, 0x30, 0x01, 0x64, 0x52, 0x54,
+ 0x5F, 0x30, 0x06, 0x66, 0x53, 0x48, 0x41, 0x32,
+ 0x35, 0x36, 0x02, 0x58, 0x20, 0x47, 0x94, 0x9D,
+ 0x27, 0x33, 0x82, 0x45, 0x1A, 0xDD, 0x25, 0xF4,
+ 0x9A, 0x89, 0x6F, 0x5F, 0xD9, 0xB0, 0xE8, 0x14,
+ 0xD3, 0xA4, 0x9B, 0x53, 0xB0, 0x44, 0x0B, 0xCF,
+ 0x32, 0x1A, 0xC4, 0xD2, 0x65, 0xA5, 0x05, 0x58,
+ 0x20, 0xB3, 0x60, 0xCA, 0xF5, 0xC9, 0x8C, 0x6B,
+ 0x94, 0x2A, 0x48, 0x82, 0xFA, 0x9D, 0x48, 0x23,
+ 0xEF, 0xB1, 0x66, 0xA9, 0xEF, 0x6A, 0x6E, 0x4A,
+ 0xA3, 0x7C, 0x19, 0x19, 0xED, 0x1F, 0xCC, 0xC0,
+ 0x49, 0x04, 0x67, 0x30, 0x2E, 0x30, 0x2E, 0x37,
+ 0x2B, 0x30, 0x01, 0x64, 0x52, 0x54, 0x5F, 0x31,
+ 0x06, 0x66, 0x53, 0x48, 0x41, 0x32, 0x35, 0x36,
+ 0x02, 0x58, 0x20, 0xCD, 0x38, 0xBE, 0xC8, 0xB7,
+ 0xC0, 0x9E, 0xD5, 0x24, 0x30, 0xFE, 0xC8, 0xD0,
+ 0x19, 0x12, 0x56, 0xB2, 0x7A, 0xA5, 0x53, 0x6F,
+ 0xBC, 0x7D, 0x09, 0xCA, 0x11, 0xDD, 0x90, 0xD7,
+ 0xD6, 0x70, 0xFD, 0xA5, 0x05, 0x58, 0x20, 0xAA,
+ 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA,
+ 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA,
+ 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA,
+ 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0x04,
+ 0x60, 0x01, 0x60, 0x06, 0x66, 0x53, 0x48, 0x41,
+ 0x32, 0x35, 0x36, 0x02, 0x58, 0x20, 0x28, 0x3D,
+ 0x0C, 0x25, 0x22, 0x0C, 0x87, 0x46, 0xA0, 0x58,
+ 0x64, 0x6C, 0x0B, 0x14, 0x37, 0x39, 0x40, 0x9D,
+ 0x2D, 0x11, 0xD1, 0xCC, 0x54, 0x51, 0xB4, 0x29,
+ 0x22, 0xCD, 0x70, 0x92, 0x71, 0xC3, 0x3A, 0x00,
+ 0x01, 0x25, 0x01, 0x77, 0x77, 0x77, 0x77, 0x2E,
+ 0x74, 0x72, 0x75, 0x73, 0x74, 0x65, 0x64, 0x66,
+ 0x69, 0x72, 0x6D, 0x77, 0x61, 0x72, 0x65, 0x2E,
+ 0x6F, 0x72, 0x67, 0x3A, 0x00, 0x01, 0x24, 0xF7,
+ 0x71, 0x50, 0x53, 0x41, 0x5F, 0x49, 0x4F, 0x54,
+ 0x5F, 0x50, 0x52, 0x4F, 0x46, 0x49, 0x4C, 0x45,
+ 0x5F, 0x31, 0x3A, 0x00, 0x01, 0x24, 0xFC, 0x70,
+ 0x30, 0x36, 0x30, 0x34, 0x35, 0x36, 0x35, 0x32,
+ 0x37, 0x32, 0x38, 0x32, 0x39, 0x31, 0x30, 0x30,
+ 0x58, 0x40, 0x1E, 0x0D, 0x2B, 0xD8, 0x7A, 0xC9,
+ 0x2D, 0xCB, 0x73, 0xD1, 0x42, 0x2F, 0xBF, 0xDA,
+ 0x24, 0x71, 0xE2, 0xAF, 0xEA, 0x48, 0x60, 0x17,
+ 0x23, 0x75, 0x64, 0xAC, 0xCC, 0x23, 0xA2, 0x67,
+ 0xC4, 0xE7, 0x8F, 0x1C, 0x7C, 0x68, 0x49, 0x42,
+ 0x4D, 0xDA, 0xC6, 0xD6, 0x21, 0x1C, 0xAA, 0x00,
+ 0xDA, 0x1E, 0x68, 0x56, 0xA3, 0x48, 0xEE, 0xA7,
+ 0x92, 0xA9, 0x09, 0x83, 0x42, 0x04, 0x06, 0x9E,
+ 0x62, 0xBB
+};
+
+psa_status_t
+psa_initial_attest_get_token(const uint8_t *auth_challenge,
+ size_t challenge_size,
+ uint8_t *token_buf,
+ size_t token_buf_size,
+ size_t *token_size)
+{
+ (void)auth_challenge;
+ (void)challenge_size;
+
+ if (token_buf_size < sizeof(platform_token)) {
+ return PSA_ERROR_BUFFER_TOO_SMALL;
+ }
+
+ (void)memcpy(token_buf, platform_token, sizeof(platform_token));
+ *token_size = sizeof(platform_token);
+
+ return PSA_SUCCESS;
+}
+#endif /* !PLAT_RSS_NOT_SUPPORTED */
diff --git a/lib/psa/measured_boot.c b/lib/psa/measured_boot.c
new file mode 100644
index 0000000..5d3ca8e
--- /dev/null
+++ b/lib/psa/measured_boot.c
@@ -0,0 +1,129 @@
+/*
+ * Copyright (c) 2022, Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ */
+
+#include <string.h>
+
+#include <common/debug.h>
+#include <measured_boot.h>
+#include <psa/client.h>
+#include <psa_manifest/sid.h>
+
+#include "measured_boot_private.h"
+
+static void print_byte_array(const uint8_t *array, size_t len)
+{
+ unsigned int i;
+
+ if (array == NULL || len == 0U) {
+ (void)printf("\n");
+ }
+
+ for (i = 0U; i < len; ++i) {
+ (void)printf(" %02x", array[i]);
+ if ((i & U(0xF)) == U(0xF)) {
+ (void)printf("\n");
+ if (i < (len - 1U)) {
+ INFO("\t\t:");
+ }
+ }
+ }
+}
+
+static void log_measurement(uint8_t index,
+ const uint8_t *signer_id,
+ size_t signer_id_size,
+ const uint8_t *version, /* string */
+ uint32_t measurement_algo,
+ const uint8_t *sw_type, /* string */
+ const uint8_t *measurement_value,
+ size_t measurement_value_size,
+ bool lock_measurement)
+{
+ INFO("Measured boot extend measurement:\n");
+ INFO(" - slot : %u\n", index);
+ INFO(" - signer_id :");
+ print_byte_array(signer_id, signer_id_size);
+ INFO(" - version : %s\n", version);
+ INFO(" - algorithm : %x\n", measurement_algo);
+ INFO(" - sw_type : %s\n", sw_type);
+ INFO(" - measurement :");
+ print_byte_array(measurement_value, measurement_value_size);
+ INFO(" - locking : %s\n", lock_measurement ? "true" : "false");
+}
+
+#if !PLAT_RSS_NOT_SUPPORTED
+psa_status_t
+rss_measured_boot_extend_measurement(uint8_t index,
+ const uint8_t *signer_id,
+ size_t signer_id_size,
+ const uint8_t *version,
+ size_t version_size,
+ uint32_t measurement_algo,
+ const uint8_t *sw_type,
+ size_t sw_type_size,
+ const uint8_t *measurement_value,
+ size_t measurement_value_size,
+ bool lock_measurement)
+{
+ struct measured_boot_extend_iovec_t extend_iov = {
+ .index = index,
+ .lock_measurement = lock_measurement,
+ .measurement_algo = measurement_algo,
+ .sw_type = {0},
+ .sw_type_size = sw_type_size,
+ };
+
+ psa_invec in_vec[] = {
+ {.base = &extend_iov,
+ .len = sizeof(struct measured_boot_extend_iovec_t)},
+ {.base = signer_id, .len = signer_id_size},
+ {.base = version, .len = version_size},
+ {.base = measurement_value, .len = measurement_value_size}
+ };
+
+ uint32_t sw_type_size_limited;
+
+ if (sw_type != NULL) {
+ sw_type_size_limited = (sw_type_size < SW_TYPE_MAX_SIZE) ?
+ sw_type_size : SW_TYPE_MAX_SIZE;
+ memcpy(extend_iov.sw_type, sw_type, sw_type_size_limited);
+ }
+
+ log_measurement(index, signer_id, signer_id_size,
+ version, measurement_algo, sw_type,
+ measurement_value, measurement_value_size,
+ lock_measurement);
+
+ return psa_call(RSS_MEASURED_BOOT_HANDLE,
+ RSS_MEASURED_BOOT_EXTEND,
+ in_vec, IOVEC_LEN(in_vec),
+ NULL, 0);
+}
+
+#else /* !PLAT_RSS_NOT_SUPPORTED */
+
+psa_status_t
+rss_measured_boot_extend_measurement(uint8_t index,
+ const uint8_t *signer_id,
+ size_t signer_id_size,
+ const uint8_t *version,
+ size_t version_size,
+ uint32_t measurement_algo,
+ const uint8_t *sw_type,
+ size_t sw_type_size,
+ const uint8_t *measurement_value,
+ size_t measurement_value_size,
+ bool lock_measurement)
+{
+ log_measurement(index, signer_id, signer_id_size,
+ version, measurement_algo, sw_type,
+ measurement_value, measurement_value_size,
+ lock_measurement);
+
+ return PSA_SUCCESS;
+}
+#endif /* !PLAT_RSS_NOT_SUPPORTED */
diff --git a/lib/psa/measured_boot_private.h b/lib/psa/measured_boot_private.h
new file mode 100644
index 0000000..649c3f6
--- /dev/null
+++ b/lib/psa/measured_boot_private.h
@@ -0,0 +1,24 @@
+/*
+ * Copyright (c) 2022, Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ */
+
+#ifndef PSA_MEASURED_BOOT_PRIVATE_H
+#define PSA_MEASURED_BOOT_PRIVATE_H
+
+#include <stdint.h>
+
+/* Measured boot message types that distinguish its services */
+#define RSS_MEASURED_BOOT_EXTEND 1002U
+
+struct measured_boot_extend_iovec_t {
+ uint8_t index;
+ uint8_t lock_measurement;
+ uint32_t measurement_algo;
+ uint8_t sw_type[SW_TYPE_MAX_SIZE];
+ uint8_t sw_type_size;
+};
+
+#endif /* PSA_MEASURED_BOOT_PRIVATE_H */
diff --git a/make_helpers/defaults.mk b/make_helpers/defaults.mk
index 6e57237..d5383a1 100644
--- a/make_helpers/defaults.mk
+++ b/make_helpers/defaults.mk
@@ -460,3 +460,6 @@
# SCR_EL3.TWEDEL(4bit) field, when FEAT_TWED is implemented.
# By default it takes 0, and need to be updated by the platforms.
TWED_DELAY := 0
+
+# By default, disable the mocking of RSS provided services
+PLAT_RSS_NOT_SUPPORTED := 0
diff --git a/plat/arm/board/fvp/fvp_bl1_measured_boot.c b/plat/arm/board/fvp/fvp_bl1_measured_boot.c
index 5468555..76cd918 100644
--- a/plat/arm/board/fvp/fvp_bl1_measured_boot.c
+++ b/plat/arm/board/fvp/fvp_bl1_measured_boot.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2021, Arm Limited. All rights reserved.
+ * Copyright (c) 2021-2022, Arm Limited. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
@@ -7,6 +7,7 @@
#include <stdint.h>
#include <drivers/measured_boot/event_log/event_log.h>
+#include <drivers/measured_boot/rss/rss_measured_boot.h>
#include <plat/arm/common/plat_arm.h>
/* Event Log data */
@@ -21,10 +22,39 @@
{ EVLOG_INVALID_ID, NULL, (unsigned int)(-1) } /* Terminator */
};
+/* FVP table with platform specific image IDs and metadata. Intentionally not a
+ * const struct, some members might set by bootloaders during trusted boot.
+ */
+struct rss_mboot_metadata fvp_rss_mboot_metadata[] = {
+ {
+ .id = FW_CONFIG_ID,
+ .slot = U(6),
+ .signer_id_size = SIGNER_ID_MIN_SIZE,
+ .sw_type = RSS_MBOOT_FW_CONFIG_STRING,
+ .lock_measurement = true },
+ {
+ .id = TB_FW_CONFIG_ID,
+ .slot = U(7),
+ .signer_id_size = SIGNER_ID_MIN_SIZE,
+ .sw_type = RSS_MBOOT_TB_FW_CONFIG_STRING,
+ .lock_measurement = true },
+ {
+ .id = BL2_IMAGE_ID,
+ .slot = U(8),
+ .signer_id_size = SIGNER_ID_MIN_SIZE,
+ .sw_type = RSS_MBOOT_BL2_STRING,
+ .lock_measurement = true },
+
+ {
+ .id = RSS_MBOOT_INVALID_ID }
+};
+
void bl1_plat_mboot_init(void)
{
event_log_init(event_log, event_log + sizeof(event_log));
event_log_write_header();
+
+ rss_measured_boot_init();
}
void bl1_plat_mboot_finish(void)
diff --git a/plat/arm/board/fvp/fvp_bl2_measured_boot.c b/plat/arm/board/fvp/fvp_bl2_measured_boot.c
index 1f38278..fd15b70 100644
--- a/plat/arm/board/fvp/fvp_bl2_measured_boot.c
+++ b/plat/arm/board/fvp/fvp_bl2_measured_boot.c
@@ -7,6 +7,7 @@
#include <stdint.h>
#include <drivers/measured_boot/event_log/event_log.h>
+#include <drivers/measured_boot/rss/rss_measured_boot.h>
#include <tools_share/tbbr_oid.h>
#include <fvp_critical_data.h>
@@ -35,6 +36,38 @@
{ EVLOG_INVALID_ID, NULL, (unsigned int)(-1) } /* Terminator */
};
+/* FVP table with platform specific image IDs and metadata. Intentionally not a
+ * const struct, some members might set by bootloaders during trusted boot.
+ */
+struct rss_mboot_metadata fvp_rss_mboot_metadata[] = {
+ {
+ .id = BL31_IMAGE_ID,
+ .slot = U(9),
+ .signer_id_size = SIGNER_ID_MIN_SIZE,
+ .sw_type = RSS_MBOOT_BL31_STRING,
+ .lock_measurement = true },
+ {
+ .id = HW_CONFIG_ID,
+ .slot = U(10),
+ .signer_id_size = SIGNER_ID_MIN_SIZE,
+ .sw_type = RSS_MBOOT_HW_CONFIG_STRING,
+ .lock_measurement = true },
+ {
+ .id = SOC_FW_CONFIG_ID,
+ .slot = U(11),
+ .signer_id_size = SIGNER_ID_MIN_SIZE,
+ .sw_type = RSS_MBOOT_SOC_FW_CONFIG_STRING,
+ .lock_measurement = true },
+ {
+ .id = RMM_IMAGE_ID,
+ .slot = U(12),
+ .signer_id_size = SIGNER_ID_MIN_SIZE,
+ .sw_type = RSS_MBOOT_RMM_STRING,
+ .lock_measurement = true },
+ {
+ .id = RSS_MBOOT_INVALID_ID }
+};
+
void bl2_plat_mboot_init(void)
{
uint8_t *event_log_start;
@@ -64,6 +97,8 @@
PLAT_ARM_EVENT_LOG_MAX_SIZE);
event_log_init((uint8_t *)event_log_start, event_log_finish);
+
+ rss_measured_boot_init();
}
int plat_mboot_measure_critical_data(unsigned int critical_data_id,
diff --git a/plat/arm/board/fvp/fvp_common_measured_boot.c b/plat/arm/board/fvp/fvp_common_measured_boot.c
index 6a403d9..93aa055 100644
--- a/plat/arm/board/fvp/fvp_common_measured_boot.c
+++ b/plat/arm/board/fvp/fvp_common_measured_boot.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2021, Arm Limited. All rights reserved.
+ * Copyright (c) 2021-2022, Arm Limited. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
@@ -9,27 +9,47 @@
#include <common/desc_image_load.h>
#include <drivers/measured_boot/event_log/event_log.h>
+#include <drivers/measured_boot/rss/rss_measured_boot.h>
#include <plat/arm/common/plat_arm.h>
#include <plat/common/platform.h>
extern event_log_metadata_t fvp_event_log_metadata[];
+extern struct rss_mboot_metadata fvp_rss_mboot_metadata[];
const event_log_metadata_t *plat_event_log_get_metadata(void)
{
return fvp_event_log_metadata;
}
+struct rss_mboot_metadata *plat_rss_mboot_get_metadata(void)
+{
+ return fvp_rss_mboot_metadata;
+}
+
int plat_mboot_measure_image(unsigned int image_id, image_info_t *image_data)
{
+ int err;
+ int rc = 0;
+
/* Calculate image hash and record data in Event Log */
- int err = event_log_measure_and_record(image_data->image_base,
- image_data->image_size,
- image_id);
+ err = event_log_measure_and_record(image_data->image_base,
+ image_data->image_size,
+ image_id);
if (err != 0) {
ERROR("%s%s image id %u (%i)\n",
- "Failed to ", "record", image_id, err);
- return err;
+ "Failed to ", "record in event log", image_id, err);
+ rc = err;
}
- return 0;
+ /* Calculate image hash and record data in RSS */
+ err = rss_mboot_measure_and_record(image_data->image_base,
+ image_data->image_size,
+ image_id);
+ if (err != 0) {
+ ERROR("%s%s image id %u (%i)\n",
+ "Failed to ", "record in RSS", image_id, err);
+ rc = (rc == 0) ? err : -1;
+ }
+
+ return rc;
}
diff --git a/plat/arm/board/fvp/platform.mk b/plat/arm/board/fvp/platform.mk
index d89e91f..89ca185 100644
--- a/plat/arm/board/fvp/platform.mk
+++ b/plat/arm/board/fvp/platform.mk
@@ -367,14 +367,36 @@
override BL1_SOURCES =
endif
+# Include Measured Boot makefile before any Crypto library makefile.
+# Crypto library makefile may need default definitions of Measured Boot build
+# flags present in Measured Boot makefile.
+ifeq (${MEASURED_BOOT},1)
+ RSS_MEASURED_BOOT_MK := drivers/measured_boot/rss/rss_measured_boot.mk
+ $(info Including ${RSS_MEASURED_BOOT_MK})
+ include ${RSS_MEASURED_BOOT_MK}
+
+ BL1_SOURCES += ${MEASURED_BOOT_SOURCES}
+ BL2_SOURCES += ${MEASURED_BOOT_SOURCES}
+endif
+
include plat/arm/board/common/board_common.mk
include plat/arm/common/arm_common.mk
ifeq (${MEASURED_BOOT},1)
BL1_SOURCES += plat/arm/board/fvp/fvp_common_measured_boot.c \
- plat/arm/board/fvp/fvp_bl1_measured_boot.c
+ plat/arm/board/fvp/fvp_bl1_measured_boot.c \
+ lib/psa/measured_boot.c
+
BL2_SOURCES += plat/arm/board/fvp/fvp_common_measured_boot.c \
- plat/arm/board/fvp/fvp_bl2_measured_boot.c
+ plat/arm/board/fvp/fvp_bl2_measured_boot.c \
+ lib/psa/measured_boot.c
+
+PLAT_INCLUDES += -Iinclude/lib/psa
+
+# RSS is not supported on FVP right now. Thus, we use the mocked version
+# of PSA Measured Boot APIs. They return with success and hard-coded data.
+PLAT_RSS_NOT_SUPPORTED := 1
+
endif
ifeq (${TRUSTED_BOARD_BOOT}, 1)