diff --git a/armsrc/Standalone/hf_legic.c b/armsrc/Standalone/hf_legic.c index 6ebe6eff6..0b4d0e2ae 100644 --- a/armsrc/Standalone/hf_legic.c +++ b/armsrc/Standalone/hf_legic.c @@ -39,7 +39,7 @@ * * To delete a dump file from flash: * - * 1. mem spiffs remove hf-legic-XXYYZZWW-dump.bin + * 1. mem spiffs remove -f hf-legic-XXYYZZWW-dump.bin * */ diff --git a/armsrc/Standalone/lf_icehid.c b/armsrc/Standalone/lf_icehid.c index d125b0c03..9164e182e 100644 --- a/armsrc/Standalone/lf_icehid.c +++ b/armsrc/Standalone/lf_icehid.c @@ -48,7 +48,7 @@ * * To delete the log file from flash: * - * 1. mem spiffs remove lf_hidcollect.log + * 1. mem spiffs remove -f lf_hidcollect.log */ #define LF_HIDCOLLECT_LOGFILE "lf_hidcollect.log" diff --git a/armsrc/Standalone/lf_tharexde.c b/armsrc/Standalone/lf_tharexde.c index 2a7a686fb..713e27d84 100644 --- a/armsrc/Standalone/lf_tharexde.c +++ b/armsrc/Standalone/lf_tharexde.c @@ -42,7 +42,7 @@ * - LED D: unmounting/sync'ing flash (normally < 100ms) * * To upload input file (eml format) to flash: - * - mem spiffs load f o lf_em4x50_simulate.eml + * - mem spiffs upload -s -d lf_em4x50_simulate.eml * * To retrieve password file from flash: * - mem spiffs dump o lf_em4x50_passwords.log f @@ -54,13 +54,13 @@ * the lab connected to PM3 client before taking it into the field. * * To delete the input file from flash: - * - mem spiffs remove lf_em4x50_simulate.eml + * - mem spiffs remove -f lf_em4x50_simulate.eml * * To delete the log file from flash: - * - mem spiffs remove lf_em4x50_passwords.log + * - mem spiffs remove -f lf_em4x50_passwords.log * * To delete the log file from flash: - * - mem spiffs remove lf_em4x50_collect.log + * - mem spiffs remove -f lf_em4x50_collect.log */ #define STATE_SIM 0 @@ -77,7 +77,7 @@ static void LoadDataInstructions(const char *inputfile) { Dbprintf("To load datafile to flash and display it:"); Dbprintf("1. edit input file %s", inputfile); Dbprintf("2. start proxmark3 client"); - Dbprintf("3. mem spiffs load f o %s", inputfile); + Dbprintf("3. mem spiffs upload -f o %s", inputfile); Dbprintf("4. start standalone mode"); } diff --git a/armsrc/appmain.c b/armsrc/appmain.c index 22190ef1a..77af73cb2 100644 --- a/armsrc/appmain.c +++ b/armsrc/appmain.c @@ -2078,7 +2078,7 @@ static void PacketReceived(PacketCommandNG *packet) { Dbprintf("transfer to client failed :: | bytes between %d - %d (%d) | result: %d", i, i + len, len, result); } // Trigger a finish downloading signal with an ACK frame - reply_mix(CMD_ACK, 1, 0, 0, 0, 0); + reply_ng(CMD_SPIFFS_DOWNLOAD, PM3_SUCCESS, NULL, 0); LED_B_OFF(); break; } @@ -2087,11 +2087,17 @@ static void PacketReceived(PacketCommandNG *packet) { uint8_t filename[32]; uint8_t *pfilename = packet->data.asBytes; memcpy(filename, pfilename, SPIFFS_OBJ_NAME_LEN); - if (DBGLEVEL >= DBG_DEBUG) Dbprintf("Filename received for spiffs STAT : %s", filename); + if (DBGLEVEL >= DBG_DEBUG) { + Dbprintf("Filename received for spiffs STAT : %s", filename); + } + int changed = rdv40_spiffs_lazy_mount(); uint32_t size = size_in_spiffs((char *)filename); - if (changed) rdv40_spiffs_lazy_unmount(); - reply_mix(CMD_ACK, size, 0, 0, 0, 0); + if (changed) { + rdv40_spiffs_lazy_unmount(); + } + + reply_ng(CMD_SPIFFS_STAT, PM3_SUCCESS, (uint8_t *)&size, sizeof(uint32_t)); LED_B_OFF(); break; } @@ -2121,12 +2127,12 @@ static void PacketReceived(PacketCommandNG *packet) { uint8_t dlen; uint8_t dest[32]; } PACKED; - struct p *payload = (struct p *) packet->data.asBytes; if (DBGLEVEL >= DBG_DEBUG) { - Dbprintf("Filename received as source for spiffs RENAME : %s", payload->src); - Dbprintf("Filename received as destination for spiffs RENAME : %s", payload->dest); + Dbprintf("SPIFFS RENAME"); + Dbprintf("Source........ %s", payload->src); + Dbprintf("Destination... %s", payload->dest); } rdv40_spiffs_rename((char *)payload->src, (char *)payload->dest, RDV40_SPIFFS_SAFETY_SAFE); reply_ng(CMD_SPIFFS_RENAME, PM3_SUCCESS, NULL, 0); @@ -2135,40 +2141,40 @@ static void PacketReceived(PacketCommandNG *packet) { } case CMD_SPIFFS_COPY: { LED_B_ON(); - uint8_t src[32]; - uint8_t dest[32]; - uint8_t *pfilename = packet->data.asBytes; - char *token; - token = strtok((char *)pfilename, ","); - strncpy((char *)src, token, sizeof(src) - 1); - token = strtok(NULL, ","); - strncpy((char *)dest, token, sizeof(dest) - 1); + struct p { + uint8_t slen; + uint8_t src[32]; + uint8_t dlen; + uint8_t dest[32]; + } PACKED; + struct p *payload = (struct p *) packet->data.asBytes; + if (DBGLEVEL >= DBG_DEBUG) { - Dbprintf("Filename received as source for spiffs COPY : %s", src); - Dbprintf("Filename received as destination for spiffs COPY : %s", dest); + Dbprintf("SPIFFS COPY"); + Dbprintf("Source........ %s", payload->src); + Dbprintf("Destination... %s", payload->dest); } - rdv40_spiffs_copy((char *) src, (char *)dest, RDV40_SPIFFS_SAFETY_SAFE); + rdv40_spiffs_copy((char *)payload->src, (char *)payload->dest, RDV40_SPIFFS_SAFETY_SAFE); + reply_ng(CMD_SPIFFS_COPY, PM3_SUCCESS, NULL, 0); LED_B_OFF(); break; } case CMD_SPIFFS_WRITE: { LED_B_ON(); - uint8_t filename[32]; - uint32_t append = packet->oldarg[0]; - uint32_t size = packet->oldarg[1]; - uint8_t *data = packet->data.asBytes; - uint8_t *pfilename = packet->data.asBytes; - memcpy(filename, pfilename, SPIFFS_OBJ_NAME_LEN); - data += SPIFFS_OBJ_NAME_LEN; - if (DBGLEVEL >= DBG_DEBUG) Dbprintf("> Filename received for spiffs WRITE : %s with APPEND SET TO : %d", filename, append); + flashmem_write_t *payload = (flashmem_write_t *)packet->data.asBytes; - if (!append) { - rdv40_spiffs_write((char *) filename, (uint8_t *)data, size, RDV40_SPIFFS_SAFETY_SAFE); - } else { - rdv40_spiffs_append((char *) filename, (uint8_t *)data, size, RDV40_SPIFFS_SAFETY_SAFE); + if (DBGLEVEL >= DBG_DEBUG) { + Dbprintf("SPIFFS WRITE, dest `%s` with APPEND set to: %c", payload->fn, payload->append ? 'Y' : 'N'); } - reply_mix(CMD_ACK, 1, 0, 0, 0, 0); + + if (payload->append) { + rdv40_spiffs_append((char *) payload->fn, payload->data, payload->bytes_in_packet, RDV40_SPIFFS_SAFETY_SAFE); + } else { + rdv40_spiffs_write((char *) payload->fn, payload->data, payload->bytes_in_packet, RDV40_SPIFFS_SAFETY_SAFE); + } + + reply_ng(CMD_SPIFFS_WRITE, PM3_SUCCESS, NULL, 0); LED_B_OFF(); break; } diff --git a/client/luascripts/mem_spiffs_readpwd.lua b/client/luascripts/mem_spiffs_readpwd.lua index b4995e406..ef529440c 100644 --- a/client/luascripts/mem_spiffs_readpwd.lua +++ b/client/luascripts/mem_spiffs_readpwd.lua @@ -76,7 +76,7 @@ local function main(args) if removeflag then print('Deleting file '..filename.. ' from SPIFFS if exists') - core.console("mem spiffs remove " ..filename) + core.console("mem spiffs remove -f " ..filename) return end diff --git a/client/src/cmdflashmemspiffs.c b/client/src/cmdflashmemspiffs.c index f0877ab0d..1a372bb60 100644 --- a/client/src/cmdflashmemspiffs.c +++ b/client/src/cmdflashmemspiffs.c @@ -17,55 +17,7 @@ static int CmdHelp(const char *Cmd); -static int usage_flashmemspiffs_copy(void) { - PrintAndLogEx(NORMAL, "Copy a file to another (destructively) in spiffs filesystem\n"); - PrintAndLogEx(NORMAL, "Usage: mem spiffs copy "); - PrintAndLogEx(NORMAL, ""); - PrintAndLogEx(NORMAL, "Examples:"); - PrintAndLogEx(NORMAL, _YELLOW_(" mem spiffs copy lasttag.bin lasttag_cpy.bin")); - return PM3_SUCCESS; -} - -static int usage_flashmemspiffs_dump(void) { - PrintAndLogEx(NORMAL, "Dumps flash memory on device into a file or in console"); - PrintAndLogEx(NORMAL, "Size is handled by first sending a STAT command against file existence\n"); - PrintAndLogEx(NORMAL, "Usage: mem spiffs dump o [f [e]] [p]"); - PrintAndLogEx(NORMAL, " o - filename in SPIFFS"); - PrintAndLogEx(NORMAL, " f - file name to save to "); - PrintAndLogEx(NORMAL, " p - print dump in console"); - PrintAndLogEx(NORMAL, " e - also save in EML format (good for tags save and dictonnary files)"); - PrintAndLogEx(NORMAL, " You must specify at lease option f or option p, both if you wish"); - PrintAndLogEx(NORMAL, ""); - PrintAndLogEx(NORMAL, "Examples:"); - PrintAndLogEx(NORMAL, _YELLOW_(" mem spiffs dump o lasttag.bin f lasttag e")); - PrintAndLogEx(NORMAL, _YELLOW_(" mem spiffs dump o lasttag.bin p")); - return PM3_SUCCESS; -} - -static int usage_flashmemspiffs_load(void) { - PrintAndLogEx(NORMAL, "Uploads binary-wise file into device filesystem"); - PrintAndLogEx(NORMAL, "Warning: mem area to be written must have been wiped first"); - PrintAndLogEx(NORMAL, "(this is already taken care when loading dictionaries)\n"); - PrintAndLogEx(NORMAL, "Usage: mem spiffs load o f "); - PrintAndLogEx(NORMAL, " o - destination filename"); - PrintAndLogEx(NORMAL, " f - local filename"); - PrintAndLogEx(NORMAL, ""); - PrintAndLogEx(NORMAL, "Examples:"); - PrintAndLogEx(NORMAL, _YELLOW_(" mem spiffs load f myfile o myapp.conf")); - return PM3_SUCCESS; -} - -static int usage_flashmemspiffs_wipe(void) { - PrintAndLogEx(NORMAL, "wipes all files on the device filesystem " _RED_("* Warning *")); - PrintAndLogEx(NORMAL, "Usage: mem spiffs wipe [h]"); - PrintAndLogEx(NORMAL, ""); - PrintAndLogEx(NORMAL, "Examples:"); - PrintAndLogEx(NORMAL, _YELLOW_(" mem spiffs wipe")); - return PM3_SUCCESS; -} - - -int flashmem_spiffs_load(uint8_t *destfn, uint8_t *data, size_t datalen) { +int flashmem_spiffs_load(char *destfn, uint8_t *data, size_t datalen) { int ret_val = PM3_SUCCESS; @@ -76,33 +28,35 @@ int flashmem_spiffs_load(uint8_t *destfn, uint8_t *data, size_t datalen) { // Send to device uint32_t bytes_sent = 0; uint32_t bytes_remaining = datalen; - uint32_t append = 0; // fast push mode conn.block_after_ACK = true; while (bytes_remaining > 0) { + uint32_t bytes_in_packet = MIN(FLASH_MEM_BLOCK_SIZE, bytes_remaining); + flashmem_write_t *payload = calloc(1, sizeof(flashmem_write_t) + bytes_in_packet); + + payload->append = (bytes_sent > 0); + payload->fnlen = strlen(destfn); + memcpy(payload->fn, destfn, strlen(destfn)); + + payload->bytes_in_packet = bytes_in_packet; + memset(payload->data, 0, bytes_in_packet); + memcpy(payload->data, data + bytes_sent, bytes_in_packet); + + PacketResponseNG resp; clearCommandBuffer(); + SendCommandNG(CMD_SPIFFS_WRITE, (uint8_t *)payload, sizeof(flashmem_write_t) + bytes_in_packet); - char fdata[32 + bytes_in_packet]; - memset(fdata, 0, sizeof(fdata)); - memcpy(fdata, destfn, 32); - memcpy(fdata + 32, data + bytes_sent, bytes_in_packet); - - if (bytes_sent > 0) - append = 1; - - SendCommandOLD(CMD_SPIFFS_WRITE, append, bytes_in_packet, 0, fdata, 32 + bytes_in_packet); + free(payload); bytes_remaining -= bytes_in_packet; bytes_sent += bytes_in_packet; - PacketResponseNG resp; - uint8_t retry = 3; - while (!WaitForResponseTimeout(CMD_ACK, &resp, 2000)) { + while (WaitForResponseTimeout(CMD_SPIFFS_WRITE, &resp, 2000) == false) { PrintAndLogEx(WARNING, "timeout while waiting for reply."); retry--; if (retry == 0) { @@ -110,13 +64,6 @@ int flashmem_spiffs_load(uint8_t *destfn, uint8_t *data, size_t datalen) { goto out; } } - - uint8_t isok = resp.oldarg[0] & 0xFF; - if (!isok) { - PrintAndLogEx(FAILED, "Flash write fail [offset %u]", bytes_sent); - ret_val = PM3_EFLASH; - break; - } } out: @@ -128,7 +75,6 @@ out: // We want to unmount after these to set things back to normal but more than this // unmouting ensure that SPIFFS CACHES are all flushed so our file is actually written on memory SendCommandNG(CMD_SPIFFS_UNMOUNT, NULL, 0); - return ret_val; } @@ -321,246 +267,273 @@ static int CmdFlashMemSpiFFSRename(const char *Cmd) { } static int CmdFlashMemSpiFFSCopy(const char *Cmd) { - int len = strlen(Cmd); - if (len < 1) { - return usage_flashmemspiffs_copy(); - } - char ctmp = tolower(param_getchar(Cmd, 0)); - if (len == 1 && ctmp == 'h') { - return usage_flashmemspiffs_copy(); - } + CLIParserContext *ctx; + CLIParserInit(&ctx, "mem spiffs copy", + "Copy a file to another (destructively) in SPIFFS file system", + "mem spiffs copy -s aaa.bin -d aaa_cpy.bin" + ); + void *argtable[] = { + arg_param_begin, + arg_str1("s", "src", "", "source file name"), + arg_str1("d", "dest", "", "destination file name"), + arg_param_end + }; + CLIExecWithReturn(ctx, Cmd, argtable, false); - char srcfilename[32] = {0}; - char destfilename[32] = {0}; - bool errors = false; + int slen = 0; + char src[32] = {0}; + CLIParamStrToBuf(arg_get_str(ctx, 1), (uint8_t *)src, 32, &slen); - if (param_getstr(Cmd, 0, srcfilename, 32) >= 32) { - PrintAndLogEx(FAILED, "Source Filename too long"); - errors = true; - } - if (srcfilename[0] == '\0') { - PrintAndLogEx(FAILED, "Source Filename missing or invalid"); - errors = true; - } + int dlen = 0; + char dest[32] = {0}; + CLIParamStrToBuf(arg_get_str(ctx, 2), (uint8_t *)dest, 32, &dlen); + CLIParserFree(ctx); - if (param_getstr(Cmd, 1, destfilename, 32) >= 32) { - PrintAndLogEx(FAILED, "Source Filename too long"); - errors = true; - } - if (destfilename[0] == '\0') { - PrintAndLogEx(FAILED, "Source Filename missing or invalid"); - errors = true; - } + struct { + uint8_t slen; + uint8_t src[32]; + uint8_t dlen; + uint8_t dest[32]; + } PACKED payload; + payload.slen = slen; + payload.dlen = dlen; - // check null filename ? - if (errors) { - usage_flashmemspiffs_copy(); - return PM3_EINVARG; - } + memcpy(payload.src, src, slen); + memcpy(payload.dest, dest, dlen); - char data[65]; - sprintf(data, "%s,%s", srcfilename, destfilename); - SendCommandMIX(CMD_SPIFFS_COPY, 0, 0, 0, (uint8_t *)data, 65); + PacketResponseNG resp; + clearCommandBuffer(); + SendCommandNG(CMD_SPIFFS_COPY, (uint8_t *)&payload, sizeof(payload)); + WaitForResponse(CMD_SPIFFS_COPY, &resp); + if (resp.status == PM3_SUCCESS) + PrintAndLogEx(INFO, "Done!"); + + PrintAndLogEx(HINT, "Try `" _YELLOW_("mem spiffs tree") "` to verify"); return PM3_SUCCESS; } static int CmdFlashMemSpiFFSDump(const char *Cmd) { + CLIParserContext *ctx; + CLIParserInit(&ctx, "mem spiffs dump", + "Dumps device SPIFFS file to a local file\n" + "Size is handled by first sending a STAT command against file to verify existence", + "mem spiffs dump -s tag.bin --> download binary file from device\n" + "mem spiffs dump -s tag.bin -d aaa -e --> download tag.bin, save as aaa.eml format" + ); - char filename[FILE_PATH_SIZE] = {0}; - uint8_t cmdp = 0; - bool errors = false; - bool print = false; - uint32_t start_index = 0, len = FLASH_MEM_MAX_SIZE; - char destfilename[32] = {0}; - bool eml = false; + void *argtable[] = { + arg_param_begin, + arg_str1("s", "src", "", "SPIFFS file to save"), + arg_str0("d", "dest", "", "file name to save to "), + arg_lit0("e", "eml", "also save in EML format"), + arg_param_end + }; + CLIExecWithReturn(ctx, Cmd, argtable, false); - while (param_getchar(Cmd, cmdp) != 0x00 && !errors) { - switch (tolower(param_getchar(Cmd, cmdp))) { - case 'h': - return usage_flashmemspiffs_dump(); - /*case 'l': - len = param_get32ex(Cmd, cmdp + 1, FLASH_MEM_MAX_SIZE, 10); - cmdp += 2; - break;*/ - case 'o': - param_getstr(Cmd, cmdp + 1, destfilename, 32); - cmdp += 2; - break; - case 'p': - print = true; - cmdp += 1; - break; - case 'e': - eml = true; - cmdp += 1; - break; - case 'f': - // File handling - if (param_getstr(Cmd, cmdp + 1, filename, FILE_PATH_SIZE) >= FILE_PATH_SIZE) { - PrintAndLogEx(FAILED, "Filename too long"); - errors = true; - break; - } - cmdp += 2; - break; - default: - PrintAndLogEx(WARNING, "Unknown parameter '%c'", param_getchar(Cmd, cmdp)); - errors = true; - break; - } - } + int slen = 0; + char src[32] = {0}; + CLIParamStrToBuf(arg_get_str(ctx, 1), (uint8_t *)src, 32, &slen); - if ((filename[0] == '\0') && (!print)) { - PrintAndLogEx(FAILED, "No print asked and local dump filename missing or invalid"); - errors = true; - } + int dlen = 0; + char dest[FILE_PATH_SIZE] = {0}; + CLIParamStrToBuf(arg_get_str(ctx, 2), (uint8_t *)dest, FILE_PATH_SIZE, &dlen); - if (destfilename[0] == '\0') { - PrintAndLogEx(FAILED, "SPIFFS filename missing or invalid"); - errors = true; - } - - // Validations - if (errors || cmdp == 0) { - usage_flashmemspiffs_dump(); - return PM3_EINVARG; - } + bool eml = arg_get_lit(ctx, 3); + CLIParserFree(ctx); // get size from spiffs itself ! - SendCommandMIX(CMD_SPIFFS_STAT, 0, 0, 0, (uint8_t *)destfilename, 32); + clearCommandBuffer(); + SendCommandNG(CMD_SPIFFS_STAT, (uint8_t *)src, slen); PacketResponseNG resp; - if (!WaitForResponseTimeout(CMD_ACK, &resp, 2000)) { + if (WaitForResponseTimeout(CMD_SPIFFS_STAT, &resp, 2000) == false) { PrintAndLogEx(WARNING, "timeout while waiting for reply."); return PM3_ETIMEOUT; } - len = resp.oldarg[0]; - + uint32_t len = resp.data.asDwords[0]; uint8_t *dump = calloc(len, sizeof(uint8_t)); if (!dump) { PrintAndLogEx(ERR, "error, cannot allocate memory "); return PM3_EMALLOC; } - PrintAndLogEx(INFO, "downloading "_YELLOW_("%u") " bytes from spiffs (flashmem)", len); - if (!GetFromDevice(SPIFFS, dump, len, start_index, (uint8_t *)destfilename, 32, NULL, -1, true)) { - PrintAndLogEx(FAILED, "ERROR; downloading from spiffs(flashmemory)"); + // download from device + uint32_t start_index = 0; + PrintAndLogEx(INFO, "downloading "_YELLOW_("%u") " bytes from `" _YELLOW_("%s") "` (spiffs)", len, src); + if (!GetFromDevice(SPIFFS, dump, len, start_index, (uint8_t *)src, slen, NULL, -1, true)) { + PrintAndLogEx(FAILED, "error, downloading from spiffs"); free(dump); return PM3_EFLASH; } - if (print) { - print_hex_break(dump, len, 32); + // save to file + char fn[FILE_PATH_SIZE] = {0}; + if (dlen == 0) { + strncpy(fn, src, slen); + } else { + strncpy(fn, dest, dlen); } - if (filename[0] != '\0') { - saveFile(filename, ".bin", dump, len); - if (eml) { - uint8_t eml_len = 16; + saveFile(fn, ".bin", dump, len); + if (eml) { + uint8_t eml_len = 16; + if (strstr(fn, "class") != NULL) + eml_len = 8; + else if (strstr(fn, "mfu") != NULL) + eml_len = 4; - if (strstr(filename, "class") != NULL) - eml_len = 8; - else if (strstr(filename, "mfu") != NULL) - eml_len = 4; - - saveFileEML(filename, dump, len, eml_len); - } + saveFileEML(fn, dump, len, eml_len); } - free(dump); return PM3_SUCCESS; } static int CmdFlashMemSpiFFSWipe(const char *Cmd) { + CLIParserContext *ctx; + CLIParserInit(&ctx, "mem spiffs wipe", + _RED_("* * * Warning * * *") " \n" + _CYAN_("This command wipes all files on the device SPIFFS file system"), + "mem spiffs wipe"); - char ctmp = tolower(param_getchar(Cmd, 0)); - if (ctmp == 'h') { - return usage_flashmemspiffs_wipe(); - } + void *argtable[] = { + arg_param_begin, + arg_param_end + }; + CLIExecWithReturn(ctx, Cmd, argtable, true); + CLIParserFree(ctx); - PrintAndLogEx(INFO, "Wiping all files from SPIFFS FileSystem"); + PrintAndLogEx(INFO, "Wiping all files from SPIFFS file system"); PacketResponseNG resp; clearCommandBuffer(); SendCommandNG(CMD_SPIFFS_WIPE, NULL, 0); WaitForResponse(CMD_SPIFFS_WIPE, &resp); - PrintAndLogEx(INFO, "Done!"); + if (resp.status == PM3_SUCCESS) + PrintAndLogEx(INFO, "Done!"); + PrintAndLogEx(HINT, "Try `" _YELLOW_("mem spiffs tree") "` to verify"); return PM3_SUCCESS; } -static int CmdFlashMemSpiFFSLoad(const char *Cmd) { +static int CmdFlashMemSpiFFSUpload(const char *Cmd) { + CLIParserContext *ctx; + CLIParserInit(&ctx, "mem spiffs upload", + "Uploads binary-wise file into device file system\n" + "Warning: mem area to be written must have been wiped first.\n" + "This is already taken care when loading dictionaries.\n" + "File names can only be 32 bytes long on device SPIFFS", + "mem spiffs upload -s local.bin -d dest.bin" + ); - char filename[FILE_PATH_SIZE] = {0}; - uint8_t destfilename[32] = {0}; - bool errors = false; - uint8_t cmdp = 0; + void *argtable[] = { + arg_param_begin, + arg_str1("s", "src", "", "source file name"), + arg_str1("d", "dest", "", "destination file name"), + arg_param_end + }; + CLIExecWithReturn(ctx, Cmd, argtable, false); - while (param_getchar(Cmd, cmdp) != 0x00 && !errors) { - switch (tolower(param_getchar(Cmd, cmdp))) { - case 'h': - return usage_flashmemspiffs_load(); - case 'f': - if (param_getstr(Cmd, cmdp + 1, filename, FILE_PATH_SIZE) >= FILE_PATH_SIZE) { - PrintAndLogEx(FAILED, "Filename too long"); - errors = true; - } - cmdp += 2; - break; - case 'o': - param_getstr(Cmd, cmdp + 1, (char *)destfilename, 32); - if (strlen((char *)destfilename) == 0) { - PrintAndLogEx(FAILED, "Destination Filename missing or invalid"); - errors = true; - } - cmdp += 2; - break; - default: - PrintAndLogEx(WARNING, "Unknown parameter '%c'", param_getchar(Cmd, cmdp)); - errors = true; - break; - } - } + int slen = 0; + char src[FILE_PATH_SIZE] = {0}; + CLIParamStrToBuf(arg_get_str(ctx, 1), (uint8_t *)src, FILE_PATH_SIZE, &slen); - // Validations - if (errors || cmdp == 0) - return usage_flashmemspiffs_load(); + int dlen = 0; + char dest[32] = {0}; + CLIParamStrToBuf(arg_get_str(ctx, 2), (uint8_t *)dest, 32, &dlen); + CLIParserFree(ctx); + + PrintAndLogEx(DEBUG, "Upload `" _YELLOW_("%s") "` -> `" _YELLOW_("%s") "`", src, dest); size_t datalen = 0; uint8_t *data = NULL; - int res = loadFile_safe(filename, "", (void **)&data, &datalen); - // int res = loadFileEML( filename, data, &datalen); + int res = loadFile_safe(src, "", (void **)&data, &datalen); if (res != PM3_SUCCESS) { free(data); return PM3_EFILE; } - res = flashmem_spiffs_load(destfilename, data, datalen); - + res = flashmem_spiffs_load(dest, data, datalen); free(data); if (res == PM3_SUCCESS) - PrintAndLogEx(SUCCESS, "Wrote "_GREEN_("%zu") " bytes to file "_GREEN_("%s"), datalen, destfilename); + PrintAndLogEx(SUCCESS, "Wrote "_GREEN_("%zu") " bytes to file "_GREEN_("%s"), datalen, dest); + PrintAndLogEx(HINT, "Try `" _YELLOW_("mem spiffs tree") "` to verify"); return res; } +static int CmdFlashMemSpiFFSView(const char *Cmd) { + + CLIParserContext *ctx; + CLIParserInit(&ctx, "mem spiffs view", + "View a file on flash memory on devicer in console", + "mem spiffs view -f tag.bin" + ); + + void *argtable[] = { + arg_param_begin, + arg_str1("f", "file", "", "SPIFFS file to view"), + arg_int0("c", "cols", "", "column breaks (def 32)"), + arg_param_end + }; + CLIExecWithReturn(ctx, Cmd, argtable, false); + + int slen = 0; + char src[32] = {0}; + CLIParamStrToBuf(arg_get_str(ctx, 1), (uint8_t *)src, 32, &slen); + + int breaks = arg_get_int_def(ctx, 2, 32); + CLIParserFree(ctx); + + // get size from spiffs itself ! + clearCommandBuffer(); + SendCommandNG(CMD_SPIFFS_STAT, (uint8_t *)src, slen); + PacketResponseNG resp; + if (WaitForResponseTimeout(CMD_SPIFFS_STAT, &resp, 2000) == false) { + PrintAndLogEx(WARNING, "timeout while waiting for reply."); + return PM3_ETIMEOUT; + } + + uint32_t len = resp.data.asDwords[0]; + uint8_t *dump = calloc(len, sizeof(uint8_t)); + if (!dump) { + PrintAndLogEx(ERR, "error, cannot allocate memory "); + return PM3_EMALLOC; + } + + uint32_t start_index = 0; + PrintAndLogEx(INFO, "downloading "_YELLOW_("%u") " bytes from `" _YELLOW_("%s") "` (spiffs)", len, src); + + if (!GetFromDevice(SPIFFS, dump, len, start_index, (uint8_t *)src, slen, NULL, -1, true)) { + PrintAndLogEx(FAILED, "error, downloading from spiffs"); + free(dump); + return PM3_EFLASH; + } + + PrintAndLogEx(NORMAL, ""); + print_hex_break(dump, len, breaks); + PrintAndLogEx(NORMAL, ""); + free(dump); + return PM3_SUCCESS; +} + static command_t CommandTable[] = { {"help", CmdHelp, AlwaysAvailable, "This help"}, {"copy", CmdFlashMemSpiFFSCopy, IfPm3Flash, "Copy a file to another (destructively) in SPIFFS file system"}, {"check", CmdFlashMemSpiFFSCheck, IfPm3Flash, "Check/try to defrag faulty/fragmented file system"}, {"dump", CmdFlashMemSpiFFSDump, IfPm3Flash, "Dump a file from SPIFFS file system"}, {"info", CmdFlashMemSpiFFSInfo, IfPm3Flash, "Print file system info and usage statistics"}, - {"load", CmdFlashMemSpiFFSLoad, IfPm3Flash, "Upload file into SPIFFS file system"}, {"mount", CmdFlashMemSpiFFSMount, IfPm3Flash, "Mount the SPIFFS file system if not already mounted"}, {"remove", CmdFlashMemSpiFFSRemove, IfPm3Flash, "Remove a file from SPIFFS file system"}, {"rename", CmdFlashMemSpiFFSRename, IfPm3Flash, "Rename/move a file in SPIFFS file system"}, {"test", CmdFlashMemSpiFFSTest, IfPm3Flash, "Test SPIFFS Operations"}, {"tree", CmdFlashMemSpiFFSTree, IfPm3Flash, "Print the Flash memory file system tree"}, {"unmount", CmdFlashMemSpiFFSUnmount, IfPm3Flash, "Un-mount the SPIFFS file system"}, - {"wipe", CmdFlashMemSpiFFSWipe, IfPm3Flash, "Wipe all files from SPIFFS file system. * " _RED_("dangerous") " *" }, + {"upload", CmdFlashMemSpiFFSUpload, IfPm3Flash, "Upload file into SPIFFS file system"}, + {"view", CmdFlashMemSpiFFSView, IfPm3Flash, "View file on SPIFFS file system"}, + {"wipe", CmdFlashMemSpiFFSWipe, IfPm3Flash, "Wipe all files from SPIFFS file system * " _RED_("dangerous") " *" }, {NULL, NULL, NULL, NULL} }; diff --git a/client/src/cmdflashmemspiffs.h b/client/src/cmdflashmemspiffs.h index 9324a541b..385d78401 100644 --- a/client/src/cmdflashmemspiffs.h +++ b/client/src/cmdflashmemspiffs.h @@ -14,6 +14,6 @@ #include "common.h" int CmdFlashMemSpiFFS(const char *Cmd); -int flashmem_spiffs_load(uint8_t *destfn, uint8_t *data, size_t datalen); +int flashmem_spiffs_load(char *destfn, uint8_t *data, size_t datalen); #endif diff --git a/client/src/cmdlfem4x50.c b/client/src/cmdlfem4x50.c index ea60c84b9..fc4f75e5b 100644 --- a/client/src/cmdlfem4x50.c +++ b/client/src/cmdlfem4x50.c @@ -471,7 +471,7 @@ int CmdEM4x50Chk(const char *Cmd) { // upload to flash. datalen = MIN(bytes_remaining, keyblock); - res = flashmem_spiffs_load(destfn, keys, datalen); + res = flashmem_spiffs_load((char*)destfn, keys, datalen); if (res != PM3_SUCCESS) { PrintAndLogEx(WARNING, "SPIFFS upload failed"); return res; diff --git a/client/src/comms.c b/client/src/comms.c index 57a03afe7..26c68d889 100644 --- a/client/src/comms.c +++ b/client/src/comms.c @@ -839,6 +839,9 @@ static bool dl_it(uint8_t *dest, uint32_t bytes, PacketResponseNG *response, siz if (response->cmd == CMD_ACK) return true; + // Spiffs download is converted to NG, + if (response->cmd == CMD_SPIFFS_DOWNLOAD) + return true; // sample_buf is a array pointer, located in data.c // arg0 = offset in transfer. Startindex of this chunk diff --git a/client/src/mifare/mifarehost.c b/client/src/mifare/mifarehost.c index c6e02013e..4a34421ba 100644 --- a/client/src/mifare/mifarehost.c +++ b/client/src/mifare/mifarehost.c @@ -695,7 +695,7 @@ int mfStaticNested(uint8_t blockNo, uint8_t keyType, uint8_t *key, uint8_t trgBl mem[4] = (chunk & 0xFF); // upload to flash. - res = flashmem_spiffs_load(destfn, mem, 5 + (chunk * 6)); + res = flashmem_spiffs_load((char*)destfn, mem, 5 + (chunk * 6)); if (res != PM3_SUCCESS) { PrintAndLogEx(WARNING, "\nSPIFFS upload failed"); free(mem); diff --git a/include/pm3_cmd.h b/include/pm3_cmd.h index 6b7f5df07..a2193a85b 100644 --- a/include/pm3_cmd.h +++ b/include/pm3_cmd.h @@ -384,6 +384,15 @@ typedef struct { bool off; } PACKED tearoff_params_t; +// when writing to SPIFFS +typedef struct { + bool append : 1; + uint16_t bytes_in_packet : 15; + uint8_t fnlen; + uint8_t fn[32]; + uint8_t data[]; +} PACKED flashmem_write_t; + // For the bootloader #define CMD_DEVICE_INFO 0x0000 //#define CMD_SETUP_WRITE 0x0001 @@ -565,6 +574,8 @@ typedef struct { #define CMD_LF_HITAGS_READ 0x0373 #define CMD_LF_HITAGS_WRITE 0x0375 +#define CMD_LF_HITAG_ELOAD 0x0376 + #define CMD_HF_ISO14443A_ANTIFUZZ 0x0380 #define CMD_HF_ISO14443B_SIMULATE 0x0381 #define CMD_HF_ISO14443B_SNIFF 0x0382