From ceed023dee03173fcfe727e33be2c27952298fdc Mon Sep 17 00:00:00 2001 From: ANTodorov Date: Sat, 30 Nov 2024 14:38:13 +0200 Subject: [PATCH] rework to use smart SPI flash detection Check JEDEC ID is in range between 0x0001 ... 0xFFFE, Compare the output from 0x90 and 0x9F, Then the size from the JEDEC ID Otherwise fall-back to 256 kB Extend the spi_flash_decode.py to handle more (known) SPI flash ICs --- CHANGELOG.md | 1 + client/pyscripts/spi_flash_decode.py | 158 ++++++++++++++++++--------- common_arm/flashmem.c | 23 ++-- common_arm/flashmem.h | 33 ------ 4 files changed, 116 insertions(+), 99 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 52e1399597..87968ef48d 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -3,6 +3,7 @@ All notable changes to this project will be documented in this file. This project uses the changelog in accordance with [keepchangelog](http://keepachangelog.com/). Please use this to write notable changes, which is not the same as git commit log... ## [unreleased][unreleased] +- Changed SPI flash detection to calculate the size instead of table lookup, updated spi_flash_decode.py script with more ICs (@ANTodorov) - Add option to set and get maximum read/write block number using `hf_mf_ultimatecard` script (@piotrva) - Added JEDEC information for SPI flash W25Q64JV (@ANTodorov) - Added special iclass legacy config cards in `hf iclass configcard` (@antiklesys) diff --git a/client/pyscripts/spi_flash_decode.py b/client/pyscripts/spi_flash_decode.py index 0f125844bf..2a89f57af9 100644 --- a/client/pyscripts/spi_flash_decode.py +++ b/client/pyscripts/spi_flash_decode.py @@ -12,62 +12,118 @@ def color(s, fg=None): return str(s) spi = { + 0x68:{ + "manufacturer": "Boya", + "jedec" : { + 0x40: { + 0x15: { + "part": "BY25Q16BS", + "size": "16mbits", + "sizeB": "2MB", + }, + }, + }, + }, 0x85:{ "manufacturer": "Puya", - 0x60: { - 0x15: { - "part": "P25Q16H", - "size": "16mbits", - "sizeB": "2MB", + "jedec" : { + 0x60: { + 0x15: { + "part": "P25Q16H", + "size": "16mbits", + "sizeB": "2MB", + }, + 0x16: { + "part": "P25Q32H", + "size": "32mbits", + "sizeB": "4MB", + }, + 0x17: { + "part": "P25Q64H", + "size": "64mbits", + "sizeB": "8MB", + }, }, }, }, 0xEF:{ "manufacturer": "Winbond", - 0x30: { - 0x11: { - "part": "W25X10BV", - "size": "1mbits", - "sizeB": "128KB", - }, - 0x12: { - "part": "W25X20BV", - "size": "2mbits", - "sizeB": "256KB", - }, - 0x13: { - "part": "W25X40BV", - "size": "4mbits", - "sizeB": "512KB", - }, - }, - 0x40: { - 0x13: { - "part": "W25Q40BV", - "size": "4mbits", - "sizeB": "512KB", - }, - 0x14: { - "part": "W25Q80BV", - "size": "8mbits", - "sizeB": "1MB", + "jedec" : { + 0x30: { + 0x11: { + "part": "W25X10BV", + "size": "1mbits", + "sizeB": "128KB", + }, + 0x12: { + "part": "W25X20BV", + "size": "2mbits", + "sizeB": "256KB", + }, + 0x13: { + "part": "W25X40BV", + "size": "4mbits", + "sizeB": "512KB", + }, }, - 0x15: { - "part": "W25Q16BV", - "size": "16mbits", - "sizeB": "2MB", + 0x40: { + 0x12: { + "part": "W25Q20BV", + "size": "2mbits", + "sizeB": "256KB", + }, + 0x13: { + "part": "W25Q40BV", + "size": "4mbits", + "sizeB": "512KB", + }, + 0x14: { + "part": "W25Q80BV", + "size": "8mbits", + "sizeB": "1MB", + }, + 0x15: { + "part": "W25Q16BV", + "size": "16mbits", + "sizeB": "2MB", + }, + 0x16: { + "part": "W25Q32BV", + "size": "32mbits", + "sizeB": "4MB", + }, + 0x17: { + "part": "W25Q64BV", + "size": "64mbits", + "sizeB": "8MB", + }, }, - 0x16: { - "part": "W25Q32BV", - "size": "32mbits", - "sizeB": "4MB", - }, - }, - 0x70: { - 0x22: { - "part": "W25Q02JV-IM", - "size": "2mbits", - "sizeB": "256KB", + 0x70: { + 0x14: { + "part": "W25Q80JV", + "size": "8mbits", + "sizeB": "1MB", + }, + 0x15: { + "part": "W25Q16JV", + "size": "16mbits", + "sizeB": "2MB", + }, + 0x16: { + "part": "W25Q32JV", + "size": "32mbits", + "sizeB": "4MB", + }, + 0x17: { + "part": "W25Q64JV", + "size": "64mbits", + "sizeB": "8MB", + }, + 0x22: { + "part": "W25Q02JV-IM", + "size": "2mbits", + "sizeB": "256KB", + }, }, }, }, @@ -90,16 +146,16 @@ def color(s, fg=None): did_h = did >> 8 did_l = did & 0xff t = None - + print(f"\n JEDEC ID....... 0x{mid:X} / 0x{did:X}") if mid in spi: mfr = spi[mid]['manufacturer'] - if did_h in spi[mid]: + if did_h in spi[mid]['jedec']: - if did_l in spi[mid][did_h]: + if did_l in spi[mid]['jedec'][did_h]: - t = spi[mid][did_h][did_l] + t = spi[mid]['jedec'][did_h][did_l] print("\n Manufacturer... " + color(f"{mfr}", fg="green") + "\n Device......... " + color(f"{t['part']}", fg="green") + "\n Size........... " + color(f"{t['size']} ({t['sizeB']})", fg="yellow") diff --git a/common_arm/flashmem.c b/common_arm/flashmem.c index 5aa88b0ebc..84a391c505 100644 --- a/common_arm/flashmem.c +++ b/common_arm/flashmem.c @@ -366,7 +366,6 @@ void Flashmem_print_status(void) { ); } - Dbprintf(" Device.................. " _YELLOW_("%s"), spi_flash_data.device); Dbprintf(" Memory size............. " _YELLOW_("%d kB (%d pages * 64k)"), spi_flash_pages64k * 64, spi_flash_pages64k); uint8_t uid[8] = {0, 0, 0, 0, 0, 0, 0, 0}; @@ -442,21 +441,15 @@ bool FlashDetect(void) { } else { if (g_dbglevel > 3) Dbprintf("Flash_ReadID failed reading Mfr/Dev (0x90)"); } - // default device is 'unknown' - spi_flash_data.device = SpiFlashTable[0].device; - + // Check JEDEC datais valid, compare the reported device types and then calcualte the number of pages + // It is covering the most (known) cases of devices but probably there are vendors with different data + // They will be handled when there is such cases if (ret) { - for (int i = 0; i < ARRAYLEN(SpiFlashTable); i++) { - if (SpiFlashTable[i].manufacturer_id == spi_flash_data.manufacturer_id) { - if (SpiFlashTable[i].jedec_id == spi_flash_data.jedec_id) { - spi_flash_pages64k = SpiFlashTable[i].pages64k; - spi_flash_data.device = SpiFlashTable[i].device; - break; - } - if (SpiFlashTable[i].device_id == spi_flash_data.device_id) { - spi_flash_data.device = SpiFlashTable[i].device; - break; - } + if (spi_flash_data.jedec_id > 0 && spi_flash_data.jedec_id < 0xFFFF) { + uint8_t jedec_p64k = (1 << (spi_flash_data.jedec_id & 0x000F)) & 0xFF; + uint8_t deviceid_p64k = (1 << ((spi_flash_data.device_id & 0x0F) + 1)) & 0xFF; + if (jedec_p64k == deviceid_p64k) { + spi_flash_pages64k = jedec_p64k; } } } diff --git a/common_arm/flashmem.h b/common_arm/flashmem.h index 616575e49c..f20dd0bff8 100644 --- a/common_arm/flashmem.h +++ b/common_arm/flashmem.h @@ -140,41 +140,8 @@ typedef struct { uint8_t manufacturer_id; uint8_t device_id; uint16_t jedec_id; - uint8_t pages64k; - char *device; } spi_flash_t; -static const spi_flash_t SpiFlashTable[] = { - // first element is the default of 4 * 64kB pages (256kB) - { 0x00, 0x00, 0x0000, 4, "unknown" }, // 256k - // Manufacturer: Puya - { 0x85, 0x14, 0x6015, 32, "P25Q16H" }, // 2048k - // Manufacturer: Winbond - { 0xEF, 0x00, 0x3012, 4, "W25X20BV" }, // 256k - { 0xEF, 0x00, 0x3013, 8, "W25X40BV" }, // 512k - - { 0xEF, 0x00, 0x4013, 8, "W25Q40BV" }, // 512k - { 0xEF, 0x00, 0x4014, 16, "W25Q80BV" }, // 1024k - { 0xEF, 0x14, 0x4015, 32, "W25Q16BV" }, // 2048k - { 0xEF, 0x15, 0x4016, 64, "W25Q32BV" }, // 4096k - - { 0xEF, 0x16, 0x7017, 128, "W25Q64JV" }, // 8192k - { 0xEF, 0x21, 0x7022, 4, "W25Q02JV" }, - - // identified by Manufacturer /Device ID only - /// Manufacturer: Renesas - { 0x1F, 0x46, 0x0000, 32, "AT25XE161D" }, // 2048k - { 0x1F, 0x47, 0x0000, 64, "AT25XE321D" }, // 4096k -// { 0xEF, 0x05, 0x0000, 1, "Winbond!!!" }, // 64k (too small !!!) - { 0xEF, 0x10, 0x0000, 2, "W25*10BV!" }, // 128k (small !!!) - { 0xEF, 0x11, 0x0000, 4, "W25*20BV" }, // 256k - { 0xEF, 0x12, 0x0000, 8, "W25*40BV" }, // 512k - { 0xEF, 0x13, 0x0000, 16, "W25*80BV" }, // 1024k - { 0xEF, 0x14, 0x0000, 32, "W25*16*" }, // 2048k - { 0xEF, 0x15, 0x0000, 64, "W25*32*" }, // 4096k - { 0xEF, 0x16, 0x0000, 128, "W25*64*" } // 8192k -}; - extern uint8_t spi_flash_pages64k; bool FlashDetect(void);