mirror of
https://gitlab.rtems.org/rtems/rtos/rtems.git
synced 2025-11-16 04:24:45 +00:00
bsps/shared/dev/nor: Add SFDP and CFI parsers
This commit is contained in:
committed by
Kinsey Moore
parent
2179cd2fee
commit
f77bb9762a
144
bsps/include/dev/nor/config-parser.h
Normal file
144
bsps/include/dev/nor/config-parser.h
Normal file
@@ -0,0 +1,144 @@
|
||||
/* SPDX-License-Identifier: BSD-2-Clause */
|
||||
|
||||
/*
|
||||
* Copyright (C) 2023 On-Line Applications Research Corporation (OAR)
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
|
||||
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include <rtems/rtems/status.h>
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
|
||||
/**
|
||||
* This struct holds the information parsed from the Common Flash Memory
|
||||
* Information (CFI) read from a flash chip.
|
||||
*/
|
||||
typedef struct NOR_Config_Data {
|
||||
/* JEDEC ID */
|
||||
uint32_t jedec_id;
|
||||
/* Sector size in bytes */
|
||||
uint32_t SectorSize;
|
||||
/* Number of sectors */
|
||||
uint32_t NumSectors;
|
||||
/* Page size in bytes. This will default to 256 if unavailable. */
|
||||
uint16_t PageSize;
|
||||
/* This is the size of the flash device */
|
||||
uint64_t DeviceSize;
|
||||
/*
|
||||
* Alternative Sector size in bytes. This will be 0 if the alternative sector
|
||||
* size is unsupported or unavailable.
|
||||
*/
|
||||
uint32_t AltSectorSize;
|
||||
/* The command byte to erase sectors in the alternative size */
|
||||
uint8_t AltSectorCmd;
|
||||
/* Number of sectors for the alternative sector size */
|
||||
uint32_t NumAltSectors;
|
||||
} NOR_Config_Data;
|
||||
|
||||
/**
|
||||
*
|
||||
* This function parses the provided buffer of CFI data into a NOR_Config_Data
|
||||
* structure.
|
||||
*
|
||||
* @param cfi_raw is a buffer containing CFI data.
|
||||
* @param cfi_raw_len is the length of the data in cfi_raw.
|
||||
* @param data is a pointer to a NOR_Config_Data struct to be filled with data
|
||||
* about the flash chip.
|
||||
*
|
||||
* @return RTEMS_SUCCESSFUL if successful.
|
||||
*/
|
||||
rtems_status_code CFI_parse_from_buffer(
|
||||
uint8_t *cfi_raw,
|
||||
size_t cfi_raw_len,
|
||||
NOR_Config_Data *data
|
||||
);
|
||||
|
||||
/**
|
||||
*
|
||||
* This function parses the provided buffer of SFDP data into a NOR_Config_Data
|
||||
* structure.
|
||||
*
|
||||
* @param sfdp_raw is a buffer containing SFDP data.
|
||||
* @param sfdp_raw_len is the length of the data in sfdp_raw.
|
||||
* @param data is a pointer to a NOR_Config_Data struct to be filled with data
|
||||
* about the flash chip.
|
||||
*
|
||||
* @return RTEMS_SUCCESSFUL if successful.
|
||||
*/
|
||||
rtems_status_code SFDP_parse_from_buffer(
|
||||
uint8_t *sfdp_raw,
|
||||
size_t sfdp_raw_len,
|
||||
NOR_Config_Data *data
|
||||
);
|
||||
|
||||
/**
|
||||
* @brief Acquire data from the NOR chip.
|
||||
*
|
||||
* @param[in] context The context data used to retrieve bytes.
|
||||
* @param[in] offset The offset to read from the flash begin in bytes.
|
||||
* @param[in] length The size of the buffer in bytes.
|
||||
*
|
||||
* @retval NULL on failure.
|
||||
* @retval pointer to the requested data on success.
|
||||
*/
|
||||
typedef uint8_t *(*NOR_Config_Resource_Acquire)(
|
||||
void *context,
|
||||
uint32_t offset,
|
||||
size_t length
|
||||
);
|
||||
|
||||
/**
|
||||
* @brief Release data acquired from the NOR chip.
|
||||
*
|
||||
* @param[in] context The context data used to retrieve bytes.
|
||||
* @param[in] data The data previously acquired.
|
||||
*/
|
||||
typedef void (*NOR_Config_Resource_Release)(
|
||||
void *context,
|
||||
uint8_t *data
|
||||
);
|
||||
|
||||
typedef struct NOR_Config_Accessor {
|
||||
/* The context provided to the acquire and release functions */
|
||||
void *context;
|
||||
/* The function used to acquire a block of data */
|
||||
NOR_Config_Resource_Acquire acquire;
|
||||
/* The function used to release a block of data */
|
||||
NOR_Config_Resource_Release release;
|
||||
} NOR_Config_Accessor;
|
||||
|
||||
/**
|
||||
*
|
||||
* This function parses a SFDP configuration space into a NOR_Config_Data
|
||||
* structure.
|
||||
*
|
||||
* @param accessor is the accessor for the SFDP configuration space.
|
||||
* @param data is a pointer to a NOR_Config_Data struct to be filled with data
|
||||
* about the flash chip.
|
||||
*
|
||||
* @return RTEMS_SUCCESSFUL if successful.
|
||||
*/
|
||||
rtems_status_code SFDP_parse(
|
||||
NOR_Config_Accessor *accessor,
|
||||
NOR_Config_Data *data
|
||||
);
|
||||
402
bsps/shared/dev/nor/config-parser.c
Normal file
402
bsps/shared/dev/nor/config-parser.c
Normal file
@@ -0,0 +1,402 @@
|
||||
/* SPDX-License-Identifier: BSD-2-Clause */
|
||||
|
||||
/*
|
||||
* Copyright (C) 2023 On-Line Applications Research Corporation (OAR)
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
|
||||
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include <dev/nor/config-parser.h>
|
||||
#include <string.h>
|
||||
|
||||
static int read_config_byte(uint8_t *config_raw, size_t config_raw_len, int datalen, int desired_byte, uint8_t *read_byte)
|
||||
{
|
||||
/* access outside buffer */
|
||||
if (desired_byte >= config_raw_len) {
|
||||
return 1;
|
||||
}
|
||||
if (datalen != 0) {
|
||||
/* access past self-declared limit */
|
||||
if (desired_byte >= datalen) {
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
*read_byte = config_raw[desired_byte];
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int verify_config_string(uint8_t *config_raw, size_t config_raw_len, int datalen, int startbyte, char *config_string)
|
||||
{
|
||||
uint8_t bufbyte;
|
||||
int endbyte = strlen(config_string) + startbyte;
|
||||
for (;startbyte < endbyte; startbyte++, config_string++) {
|
||||
if (read_config_byte(config_raw, config_raw_len, datalen, startbyte, &bufbyte)) {
|
||||
return 1;
|
||||
}
|
||||
if (bufbyte != *config_string) {
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Read two consecutive bytes as a little endian short */
|
||||
static int read_config_short(uint8_t *config_raw, size_t config_raw_len, int datalen, int startbyte, uint16_t *config_short)
|
||||
{
|
||||
uint8_t bufbyte;
|
||||
if (read_config_byte(config_raw, config_raw_len, datalen, startbyte + 1, &bufbyte)) {
|
||||
return 1;
|
||||
}
|
||||
*config_short = bufbyte;
|
||||
*config_short <<= 8;
|
||||
if (read_config_byte(config_raw, config_raw_len, datalen, startbyte, &bufbyte)) {
|
||||
return 1;
|
||||
}
|
||||
*config_short |= bufbyte;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Read two consecutive shorts as an int */
|
||||
static int read_config_int(uint8_t *config_raw, size_t config_raw_len, int datalen, int startbyte, uint32_t *config_int)
|
||||
{
|
||||
uint16_t bufshort;
|
||||
if (read_config_short(config_raw, config_raw_len, datalen, startbyte + 2, &bufshort)) {
|
||||
return 1;
|
||||
}
|
||||
*config_int = bufshort;
|
||||
*config_int <<= 16;
|
||||
if (read_config_short(config_raw, config_raw_len, datalen, startbyte, &bufshort)) {
|
||||
return 1;
|
||||
}
|
||||
*config_int |= bufshort;
|
||||
return 0;
|
||||
}
|
||||
|
||||
rtems_status_code CFI_parse_from_buffer(
|
||||
uint8_t *cfi_raw,
|
||||
size_t cfi_raw_len,
|
||||
NOR_Config_Data *data
|
||||
)
|
||||
{
|
||||
memset(data, 0, sizeof(NOR_Config_Data));
|
||||
|
||||
if (cfi_raw_len < 4 || cfi_raw_len > 512) {
|
||||
return RTEMS_INVALID_SIZE;
|
||||
}
|
||||
|
||||
data->jedec_id = ((cfi_raw[0] << 16) | (cfi_raw[1] << 8) | cfi_raw[2]);
|
||||
int datalen = cfi_raw[3];
|
||||
if (datalen != 0) {
|
||||
/*
|
||||
* datalen as read is remaining valid bytes after 0x3 (the 4th byte), so
|
||||
* account for those bytes since this is used as an absolute index limit
|
||||
* */
|
||||
datalen += 4;
|
||||
}
|
||||
|
||||
/* verify query string ("QRY") exists */
|
||||
if (verify_config_string(cfi_raw, cfi_raw_len, datalen, 0x10, "QRY")) {
|
||||
return RTEMS_INVALID_NAME;
|
||||
}
|
||||
|
||||
/* get device geometry */
|
||||
uint8_t bufbyte;
|
||||
/* Device size for at least s25fl512s is off by 1, calculate with sectors */
|
||||
if (read_config_byte(cfi_raw, cfi_raw_len, datalen, 0x27, &bufbyte)) {
|
||||
return RTEMS_INVALID_ADDRESS;
|
||||
}
|
||||
data->DeviceSize = 1UL << bufbyte;
|
||||
|
||||
uint16_t page_power;
|
||||
if (read_config_short(cfi_raw, cfi_raw_len, datalen, 0x2a, &page_power)) {
|
||||
return RTEMS_INVALID_ADDRESS;
|
||||
}
|
||||
data->PageSize = 1UL << page_power;
|
||||
|
||||
if (read_config_byte(cfi_raw, cfi_raw_len, datalen, 0x2c, &bufbyte)) {
|
||||
return RTEMS_INVALID_ADDRESS;
|
||||
}
|
||||
/* this parser only supports one erase block region */
|
||||
if (bufbyte != 1) {
|
||||
return RTEMS_TOO_MANY;
|
||||
}
|
||||
|
||||
uint16_t num_sectors_sub;
|
||||
if (read_config_short(cfi_raw, cfi_raw_len, datalen, 0x2d, &num_sectors_sub)) {
|
||||
return RTEMS_INVALID_ADDRESS;
|
||||
}
|
||||
data->NumSectors = num_sectors_sub + 1;
|
||||
|
||||
uint16_t sector_base;
|
||||
if (read_config_short(cfi_raw, cfi_raw_len, datalen, 0x2f, §or_base)) {
|
||||
return RTEMS_INVALID_ADDRESS;
|
||||
}
|
||||
data->SectorSize = sector_base * 256UL;
|
||||
|
||||
data->DeviceSize = data->NumSectors * data->SectorSize;
|
||||
|
||||
return RTEMS_SUCCESSFUL;
|
||||
}
|
||||
|
||||
static int parse_sfdp_jedec_table(
|
||||
uint8_t *tdata,
|
||||
size_t tlen,
|
||||
int version,
|
||||
NOR_Config_Data *data
|
||||
)
|
||||
{
|
||||
/* locals to be applied once parsing is guaranteed successful */
|
||||
NOR_Config_Data local = {0,};
|
||||
local.PageSize = 256;
|
||||
|
||||
int datalen = 0;
|
||||
/* Read raw size from second dword */
|
||||
uint32_t raw_size;
|
||||
int raw_size_offset = 4;
|
||||
if (read_config_int(tdata, tlen, datalen, raw_size_offset, &raw_size)) {
|
||||
return -1;
|
||||
}
|
||||
if (raw_size & 0x80000000UL) {
|
||||
raw_size &= 0x7FFFFFFFUL;
|
||||
local.DeviceSize = 1ULL << raw_size;
|
||||
} else {
|
||||
local.DeviceSize = raw_size + 1;
|
||||
}
|
||||
/* Device size is specified in bits, convert to bytes */
|
||||
local.DeviceSize /= 8;
|
||||
|
||||
/* Parse sector information from dwords 8 and 9 */
|
||||
int sector_erase_dword_offset = 7;
|
||||
int sector_erase_offset = 4 * sector_erase_dword_offset;
|
||||
uint8_t bufbyte;
|
||||
for (int sect_erase_index = 0; sect_erase_index < 4; sect_erase_index++) {
|
||||
int sector_info_offset = sector_erase_offset + 2 * sect_erase_index;
|
||||
if (read_config_byte(tdata, tlen, datalen, sector_info_offset, &bufbyte)) {
|
||||
return -1;
|
||||
}
|
||||
if (bufbyte == 0) {
|
||||
/* empty sector descriptor */
|
||||
continue;
|
||||
}
|
||||
int sector_size = 1UL << bufbyte;
|
||||
if (read_config_byte(tdata, tlen, datalen, sector_info_offset + 1, &bufbyte)) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (bufbyte == 0xD8) {
|
||||
/* This is the 'normal' sector size */
|
||||
local.SectorSize = sector_size;
|
||||
local.NumSectors = (uint32_t)(local.DeviceSize/local.SectorSize);
|
||||
} else {
|
||||
/* store the alternate sector size/command */
|
||||
local.AltSectorSize = sector_size;
|
||||
local.AltSectorCmd = bufbyte;
|
||||
local.NumAltSectors = (uint32_t)(local.DeviceSize/local.AltSectorSize);
|
||||
}
|
||||
}
|
||||
|
||||
if (version >= 5) {
|
||||
int page_info_dword_offset = 10;
|
||||
int page_info_offset = 4 * page_info_dword_offset;
|
||||
if (read_config_byte(tdata, tlen, datalen, page_info_offset, &bufbyte)) {
|
||||
return -1;
|
||||
}
|
||||
bufbyte >>= 4;
|
||||
bufbyte &= 0xF;
|
||||
local.PageSize = 1U << bufbyte;
|
||||
}
|
||||
|
||||
/* Apply local parse data now that parsing has succeeded */
|
||||
*data = local;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int parse_sfdp_basic_header(
|
||||
NOR_Config_Accessor *accessor,
|
||||
uint8_t *header_base,
|
||||
NOR_Config_Data *data
|
||||
)
|
||||
{
|
||||
int datalen = 0;
|
||||
uint8_t bufbyte;
|
||||
int hlen = 8;
|
||||
|
||||
/* check minor version */
|
||||
if (read_config_byte(header_base, hlen, datalen, 0x1, &bufbyte)) {
|
||||
return -1;
|
||||
}
|
||||
int version = bufbyte;
|
||||
|
||||
/* get table length in 4-byte words */
|
||||
if (read_config_byte(header_base, hlen, datalen, 0x3, &bufbyte)) {
|
||||
return -1;
|
||||
}
|
||||
int tlen = bufbyte;
|
||||
tlen *= 4;
|
||||
|
||||
/* read table offset */
|
||||
uint32_t toffset = 0;
|
||||
if (read_config_int(header_base, hlen, datalen, 0x4, &toffset)) {
|
||||
return -1;
|
||||
}
|
||||
/* mask off the top byte */
|
||||
toffset &= 0xFFFFFFUL;
|
||||
|
||||
uint8_t *table_data = accessor->acquire(accessor->context, toffset, tlen);
|
||||
if (table_data == NULL) {
|
||||
return RTEMS_INVALID_SIZE;
|
||||
}
|
||||
if (parse_sfdp_jedec_table(table_data, tlen, version, data)) {
|
||||
accessor->release(accessor->context, table_data);
|
||||
table_data = NULL;
|
||||
return -1;
|
||||
}
|
||||
accessor->release(accessor->context, table_data);
|
||||
table_data = NULL;
|
||||
return 0;
|
||||
}
|
||||
|
||||
rtems_status_code SFDP_parse(
|
||||
NOR_Config_Accessor *accessor,
|
||||
NOR_Config_Data *data
|
||||
)
|
||||
{
|
||||
int datalen = 0;
|
||||
memset(data, 0, sizeof(NOR_Config_Data));
|
||||
|
||||
size_t header_len = 8;
|
||||
uint8_t *header_data = accessor->acquire(accessor->context, 0, header_len);
|
||||
if (header_data == NULL) {
|
||||
return RTEMS_INVALID_SIZE;
|
||||
}
|
||||
|
||||
/* verify SFDP ID string ("SFDP") exists */
|
||||
if (verify_config_string(header_data, header_len, datalen, 0x0, "SFDP")) {
|
||||
return RTEMS_INVALID_NAME;
|
||||
}
|
||||
|
||||
/* check major version */
|
||||
uint8_t bufbyte;
|
||||
if (read_config_byte(header_data, header_len, datalen, 0x05, &bufbyte)) {
|
||||
return RTEMS_INVALID_ADDRESS;
|
||||
}
|
||||
if (bufbyte != 1) {
|
||||
return RTEMS_TOO_MANY;
|
||||
}
|
||||
|
||||
/* get count of parameter headers */
|
||||
if (read_config_byte(header_data, header_len, datalen, 0x06, &bufbyte)) {
|
||||
return RTEMS_INVALID_ADDRESS;
|
||||
}
|
||||
int pheaders_count = bufbyte + 1;
|
||||
accessor->release(accessor->context, header_data);
|
||||
header_data = NULL;
|
||||
|
||||
/* get parameter table descriptors */
|
||||
size_t ptd_len = 8;
|
||||
size_t total_ptd_len = ptd_len * pheaders_count;
|
||||
uint8_t *ptable_desc = accessor->acquire(accessor->context, header_len, total_ptd_len);
|
||||
if (ptable_desc == NULL) {
|
||||
return RTEMS_INVALID_SIZE;
|
||||
}
|
||||
|
||||
int pheader_index;
|
||||
int param_version_seen = -1;
|
||||
for (pheader_index = 0; pheader_index < pheaders_count; pheader_index++) {
|
||||
int ptable_offset = pheader_index * ptd_len;
|
||||
uint8_t *header_base = ptable_desc + ptable_offset;
|
||||
|
||||
/* only parse JEDEC SFDP Basic SPI Flash Parameter */
|
||||
if (read_config_byte(header_base, ptd_len, datalen, 0x0, &bufbyte)) {
|
||||
accessor->release(accessor->context, ptable_desc);
|
||||
ptable_desc = NULL;
|
||||
return -1;
|
||||
}
|
||||
if (bufbyte != 0) {
|
||||
continue;
|
||||
}
|
||||
|
||||
/* check minor version */
|
||||
if (read_config_byte(header_base, ptd_len, datalen, 0x1, &bufbyte)) {
|
||||
accessor->release(accessor->context, ptable_desc);
|
||||
ptable_desc = NULL;
|
||||
return -1;
|
||||
}
|
||||
int version = bufbyte;
|
||||
if (version > param_version_seen) {
|
||||
/* only parse if interested in this version */
|
||||
if (parse_sfdp_basic_header(accessor, header_base, data)) {
|
||||
/* parse failed, continue */
|
||||
continue;
|
||||
}
|
||||
param_version_seen = version;
|
||||
}
|
||||
}
|
||||
|
||||
accessor->release(accessor->context, ptable_desc);
|
||||
ptable_desc = NULL;
|
||||
|
||||
if (param_version_seen == -1) {
|
||||
return RTEMS_INVALID_ADDRESS;
|
||||
}
|
||||
return RTEMS_SUCCESSFUL;
|
||||
}
|
||||
|
||||
struct buffer_context {
|
||||
uint8_t *data;
|
||||
size_t length;
|
||||
};
|
||||
|
||||
static uint8_t *buffer_acquire(
|
||||
void *arg,
|
||||
uint32_t offset,
|
||||
size_t length
|
||||
)
|
||||
{
|
||||
struct buffer_context *context = arg;
|
||||
if (offset + length > context->length) return NULL;
|
||||
return context->data + offset;
|
||||
}
|
||||
|
||||
static void buffer_release(
|
||||
void *arg,
|
||||
uint8_t *data
|
||||
)
|
||||
{
|
||||
(void) arg;
|
||||
(void) data;
|
||||
/* Do nothing */
|
||||
}
|
||||
|
||||
rtems_status_code SFDP_parse_from_buffer(
|
||||
uint8_t *sfdp_raw,
|
||||
size_t sfdp_raw_len,
|
||||
NOR_Config_Data *data
|
||||
)
|
||||
{
|
||||
struct buffer_context context = {sfdp_raw, sfdp_raw_len};
|
||||
NOR_Config_Accessor accessor;
|
||||
accessor.context = &context;
|
||||
accessor.acquire = buffer_acquire;
|
||||
accessor.release = buffer_release;
|
||||
return SFDP_parse(&accessor, data);
|
||||
}
|
||||
@@ -55,6 +55,9 @@ install:
|
||||
- bsps/include/libchip/spi-memdrv.h
|
||||
- bsps/include/libchip/spi-sd-card.h
|
||||
- bsps/include/libchip/wd80x3.h
|
||||
- destination: ${BSP_INCLUDEDIR}/dev/nor
|
||||
source:
|
||||
- bsps/include/dev/nor/config-parser.h
|
||||
- destination: ${BSP_INCLUDEDIR}/dev/flash
|
||||
source:
|
||||
- bsps/include/dev/flash/jffs2_flashdev.h
|
||||
@@ -89,6 +92,7 @@ source:
|
||||
- bsps/shared/dev/ide/ata.c
|
||||
- bsps/shared/dev/ide/ata_util.c
|
||||
- bsps/shared/dev/ide/ide_controller.c
|
||||
- bsps/shared/dev/nor/config-parser.c
|
||||
- bsps/shared/dev/rtc/abeoz9.c
|
||||
- bsps/shared/dev/rtc/ds1375.c
|
||||
- bsps/shared/dev/rtc/i2c-rtc.c
|
||||
|
||||
Reference in New Issue
Block a user