mirror of
https://github.com/RfidResearchGroup/proxmark3.git
synced 2025-08-14 18:48:13 -07:00
Adding processor flash memory reading, viewing and writing to file.
Works when the device is running either osimage or bootloader. - New memory reading command in osimage and bootloader. - Extended 'hw readmem' command with length parameter, file writing and hex viewer. - Introduced '--dumpmem' option to proxmark3 executable to support dumping from bootloader. Simple interactive examples: hw readmem -f flashdump hw readmem -l 1024 CLI example: ./pm3 --dumpmem flashdump.bin Reading from arbitrary memory ranges can be unlocked using the 'raw' option.
This commit is contained in:
parent
c6adda54ed
commit
e35385fde1
10 changed files with 386 additions and 12 deletions
|
@ -2364,6 +2364,52 @@ static void PacketReceived(PacketCommandNG *packet) {
|
|||
ReadMem(packet->data.asDwords[0]);
|
||||
break;
|
||||
}
|
||||
case CMD_READ_MEM_DOWNLOAD: {
|
||||
LED_B_ON();
|
||||
|
||||
size_t offset = packet->oldarg[0];
|
||||
size_t count = packet->oldarg[1];
|
||||
uint32_t flags = packet->oldarg[2];
|
||||
|
||||
bool isok = true;
|
||||
uint8_t *base = NULL;
|
||||
|
||||
bool raw_address_mode = (flags & CMD_READ_MEM_DOWNLOAD_RAW) != 0;
|
||||
if (!raw_address_mode) {
|
||||
|
||||
base = (uint8_t *) _flash_start;
|
||||
|
||||
size_t flash_size = get_flash_size();
|
||||
|
||||
// Boundary check the offset.
|
||||
if (offset > flash_size) {
|
||||
isok = false;
|
||||
Dbprintf("reading mcu flash failed :: | out of bounds, offset %u count %u", offset, count);
|
||||
}
|
||||
|
||||
// Clip the length if it goes past the end of the flash memory.
|
||||
count = MIN(count, flash_size - offset);
|
||||
|
||||
} else {
|
||||
// Allow reading from any memory address and length in special 'raw' mode.
|
||||
base = NULL;
|
||||
}
|
||||
|
||||
if (isok) {
|
||||
for (size_t pos = 0; pos < count; pos += PM3_CMD_DATA_SIZE) {
|
||||
size_t len = MIN((count - pos), PM3_CMD_DATA_SIZE);
|
||||
isok = 0 == reply_old(CMD_READ_MEM_DOWNLOADED, pos, len, 0, &base[offset + pos], len);
|
||||
if (!isok) {
|
||||
Dbprintf("transfer to client failed :: | pos %u len %u", pos, len);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
reply_old(CMD_ACK, 1, 0, 0, 0, 0);
|
||||
LED_B_OFF();
|
||||
break;
|
||||
}
|
||||
#ifdef WITH_FLASH
|
||||
case CMD_SPIFFS_TEST: {
|
||||
test_spiffs();
|
||||
|
|
|
@ -321,3 +321,34 @@ bool data_available_fast(void) {
|
|||
return usb_available_length();
|
||||
#endif
|
||||
}
|
||||
|
||||
uint32_t flash_size_from_cidr(uint32_t cidr) {
|
||||
uint8_t nvpsiz = (cidr & 0xF00) >> 8;
|
||||
switch (nvpsiz) {
|
||||
case 0:
|
||||
return 0;
|
||||
case 1:
|
||||
return 8*1024;
|
||||
case 2:
|
||||
return 16*1024;
|
||||
case 3:
|
||||
return 32*1024;
|
||||
case 5:
|
||||
return 64*1024;
|
||||
case 7:
|
||||
return 128*1024;
|
||||
case 9:
|
||||
return 256*1024;
|
||||
case 10:
|
||||
return 512*1024;
|
||||
case 12:
|
||||
return 1024*1024;
|
||||
case 14:
|
||||
default: // for 'reserved' values, guess 2MB
|
||||
return 2048*1024;
|
||||
}
|
||||
}
|
||||
|
||||
uint32_t get_flash_size(void) {
|
||||
return flash_size_from_cidr(*AT91C_DBGU_CIDR);
|
||||
}
|
||||
|
|
|
@ -103,4 +103,7 @@ int BUTTON_HELD(int ms);
|
|||
bool data_available(void);
|
||||
bool data_available_fast(void);
|
||||
|
||||
uint32_t flash_size_from_cidr(uint32_t cidr);
|
||||
uint32_t get_flash_size(void);
|
||||
|
||||
#endif
|
||||
|
|
|
@ -89,6 +89,37 @@ static void Fatal(void) {
|
|||
for (;;) {};
|
||||
}
|
||||
|
||||
static uint32_t flash_size_from_cidr(uint32_t cidr) {
|
||||
uint8_t nvpsiz = (cidr & 0xF00) >> 8;
|
||||
switch (nvpsiz) {
|
||||
case 0:
|
||||
return 0;
|
||||
case 1:
|
||||
return 8*1024;
|
||||
case 2:
|
||||
return 16*1024;
|
||||
case 3:
|
||||
return 32*1024;
|
||||
case 5:
|
||||
return 64*1024;
|
||||
case 7:
|
||||
return 128*1024;
|
||||
case 9:
|
||||
return 256*1024;
|
||||
case 10:
|
||||
return 512*1024;
|
||||
case 12:
|
||||
return 1024*1024;
|
||||
case 14:
|
||||
default: // for 'reserved' values, guess 2MB
|
||||
return 2048*1024;
|
||||
}
|
||||
}
|
||||
|
||||
static uint32_t get_flash_size(void) {
|
||||
return flash_size_from_cidr(*AT91C_DBGU_CIDR);
|
||||
}
|
||||
|
||||
static void UsbPacketReceived(uint8_t *packet) {
|
||||
bool ack = true;
|
||||
PacketCommandOLD *c = (PacketCommandOLD *)packet;
|
||||
|
@ -104,7 +135,8 @@ static void UsbPacketReceived(uint8_t *packet) {
|
|||
DEVICE_INFO_FLAG_CURRENT_MODE_BOOTROM |
|
||||
DEVICE_INFO_FLAG_UNDERSTANDS_START_FLASH |
|
||||
DEVICE_INFO_FLAG_UNDERSTANDS_CHIP_INFO |
|
||||
DEVICE_INFO_FLAG_UNDERSTANDS_VERSION;
|
||||
DEVICE_INFO_FLAG_UNDERSTANDS_VERSION |
|
||||
DEVICE_INFO_FLAG_UNDERSTANDS_READ_MEM;
|
||||
if (g_common_area.flags.osimage_present)
|
||||
arg0 |= DEVICE_INFO_FLAG_OSIMAGE_PRESENT;
|
||||
|
||||
|
@ -126,6 +158,54 @@ static void UsbPacketReceived(uint8_t *packet) {
|
|||
}
|
||||
break;
|
||||
|
||||
case CMD_READ_MEM_DOWNLOAD: {
|
||||
ack = false;
|
||||
LED_B_ON();
|
||||
|
||||
size_t offset = (size_t) c->arg[0];
|
||||
size_t count = (size_t) c->arg[1];
|
||||
uint32_t flags = (uint32_t) c->arg[2];
|
||||
|
||||
bool isok = true;
|
||||
uint8_t *base = NULL;
|
||||
|
||||
bool raw_address_mode = (flags & CMD_READ_MEM_DOWNLOAD_RAW) != 0;
|
||||
if (!raw_address_mode) {
|
||||
|
||||
base = (uint8_t *) _flash_start;
|
||||
|
||||
size_t flash_size = get_flash_size();
|
||||
|
||||
// Boundary check the offset.
|
||||
if (offset > flash_size)
|
||||
isok = false;
|
||||
|
||||
// Clip the length if it goes past the end of the flash memory.
|
||||
count = MIN(count, flash_size - offset);
|
||||
|
||||
} else {
|
||||
// Allow reading from any memory address and length in special 'raw' mode.
|
||||
base = NULL;
|
||||
}
|
||||
|
||||
if (isok) {
|
||||
for (size_t pos = 0; pos < count; pos += PM3_CMD_DATA_SIZE) {
|
||||
size_t len = MIN((count - pos), PM3_CMD_DATA_SIZE);
|
||||
isok = 0 == reply_old(CMD_READ_MEM_DOWNLOADED, pos, len, 0, &base[offset + pos], len);
|
||||
if (!isok)
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (isok)
|
||||
reply_old(CMD_ACK, 1, 0, 0, 0, 0);
|
||||
else
|
||||
reply_old(CMD_NACK, 0, 0, 0, 0, 0);
|
||||
|
||||
LED_B_OFF();
|
||||
break;
|
||||
}
|
||||
|
||||
case CMD_FINISH_WRITE: {
|
||||
#if defined ICOPYX
|
||||
if (c->arg[1] == 0xff && c->arg[2] == 0x1fd) {
|
||||
|
|
|
@ -633,20 +633,63 @@ static int CmdLCDReset(const char *Cmd) {
|
|||
static int CmdReadmem(const char *Cmd) {
|
||||
CLIParserContext *ctx;
|
||||
CLIParserInit(&ctx, "hw readmem",
|
||||
"Read memory at decimal address from ARM chip flash.",
|
||||
"hw readmem -a 10000"
|
||||
"Reads processor flash memory into a file or views on console",
|
||||
"hw readmem -f myfile -> save 512KB processor flash memory to file\n"
|
||||
"hw readmem -a 8192 -l 512 -> display 512 bytes from offset 8192\n"
|
||||
);
|
||||
|
||||
void *argtable[] = {
|
||||
arg_param_begin,
|
||||
arg_u64_1("a", "adr", "<dec>", "address to read"),
|
||||
arg_int0("a", "adr", "<dec>", "flash address to start reading from"),
|
||||
arg_int0("l", "len", "<dec>", "length (default 32 or 512KB)"),
|
||||
arg_str0("f", "file", "<fn>", "save to file"),
|
||||
arg_int0("c", "cols", "<dec>", "column breaks"),
|
||||
arg_lit0("r", "raw", "use raw address mode: read from anywhere, not just flash"),
|
||||
arg_param_end
|
||||
};
|
||||
CLIExecWithReturn(ctx, Cmd, argtable, true);
|
||||
uint32_t address = arg_get_u32(ctx, 1);
|
||||
CLIExecWithReturn(ctx, Cmd, argtable, false);
|
||||
|
||||
// check for -file option first to determine the output mode
|
||||
int fnlen = 0;
|
||||
char filename[FILE_PATH_SIZE] = {0};
|
||||
CLIParamStrToBuf(arg_get_str(ctx, 3), (uint8_t *)filename, FILE_PATH_SIZE, &fnlen);
|
||||
bool save_to_file = fnlen > 0;
|
||||
|
||||
// default len to 512KB when saving to file, to 32 bytes when viewing on the console.
|
||||
uint32_t default_len = save_to_file ? 512*1024 : 32;
|
||||
|
||||
uint32_t address = arg_get_u32_def(ctx, 1, 0);
|
||||
uint32_t len = arg_get_u32_def(ctx, 2, default_len);
|
||||
int breaks = arg_get_int_def(ctx, 4, 32);
|
||||
bool raw = arg_get_lit(ctx, 5);
|
||||
CLIParserFree(ctx);
|
||||
clearCommandBuffer();
|
||||
SendCommandNG(CMD_READ_MEM, (uint8_t *)&address, sizeof(address));
|
||||
|
||||
uint8_t *buffer = calloc(len, sizeof(uint8_t));
|
||||
if (!buffer) {
|
||||
PrintAndLogEx(ERR, "error, cannot allocate memory ");
|
||||
return PM3_EMALLOC;
|
||||
}
|
||||
|
||||
const char *flash_str = raw ? "" : " flash";
|
||||
PrintAndLogEx(INFO, "reading "_YELLOW_("%u")" bytes from processor%s memory",
|
||||
len, flash_str);
|
||||
|
||||
DeviceMemType_t type = raw ? MCU_MEM : MCU_FLASH;
|
||||
if (!GetFromDevice(type, buffer, len, address, NULL, 0, NULL, -1, true)) {
|
||||
PrintAndLogEx(FAILED, "ERROR; reading from MCU flash memory");
|
||||
free(buffer);
|
||||
return PM3_EFLASH;
|
||||
}
|
||||
|
||||
if (save_to_file) {
|
||||
PrintAndLogEx(INFO, "saving to "_YELLOW_("%s"), filename);
|
||||
saveFile(filename, ".bin", buffer, len);
|
||||
} else {
|
||||
PrintAndLogEx(INFO, "---- " _CYAN_("processor%s memory") " ----", flash_str);
|
||||
print_hex_break(buffer, len, breaks);
|
||||
}
|
||||
|
||||
free(buffer);
|
||||
return PM3_SUCCESS;
|
||||
}
|
||||
|
||||
|
@ -1150,7 +1193,7 @@ static command_t CommandTable[] = {
|
|||
{"lcd", CmdLCD, IfPm3Lcd, "Send command/data to LCD"},
|
||||
{"lcdreset", CmdLCDReset, IfPm3Lcd, "Hardware reset LCD"},
|
||||
{"ping", CmdPing, IfPm3Present, "Test if the Proxmark3 is responsive"},
|
||||
{"readmem", CmdReadmem, IfPm3Present, "Read memory at decimal address from flash"},
|
||||
{"readmem", CmdReadmem, IfPm3Present, "Read from processor flash"},
|
||||
{"reset", CmdReset, IfPm3Present, "Reset the Proxmark3"},
|
||||
{"setlfdivisor", CmdSetDivisor, IfPm3Present, "Drive LF antenna at 12MHz / (divisor + 1)"},
|
||||
{"setmux", CmdSetMux, IfPm3Present, "Set the ADC mux to a specific value"},
|
||||
|
|
|
@ -1134,6 +1134,12 @@ bool GetFromDevice(DeviceMemType_t memtype, uint8_t *dest, uint32_t bytes, uint3
|
|||
SendCommandNG(CMD_FPGAMEM_DOWNLOAD, NULL, 0);
|
||||
return dl_it(dest, bytes, response, ms_timeout, show_warning, CMD_FPGAMEM_DOWNLOADED);
|
||||
}
|
||||
case MCU_FLASH:
|
||||
case MCU_MEM: {
|
||||
uint32_t flags = memtype == MCU_MEM ? CMD_READ_MEM_DOWNLOAD_RAW : 0;
|
||||
SendCommandBL(CMD_READ_MEM_DOWNLOAD, start_index, bytes, flags, NULL, 0);
|
||||
return dl_it(dest, bytes, response, ms_timeout, show_warning, CMD_READ_MEM_DOWNLOADED);
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
|
|
@ -54,6 +54,8 @@ typedef enum {
|
|||
SIM_MEM,
|
||||
SPIFFS,
|
||||
FPGA_MEM,
|
||||
MCU_FLASH,
|
||||
MCU_MEM,
|
||||
} DeviceMemType_t;
|
||||
|
||||
typedef enum {
|
||||
|
|
|
@ -636,6 +636,11 @@ static void show_help(bool showFullHelp, char *exec_name) {
|
|||
PrintAndLogEx(NORMAL, " --unlock-bootloader Enable flashing of bootloader area *DANGEROUS* (need --flash)");
|
||||
PrintAndLogEx(NORMAL, " --force Enable flashing even if firmware seems to not match client version");
|
||||
PrintAndLogEx(NORMAL, " --image <imagefile> image to flash. Can be specified several times.");
|
||||
PrintAndLogEx(NORMAL, "\nOptions in memory dump mode:");
|
||||
PrintAndLogEx(NORMAL, " --dumpmem <dumpfile> dumps Proxmark3 flash memory to file");
|
||||
PrintAndLogEx(NORMAL, " --dumpaddr <address> starting address for dump, default 0");
|
||||
PrintAndLogEx(NORMAL, " --dumplen <length> number of bytes to dump, default 512KB");
|
||||
PrintAndLogEx(NORMAL, " --dumpraw raw address mode: dump from anywhere, not just flash");
|
||||
PrintAndLogEx(NORMAL, "\nExamples:");
|
||||
PrintAndLogEx(NORMAL, "\n to run Proxmark3 client:\n");
|
||||
PrintAndLogEx(NORMAL, " %s "SERIAL_PORT_EXAMPLE_H" -- runs the pm3 client", exec_name);
|
||||
|
@ -660,6 +665,109 @@ static void show_help(bool showFullHelp, char *exec_name) {
|
|||
}
|
||||
}
|
||||
|
||||
static int dumpmem_to_file(const char *filename, uint32_t addr, uint32_t len, bool raw, bool in_bootloader) {
|
||||
int res = PM3_EUNDEF;
|
||||
|
||||
uint8_t *buffer = calloc(len, sizeof(uint8_t));
|
||||
if (!buffer) {
|
||||
PrintAndLogEx(ERR, "error, cannot allocate memory ");
|
||||
res = PM3_EMALLOC;
|
||||
goto fail;
|
||||
}
|
||||
|
||||
size_t read = 0;
|
||||
DeviceMemType_t type = raw ? MCU_MEM : MCU_FLASH;
|
||||
if (GetFromDevice(type, buffer, len, addr, NULL, 0, NULL, 1000, true)) {
|
||||
res = PM3_SUCCESS;
|
||||
read = len; // GetFromDevice does not report the actual number of bytes received.
|
||||
}
|
||||
|
||||
if (res == PM3_SUCCESS) {
|
||||
FILE *fd = fopen(filename, "wb");
|
||||
if (!fd) {
|
||||
PrintAndLogEx(ERR, _RED_("Could not open file") " %s >>> ", filename);
|
||||
res = PM3_EFILE;
|
||||
goto fail2;
|
||||
}
|
||||
fwrite(buffer, 1, read, fd);
|
||||
fclose(fd);
|
||||
}
|
||||
|
||||
fail2:
|
||||
free(buffer);
|
||||
fail:
|
||||
return res;
|
||||
}
|
||||
|
||||
static int dumpmem_pm3(char *serial_port_name, const char *filename, uint32_t addr, uint32_t len, bool raw) {
|
||||
int ret = PM3_EUNDEF;
|
||||
bool in_bootloader = false;
|
||||
|
||||
if (serial_port_name == NULL) {
|
||||
PrintAndLogEx(ERR, "You must specify a port.\n");
|
||||
return PM3_EINVARG;
|
||||
}
|
||||
|
||||
if (OpenProxmark(&g_session.current_device, serial_port_name, true, 60, true, FLASHMODE_SPEED)) {
|
||||
PrintAndLogEx(NORMAL, _GREEN_(" found"));
|
||||
msleep(200);
|
||||
} else {
|
||||
PrintAndLogEx(ERR, "Could not find Proxmark3 on " _RED_("%s") ".\n", serial_port_name);
|
||||
ret = PM3_ETIMEOUT;
|
||||
goto finish;
|
||||
}
|
||||
|
||||
// Determine if we're talking to a bootloader or main firmware.
|
||||
SendCommandBL(CMD_DEVICE_INFO, 0, 0, 0, NULL, 0);
|
||||
PacketResponseNG resp;
|
||||
if (WaitForResponseTimeout(CMD_UNKNOWN, &resp, 1000) == false) {
|
||||
PrintAndLogEx(ERR, "Could not get device info.");
|
||||
goto finish2;
|
||||
}
|
||||
uint32_t dev_info = resp.oldarg[0];
|
||||
in_bootloader = (dev_info & DEVICE_INFO_FLAG_CURRENT_MODE_BOOTROM) != 0;
|
||||
if (in_bootloader) {
|
||||
if ((dev_info & DEVICE_INFO_FLAG_UNDERSTANDS_READ_MEM) != 0) {
|
||||
PrintAndLogEx(INFO, "Device is running the bootloader.");
|
||||
}
|
||||
else {
|
||||
PrintAndLogEx(ERR, "Device is running the bootloader, but the bootloader"
|
||||
" doesn't understand the READ MEM command.");
|
||||
goto finish2;
|
||||
}
|
||||
}
|
||||
|
||||
PrintAndLogEx(SUCCESS,"Dump requested from address "_YELLOW_("%u")", length "_YELLOW_("%u")"%s.",
|
||||
addr, len, raw ? ", in raw address mode" : "");
|
||||
|
||||
PrintAndLogEx(SUCCESS, _CYAN_("Memory dumping to file..."));
|
||||
ret = dumpmem_to_file(filename, addr, len, raw, in_bootloader);
|
||||
if (ret != PM3_SUCCESS) {
|
||||
goto finish2;
|
||||
}
|
||||
PrintAndLogEx(NORMAL, "");
|
||||
|
||||
finish2:
|
||||
clearCommandBuffer();
|
||||
if (in_bootloader) {
|
||||
g_session.current_device->g_conn->run = false;
|
||||
SendCommandOLD(CMD_PING, 0, 0, 0, NULL, 0);
|
||||
} else {
|
||||
SendCommandNG(CMD_QUIT_SESSION, NULL, 0);
|
||||
msleep(100);
|
||||
}
|
||||
CloseProxmark(g_session.current_device);
|
||||
|
||||
finish:
|
||||
if (ret == PM3_SUCCESS)
|
||||
PrintAndLogEx(SUCCESS, _CYAN_("All done"));
|
||||
else if (ret == PM3_EOPABORTED)
|
||||
PrintAndLogEx(FAILED, "Aborted by user");
|
||||
else
|
||||
PrintAndLogEx(ERR, "Aborted on error %u", ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int flash_pm3(char *serial_port_name, uint8_t num_files, const char *filenames[FLASH_MAX_FILES], bool can_write_bl, bool force) {
|
||||
|
||||
int ret = PM3_EUNDEF;
|
||||
|
@ -812,6 +920,11 @@ int main(int argc, char *argv[]) {
|
|||
bool debug_mode_forced = false;
|
||||
int flash_num_files = 0;
|
||||
const char *flash_filenames[FLASH_MAX_FILES];
|
||||
bool dumpmem_mode = false;
|
||||
const char *dumpmem_filename = NULL;
|
||||
uint32_t dumpmem_addr = 0;
|
||||
uint32_t dumpmem_len = 512*1024;
|
||||
bool dumpmem_raw = false;
|
||||
|
||||
// color management:
|
||||
// 1. default = no color
|
||||
|
@ -1013,6 +1126,44 @@ int main(int argc, char *argv[]) {
|
|||
continue;
|
||||
}
|
||||
|
||||
// go to dump mode
|
||||
if (strcmp(argv[i], "--dumpmem") == 0) {
|
||||
dumpmem_mode = true;
|
||||
if (i + 1 == argc) {
|
||||
PrintAndLogEx(ERR, _RED_("ERROR:") " missing file specification after --dumpmem\n");
|
||||
show_help(false, exec_name);
|
||||
return 1;
|
||||
}
|
||||
dumpmem_filename = argv[++i];
|
||||
continue;
|
||||
}
|
||||
if (strcmp(argv[i], "--dumpaddr") == 0) {
|
||||
if (i + 1 == argc) {
|
||||
PrintAndLogEx(ERR, _RED_("ERROR:") " missing address specification after -dumpaddr\n");
|
||||
show_help(false, exec_name);
|
||||
return 1;
|
||||
}
|
||||
uint32_t tmpaddr = strtol(argv[i + 1], NULL, 10);
|
||||
dumpmem_addr = tmpaddr;
|
||||
i++;
|
||||
continue;
|
||||
}
|
||||
if (strcmp(argv[i], "--dumplen") == 0) {
|
||||
if (i + 1 == argc) {
|
||||
PrintAndLogEx(ERR, _RED_("ERROR:") " missing address specification after -dumplen\n");
|
||||
show_help(false, exec_name);
|
||||
return 1;
|
||||
}
|
||||
uint32_t tmplen = strtol(argv[i + 1], NULL, 10);
|
||||
dumpmem_len = tmplen;
|
||||
i++;
|
||||
continue;
|
||||
}
|
||||
if (strcmp(argv[i], "--dumpraw") == 0) {
|
||||
dumpmem_raw = true;
|
||||
continue;
|
||||
}
|
||||
|
||||
// go to flash mode
|
||||
if (strcmp(argv[i], "--flash") == 0) {
|
||||
flash_mode = true;
|
||||
|
@ -1094,6 +1245,11 @@ int main(int argc, char *argv[]) {
|
|||
if (speed == 0)
|
||||
speed = USART_BAUD_RATE;
|
||||
|
||||
if (dumpmem_mode) {
|
||||
dumpmem_pm3(port, dumpmem_filename, dumpmem_addr, dumpmem_len, dumpmem_raw);
|
||||
exit(EXIT_SUCCESS);
|
||||
}
|
||||
|
||||
if (flash_mode) {
|
||||
flash_pm3(port, flash_num_files, flash_filenames, flash_can_write_bl, flash_force);
|
||||
exit(EXIT_SUCCESS);
|
||||
|
@ -1148,7 +1304,7 @@ int main(int argc, char *argv[]) {
|
|||
}
|
||||
|
||||
// ascii art only in interactive client
|
||||
if (!script_cmds_file && !script_cmd && g_session.stdinOnTTY && g_session.stdoutOnTTY && !flash_mode && !reboot_bootloader_mode) {
|
||||
if (!script_cmds_file && !script_cmd && g_session.stdinOnTTY && g_session.stdoutOnTTY && !dumpmem_mode && !flash_mode && !reboot_bootloader_mode) {
|
||||
showBanner();
|
||||
}
|
||||
|
||||
|
|
|
@ -798,7 +798,7 @@ Check column "offline" for their availability.
|
|||
|`hw lcd `|N |`Send command/data to LCD`
|
||||
|`hw lcdreset `|N |`Hardware reset LCD`
|
||||
|`hw ping `|N |`Test if the Proxmark3 is responsive`
|
||||
|`hw readmem `|N |`Read memory at decimal address from flash`
|
||||
|`hw readmem `|N |`Read from processor flash`
|
||||
|`hw reset `|N |`Reset the Proxmark3`
|
||||
|`hw setlfdivisor `|N |`Drive LF antenna at 12MHz / (divisor + 1)`
|
||||
|`hw setmux `|N |`Set the ADC mux to a specific value`
|
||||
|
|
|
@ -379,7 +379,9 @@ typedef struct {
|
|||
#define CMD_LCD_RESET 0x0103
|
||||
#define CMD_LCD 0x0104
|
||||
#define CMD_BUFF_CLEAR 0x0105
|
||||
#define CMD_READ_MEM 0x0106
|
||||
#define CMD_READ_MEM 0x0106 // legacy
|
||||
#define CMD_READ_MEM_DOWNLOAD 0x010A
|
||||
#define CMD_READ_MEM_DOWNLOADED 0x010B
|
||||
#define CMD_VERSION 0x0107
|
||||
#define CMD_STATUS 0x0108
|
||||
#define CMD_PING 0x0109
|
||||
|
@ -880,6 +882,9 @@ typedef struct {
|
|||
/* Set if this device understands the version command */
|
||||
#define DEVICE_INFO_FLAG_UNDERSTANDS_VERSION (1<<6)
|
||||
|
||||
/* Set if this device understands the read memory command */
|
||||
#define DEVICE_INFO_FLAG_UNDERSTANDS_READ_MEM (1<<7)
|
||||
|
||||
#define BL_VERSION_MAJOR(version) ((uint32_t)(version) >> 22)
|
||||
#define BL_VERSION_MINOR(version) (((uint32_t)(version) >> 12) & 0x3ff)
|
||||
#define BL_VERSION_PATCH(version) ((uint32_t)(version) & 0xfff)
|
||||
|
@ -891,6 +896,8 @@ typedef struct {
|
|||
// Different versions here. Each version should increase the numbers
|
||||
#define BL_VERSION_1_0_0 BL_MAKE_VERSION(1, 0, 0)
|
||||
|
||||
/* CMD_READ_MEM_DOWNLOAD flags */
|
||||
#define CMD_READ_MEM_DOWNLOAD_RAW (1<<0)
|
||||
|
||||
/* CMD_START_FLASH may have three arguments: start of area to flash,
|
||||
end of area to flash, optional magic.
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue