Boot: Save boot status to shared data area

Details:
 - PSA requirement: Attestation service must include
   the measured boot status to attestation token. Secure
   bootloader measuring the runtime SW (calculatinig its hash)
   ans shares the measurements with runtime SW through a shared
   memory area.
 - add new functions to save the boot status in TLV
   encoded format to the shared data area
 - save combined (S+NS) image hash to boot status

Change-Id: I4f7b4f134294aea75fe5bce10cd98c74614c32e8
Signed-off-by: Tamas Ban <tamas.ban@arm.com>
diff --git a/bl2/src/boot_record.c b/bl2/src/boot_record.c
new file mode 100644
index 0000000..e11059a
--- /dev/null
+++ b/bl2/src/boot_record.c
@@ -0,0 +1,96 @@
+/*
+ * Copyright (c) 2018, Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ */
+
+#include "boot_record.h"
+#include "tfm_boot_status.h"
+#include "target.h"
+#include <stdint.h>
+#include <string.h>
+
+/*!
+ * \var shared_memory_init_done
+ *
+ * \brief Indicates whether shared memory area was already initialized.
+ *
+ */
+static uint32_t shared_memory_init_done;
+
+/*!
+ * \def SHARED_MEMORY_UNINITIALZED
+ *
+ * \brief Indicates that shared memory is uninitialized.
+ */
+#define SHARED_MEMORY_UNINITIALZED (0u)
+
+/*!
+ * \def SHARED_MEMORY_INITIALZED
+ *
+ * \brief Indicates that shared memory was already initialized.
+ */
+#define SHARED_MEMORY_INITIALZED   (1u)
+
+enum shared_memory_err_t
+boot_add_data_to_shared_area(uint8_t        major_type,
+                             uint8_t        minor_type,
+                             size_t         size,
+                             const uint8_t *data)
+{
+    struct shared_data_tlv_entry tlv_entry = {0};
+    struct shared_data_tlv_header *tlv_header;
+    uint8_t *next_tlv;
+    uintptr_t tlv_end, offset;
+
+    tlv_header = (struct shared_data_tlv_header *)BOOT_TFM_SHARED_DATA_BASE;
+
+    /* Check whether first time to call this function. If does then initialise
+     * shared data area.
+     */
+    if (shared_memory_init_done == SHARED_MEMORY_UNINITIALZED) {
+        memset((void *)BOOT_TFM_SHARED_DATA_BASE, 0, BOOT_TFM_SHARED_DATA_SIZE);
+        tlv_header->tlv_magic   = SHARED_DATA_TLV_INFO_MAGIC;
+        tlv_header->tlv_tot_len = SHARED_DATA_HEADER_SIZE;
+        shared_memory_init_done = SHARED_MEMORY_INITIALZED;
+    }
+
+    /* Check whether TLV entry is already added.
+     * Get the boundaries of TLV section
+     */
+    tlv_end = BOOT_TFM_SHARED_DATA_BASE + tlv_header->tlv_tot_len;
+    offset  = BOOT_TFM_SHARED_DATA_BASE + SHARED_DATA_HEADER_SIZE;
+
+    /* Iterates over the TLV section looks for the same entry if found then
+     * returns with error: SHARED_MEMORY_OVERWRITE
+     */
+    for(; offset < tlv_end; offset += tlv_entry.tlv_len) {
+        tlv_entry = *((struct shared_data_tlv_entry *)offset);
+        if (tlv_entry.tlv_major_type == major_type &&
+            tlv_entry.tlv_minor_type == minor_type ) {
+            return SHARED_MEMORY_OVERWRITE;
+        }
+    }
+
+    /* Add TLV entry */
+    tlv_entry.tlv_major_type = major_type;
+    tlv_entry.tlv_minor_type = minor_type;
+    tlv_entry.tlv_len        = SHARED_DATA_ENTRY_SIZE(size);
+
+    /* Verify overflow of shared area */
+    if ((tlv_header->tlv_tot_len + tlv_entry.tlv_len) >
+         BOOT_TFM_SHARED_DATA_SIZE){
+        return SHARED_MEMORY_OVERFLOW;
+    }
+
+    next_tlv = (uint8_t *)tlv_header + tlv_header->tlv_tot_len;
+    memcpy(next_tlv, &tlv_entry, SHARED_DATA_ENTRY_HEADER_SIZE);
+
+    next_tlv += SHARED_DATA_ENTRY_HEADER_SIZE;
+    memcpy(next_tlv, data, size);
+
+    tlv_header->tlv_tot_len = tlv_header->tlv_tot_len + tlv_entry.tlv_len;
+
+    return SHARED_MEMORY_OK;
+}