diff options
author | Manoj Kumar <manoj.kumar3@arm.com> | 2018-10-26 10:57:34 +0530 |
---|---|---|
committer | davidcunado-arm <david.cunado@arm.com> | 2018-10-30 16:58:33 +0000 |
commit | cb01065c185960df4f4451abf967288afa228208 (patch) | |
tree | 7f4a9f657daaf975da15a07a0c3b11e3545f4de8 /product/n1sdp | |
parent | 71343b0efa7e2c240cd44c40acfe363c86a4b434 (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')
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, +}; |