From 96259d11c89634b3535ca67955e0234d4b10e1d5 Mon Sep 17 00:00:00 2001 From: dragonmux Date: Fri, 5 Aug 2022 03:10:19 +0100 Subject: [PATCH] sfdp: Implemented the logic needed to read the headers and basic parameter table --- src/Makefile | 1 + src/target/sfdp.c | 90 +++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 91 insertions(+) create mode 100644 src/target/sfdp.c diff --git a/src/Makefile b/src/Makefile index 03f0db1..4b7050b 100644 --- a/src/Makefile +++ b/src/Makefile @@ -53,6 +53,7 @@ SRC = \ sam4l.c \ samd.c \ samx5x.c \ + sfdp.c \ stm32f1.c \ ch32f1.c \ stm32f4.c \ diff --git a/src/target/sfdp.c b/src/target/sfdp.c new file mode 100644 index 0000000..3c61eda --- /dev/null +++ b/src/target/sfdp.c @@ -0,0 +1,90 @@ +/* + * This file is part of the Black Magic Debug project. + * + * Copyright (C) 2022 1BitSquared + * Written by Rachel Mant + * All rights reserved. + * + * 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. + * + * 3. Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * 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 HOLDER 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 +#include "sfdp_internal.h" + +#ifdef MIN +#undef MIN +#endif +#define MIN(a, b) ((a) < (b) ? (a) : (b)) + +static inline size_t sfdp_memory_density_to_capacity_bits(const uint8_t *const density) +{ + if (SFDP_DENSITY_IS_EXPONENTIAL(density)) + return 1U << SFDP_DENSITY_VALUE(density); + else /* NOLINT(readability-else-after-return) */ + return SFDP_DENSITY_VALUE(density) + 1U; +} + +static spi_parameters_s sfdp_read_basic_parameter_table(target *const t, const uint32_t address, const size_t length, + const read_sfdp_func sfdp_read) +{ + sfdp_basic_parameter_table_s parameter_table; + const size_t table_length = MIN(sizeof(sfdp_basic_parameter_table_s), length); + sfdp_read(t, address, ¶meter_table, table_length); + + spi_parameters_s result; + result.capacity = sfdp_memory_density_to_capacity_bits(parameter_table.memory_density) >> 3U; + for (size_t i = 0; i < SFDP_ERASE_TYPES; ++i) { + erase_parameters_s *erase_type = ¶meter_table.erase_types[i]; + if (erase_type->opcode == parameter_table.sector_erase_opcode) { + result.sector_erase_opcode = erase_type->opcode; + result.sector_size = SFDP_ERASE_SIZE(erase_type); + break; + } + } + result.page_size = SFDP_PAGE_SIZE(parameter_table); + return result; +} + +bool sfdp_read_parameters(target *const t, spi_parameters_s *params, const read_sfdp_func sfdp_read) +{ + sfdp_header_s header; + sfdp_read(t, SFDP_HEADER_ADDRESS, &header, sizeof(header)); + if (memcmp(header.magic, SFDP_MAGIC, 4) != 0) + return false; + + for (size_t i = 0; i <= header.parameter_headers_count; ++i) { + sfdp_parameter_table_header_s table_header; + sfdp_read(t, SFDP_TABLE_HEADER_ADDRESS + (sizeof(table_header) * i), &table_header, sizeof(table_header)); + const uint16_t jedec_parameter_id = SFDP_JEDEC_PARAMETER_ID(table_header); + if (jedec_parameter_id == SFDP_BASIC_SPI_PARAMETER_TABLE) { + const uint32_t table_address = SFDP_TABLE_ADDRESS(table_header); + const uint16_t table_length = table_header.table_length_in_u32s * 4U; + *params = sfdp_read_basic_parameter_table(t, table_address, table_length, sfdp_read); + return true; + } + } + return false; +}