Skip to content

Commit 19c9735

Browse files
author
Veijo Pesonen
committed
Bugfix: SFDP Sector Map Param Tbl size is variable
Earlier it was assumed that the table has a certain max length but that isn't true.
1 parent a088d30 commit 19c9735

File tree

1 file changed

+31
-11
lines changed

1 file changed

+31
-11
lines changed

drivers/source/SFDP.cpp

Lines changed: 31 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717

1818
#include <algorithm>
1919
#include <cstdint>
20+
#include <cstdlib>
2021
#include <cstring>
2122
#include "drivers/internal/SFDP.h"
2223

@@ -178,8 +179,16 @@ int sfdp_parse_headers(Callback<int(bd_addr_t, void *, bd_size_t)> sfdp_reader,
178179

179180
int sfdp_parse_sector_map_table(Callback<int(bd_addr_t, void *, bd_size_t)> sfdp_reader, sfdp_hdr_info &sfdp_info)
180181
{
181-
uint8_t sector_map_table[SFDP_BASIC_PARAMS_TBL_SIZE]; /* Up To 20 DWORDS = 80 Bytes */
182+
/* The number of
183+
* - sector map configuration detection commands
184+
* - configurations
185+
* - regions in each configuration
186+
* is variable -> the size of this table is variable
187+
*/
188+
uint8_t *smptbl_buff;
189+
int status = 0;
182190
uint32_t tmp_region_size = 0;
191+
uint8_t type_mask;
183192
int i_ind = 0;
184193
int prev_boundary = 0;
185194
// Default set to all type bits 1-4 are common
@@ -194,35 +203,43 @@ int sfdp_parse_sector_map_table(Callback<int(bd_addr_t, void *, bd_size_t)> sfdp
194203
return 0;
195204
}
196205

206+
smptbl_buff = (uint8_t *)malloc(sfdp_info.smptbl.size);
207+
if (!smptbl_buff) {
208+
tr_error("Failed to allocate memory");
209+
return -1;
210+
}
211+
197212
tr_debug("Parsing Sector Map Table - addr: 0x%" PRIx32 ", Size: %d", sfdp_info.smptbl.addr, sfdp_info.smptbl.size);
198213

199-
int status = sfdp_reader(sfdp_info.smptbl.addr, sector_map_table, sfdp_info.smptbl.size);
214+
status = sfdp_reader(sfdp_info.smptbl.addr, smptbl_buff, sfdp_info.smptbl.size);
200215
if (status < 0) {
201216
tr_error("Sector Map: Table retrieval failed");
202-
return -1;
217+
goto EXIT;
203218
}
204219

205220
// Currently we support only Single Map Descriptor
206-
if (!((sector_map_table[0] & 0x3) == 0x03) && (sector_map_table[1] == 0x0)) {
221+
if (!((smptbl_buff[0] & 0x3) == 0x03) && (smptbl_buff[1] == 0x0)) {
207222
tr_error("Sector Map: Supporting Only Single Map Descriptor (not map commands)");
208-
return -1;
223+
status = -1;
224+
goto EXIT;
209225
}
210226

211-
sfdp_info.smptbl.region_cnt = sector_map_table[2] + 1;
227+
sfdp_info.smptbl.region_cnt = smptbl_buff[2] + 1;
212228
if (sfdp_info.smptbl.region_cnt > SFDP_SECTOR_MAP_MAX_REGIONS) {
213229
tr_error("Sector Map: Supporting up to %d regions, current setup to %d regions - fail",
214230
SFDP_SECTOR_MAP_MAX_REGIONS,
215231
sfdp_info.smptbl.region_cnt);
216-
return -1;
232+
status = -1;
233+
goto EXIT;
217234
}
218235

219236
// Loop through Regions and set for each one: size, supported erase types, high boundary offset
220237
// Calculate minimum Common Erase Type for all Regions
221238
for (i_ind = 0; i_ind < sfdp_info.smptbl.region_cnt; i_ind++) {
222-
tmp_region_size = ((*((uint32_t *)&sector_map_table[(i_ind + 1) * 4])) >> 8) & 0x00FFFFFF; // bits 9-32
239+
tmp_region_size = ((*((uint32_t *)&smptbl_buff[(i_ind + 1) * 4])) >> 8) & 0x00FFFFFF; // bits 9-32
223240
sfdp_info.smptbl.region_size[i_ind] = (tmp_region_size + 1) * 256; // Region size is 0 based multiple of 256 bytes;
224241

225-
sfdp_info.smptbl.region_erase_types_bitfld[i_ind] = sector_map_table[(i_ind + 1) * 4] & 0x0F; // bits 1-4
242+
sfdp_info.smptbl.region_erase_types_bitfld[i_ind] = smptbl_buff[(i_ind + 1) * 4] & 0x0F; // bits 1-4
226243

227244
min_common_erase_type_bits &= sfdp_info.smptbl.region_erase_types_bitfld[i_ind];
228245

@@ -232,7 +249,7 @@ int sfdp_parse_sector_map_table(Callback<int(bd_addr_t, void *, bd_size_t)> sfdp
232249
}
233250

234251
// Calc minimum Common Erase Size from min_common_erase_type_bits
235-
uint8_t type_mask = SFDP_ERASE_BITMASK_TYPE1;
252+
type_mask = SFDP_ERASE_BITMASK_TYPE1;
236253
for (i_ind = 0; i_ind < 4; i_ind++) {
237254
if (min_common_erase_type_bits & type_mask) {
238255
sfdp_info.smptbl.regions_min_common_erase_size = sfdp_info.smptbl.erase_type_size_arr[i_ind];
@@ -246,7 +263,10 @@ int sfdp_parse_sector_map_table(Callback<int(bd_addr_t, void *, bd_size_t)> sfdp
246263
sfdp_info.smptbl.regions_min_common_erase_size = 0;
247264
}
248265

249-
return 0;
266+
EXIT:
267+
free(smptbl_buff);
268+
269+
return status;
250270
}
251271

252272
size_t sfdp_detect_page_size(uint8_t *basic_param_table_ptr, size_t basic_param_table_size)

0 commit comments

Comments
 (0)