Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

use all spi flash v0.1 #2638

Merged
merged 6 commits into from
Nov 18, 2024
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -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]
- Use all available space from the SPI flash (@ANTodorov)
- Fixed wrong size check in MifareSim (@iceman1001)
- Fixed `hf mf sim` not to respond to authentication attempts for sectors out of bound for selected Mifare type (@piotrva)
- Added option to build against non-default python3 with CMake as well (@doegox)
Expand Down
21 changes: 19 additions & 2 deletions armsrc/appmain.c
Original file line number Diff line number Diff line change
Expand Up @@ -2789,7 +2789,7 @@ static void PacketReceived(PacketCommandNG *packet) {
LED_B_OFF();
break;
}
if (page < 3) {
if (page < spi_flash_p64k-1) {
isok = Flash_WipeMemoryPage(page);
// let spiffs check and update its info post flash erase
rdv40_spiffs_check();
Expand Down Expand Up @@ -2836,7 +2836,7 @@ static void PacketReceived(PacketCommandNG *packet) {
LED_B_ON();
rdv40_validation_t *info = (rdv40_validation_t *)BigBuf_malloc(sizeof(rdv40_validation_t));

bool isok = Flash_ReadData(FLASH_MEM_SIGNATURE_OFFSET, info->signature, FLASH_MEM_SIGNATURE_LEN);
bool isok = Flash_ReadData(FLASH_MEM_SIGNATURE_OFFSET_P(spi_flash_p64k), info->signature, FLASH_MEM_SIGNATURE_LEN);

if (FlashInit()) {
Flash_UniqueID(info->flashid);
Expand All @@ -2845,6 +2845,23 @@ static void PacketReceived(PacketCommandNG *packet) {
reply_mix(CMD_ACK, isok, 0, 0, info, sizeof(rdv40_validation_t));
BigBuf_free();

LED_B_OFF();
break;
}
case CMD_FLASHMEM_PAGES64K: {

LED_B_ON();

bool isok = false;
if (FlashInit()) {
isok = true;
if (g_dbglevel >= DBG_DEBUG) {
Dbprintf(" CMD_FLASHMEM_PAGE64K 0x%02x (%d 64k pages)", spi_flash_p64k, spi_flash_p64k);
}
FlashStop();
}
reply_mix(CMD_ACK, isok, 0, 0, &spi_flash_p64k, sizeof(uint8_t));

LED_B_OFF();
break;
}
Expand Down
1 change: 0 additions & 1 deletion armsrc/spiffs.c
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,6 @@
// SPIFFS api for RDV40 Integration
//-----------------------------------------------------------------------------

#define SPIFFS_CFG_PHYS_SZ (1024 * 192)
#define SPIFFS_CFG_PHYS_ERASE_SZ (4 * 1024)
#define SPIFFS_CFG_PHYS_ADDR (0)
#define SPIFFS_CFG_LOG_PAGE_SZ (256)
Expand Down
2 changes: 1 addition & 1 deletion armsrc/spiffs_config.h
Original file line number Diff line number Diff line change
Expand Up @@ -236,7 +236,7 @@ typedef uint8_t u8_t;
// Instead of giving parameters in config struct, singleton build must
// give parameters in defines below.
#ifndef SPIFFS_CFG_PHYS_SZ
#define SPIFFS_CFG_PHYS_SZ(ignore) (1024*192)
#define SPIFFS_CFG_PHYS_SZ(ignore) (1024 * 64 * (spi_flash_p64k - 1))
#endif
#ifndef SPIFFS_CFG_PHYS_ERASE_SZ
#define SPIFFS_CFG_PHYS_ERASE_SZ(ignore) (4*1024)
Expand Down
73 changes: 62 additions & 11 deletions client/src/cmdflashmem.c
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,29 @@ static int CmdHelp(const char *Cmd);

//-------------------------------------------------------------------------------------

int rdv4_get_flash_pages64k(uint8_t *pages64k) {
if (pages64k == NULL) {
return PM3_EINVARG;
}

clearCommandBuffer();
SendCommandNG(CMD_FLASHMEM_PAGES64K, NULL, 0);
PacketResponseNG resp;
if (WaitForResponseTimeout(CMD_ACK, &resp, 2500) == false) {
PrintAndLogEx(WARNING, "rdv4_get_flash_pages64k() timeout while waiting for reply");
return PM3_ETIMEOUT;
}

uint8_t isok = resp.oldarg[0] & 0xFF;
if (isok == false) {
PrintAndLogEx(FAILED, "fail reading from flash (pages 64k)");
return PM3_EFLASH;
}

memcpy(pages64k, (uint8_t *)resp.data.asBytes, sizeof(uint8_t));
return PM3_SUCCESS;
}

int rdv4_get_signature(rdv40_validation_t *out) {
if (out == NULL) {
return PM3_EINVARG;
Expand Down Expand Up @@ -98,8 +121,16 @@ int rdv4_validate(rdv40_validation_t *mem) {
}

static int rdv4_sign_write(uint8_t *signature, uint8_t slen) {

uint8_t spi_flash_pages = 0;
int res = rdv4_get_flash_pages64k(&spi_flash_pages);
if (res != PM3_SUCCESS) {
PrintAndLogEx(ERR, "failed to get flash pages (%x)", res);
return res;
}

flashmem_old_write_t payload = {
.startidx = FLASH_MEM_SIGNATURE_OFFSET,
.startidx = FLASH_MEM_SIGNATURE_OFFSET_P(spi_flash_pages),
.len = FLASH_MEM_SIGNATURE_LEN,
};
memcpy(payload.data, signature, slen);
Expand Down Expand Up @@ -201,15 +232,21 @@ static int CmdFlashMemLoad(const char *Cmd) {
PrintAndLogEx(INFO, "treating file as T55xx passwords");
}

uint8_t spi_flash_pages = 0;
int res = rdv4_get_flash_pages64k(&spi_flash_pages);
if (res != PM3_SUCCESS) {
PrintAndLogEx(ERR, "failed to get flash pages count (%x)", res);
return res;
}

size_t datalen = 0;
uint32_t keycount = 0;
int res = 0;
uint8_t keylen = 0;
uint8_t *data = calloc(FLASH_MEM_MAX_SIZE, sizeof(uint8_t));
uint8_t *data = calloc(FLASH_MEM_MAX_SIZE_P(spi_flash_pages), sizeof(uint8_t));

switch (d) {
case DICTIONARY_MIFARE:
offset = DEFAULT_MF_KEYS_OFFSET;
offset = DEFAULT_MF_KEYS_OFFSET_P(spi_flash_pages);
keylen = 6;
res = loadFileDICTIONARY(filename, data + 2, &datalen, keylen, &keycount);
if (res || !keycount) {
Expand All @@ -227,7 +264,7 @@ static int CmdFlashMemLoad(const char *Cmd) {
datalen += 2;
break;
case DICTIONARY_T55XX:
offset = DEFAULT_T55XX_KEYS_OFFSET;
offset = DEFAULT_T55XX_KEYS_OFFSET_P(spi_flash_pages);
keylen = 4;
res = loadFileDICTIONARY(filename, data + 2, &datalen, keylen, &keycount);
if (res || !keycount) {
Expand All @@ -245,7 +282,7 @@ static int CmdFlashMemLoad(const char *Cmd) {
datalen += 2;
break;
case DICTIONARY_ICLASS:
offset = DEFAULT_ICLASS_KEYS_OFFSET;
offset = DEFAULT_ICLASS_KEYS_OFFSET_P(spi_flash_pages);
res = loadFileDICTIONARY(filename, data + 2, &datalen, keylen, &keycount);
if (res || !keycount) {
free(data);
Expand All @@ -268,7 +305,7 @@ static int CmdFlashMemLoad(const char *Cmd) {
return PM3_EFILE;
}

if (datalen > FLASH_MEM_MAX_SIZE) {
if (datalen > FLASH_MEM_MAX_SIZE_P(spi_flash_pages)) {
PrintAndLogEx(ERR, "error, filesize is larger than available memory");
free(data);
return PM3_EOVFLOW;
Expand Down Expand Up @@ -351,8 +388,15 @@ static int CmdFlashMemDump(const char *Cmd) {
};
CLIExecWithReturn(ctx, Cmd, argtable, false);

uint8_t spi_flash_pages = 0;
int res = rdv4_get_flash_pages64k(&spi_flash_pages);
if (res != PM3_SUCCESS) {
PrintAndLogEx(ERR, "failed to get flash pages count (%x)", res);
return res;
}

int offset = arg_get_int_def(ctx, 1, 0);
int len = arg_get_int_def(ctx, 2, FLASH_MEM_MAX_SIZE);
int len = arg_get_int_def(ctx, 2, FLASH_MEM_MAX_SIZE_P(spi_flash_pages));
bool view = arg_get_lit(ctx, 3);
int fnlen = 0;
char filename[FILE_PATH_SIZE] = {0};
Expand Down Expand Up @@ -409,15 +453,22 @@ static int CmdFlashMemWipe(const char *Cmd) {
// initialwipe = arg_get_lit(ctx, 2);
CLIParserFree(ctx);

if (page < 0 || page > 2) {
PrintAndLogEx(WARNING, "page must be 0, 1 or 2");
uint8_t spi_flash_pages = 0;
int res = rdv4_get_flash_pages64k(&spi_flash_pages);
if (res != PM3_SUCCESS) {
PrintAndLogEx(ERR, "failed to get flash pages count (%x)", res);
return res;
}

if (page < 0 || page > (spi_flash_pages - 1)) {
PrintAndLogEx(WARNING, "page must be between 0 and %d", spi_flash_pages - 1);
return PM3_EINVARG;
}

clearCommandBuffer();
SendCommandMIX(CMD_FLASHMEM_WIPE, page, initialwipe, 0, NULL, 0);
PacketResponseNG resp;
if (!WaitForResponseTimeout(CMD_ACK, &resp, 8000)) {
if (!WaitForResponseTimeout(CMD_ACK, &resp, 10000)) {
PrintAndLogEx(WARNING, "timeout while waiting for reply.");
return PM3_ETIMEOUT;
}
Expand Down
1 change: 1 addition & 0 deletions client/src/cmdflashmem.h
Original file line number Diff line number Diff line change
Expand Up @@ -32,4 +32,5 @@ typedef enum {
int CmdFlashMem(const char *Cmd);
int rdv4_get_signature(rdv40_validation_t *out);
int rdv4_validate(rdv40_validation_t *mem);
int rdv4_get_flash_pages64k(uint8_t *pages64k);
#endif
77 changes: 56 additions & 21 deletions common_arm/flashmem.c
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,8 @@ static uint32_t FLASHMEM_SPIBAUDRATE = FLASH_BAUD;

#ifndef AS_BOOTROM

uint8_t spi_flash_p64k = 0;

void FlashmemSetSpiBaudrate(uint32_t baudrate) {
FLASHMEM_SPIBAUDRATE = baudrate;
Dbprintf("Spi Baudrate : %dMHz", FLASHMEM_SPIBAUDRATE / 1000000);
Expand Down Expand Up @@ -144,14 +146,15 @@ uint16_t Flash_WriteData(uint32_t address, uint8_t *in, uint16_t len) {
return 0;
}

// out-of-range
if (((address >> 16) & 0xFF) > MAX_BLOCKS) {
Dbprintf("Flash_WriteData, block out-of-range");
if (!FlashInit()) {
if (g_dbglevel > 3) Dbprintf("Flash_WriteData init fail");
return 0;
}

if (!FlashInit()) {
if (g_dbglevel > 3) Dbprintf("Flash_WriteData init fail");
// out-of-range
if (((address >> 16) & 0xFF) > spi_flash_p64k) {
Dbprintf("Flash_WriteData, block out-of-range %02x > %02x", (address >> 16) & 0xFF, spi_flash_p64k);
FlashStop();
return 0;
}

Expand Down Expand Up @@ -187,8 +190,8 @@ uint16_t Flash_WriteDataCont(uint32_t address, uint8_t *in, uint16_t len) {
return 0;
}

if (((address >> 16) & 0xFF) > MAX_BLOCKS) {
Dbprintf("Flash_WriteDataCont, block out-of-range");
if (((address >> 16) & 0xFF) > spi_flash_p64k) {
Dbprintf("Flash_WriteDataCont, block out-of-range %02x > %02x", (address >> 16) & 0xFF, spi_flash_p64k);
return 0;
}

Expand Down Expand Up @@ -266,18 +269,11 @@ bool Flash_WipeMemory(void) {

// Each block is 64Kb. Four blocks
// one block erase takes 1s ( 1000ms )
Flash_WriteEnable();
Flash_Erase64k(0);
Flash_CheckBusy(BUSY_TIMEOUT);
Flash_WriteEnable();
Flash_Erase64k(1);
Flash_CheckBusy(BUSY_TIMEOUT);
Flash_WriteEnable();
Flash_Erase64k(2);
Flash_CheckBusy(BUSY_TIMEOUT);
Flash_WriteEnable();
Flash_Erase64k(3);
Flash_CheckBusy(BUSY_TIMEOUT);
for (uint8_t i=0; i < spi_flash_p64k; i++) {
Flash_WriteEnable();
Flash_Erase64k(i);
Flash_CheckBusy(BUSY_TIMEOUT);
}

FlashStop();
return true;
Expand All @@ -293,7 +289,7 @@ void Flash_WriteEnable(void) {
// execution time: 0.8ms / 800us
bool Flash_Erase4k(uint8_t block, uint8_t sector) {

if (block > MAX_BLOCKS || sector > MAX_SECTORS) return false;
if (block > spi_flash_p64k || sector > MAX_SECTORS) return false;

FlashSendByte(SECTORERASE);
FlashSendByte(block);
Expand Down Expand Up @@ -328,7 +324,7 @@ bool Flash_Erase32k(uint32_t address) {
// 0x03 00 00 -- 0x 03 FF FF == block 3
bool Flash_Erase64k(uint8_t block) {

if (block > MAX_BLOCKS) return false;
if (block > spi_flash_p64k) return false;

FlashSendByte(BLOCK64ERASE);
FlashSendByte(block);
Expand Down Expand Up @@ -404,6 +400,7 @@ void Flashmem_print_status(void) {
);
}
}
Dbprintf(" Flash pages (64k)....... " _YELLOW_("0x%02x (%u)"), spi_flash_p64k, spi_flash_p64k);

uint8_t uid[8] = {0, 0, 0, 0, 0, 0, 0, 0};
Flash_UniqueID(uid);
Expand Down Expand Up @@ -457,6 +454,38 @@ void Flashmem_print_info(void) {
FlashStop();
}

//read spi flash JEDEC ID and fill the global variable spi_flash_p64k
bool FlashDetect(bool flash_init) {
flash_device_type_t flash_device = {0};

if (flash_init) {
if (!FlashInit()) {
if (g_dbglevel > 3) Dbprintf("FlashDetect() FlashInit fail");
return 0;
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

don't mix return codes.

}
}

if (!Flash_ReadID(&flash_device, true)) {
if (g_dbglevel > 3) Dbprintf("Flash_ReadID failed");
return false;
}

uint32_t identifier = (flash_device.manufacturer_id <<16) + (flash_device.device_id <<8) + flash_device.device_id2;
int i = 0;
for (; i < ARRAYLEN(SpiFlashTable); i++) {
if (SpiFlashTable[i].identifier == identifier) {
break;
}
}

spi_flash_p64k = SpiFlashTable[i].pages64;

if (flash_init) {
FlashStop();
}
return true;
}

#endif // #ifndef AS_BOOTROM


Expand All @@ -471,6 +500,12 @@ bool FlashInit(void) {
return false;
}

#ifndef AS_BOOTROM
if (spi_flash_p64k == 0){
if (!FlashDetect(false)) return 0;
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

use same style with Curly Brackets

}
#endif // #ifndef AS_BOOTROM

return true;
}

Expand Down
31 changes: 31 additions & 0 deletions common_arm/flashmem.h
Original file line number Diff line number Diff line change
Expand Up @@ -145,6 +145,37 @@ uint16_t Flash_WriteDataCont(uint32_t address, uint8_t *in, uint16_t len);
void Flashmem_print_status(void);
void Flashmem_print_info(void);

typedef struct spi_flash_s {
const uint32_t identifier;
const uint8_t pages64;
const char *desc;
} spi_flash_t;

// spi_flash_t is expected to be NULL terminated
const static spi_flash_t SpiFlashTable[] = {
// Manufacturer: Puya
{ 0x856015, 32, "P25Q16H" },
// Manufacturer: Winbond
{ 0xEF3012, 4, "W25X20BV" },
{ 0xEF3013, 8, "W25X40BV" },

{ 0xEF4013, 8, "W25Q40BV" },
{ 0xEF4014, 16, "W25Q80BV" },
{ 0xEF4015, 32, "W25Q16BV" },
{ 0xEF4016, 64, "W25Q32BV" },

{ 0xEF7022, 4, "W25Q02JV" },
{ 0x000000, 4, "Unknown!" }
};

#ifndef ARRAYLEN
# define ARRAYLEN(x) (sizeof(x)/sizeof((x)[0]))
#endif

extern uint8_t spi_flash_p64k;

bool FlashDetect(bool);

#endif // #ifndef AS_BOOTROM


Expand Down
Loading
Loading