1616 */
1717
1818#include < algorithm>
19- #include < cstdint>
20- #include < cstring>
19+ #include < memory>
20+ #include < stdint.h>
21+ #include < stdlib.h>
22+ #include < string.h>
23+
24+ #include " platform/mbed_error.h"
2125#include " drivers/internal/SFDP.h"
2226
2327#if (DEVICE_SPI || DEVICE_QSPI)
@@ -107,20 +111,69 @@ int sfdp_parse_single_param_header(sfdp_prm_hdr *phdr_ptr, sfdp_hdr_info &hdr_in
107111 return -1 ;
108112 }
109113
110- if ((phdr_ptr->PID_LSB == 0 ) && (sfdp_get_param_id_msb (phdr_ptr->DWORD2 ) == 0xFF )) {
111- tr_debug (" Parameter header: Basic Parameter Header" );
112- hdr_info.bptbl .addr = sfdp_get_param_tbl_ptr (phdr_ptr->DWORD2 );
113- hdr_info.bptbl .size = std::min ((phdr_ptr->P_LEN * 4 ), SFDP_BASIC_PARAMS_TBL_SIZE);
114+ int param_id_msb = sfdp_get_param_id_msb (phdr_ptr->DWORD2 );
114115
115- } else if ((phdr_ptr->PID_LSB == 0x81 ) && (sfdp_get_param_id_msb (phdr_ptr->DWORD2 ) == 0xFF )) {
116- tr_debug (" Parameter header: Sector Map Parameter Header" );
117- hdr_info.smptbl .addr = sfdp_get_param_tbl_ptr (phdr_ptr->DWORD2 );
118- hdr_info.smptbl .size = phdr_ptr->P_LEN * 4 ;
116+ /* MSB JEDEC ID */
117+ if (param_id_msb == 0xFF ) {
119118
120- } else {
121- tr_debug (" Parameter header: header vendor specific or unknown. Parameter ID LSB: 0x%" PRIX8 " ; MSB: 0x%" PRIX8 " " ,
119+ /* LSB JEDEC ID */
120+ switch (phdr_ptr->PID_LSB ) {
121+ case 0x0 :
122+ tr_debug (" Parameter header: JEDEC Basic Flash - Revision %" PRIX8 " .%" PRIX8 " " ,
123+ phdr_ptr->P_MAJOR ,
124+ phdr_ptr->P_MINOR );
125+ hdr_info.bptbl .addr = sfdp_get_param_tbl_ptr (phdr_ptr->DWORD2 );
126+ hdr_info.bptbl .size = std::min ((phdr_ptr->P_LEN * 4 ), SFDP_BASIC_PARAMS_TBL_SIZE);
127+ break ;
128+ case 0x81 :
129+ tr_info (" Parameter header: Sector Map" );
130+ hdr_info.smptbl .addr = sfdp_get_param_tbl_ptr (phdr_ptr->DWORD2 );
131+ hdr_info.smptbl .size = phdr_ptr->P_LEN * 4 ;
132+ break ;
133+ /* Unsupported */
134+ case 0x03 :
135+ tr_info (" UNSUPPORTED:Parameter header: Replay Protected Monotonic Counters" );
136+ break ;
137+ case 0x84 :
138+ tr_info (" UNSUPPORTED:Parameter header: 4-byte Address Instruction" );
139+ break ;
140+ case 0x05 :
141+ tr_info (" UNSUPPORTED:Parameter header: eXtended Serial Peripheral Interface (xSPI) Profile 1.0" );
142+ break ;
143+ case 0x06 :
144+ tr_info (" UNSUPPORTED:Parameter header: eXtended Serial Peripheral Interface (xSPI) Profile 2.0" );
145+ break ;
146+ case 0x87 :
147+ tr_info (" UNSUPPORTED:Parameter header: SCCR Map for SPI Memory Devices" );
148+ break ;
149+ case 0x88 :
150+ tr_info (" UNSUPPORTED:Parameter header: SCCR Map Offsets for Multi-Chip SPI Memory Devices" );
151+ break ;
152+ case 0x09 :
153+ tr_info (" UNSUPPORTED:Parameter header: SCCR Map for xSPI Profile 2.0 Memory Devices" );
154+ break ;
155+ case 0x0A :
156+ tr_info (" UNSUPPORTED:Parameter header: Command Sequences to Change to Octal DDR (8D-8D-8D) mode" );
157+ break ;
158+ case 0x0C :
159+ tr_info (" UNSUPPORTED:Parameter header: x4 Quad IO with DS" );
160+ break ;
161+ case 0x8D :
162+ tr_info (" UNSUPPORTED:Parameter header: Command Sequences to Change to Quad DDR (4S-4D-4D) mode" );
163+ break ;
164+ default :
165+ tr_debug (" Parameter header: unknown JEDEC header. Parameter ID LSB: 0x%" PRIX8 " ; MSB: 0x%" PRIX8 " " ,
166+ phdr_ptr->PID_LSB ,
167+ sfdp_get_param_id_msb (phdr_ptr->DWORD2 ));
168+ }
169+ } else if (param_id_msb >= 0x80 ) { // MSB JEDEC ID
170+ tr_debug (" Parameter header: unknown JEDEC header. Parameter ID LSB: 0x%" PRIX8 " ; MSB: 0x%" PRIX8 " " ,
122171 phdr_ptr->PID_LSB ,
123172 sfdp_get_param_id_msb (phdr_ptr->DWORD2 ));
173+ } else { // MSB Vendor ID
174+ tr_info (" Parameter header: vendor specific header. Parameter ID LSB: 0x%" PRIX8 " ; MSB: 0x%" PRIX8 " " ,
175+ phdr_ptr->PID_LSB ,
176+ sfdp_get_param_id_msb (phdr_ptr->DWORD2 ));
124177 }
125178
126179 return 0 ;
@@ -157,10 +210,10 @@ int sfdp_parse_headers(Callback<int(bd_addr_t, void *, bd_size_t)> sfdp_reader,
157210 int hdr_status;
158211
159212 // Loop over Param Headers and parse them (currently supports Basic Param Table and Sector Region Map Table)
160- for (int i_ind = 0 ; i_ind < number_of_param_headers; i_ind ++) {
213+ for (int idx = 0 ; idx < number_of_param_headers; idx ++) {
161214 status = sfdp_reader (addr, param_header, data_length);
162215 if (status < 0 ) {
163- tr_error (" Retrieving a parameter header %d failed" , i_ind + 1 );
216+ tr_error (" Retrieving a parameter header %d failed" , idx + 1 );
164217 return -1 ;
165218 }
166219
@@ -178,9 +231,8 @@ int sfdp_parse_headers(Callback<int(bd_addr_t, void *, bd_size_t)> sfdp_reader,
178231
179232int sfdp_parse_sector_map_table (Callback<int (bd_addr_t , void *, bd_size_t )> sfdp_reader, sfdp_hdr_info &sfdp_info)
180233{
181- uint8_t sector_map_table[SFDP_BASIC_PARAMS_TBL_SIZE]; /* Up To 20 DWORDS = 80 Bytes */
182234 uint32_t tmp_region_size = 0 ;
183- int i_ind = 0 ;
235+ uint8_t type_mask ;
184236 int prev_boundary = 0 ;
185237 // Default set to all type bits 1-4 are common
186238 int min_common_erase_type_bits = SFDP_ERASE_BITMASK_ALL;
@@ -191,25 +243,36 @@ int sfdp_parse_sector_map_table(Callback<int(bd_addr_t, void *, bd_size_t)> sfdp
191243
192244 if (!sfdp_info.smptbl .addr || !sfdp_info.smptbl .size ) {
193245 tr_debug (" No Sector Map Table" );
194- return 0 ;
246+ return MBED_SUCCESS ;
195247 }
196248
197- tr_debug (" Parsing Sector Map Table - addr: 0x%" PRIx32 " , Size: %d" , sfdp_info.smptbl .addr , sfdp_info.smptbl .size );
249+ /* The number of
250+ * - sector map configuration detection commands
251+ * - configurations
252+ * - regions in each configuration
253+ * is variable -> the size of this table is variable
254+ */
255+ auto smptbl_buff = std::make_unique<uint8_t []>(sfdp_info.smptbl .size );
256+ if (!smptbl_buff) {
257+ tr_error (" Failed to allocate memory" );
258+ return -1 ;
259+ }
198260
261+ tr_debug (" Parsing Sector Map Table - addr: 0x%" PRIx32 " , Size: %d" , sfdp_info.smptbl .addr , sfdp_info.smptbl .size );
199262
200- int status = sfdp_reader (sfdp_info.smptbl .addr , sector_map_table , sfdp_info.smptbl .size );
263+ int status = sfdp_reader (sfdp_info.smptbl .addr , smptbl_buff. get () , sfdp_info.smptbl .size );
201264 if (status < 0 ) {
202265 tr_error (" Sector Map: Table retrieval failed" );
203266 return -1 ;
204267 }
205268
206269 // Currently we support only Single Map Descriptor
207- if (!((sector_map_table [0 ] & 0x3 ) == 0x03 ) && (sector_map_table [1 ] == 0x0 )) {
270+ if (!((smptbl_buff [0 ] & 0x3 ) == 0x03 ) && (smptbl_buff [1 ] == 0x0 )) {
208271 tr_error (" Sector Map: Supporting Only Single Map Descriptor (not map commands)" );
209272 return -1 ;
210273 }
211274
212- sfdp_info.smptbl .region_cnt = sector_map_table [2 ] + 1 ;
275+ sfdp_info.smptbl .region_cnt = smptbl_buff [2 ] + 1 ;
213276 if (sfdp_info.smptbl .region_cnt > SFDP_SECTOR_MAP_MAX_REGIONS) {
214277 tr_error (" Sector Map: Supporting up to %d regions, current setup to %d regions - fail" ,
215278 SFDP_SECTOR_MAP_MAX_REGIONS,
@@ -219,34 +282,31 @@ int sfdp_parse_sector_map_table(Callback<int(bd_addr_t, void *, bd_size_t)> sfdp
219282
220283 // Loop through Regions and set for each one: size, supported erase types, high boundary offset
221284 // Calculate minimum Common Erase Type for all Regions
222- for (i_ind = 0 ; i_ind < sfdp_info.smptbl .region_cnt ; i_ind ++) {
223- tmp_region_size = ((*((uint32_t *)§or_map_table[(i_ind + 1 ) * 4 ])) >> 8 ) & 0x00FFFFFF ; // bits 9-32
224- sfdp_info.smptbl .region_size [i_ind ] = (tmp_region_size + 1 ) * 256 ; // Region size is 0 based multiple of 256 bytes;
285+ for (auto idx = 0 ; idx < sfdp_info.smptbl .region_cnt ; idx ++) {
286+ tmp_region_size = ((*((uint32_t *)&smptbl_buff[(idx + 1 ) * 4 ])) >> 8 ) & 0x00FFFFFF ; // bits 9-32
287+ sfdp_info.smptbl .region_size [idx ] = (tmp_region_size + 1 ) * 256 ; // Region size is 0 based multiple of 256 bytes;
225288
226- sfdp_info.smptbl .region_erase_types_bitfld [i_ind ] = sector_map_table[(i_ind + 1 ) * 4 ] & 0x0F ; // bits 1-4
289+ sfdp_info.smptbl .region_erase_types_bitfld [idx ] = smptbl_buff[(idx + 1 ) * 4 ] & 0x0F ; // bits 1-4
227290
228- min_common_erase_type_bits &= sfdp_info.smptbl .region_erase_types_bitfld [i_ind ];
291+ min_common_erase_type_bits &= sfdp_info.smptbl .region_erase_types_bitfld [idx ];
229292
230- sfdp_info.smptbl .region_high_boundary [i_ind ] = (sfdp_info.smptbl .region_size [i_ind ] - 1 ) + prev_boundary;
293+ sfdp_info.smptbl .region_high_boundary [idx ] = (sfdp_info.smptbl .region_size [idx ] - 1 ) + prev_boundary;
231294
232- prev_boundary = sfdp_info.smptbl .region_high_boundary [i_ind ] + 1 ;
295+ prev_boundary = sfdp_info.smptbl .region_high_boundary [idx ] + 1 ;
233296 }
234297
235298 // Calc minimum Common Erase Size from min_common_erase_type_bits
236- uint8_t type_mask = SFDP_ERASE_BITMASK_TYPE1;
237- for (i_ind = 0 ; i_ind < 4 ; i_ind++) {
299+ type_mask = SFDP_ERASE_BITMASK_TYPE1;
300+ // If no common erase type is found between regions
301+ sfdp_info.smptbl .regions_min_common_erase_size = 0 ;
302+ for (auto idx = 0 ; idx < 4 ; idx++) {
238303 if (min_common_erase_type_bits & type_mask) {
239- sfdp_info.smptbl .regions_min_common_erase_size = sfdp_info.smptbl .erase_type_size_arr [i_ind ];
304+ sfdp_info.smptbl .regions_min_common_erase_size = sfdp_info.smptbl .erase_type_size_arr [idx ];
240305 break ;
241306 }
242307 type_mask = type_mask << 1 ;
243308 }
244309
245- if (i_ind == 4 ) {
246- // No common erase type was found between regions
247- sfdp_info.smptbl .regions_min_common_erase_size = 0 ;
248- }
249-
250310 return 0 ;
251311}
252312
@@ -275,27 +335,27 @@ int sfdp_detect_erase_types_inst_and_size(uint8_t *bptbl_ptr, sfdp_hdr_info &sfd
275335 // Erase 4K Inst is taken either from param table legacy 4K erase or superseded by erase Instruction for type of size 4K
276336 if (sfdp_info.bptbl .size > SFDP_BASIC_PARAM_TABLE_ERASE_TYPE_1_SIZE_BYTE) {
277337 // Loop Erase Types 1-4
278- for (int i_ind = 0 ; i_ind < 4 ; i_ind ++) {
279- sfdp_info.smptbl .erase_type_inst_arr [i_ind ] = -1 ; // Default for unsupported type
280- sfdp_info.smptbl .erase_type_size_arr [i_ind ] = 1
281- << bptbl_ptr[SFDP_BASIC_PARAM_TABLE_ERASE_TYPE_1_SIZE_BYTE + 2 * i_ind ]; // Size is 2^N where N is the table value
282- tr_debug (" Erase Type(A) %d - Inst: 0x%xh, Size: %d" , (i_ind + 1 ), sfdp_info.smptbl .erase_type_inst_arr [i_ind ],
283- sfdp_info.smptbl .erase_type_size_arr [i_ind ]);
284- if (sfdp_info.smptbl .erase_type_size_arr [i_ind ] > 1 ) {
338+ for (int idx = 0 ; idx < 4 ; idx ++) {
339+ sfdp_info.smptbl .erase_type_inst_arr [idx ] = -1 ; // Default for unsupported type
340+ sfdp_info.smptbl .erase_type_size_arr [idx ] = 1
341+ << bptbl_ptr[SFDP_BASIC_PARAM_TABLE_ERASE_TYPE_1_SIZE_BYTE + 2 * idx ]; // Size is 2^N where N is the table value
342+ tr_debug (" Erase Type(A) %d - Inst: 0x%xh, Size: %d" , (idx + 1 ), sfdp_info.smptbl .erase_type_inst_arr [idx ],
343+ sfdp_info.smptbl .erase_type_size_arr [idx ]);
344+ if (sfdp_info.smptbl .erase_type_size_arr [idx ] > 1 ) {
285345 // if size==1 type is not supported
286- sfdp_info.smptbl .erase_type_inst_arr [i_ind ] = bptbl_ptr[SFDP_BASIC_PARAM_TABLE_ERASE_TYPE_1_BYTE
287- + 2 * i_ind ];
346+ sfdp_info.smptbl .erase_type_inst_arr [idx ] = bptbl_ptr[SFDP_BASIC_PARAM_TABLE_ERASE_TYPE_1_BYTE
347+ + 2 * idx ];
288348
289- if ((sfdp_info.smptbl .erase_type_size_arr [i_ind ] < sfdp_info.smptbl .regions_min_common_erase_size )
349+ if ((sfdp_info.smptbl .erase_type_size_arr [idx ] < sfdp_info.smptbl .regions_min_common_erase_size )
290350 || (sfdp_info.smptbl .regions_min_common_erase_size == 0 )) {
291351 // Set default minimal common erase for signal region
292- sfdp_info.smptbl .regions_min_common_erase_size = sfdp_info.smptbl .erase_type_size_arr [i_ind ];
352+ sfdp_info.smptbl .regions_min_common_erase_size = sfdp_info.smptbl .erase_type_size_arr [idx ];
293353 }
294354 sfdp_info.smptbl .region_erase_types_bitfld [0 ] |= bitfield; // If there's no region map, set region "0" types bitfield as default
295355 }
296356
297- tr_debug (" Erase Type %d - Inst: 0x%xh, Size: %d" , (i_ind + 1 ), sfdp_info.smptbl .erase_type_inst_arr [i_ind ],
298- sfdp_info.smptbl .erase_type_size_arr [i_ind ]);
357+ tr_debug (" Erase Type %d - Inst: 0x%xh, Size: %d" , (idx + 1 ), sfdp_info.smptbl .erase_type_inst_arr [idx ],
358+ sfdp_info.smptbl .erase_type_size_arr [idx ]);
299359 bitfield = bitfield << 1 ;
300360 }
301361 } else {
@@ -321,10 +381,10 @@ int sfdp_find_addr_region(bd_size_t offset, const sfdp_hdr_info &sfdp_info)
321381 return 0 ;
322382 }
323383
324- for (int i_ind = sfdp_info.smptbl .region_cnt - 2 ; i_ind >= 0 ; i_ind --) {
384+ for (int idx = sfdp_info.smptbl .region_cnt - 2 ; idx >= 0 ; idx --) {
325385
326- if (offset > sfdp_info.smptbl .region_high_boundary [i_ind ]) {
327- return (i_ind + 1 );
386+ if (offset > sfdp_info.smptbl .region_high_boundary [idx ]) {
387+ return (idx + 1 );
328388 }
329389 }
330390 return -1 ;
@@ -338,11 +398,12 @@ int sfdp_iterate_next_largest_erase_type(uint8_t &bitfield,
338398 const sfdp_smptbl_info &smptbl)
339399{
340400 uint8_t type_mask = SFDP_ERASE_BITMASK_TYPE4;
341- int i_ind = 0 ;
342401 int largest_erase_type = 0 ;
343- for (i_ind = 3 ; i_ind >= 0 ; i_ind--) {
402+
403+ int idx;
404+ for (idx = 3 ; idx >= 0 ; idx--) {
344405 if (bitfield & type_mask) {
345- largest_erase_type = i_ind ;
406+ largest_erase_type = idx ;
346407 if ((size > (int )(smptbl.erase_type_size_arr [largest_erase_type])) &&
347408 ((smptbl.region_high_boundary [region] - offset)
348409 > (int )(smptbl.erase_type_size_arr [largest_erase_type]))) {
@@ -354,7 +415,7 @@ int sfdp_iterate_next_largest_erase_type(uint8_t &bitfield,
354415 type_mask = type_mask >> 1 ;
355416 }
356417
357- if (i_ind == 4 ) {
418+ if (idx == - 1 ) {
358419 tr_error (" No erase type was found for current region addr" );
359420 }
360421 return largest_erase_type;
0 commit comments