aboutsummaryrefslogtreecommitdiff
path: root/product/n1sdp
diff options
context:
space:
mode:
authorManoj Kumar <manoj.kumar3@arm.com>2018-10-26 10:57:34 +0530
committerdavidcunado-arm <david.cunado@arm.com>2018-10-30 16:58:33 +0000
commitcb01065c185960df4f4451abf967288afa228208 (patch)
tree7f4a9f657daaf975da15a07a0c3b11e3545f4de8 /product/n1sdp
parent71343b0efa7e2c240cd44c40acfe363c86a4b434 (diff)
n1sdp/n1sdp_flash: add new module n1sdp_flash
This patch adds new n1sdp_flash module under product/n1sdp/module/ directory. N1SDP board has external QSPI flash memory in which the firmware image containing SCP BL2, MCP BL2, AP-BL31, AP-BL33 & NVM configuration data will be placed in N1SDP specific customized layout. The n1sdp_flash module is responsible for parsing the customized layout, identifying the images and saving the image descriptors in its context. Other modules can bind to n1sdp_flash to retrieve this information. Change-Id: I29643045b1cb91ec37f4772183f40e269714ac5a Signed-off-by: Manoj Kumar <manoj.kumar3@arm.com>
Diffstat (limited to 'product/n1sdp')
-rw-r--r--product/n1sdp/module/n1sdp_flash/include/internal/n1sdp_flash_layout.h95
-rw-r--r--product/n1sdp/module/n1sdp_flash/include/internal/uuid.h38
-rw-r--r--product/n1sdp/module/n1sdp_flash/include/mod_n1sdp_flash.h213
-rw-r--r--product/n1sdp/module/n1sdp_flash/src/Makefile11
-rw-r--r--product/n1sdp/module/n1sdp_flash/src/mod_n1sdp_flash.c303
5 files changed, 660 insertions, 0 deletions
diff --git a/product/n1sdp/module/n1sdp_flash/include/internal/n1sdp_flash_layout.h b/product/n1sdp/module/n1sdp_flash/include/internal/n1sdp_flash_layout.h
new file mode 100644
index 00000000..0c92c5da
--- /dev/null
+++ b/product/n1sdp/module/n1sdp_flash/include/internal/n1sdp_flash_layout.h
@@ -0,0 +1,95 @@
+/*
+ * Arm SCP/MCP Software
+ * Copyright (c) 2018, Arm Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ * Description:
+ * Header file defining the N1SDP flash layout showing the structures of
+ * flash table of content (TOC), N1SDP FIP table of content, TOC signatures
+ * and UUID values of binary images within the firmware package.
+ */
+
+#ifndef N1SDP_FLASH_LAYOUT_H
+#define N1SDP_FLASH_LAYOUT_H
+
+#include <stdint.h>
+#include "uuid.h"
+
+/*
+ * Flash entry definitions
+ */
+
+/* Flash signature */
+#define FLASH_TOC_SIGNATURE 0x5A5AA5A5
+
+/* Flash TOC entries */
+struct n1sdp_flash_toc_entry {
+ uint32_t type:16;
+ uint32_t instance:8;
+ uint32_t reserved:8;
+ uint32_t offset;
+ uint32_t size;
+ uint32_t flags:16;
+ uint32_t checksum:16;
+} __packed;
+
+/* Flash Table of contents (TOC) */
+struct n1sdp_flash_memory_toc {
+ uint32_t signature;
+ uint32_t major_version:8;
+ uint32_t minor_version:8;
+ uint32_t rev_number:8;
+ uint32_t pass_number:8;
+ uint32_t date_of_last_update;
+ uint32_t entry_count:16;
+ uint32_t checksum:16;
+ struct n1sdp_flash_toc_entry entry[];
+} __packed;
+
+
+/*
+ * N1SDP Firmware Image Package (NFIP) entry definitions
+ */
+
+/* NFIP signature */
+#define NFIP_TOC_SIGNATURE 0xAA640001
+
+/*
+ * UUID values of NFIP entries
+ */
+#define UUID_SCP_FIRMWARE_SCP_BL2 \
+{0x3dfd6697, 0xbe89, 0x49e8, 0xae, 0x5d, {0x78, 0xa1, 0x40, 0x60, 0x82, 0x13} }
+#define UUID_MCP_FIRMWARE_MCP_BL2 \
+{0xce1e5890, 0x52d5, 0x11e7, 0xb1, 0x14, {0xb2, 0xf9, 0x33, 0xd5, 0xfe, 0x66} }
+#define UUID_EL3_RUNTIME_FIRMWARE_BL31 \
+{0x6d08d447, 0xfe4c, 0x4698, 0x9b, 0x95, {0x29, 0x50, 0xcb, 0xbd, 0x5a, 0x00} }
+#define UUID_SECURE_PAYLOAD_BL32 \
+{0x89e1d005, 0xdc53, 0x4713, 0x8d, 0x2b, {0x50, 0x0a, 0x4b, 0x7a, 0x3e, 0x38} }
+#define UUID_NON_TRUSTED_FIRMWARE_BL33 \
+{0xa7eed0d6, 0xeafc, 0x4bd5, 0x97, 0x82, {0x99, 0x34, 0xf2, 0x34, 0xb6, 0xe4} }
+
+/* NFIP TOC entry */
+struct n1sdp_fip_toc_entry {
+ struct uuid_t uuid;
+ uint32_t offset;
+ uint32_t size;
+ uint32_t flags;
+ uint32_t image_checksum:16;
+ uint32_t checksum:16;
+} __packed;
+
+/* NFIP Table of contents (TOC) */
+struct n1sdp_fip_memory_toc {
+ uint32_t signature;
+ uint32_t major_version:8;
+ uint32_t minor_version:8;
+ uint32_t rev_number:8;
+ uint32_t pass_number:8;
+ uint32_t date_of_last_update;
+ uint32_t entry_count:16;
+ uint32_t checksum:16;
+ struct n1sdp_fip_toc_entry entry[];
+} __packed;
+
+#endif /* N1SDP_FLASH_LAYOUT_H */
diff --git a/product/n1sdp/module/n1sdp_flash/include/internal/uuid.h b/product/n1sdp/module/n1sdp_flash/include/internal/uuid.h
new file mode 100644
index 00000000..fd5ad9b3
--- /dev/null
+++ b/product/n1sdp/module/n1sdp_flash/include/internal/uuid.h
@@ -0,0 +1,38 @@
+/*
+ * Arm SCP/MCP Software
+ * Copyright (c) 2018, Arm Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ * Description:
+ * Header file defining the structure of the Universally Unique
+ * IDentifier (UUID) used to identify different binaries within
+ * the firmware package.
+ */
+
+#ifndef UUID_H
+#define UUID_H
+
+/* Length of a node address (an IEEE 802 address). */
+#define _UUID_NODE_LEN 6
+
+/* Length of UUID string including dashes. */
+#define _UUID_STR_LEN 36
+
+/*
+ * See also:
+ * http://www.opengroup.org/dce/info/draft-leach-uuids-guids-01.txt
+ * http://www.opengroup.org/onlinepubs/009629399/apdxa.htm
+ *
+ * A DCE 1.1 compatible source representation of UUIDs.
+ */
+struct uuid_t {
+ uint32_t time_low;
+ uint16_t time_mid;
+ uint16_t time_hi_and_version;
+ uint8_t clock_seq_hi_and_reserved;
+ uint8_t clock_seq_low;
+ uint8_t node[_UUID_NODE_LEN];
+};
+
+#endif /* UUID_H */
diff --git a/product/n1sdp/module/n1sdp_flash/include/mod_n1sdp_flash.h b/product/n1sdp/module/n1sdp_flash/include/mod_n1sdp_flash.h
new file mode 100644
index 00000000..c5b89625
--- /dev/null
+++ b/product/n1sdp/module/n1sdp_flash/include/mod_n1sdp_flash.h
@@ -0,0 +1,213 @@
+/*
+ * Arm SCP/MCP Software
+ * Copyright (c) 2018, Arm Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ * Description:
+ * Header file for N1SDP flash driver module used to parse the firmware
+ * package residing in on-board QSPI flash memory.
+ */
+
+#ifndef MOD_N1SDP_FLASH_H
+#define MOD_N1SDP_FLASH_H
+
+#include <stddef.h>
+#include <stdint.h>
+#include <fwk_id.h>
+
+/*!
+ * \addtogroup GroupModules Modules
+ * @{
+ */
+
+/*!
+ * \defgroup GroupModuleN1SDPFlash N1SDP Flash
+ *
+ * \brief Provides an API to access N1SDP's QSPI flash memory.
+ *
+ * \details This module provides a table of descriptors that each describe a
+ * block of data in the QSPI flash memory.
+ *
+ * \{
+ */
+
+/*!
+ * \brief CRC-16-CCITT reversed polynomial used for CRC calculation.
+ */
+#define CRC16_POLYNOMIAL UINT16_C(0x8408)
+
+/*!
+ * \brief Type of flash entry.
+ */
+enum mod_n1sdp_flash_data_type {
+ /*! SCP bypass ROM */
+ MOD_N1SDP_FLASH_DATA_TYPE_ROM_BYPASS = 1,
+
+ /*! N1SDP Firmware Image Package (NFIP) */
+ MOD_N1SDP_FLASH_DATA_TYPE_NFIP,
+
+ /*! NVM configuration space */
+ MOD_N1SDP_FLASH_DATA_TYPE_NVM_CFG,
+
+ /*! NVM log space */
+ MOD_N1SDP_FLASH_DATA_TYPE_NVM_LOG,
+
+ /*! Number of flash entry types */
+ MOD_N1SDP_FLASH_DATA_TYPE_COUNT,
+};
+
+/*!
+ * \brief Type of N1SDP FIP entry.
+ */
+enum mod_n1sdp_fip_data_type {
+ /*! SCP BL2 Binary */
+ MOD_N1SDP_FIP_TYPE_SCP_BL2,
+
+ /*! MCP BL2 Binary */
+ MOD_N1SDP_FIP_TYPE_MCP_BL2,
+
+ /*! EL3 Runtime - BL31 Binary */
+ MOD_N1SDP_FIP_TYPE_TF_BL31,
+
+ /*! Secure Payload BL32 Binary */
+ MOD_N1SDP_FIP_TYPE_TF_BL32,
+
+ /*! Non-secure BL33 (UEFI) Binary */
+ MOD_N1SDP_FIP_TYPE_NS_BL33,
+
+ /*! Number of N1SDP FIP entry types */
+ MOD_N1SDP_FIP_TYPE_COUNT,
+};
+
+/*!
+ * \brief Attribute flags used for flash & NFIP entries.
+ */
+enum mod_n1sdp_flash_data_flag {
+ MOD_N1SDP_FLASH_DATA_FLAG_ACTIVE = (1 << 0),
+ MOD_N1SDP_FLASH_DATA_FLAG_ENABLED = (1 << 1),
+ MOD_N1SDP_FLASH_DATA_FLAG_CRC16_ENABLED = (1 << 2),
+ MOD_N1SDP_FLASH_DATA_FLAG_SECURE = (1 << 3),
+};
+
+/*!
+ * \brief Descriptor for a flash table entry.
+ */
+struct mod_n1sdp_flash_descriptor {
+ /*! The type of the flash entry */
+ enum mod_n1sdp_flash_data_type type;
+
+ /*!
+ * The absolute address of the start of the data described by this
+ * entry.
+ */
+ uintptr_t address;
+
+ /*! The size of the data described by this entry */
+ size_t size;
+
+ /*! Attribute flags of the data described by this entry */
+ enum mod_n1sdp_flash_data_flag flags;
+};
+
+/*!
+ * \brief Descriptor for a NFIP table entry.
+ */
+struct mod_n1sdp_fip_descriptor {
+ /*! The type of the NFIP table entry */
+ enum mod_n1sdp_fip_data_type type;
+
+ /*!
+ * The absolute address of the start of the data described by this
+ * entry.
+ */
+ uintptr_t address;
+
+ /*! The size of the data described by this entry */
+ size_t size;
+
+ /*! Attribute flags of the data described by this entry */
+ enum mod_n1sdp_flash_data_flag flags;
+};
+
+/*!
+ * \brief N1SDP Flash Module configuration
+ */
+struct mod_n1sdp_flash_config {
+ /*! Base address of the memory-mapped flash memory. */
+ uintptr_t flash_base_address;
+
+ /*! Alternate base address of the memory-mapped flash memory. */
+ uintptr_t flash_base_address_alt;
+
+ /*! Offset of the Flash Table of Contents (TOC) from flash base address. */
+ uintptr_t toc_offset;
+};
+
+/*!
+ * \brief APIs to access the descriptors in the flash memory.
+ */
+struct mod_n1sdp_flash_api {
+ /*!
+ * \brief Get the total number of flash descriptors.
+ *
+ * \param id Module identifier.
+ * \param count Pointer to storage for the descriptor count.
+ *
+ * \retval FWK_SUCCESS Operation succeeded.
+ * \retval FWK_E_PARAM The \p count parameter was invalid.
+ * \return One of the other specific error codes described by framework.
+ */
+ int (*get_flash_descriptor_count)(fwk_id_t id, unsigned int *count);
+
+ /*!
+ * \brief Get a pointer to the table of descriptors that describe the flash
+ * memory.
+ *
+ * \param id Module identifier.
+ * \param count Pointer to storage for the descriptor table.
+ *
+ * \retval FWK_SUCCESS Operation succeeded.
+ * \retval FWK_E_PARAM The \p table parameter was invalid.
+ * \return One of the other specific error codes described by framework.
+ */
+ int (*get_flash_descriptor_table)(
+ fwk_id_t id,
+ struct mod_n1sdp_flash_descriptor **table);
+ /*!
+ * \brief Get the total number of NFIP descriptors.
+ *
+ * \param id Module identifier.
+ * \param count Pointer to storage for the descriptor count.
+ *
+ * \retval FWK_SUCCESS Operation succeeded.
+ * \retval FWK_E_PARAM The \p count parameter was invalid.
+ * \return One of the other specific error codes described by framework.
+ */
+ int (*get_n1sdp_fip_descriptor_count)(fwk_id_t id, unsigned int *count);
+
+ /*!
+ * \brief Get a pointer to the table of descriptors that describe the FIP
+ * memory.
+ *
+ * \param id Module identifier.
+ * \param count Pointer to storage for the descriptor table.
+ *
+ * \retval FWK_SUCCESS Operation succeeded.
+ * \retval FWK_E_PARAM The \p table parameter was invalid.
+ * \return One of the other specific error codes described by framework.
+ */
+ int (*get_n1sdp_fip_descriptor_table)(
+ fwk_id_t id,
+ struct mod_n1sdp_fip_descriptor **table);
+};
+
+/*!
+ * \}
+ */
+
+/*!
+ * \}
+ */
+
+#endif /* MOD_N1SDP_FLASH_H */
diff --git a/product/n1sdp/module/n1sdp_flash/src/Makefile b/product/n1sdp/module/n1sdp_flash/src/Makefile
new file mode 100644
index 00000000..e1c354a7
--- /dev/null
+++ b/product/n1sdp/module/n1sdp_flash/src/Makefile
@@ -0,0 +1,11 @@
+#
+# Arm SCP/MCP Software
+# Copyright (c) 2018, Arm Limited and Contributors. All rights reserved.
+#
+# SPDX-License-Identifier: BSD-3-Clause
+#
+
+BS_LIB_NAME := "N1SDP Flash"
+BS_LIB_SOURCES = mod_n1sdp_flash.c
+
+include $(BS_DIR)/lib.mk
diff --git a/product/n1sdp/module/n1sdp_flash/src/mod_n1sdp_flash.c b/product/n1sdp/module/n1sdp_flash/src/mod_n1sdp_flash.c
new file mode 100644
index 00000000..33a16c30
--- /dev/null
+++ b/product/n1sdp/module/n1sdp_flash/src/mod_n1sdp_flash.c
@@ -0,0 +1,303 @@
+/*
+ * Arm SCP/MCP Software
+ * Copyright (c) 2018, Arm Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ * Description:
+ * Source file for N1SDP flash driver module used to parse the firmware
+ * package residing in on-board QSPI flash memory.
+ */
+
+#include <string.h>
+#include <assert.h>
+#include <fwk_errno.h>
+#include <fwk_id.h>
+#include <fwk_mm.h>
+#include <fwk_module.h>
+#include <mod_n1sdp_flash.h>
+#include <internal/n1sdp_flash_layout.h>
+
+/*
+ * Module context
+ */
+struct mod_n1sdp_flash_ctx {
+ /* Flash descriptor count */
+ unsigned int flash_desc_count;
+
+ /* NFIP descriptor count */
+ unsigned int n1sdp_fip_desc_count;
+
+ /* Flash descriptor table */
+ struct mod_n1sdp_flash_descriptor *flash_desc_table;
+
+ /* FIP descriptor table */
+ struct mod_n1sdp_fip_descriptor *n1sdp_fip_desc_table;
+};
+
+static struct mod_n1sdp_flash_ctx n1sdp_flash_ctx;
+
+/*
+ * Module API Implementation
+ */
+static int get_flash_descriptor_count(fwk_id_t id, unsigned int *count)
+{
+ int status = fwk_module_check_call(id);
+ if (status != FWK_SUCCESS)
+ return status;
+
+ if (count == NULL)
+ return FWK_E_PARAM;
+
+ *count = n1sdp_flash_ctx.flash_desc_count;
+
+ return FWK_SUCCESS;
+}
+
+static int get_flash_descriptor_table(
+ fwk_id_t id,
+ struct mod_n1sdp_flash_descriptor **table)
+{
+ int status = fwk_module_check_call(id);
+ if (status != FWK_SUCCESS)
+ return status;
+
+ if (table == NULL)
+ return FWK_E_PARAM;
+
+ *table = n1sdp_flash_ctx.flash_desc_table;
+
+ return FWK_SUCCESS;
+}
+
+static int get_n1sdp_fip_descriptor_count(fwk_id_t id, unsigned int *count)
+{
+ int status = fwk_module_check_call(id);
+ if (status != FWK_SUCCESS)
+ return status;
+
+ if (count == NULL)
+ return FWK_E_PARAM;
+
+ *count = n1sdp_flash_ctx.n1sdp_fip_desc_count;
+
+ return FWK_SUCCESS;
+}
+
+static int get_n1sdp_fip_descriptor_table(
+ fwk_id_t id,
+ struct mod_n1sdp_fip_descriptor **table)
+{
+ int status = fwk_module_check_call(id);
+ if (status != FWK_SUCCESS)
+ return status;
+
+ if (table == NULL)
+ return FWK_E_PARAM;
+
+ *table = n1sdp_flash_ctx.n1sdp_fip_desc_table;
+
+ return FWK_SUCCESS;
+}
+
+static struct mod_n1sdp_flash_api module_api = {
+ .get_flash_descriptor_count = get_flash_descriptor_count,
+ .get_flash_descriptor_table = get_flash_descriptor_table,
+ .get_n1sdp_fip_descriptor_count = get_n1sdp_fip_descriptor_count,
+ .get_n1sdp_fip_descriptor_table = get_n1sdp_fip_descriptor_table,
+};
+
+/*
+ * Utility functions
+ */
+static uint16_t crc16(const void *data, uint32_t size)
+{
+ uint16_t crc = 0;
+ uint16_t poly = CRC16_POLYNOMIAL;
+ const uint8_t *byte = data;
+ uint32_t i = 0, j = 0;
+
+ assert(data != NULL);
+ assert(size != 0);
+
+ for (i = 0; i < size; ++i) {
+ crc = crc ^ byte[i];
+ for (j = 0; j < 8; j++) {
+ if (crc & 0x0001)
+ crc = (crc >> 1) ^ poly;
+ else
+ crc = crc >> 1;
+ }
+ }
+
+ return crc;
+}
+
+/*
+ * Flash & FIP parsing functions
+ */
+static int n1sdp_fip_parse(uintptr_t n1sdp_fip_base)
+{
+ const struct n1sdp_fip_memory_toc *n1sdp_fip_toc = NULL;
+ const struct n1sdp_fip_toc_entry *toc_entry = NULL;
+ struct mod_n1sdp_fip_descriptor *n1sdp_fip_desc = NULL;
+ struct uuid_t scp_bl2_uuid = UUID_SCP_FIRMWARE_SCP_BL2;
+ struct uuid_t mcp_bl2_uuid = UUID_MCP_FIRMWARE_MCP_BL2;
+ struct uuid_t bl31_uuid = UUID_EL3_RUNTIME_FIRMWARE_BL31;
+ struct uuid_t bl32_uuid = UUID_SECURE_PAYLOAD_BL32;
+ struct uuid_t bl33_uuid = UUID_NON_TRUSTED_FIRMWARE_BL33;
+
+ n1sdp_fip_toc = (const struct n1sdp_fip_memory_toc *)n1sdp_fip_base;
+ if (n1sdp_fip_toc == NULL)
+ return FWK_E_PANIC;
+
+ if (crc16(n1sdp_fip_toc, sizeof(struct n1sdp_fip_memory_toc)) != 0)
+ return FWK_E_DATA;
+
+ if (n1sdp_fip_toc->signature != NFIP_TOC_SIGNATURE)
+ return FWK_E_DATA;
+
+ if (n1sdp_fip_toc->entry_count == 0)
+ return FWK_E_DATA;
+
+ n1sdp_flash_ctx.n1sdp_fip_desc_count = n1sdp_fip_toc->entry_count;
+
+ n1sdp_flash_ctx.n1sdp_fip_desc_table = fwk_mm_calloc(
+ n1sdp_flash_ctx.n1sdp_fip_desc_count,
+ sizeof(struct mod_n1sdp_fip_descriptor));
+ if (n1sdp_flash_ctx.n1sdp_fip_desc_table == NULL)
+ return FWK_E_NOMEM;
+
+ for (unsigned int i = 0; i < n1sdp_flash_ctx.n1sdp_fip_desc_count; i++) {
+ toc_entry = &n1sdp_fip_toc->entry[i];
+ /* Check if CRC has to be calculated */
+ if (toc_entry->flags & MOD_N1SDP_FLASH_DATA_FLAG_CRC16_ENABLED) {
+ if (crc16(toc_entry, sizeof(*toc_entry)) != 0)
+ return FWK_E_DATA;
+ }
+
+ n1sdp_fip_desc = &n1sdp_flash_ctx.n1sdp_fip_desc_table[i];
+ n1sdp_fip_desc->address = (n1sdp_fip_base + toc_entry->offset);
+ n1sdp_fip_desc->size = toc_entry->size;
+ n1sdp_fip_desc->flags = toc_entry->flags;
+
+ if (!memcmp(&toc_entry->uuid,
+ &scp_bl2_uuid,
+ sizeof(struct uuid_t))) {
+ n1sdp_fip_desc->type = MOD_N1SDP_FIP_TYPE_SCP_BL2;
+ } else if (!memcmp(&toc_entry->uuid,
+ &mcp_bl2_uuid, sizeof(struct uuid_t))) {
+ n1sdp_fip_desc->type = MOD_N1SDP_FIP_TYPE_MCP_BL2;
+ } else if (!memcmp(&toc_entry->uuid,
+ &bl31_uuid, sizeof(struct uuid_t))) {
+ n1sdp_fip_desc->type = MOD_N1SDP_FIP_TYPE_TF_BL31;
+ } else if (!memcmp(&toc_entry->uuid,
+ &bl32_uuid, sizeof(struct uuid_t))) {
+ n1sdp_fip_desc->type = MOD_N1SDP_FIP_TYPE_TF_BL32;
+ } else if (!memcmp(&toc_entry->uuid,
+ &bl33_uuid, sizeof(struct uuid_t))) {
+ n1sdp_fip_desc->type = MOD_N1SDP_FIP_TYPE_NS_BL33;
+ } else {
+ return FWK_E_DATA;
+ }
+ }
+
+ return FWK_SUCCESS;
+}
+
+static int n1sdp_flash_parse(uintptr_t address, uintptr_t offset)
+{
+ const struct n1sdp_flash_memory_toc *toc = NULL;
+ const struct n1sdp_flash_toc_entry *toc_entry = NULL;
+ struct mod_n1sdp_flash_descriptor *flash_desc = NULL;
+ int status;
+
+ toc = (void *)(address + offset);
+
+ if (crc16(toc, sizeof(struct n1sdp_flash_memory_toc)) != 0)
+ return FWK_E_DATA;
+
+ if (toc->signature != FLASH_TOC_SIGNATURE)
+ return FWK_E_DATA;
+
+ if (toc->entry_count == 0)
+ return FWK_E_DATA;
+
+ n1sdp_flash_ctx.flash_desc_count = toc->entry_count;
+
+ n1sdp_flash_ctx.flash_desc_table = fwk_mm_calloc(
+ n1sdp_flash_ctx.flash_desc_count,
+ sizeof(struct mod_n1sdp_flash_descriptor));
+
+ if (n1sdp_flash_ctx.flash_desc_table == NULL)
+ return FWK_E_NOMEM;
+
+ for (unsigned int i = 0; i < n1sdp_flash_ctx.flash_desc_count; ++i) {
+ toc_entry = &toc->entry[i];
+ /* Check if CRC has to be calculated */
+ if (toc_entry->flags & MOD_N1SDP_FLASH_DATA_FLAG_CRC16_ENABLED) {
+ if (crc16(toc_entry, sizeof(*toc_entry)) != 0)
+ return FWK_E_DATA;
+ }
+
+ flash_desc = &n1sdp_flash_ctx.flash_desc_table[i];
+ flash_desc->address = (address + toc_entry->offset);
+ flash_desc->size = toc_entry->size;
+ flash_desc->flags = toc_entry->flags;
+ flash_desc->type = toc_entry->type;
+
+ /* If flash entry type is N1SDP FIP (NFIP) then parse it */
+ if (toc->entry[i].type == MOD_N1SDP_FLASH_DATA_TYPE_NFIP) {
+ status = n1sdp_fip_parse(flash_desc->address);
+ if (status != FWK_SUCCESS)
+ return FWK_E_DATA;
+ }
+ }
+ return FWK_SUCCESS;
+}
+
+/*
+ * Framework handlers
+ */
+
+static int n1sdp_flash_init(
+ fwk_id_t module_id,
+ unsigned int element_count,
+ const void *data)
+{
+ int status;
+ const struct mod_n1sdp_flash_config *config = NULL;
+
+ config = (const struct mod_n1sdp_flash_config *)data;
+ if ((config == NULL) || (element_count > 0))
+ return FWK_E_PANIC;
+
+ /* Parse & validate the flash base address */
+ status = n1sdp_flash_parse(config->flash_base_address, config->toc_offset);
+
+ /* No valid records found. Parse & validate alternate base address */
+ if (status == FWK_E_DATA) {
+ return n1sdp_flash_parse(config->flash_base_address_alt,
+ config->toc_offset);
+ }
+
+ return status;
+}
+
+static int n1sdp_flash_process_bind_request(
+ fwk_id_t requester_id,
+ fwk_id_t id,
+ fwk_id_t api_id,
+ const void **api)
+{
+ *api = &module_api;
+ return FWK_SUCCESS;
+}
+
+const struct fwk_module module_n1sdp_flash = {
+ .name = "N1SDP Flash",
+ .type = FWK_MODULE_TYPE_SERVICE,
+ .api_count = 1,
+ .init = n1sdp_flash_init,
+ .process_bind_request = n1sdp_flash_process_bind_request,
+};