mirror of
https://github.com/RfidResearchGroup/proxmark3.git
synced 2025-08-21 13:53:55 -07:00
Merge pull request #1914 from henrygab/serial_from_flash_uniqueid
Use unique USB Serial using flash's uniqueID
This commit is contained in:
commit
21ab53c7cf
15 changed files with 618 additions and 493 deletions
|
@ -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]
|
||||
- Enable unique USB serial numbers when built with `FLASH` -- **_UPDATES BOOTROM ALSO_**
|
||||
- Changed the readline package to v8.2 in the CMAKE files for the client (@iceman1001)
|
||||
- Add ICECLASS standalone read/sim mode (@natesales)
|
||||
- Added verbose flag to `hf iclass encode` (@natesales)
|
||||
|
|
|
@ -5,6 +5,8 @@ PLATFORM=PM3RDV4
|
|||
#PLATFORM=PM3GENERIC
|
||||
# If you want more than one PLATFORM_EXTRAS option, separate them by spaces:
|
||||
#PLATFORM_EXTRAS=BTADDON
|
||||
#PLATFORM_EXTRAS=FLASH
|
||||
#PLATFORM_EXTRAS=BTADDON FLASH
|
||||
#STANDALONE=LF_SAMYRUN
|
||||
|
||||
# Uncomment the lines below in order to make a 256KB image
|
||||
|
|
|
@ -2471,8 +2471,11 @@ static void PacketReceived(PacketCommandNG *packet) {
|
|||
LED_B_OFF();
|
||||
break;
|
||||
}
|
||||
if (page < 3)
|
||||
if (page < 3) {
|
||||
isok = Flash_WipeMemoryPage(page);
|
||||
// let spiffs check and update its info post flash erase
|
||||
rdv40_spiffs_check();
|
||||
}
|
||||
|
||||
reply_mix(CMD_ACK, isok, 0, 0, 0, 0);
|
||||
LED_B_OFF();
|
||||
|
@ -2677,6 +2680,17 @@ void __attribute__((noreturn)) AppMain(void) {
|
|||
I2C_init(false);
|
||||
#endif
|
||||
|
||||
#ifdef WITH_FLASH
|
||||
if (FlashInit()) {
|
||||
uint64_t flash_uniqueID = 0;
|
||||
if (!Flash_CheckBusy(BUSY_TIMEOUT)) { // OK because firmware was built for devices with flash
|
||||
Flash_UniqueID((uint8_t *)(&flash_uniqueID));
|
||||
}
|
||||
FlashStop();
|
||||
usb_update_serial(flash_uniqueID);
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef WITH_FPC_USART
|
||||
usart_init(USART_BAUD_RATE, USART_PARITY);
|
||||
#endif
|
||||
|
|
|
@ -34,11 +34,17 @@ VERSIONSRC = version_pm3.c
|
|||
# THUMBSRC :=
|
||||
|
||||
# stdint.h provided locally until GCC 4.5 becomes C99 compliant
|
||||
APP_CFLAGS = -I. -ffunction-sections -fdata-sections
|
||||
APP_CFLAGS = -I. -ffunction-sections -fdata-sections -DAS_BOOTROM
|
||||
|
||||
# stack-protect , no-pie reduces size on Gentoo Hardened 8.2 gcc, no-common makes sure uninitialized vars don't end up in COMMON area
|
||||
APP_CFLAGS += -fno-stack-protector -fno-pie -fno-common
|
||||
|
||||
ifneq (,$(findstring WITH_FLASH,$(PLATFORM_DEFS)))
|
||||
APP_CFLAGS += -DWITH_FLASH
|
||||
APP_CFLAGS += -I../common_arm
|
||||
THUMBSRC += flashmem.c ticks.c
|
||||
endif
|
||||
|
||||
|
||||
# Do not move this inclusion before the definition of {THUMB,ASM,ARM}SRC
|
||||
include ../common_arm/Makefile.common
|
||||
|
|
|
@ -20,6 +20,10 @@
|
|||
#include "clocks.h"
|
||||
#include "usb_cdc.h"
|
||||
|
||||
#ifdef WITH_FLASH
|
||||
#include "flashmem.h"
|
||||
#endif
|
||||
|
||||
#include "proxmark3_arm.h"
|
||||
#define DEBUG 0
|
||||
|
||||
|
@ -214,8 +218,18 @@ static void flash_mode(void) {
|
|||
bootrom_unlocked = false;
|
||||
uint8_t rx[sizeof(PacketCommandOLD)];
|
||||
g_common_area.command = COMMON_AREA_COMMAND_NONE;
|
||||
if (!g_common_area.flags.button_pressed && BUTTON_PRESS())
|
||||
if (!g_common_area.flags.button_pressed && BUTTON_PRESS()) {
|
||||
g_common_area.flags.button_pressed = 1;
|
||||
}
|
||||
|
||||
#ifdef WITH_FLASH
|
||||
if (FlashInit()) { // checks for existence of flash also ... OK because bootrom was built for devices with flash
|
||||
uint64_t flash_uniqueID = 0;
|
||||
Flash_UniqueID((uint8_t *)&flash_uniqueID);
|
||||
FlashStop();
|
||||
usb_update_serial(flash_uniqueID);
|
||||
}
|
||||
#endif
|
||||
|
||||
usb_enable();
|
||||
|
||||
|
|
|
@ -53,6 +53,7 @@ SECTIONS
|
|||
*(.rodata.*)
|
||||
*(.data)
|
||||
*(.data.*)
|
||||
*(.ramfunc)
|
||||
. = ALIGN(4);
|
||||
} >ram AT>bootphase2 :phase2
|
||||
|
||||
|
|
|
@ -1407,7 +1407,7 @@ static int CmdHFiClassDecrypt(const char *Cmd) {
|
|||
case DES:
|
||||
case RFU:
|
||||
case None:
|
||||
// Nothing to do for None anyway...
|
||||
// Nothing to do for None anyway...
|
||||
default:
|
||||
continue;
|
||||
}
|
||||
|
|
|
@ -114,6 +114,10 @@ endif
|
|||
|
||||
# parsing additional PLATFORM_EXTRAS tokens
|
||||
PLATFORM_EXTRAS_TMP:=$(PLATFORM_EXTRAS)
|
||||
ifneq (,$(findstring FLASH,$(PLATFORM_EXTRAS_TMP)))
|
||||
PLATFORM_DEFS += -DWITH_FLASH
|
||||
PLATFORM_EXTRAS_TMP := $(strip $(filter-out FLASH,$(PLATFORM_EXTRAS_TMP)))
|
||||
endif
|
||||
ifneq (,$(findstring BTADDON,$(PLATFORM_EXTRAS_TMP)))
|
||||
PLATFORM_DEFS += -DWITH_FPC_USART_HOST
|
||||
PLATFORM_EXTRAS_TMP := $(strip $(filter-out BTADDON,$(PLATFORM_EXTRAS_TMP)))
|
||||
|
|
|
@ -20,9 +20,13 @@
|
|||
|
||||
#include "proxmark3_arm.h"
|
||||
#include "ticks.h"
|
||||
|
||||
#ifndef AS_BOOTROM
|
||||
#include "dbprint.h"
|
||||
#endif // AS_BOOTROM
|
||||
|
||||
#include "string.h"
|
||||
#include "spiffs.h"
|
||||
#include "usb_cdc.h"
|
||||
|
||||
/* here: use NCPS2 @ PA10: */
|
||||
#define SPI_CSR_NUM 2
|
||||
|
@ -37,11 +41,378 @@
|
|||
static uint32_t FLASHMEM_SPIBAUDRATE = FLASH_BAUD;
|
||||
#define FASTFLASH (FLASHMEM_SPIBAUDRATE > FLASH_MINFAST)
|
||||
|
||||
#ifndef AS_BOOTROM
|
||||
|
||||
void FlashmemSetSpiBaudrate(uint32_t baudrate) {
|
||||
FLASHMEM_SPIBAUDRATE = baudrate;
|
||||
Dbprintf("Spi Baudrate : %dMHz", FLASHMEM_SPIBAUDRATE / 1000000);
|
||||
}
|
||||
|
||||
// read ID out
|
||||
bool Flash_ReadID_90(flash_device_type_90_t *result) {
|
||||
|
||||
if (Flash_CheckBusy(BUSY_TIMEOUT)) return false;
|
||||
|
||||
// Manufacture ID / device ID
|
||||
FlashSendByte(ID);
|
||||
FlashSendByte(0x00);
|
||||
FlashSendByte(0x00);
|
||||
FlashSendByte(0x00);
|
||||
|
||||
result->manufacturer_id = FlashSendByte(0xFF);
|
||||
result->device_id = FlashSendLastByte(0xFF);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
uint16_t Flash_ReadData(uint32_t address, uint8_t *out, uint16_t len) {
|
||||
|
||||
if (!FlashInit()) return 0;
|
||||
|
||||
// length should never be zero
|
||||
if (!len || Flash_CheckBusy(BUSY_TIMEOUT)) return 0;
|
||||
|
||||
uint8_t cmd = (FASTFLASH) ? FASTREAD : READDATA;
|
||||
|
||||
FlashSendByte(cmd);
|
||||
Flash_TransferAdresse(address);
|
||||
|
||||
if (FASTFLASH) {
|
||||
FlashSendByte(DUMMYBYTE);
|
||||
}
|
||||
|
||||
uint16_t i = 0;
|
||||
for (; i < (len - 1); i++)
|
||||
out[i] = FlashSendByte(0xFF);
|
||||
|
||||
out[i] = FlashSendLastByte(0xFF);
|
||||
FlashStop();
|
||||
return len;
|
||||
}
|
||||
|
||||
void Flash_TransferAdresse(uint32_t address) {
|
||||
FlashSendByte((address >> 16) & 0xFF);
|
||||
FlashSendByte((address >> 8) & 0xFF);
|
||||
FlashSendByte((address >> 0) & 0xFF);
|
||||
}
|
||||
|
||||
/* This ensures we can ReadData without having to cycle through initialization every time */
|
||||
uint16_t Flash_ReadDataCont(uint32_t address, uint8_t *out, uint16_t len) {
|
||||
|
||||
// length should never be zero
|
||||
if (!len) return 0;
|
||||
|
||||
uint8_t cmd = (FASTFLASH) ? FASTREAD : READDATA;
|
||||
|
||||
FlashSendByte(cmd);
|
||||
Flash_TransferAdresse(address);
|
||||
|
||||
if (FASTFLASH) {
|
||||
FlashSendByte(DUMMYBYTE);
|
||||
}
|
||||
|
||||
uint16_t i = 0;
|
||||
for (; i < (len - 1); i++)
|
||||
out[i] = FlashSendByte(0xFF);
|
||||
|
||||
out[i] = FlashSendLastByte(0xFF);
|
||||
return len;
|
||||
}
|
||||
|
||||
////////////////////////////////////////
|
||||
// Write data can only program one page. A page has 256 bytes.
|
||||
// if len > 256, it might wrap around and overwrite pos 0.
|
||||
uint16_t Flash_WriteData(uint32_t address, uint8_t *in, uint16_t len) {
|
||||
|
||||
// length should never be zero
|
||||
if (!len)
|
||||
return 0;
|
||||
|
||||
// Max 256 bytes write
|
||||
if (((address & 0xFF) + len) > 256) {
|
||||
Dbprintf("Flash_WriteData 256 fail [ 0x%02x ] [ %u ]", (address & 0xFF) + len, len);
|
||||
return 0;
|
||||
}
|
||||
|
||||
// out-of-range
|
||||
if (((address >> 16) & 0xFF) > MAX_BLOCKS) {
|
||||
Dbprintf("Flash_WriteData, block out-of-range");
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (!FlashInit()) {
|
||||
if (g_dbglevel > 3) Dbprintf("Flash_WriteData init fail");
|
||||
return 0;
|
||||
}
|
||||
|
||||
Flash_CheckBusy(BUSY_TIMEOUT);
|
||||
|
||||
Flash_WriteEnable();
|
||||
|
||||
FlashSendByte(PAGEPROG);
|
||||
FlashSendByte((address >> 16) & 0xFF);
|
||||
FlashSendByte((address >> 8) & 0xFF);
|
||||
FlashSendByte((address >> 0) & 0xFF);
|
||||
|
||||
uint16_t i = 0;
|
||||
for (; i < (len - 1); i++)
|
||||
FlashSendByte(in[i]);
|
||||
|
||||
FlashSendLastByte(in[i]);
|
||||
|
||||
FlashStop();
|
||||
return len;
|
||||
}
|
||||
|
||||
// length should never be zero
|
||||
// Max 256 bytes write
|
||||
// out-of-range
|
||||
uint16_t Flash_WriteDataCont(uint32_t address, uint8_t *in, uint16_t len) {
|
||||
|
||||
if (!len)
|
||||
return 0;
|
||||
|
||||
if (((address & 0xFF) + len) > 256) {
|
||||
Dbprintf("Flash_WriteDataCont 256 fail [ 0x%02x ] [ %u ]", (address & 0xFF) + len, len);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (((address >> 16) & 0xFF) > MAX_BLOCKS) {
|
||||
Dbprintf("Flash_WriteDataCont, block out-of-range");
|
||||
return 0;
|
||||
}
|
||||
|
||||
FlashSendByte(PAGEPROG);
|
||||
FlashSendByte((address >> 16) & 0xFF);
|
||||
FlashSendByte((address >> 8) & 0xFF);
|
||||
FlashSendByte((address >> 0) & 0xFF);
|
||||
|
||||
uint16_t i = 0;
|
||||
for (; i < (len - 1); i++)
|
||||
FlashSendByte(in[i]);
|
||||
|
||||
FlashSendLastByte(in[i]);
|
||||
return len;
|
||||
}
|
||||
|
||||
// assumes valid start 256 based 00 address
|
||||
//
|
||||
uint16_t Flash_Write(uint32_t address, uint8_t *in, uint16_t len) {
|
||||
|
||||
bool isok;
|
||||
uint16_t res, bytes_sent = 0, bytes_remaining = len;
|
||||
uint8_t buf[FLASH_MEM_BLOCK_SIZE];
|
||||
while (bytes_remaining > 0) {
|
||||
|
||||
Flash_CheckBusy(BUSY_TIMEOUT);
|
||||
Flash_WriteEnable();
|
||||
|
||||
uint32_t bytes_in_packet = MIN(FLASH_MEM_BLOCK_SIZE, bytes_remaining);
|
||||
|
||||
memcpy(buf, in + bytes_sent, bytes_in_packet);
|
||||
|
||||
res = Flash_WriteDataCont(address + bytes_sent, buf, bytes_in_packet);
|
||||
|
||||
bytes_remaining -= bytes_in_packet;
|
||||
bytes_sent += bytes_in_packet;
|
||||
|
||||
isok = (res == bytes_in_packet);
|
||||
|
||||
if (!isok)
|
||||
goto out;
|
||||
}
|
||||
|
||||
out:
|
||||
FlashStop();
|
||||
return len;
|
||||
}
|
||||
|
||||
// WARNING -- if callers are using a file system (such as SPIFFS),
|
||||
// they should inform the file system of this change
|
||||
// e.g., rdv40_spiffs_check()
|
||||
bool Flash_WipeMemoryPage(uint8_t page) {
|
||||
if (!FlashInit()) {
|
||||
if (g_dbglevel > 3) Dbprintf("Flash_WriteData init fail");
|
||||
return false;
|
||||
}
|
||||
Flash_ReadStat1();
|
||||
|
||||
// Each block is 64Kb. One block erase takes 1s ( 1000ms )
|
||||
Flash_WriteEnable();
|
||||
Flash_Erase64k(page);
|
||||
Flash_CheckBusy(BUSY_TIMEOUT);
|
||||
|
||||
FlashStop();
|
||||
|
||||
return true;
|
||||
}
|
||||
// Wipes flash memory completely, fills with 0xFF
|
||||
bool Flash_WipeMemory(void) {
|
||||
if (!FlashInit()) {
|
||||
if (g_dbglevel > 3) Dbprintf("Flash_WriteData init fail");
|
||||
return false;
|
||||
}
|
||||
Flash_ReadStat1();
|
||||
|
||||
// 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);
|
||||
|
||||
FlashStop();
|
||||
return true;
|
||||
}
|
||||
|
||||
// enable the flash write
|
||||
void Flash_WriteEnable(void) {
|
||||
FlashSendLastByte(WRITEENABLE);
|
||||
if (g_dbglevel > 3) Dbprintf("Flash Write enabled");
|
||||
}
|
||||
|
||||
// erase 4K at one time
|
||||
// execution time: 0.8ms / 800us
|
||||
bool Flash_Erase4k(uint8_t block, uint8_t sector) {
|
||||
|
||||
if (block > MAX_BLOCKS || sector > MAX_SECTORS) return false;
|
||||
|
||||
FlashSendByte(SECTORERASE);
|
||||
FlashSendByte(block);
|
||||
FlashSendByte(sector << 4);
|
||||
FlashSendLastByte(00);
|
||||
return true;
|
||||
}
|
||||
|
||||
/*
|
||||
// erase 32K at one time
|
||||
// execution time: 0,3s / 300ms
|
||||
bool Flash_Erase32k(uint32_t address) {
|
||||
if (address & (32*1024 - 1)) {
|
||||
if ( g_dbglevel > 1 ) Dbprintf("Flash_Erase32k : Address is not align at 4096");
|
||||
return false;
|
||||
}
|
||||
FlashSendByte(BLOCK32ERASE);
|
||||
FlashSendByte((address >> 16) & 0xFF);
|
||||
FlashSendByte((address >> 8) & 0xFF);
|
||||
FlashSendLastByte((address >> 0) & 0xFF);
|
||||
return true;
|
||||
}
|
||||
*/
|
||||
|
||||
// erase 64k at one time
|
||||
// since a block is 64kb, and there is four blocks.
|
||||
// we only need block number, as MSB
|
||||
// execution time: 1s / 1000ms
|
||||
// 0x00 00 00 -- 0x 00 FF FF == block 0
|
||||
// 0x01 00 00 -- 0x 01 FF FF == block 1
|
||||
// 0x02 00 00 -- 0x 02 FF FF == block 2
|
||||
// 0x03 00 00 -- 0x 03 FF FF == block 3
|
||||
bool Flash_Erase64k(uint8_t block) {
|
||||
|
||||
if (block > MAX_BLOCKS) return false;
|
||||
|
||||
FlashSendByte(BLOCK64ERASE);
|
||||
FlashSendByte(block);
|
||||
FlashSendByte(0x00);
|
||||
FlashSendLastByte(0x00);
|
||||
return true;
|
||||
}
|
||||
|
||||
/*
|
||||
// Erase chip
|
||||
void Flash_EraseChip(void) {
|
||||
FlashSendLastByte(CHIPERASE);
|
||||
}
|
||||
*/
|
||||
|
||||
void Flashmem_print_status(void) {
|
||||
DbpString(_CYAN_("Flash memory"));
|
||||
Dbprintf(" Baudrate................ " _GREEN_("%d MHz"), FLASHMEM_SPIBAUDRATE / 1000000);
|
||||
|
||||
if (!FlashInit()) {
|
||||
DbpString(" Init.................... " _RED_("FAILED"));
|
||||
return;
|
||||
}
|
||||
DbpString(" Init.................... " _GREEN_("OK"));
|
||||
|
||||
// NOTE: It would likely be more useful to use JDEC ID command 9F,
|
||||
// as it provides a third byte indicative of capacity.
|
||||
flash_device_type_90_t device_type = {0};
|
||||
if (!Flash_ReadID_90(&device_type)) {
|
||||
DbpString(" Device ID............... " _RED_(" --> Not Found <--"));
|
||||
} else {
|
||||
if ((device_type.manufacturer_id == WINBOND_MANID) && (device_type.device_id == WINBOND_DEVID)) {
|
||||
DbpString(" Memory size............. " _GREEN_("2 mbits / 256 kb"));
|
||||
} else {
|
||||
Dbprintf(" Device ID............... " _YELLOW_("%02X / %02X (unknown)"),
|
||||
device_type.manufacturer_id, device_type.device_id);
|
||||
}
|
||||
}
|
||||
|
||||
uint8_t uid[8] = {0, 0, 0, 0, 0, 0, 0, 0};
|
||||
Flash_UniqueID(uid);
|
||||
Dbprintf(" Unique ID (be).......... " _YELLOW_("0x%02X%02X%02X%02X%02X%02X%02X%02X"),
|
||||
uid[0], uid[1], uid[2], uid[3],
|
||||
uid[4], uid[5], uid[6], uid[7]
|
||||
);
|
||||
if (g_dbglevel > 3) {
|
||||
Dbprintf(" Unique ID (le).......... " _YELLOW_("0x%02X%02X%02X%02X%02X%02X%02X%02X"),
|
||||
uid[7], uid[6], uid[5], uid[4],
|
||||
uid[3], uid[2], uid[1], uid[0]
|
||||
);
|
||||
}
|
||||
FlashStop();
|
||||
}
|
||||
|
||||
void Flashmem_print_info(void) {
|
||||
|
||||
if (!FlashInit()) return;
|
||||
|
||||
DbpString(_CYAN_("Flash memory dictionary loaded"));
|
||||
|
||||
// load dictionary offsets.
|
||||
uint8_t keysum[2];
|
||||
uint16_t num;
|
||||
|
||||
Flash_CheckBusy(BUSY_TIMEOUT);
|
||||
uint16_t isok = Flash_ReadDataCont(DEFAULT_MF_KEYS_OFFSET, keysum, 2);
|
||||
if (isok == 2) {
|
||||
num = ((keysum[1] << 8) | keysum[0]);
|
||||
if (num != 0xFFFF && num != 0x0)
|
||||
Dbprintf(" Mifare.................. "_YELLOW_("%d")" / "_GREEN_("%d")" keys", num, DEFAULT_MF_KEYS_MAX);
|
||||
}
|
||||
|
||||
Flash_CheckBusy(BUSY_TIMEOUT);
|
||||
isok = Flash_ReadDataCont(DEFAULT_T55XX_KEYS_OFFSET, keysum, 2);
|
||||
if (isok == 2) {
|
||||
num = ((keysum[1] << 8) | keysum[0]);
|
||||
if (num != 0xFFFF && num != 0x0)
|
||||
Dbprintf(" T55x7................... "_YELLOW_("%d")" / "_GREEN_("%d")" keys", num, DEFAULT_T55XX_KEYS_MAX);
|
||||
}
|
||||
|
||||
Flash_CheckBusy(BUSY_TIMEOUT);
|
||||
isok = Flash_ReadDataCont(DEFAULT_ICLASS_KEYS_OFFSET, keysum, 2);
|
||||
if (isok == 2) {
|
||||
num = ((keysum[1] << 8) | keysum[0]);
|
||||
if (num != 0xFFFF && num != 0x0)
|
||||
Dbprintf(" iClass.................. "_YELLOW_("%d")" / "_GREEN_("%d")" keys", num, DEFAULT_ICLASS_KEYS_MAX);
|
||||
}
|
||||
|
||||
FlashStop();
|
||||
}
|
||||
|
||||
#endif // #ifndef AS_BOOTROM
|
||||
|
||||
|
||||
// initialize
|
||||
bool FlashInit(void) {
|
||||
FlashSetup(FLASHMEM_SPIBAUDRATE);
|
||||
|
@ -56,6 +427,52 @@ bool FlashInit(void) {
|
|||
return true;
|
||||
}
|
||||
|
||||
// read unique id for chip.
|
||||
void Flash_UniqueID(uint8_t *uid) {
|
||||
|
||||
if (Flash_CheckBusy(BUSY_TIMEOUT)) return;
|
||||
|
||||
// reading unique serial number
|
||||
FlashSendByte(UNIQUE_ID);
|
||||
FlashSendByte(0xFF);
|
||||
FlashSendByte(0xFF);
|
||||
FlashSendByte(0xFF);
|
||||
FlashSendByte(0xFF);
|
||||
|
||||
uid[7] = FlashSendByte(0xFF);
|
||||
uid[6] = FlashSendByte(0xFF);
|
||||
uid[5] = FlashSendByte(0xFF);
|
||||
uid[4] = FlashSendByte(0xFF);
|
||||
uid[3] = FlashSendByte(0xFF);
|
||||
uid[2] = FlashSendByte(0xFF);
|
||||
uid[1] = FlashSendByte(0xFF);
|
||||
uid[0] = FlashSendLastByte(0xFF);
|
||||
}
|
||||
|
||||
void FlashStop(void) {
|
||||
//Bof
|
||||
//* Reset all the Chip Select register
|
||||
AT91C_BASE_SPI->SPI_CSR[0] = 0;
|
||||
AT91C_BASE_SPI->SPI_CSR[1] = 0;
|
||||
AT91C_BASE_SPI->SPI_CSR[2] = 0;
|
||||
AT91C_BASE_SPI->SPI_CSR[3] = 0;
|
||||
|
||||
// Reset the SPI mode
|
||||
AT91C_BASE_SPI->SPI_MR = 0;
|
||||
|
||||
// Disable all interrupts
|
||||
AT91C_BASE_SPI->SPI_IDR = 0xFFFFFFFF;
|
||||
|
||||
// SPI disable
|
||||
AT91C_BASE_SPI->SPI_CR = AT91C_SPI_SPIDIS;
|
||||
|
||||
#ifndef AS_BOOTROM
|
||||
if (g_dbglevel > 3) Dbprintf("FlashStop");
|
||||
#endif // AS_BOOTROM
|
||||
|
||||
StopTicks();
|
||||
}
|
||||
|
||||
void FlashSetup(uint32_t baudrate) {
|
||||
//WDT_DISABLE
|
||||
AT91C_BASE_WDTC->WDTC_WDMR = AT91C_WDTC_WDDIS;
|
||||
|
@ -156,26 +573,32 @@ void FlashSetup(uint32_t baudrate) {
|
|||
if (AT91C_BASE_SPI->SPI_RDR == 0) {};
|
||||
}
|
||||
|
||||
void FlashStop(void) {
|
||||
//Bof
|
||||
//* Reset all the Chip Select register
|
||||
AT91C_BASE_SPI->SPI_CSR[0] = 0;
|
||||
AT91C_BASE_SPI->SPI_CSR[1] = 0;
|
||||
AT91C_BASE_SPI->SPI_CSR[2] = 0;
|
||||
AT91C_BASE_SPI->SPI_CSR[3] = 0;
|
||||
bool Flash_CheckBusy(uint32_t timeout) {
|
||||
WaitUS(WINBOND_WRITE_DELAY);
|
||||
StartCountUS();
|
||||
uint32_t _time = GetCountUS();
|
||||
|
||||
// Reset the SPI mode
|
||||
AT91C_BASE_SPI->SPI_MR = 0;
|
||||
#ifndef AS_BOOTROM
|
||||
if (g_dbglevel > 3) Dbprintf("Checkbusy in...");
|
||||
#endif // AS_BOOTROM
|
||||
|
||||
// Disable all interrupts
|
||||
AT91C_BASE_SPI->SPI_IDR = 0xFFFFFFFF;
|
||||
do {
|
||||
if (!(Flash_ReadStat1() & BUSY)) {
|
||||
return false;
|
||||
}
|
||||
} while ((GetCountUS() - _time) < timeout);
|
||||
|
||||
// SPI disable
|
||||
AT91C_BASE_SPI->SPI_CR = AT91C_SPI_SPIDIS;
|
||||
if (timeout <= (GetCountUS() - _time)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if (g_dbglevel > 3) Dbprintf("FlashStop");
|
||||
return false;
|
||||
}
|
||||
|
||||
StopTicks();
|
||||
// read state register 1
|
||||
uint8_t Flash_ReadStat1(void) {
|
||||
FlashSendByte(READSTAT1);
|
||||
return FlashSendLastByte(0xFF);
|
||||
}
|
||||
|
||||
// send one byte over SPI
|
||||
|
@ -201,419 +624,3 @@ uint16_t FlashSendByte(uint32_t data) {
|
|||
uint16_t FlashSendLastByte(uint32_t data) {
|
||||
return FlashSendByte(data | AT91C_SPI_LASTXFER);
|
||||
}
|
||||
|
||||
// read state register 1
|
||||
uint8_t Flash_ReadStat1(void) {
|
||||
FlashSendByte(READSTAT1);
|
||||
return FlashSendLastByte(0xFF);
|
||||
}
|
||||
|
||||
bool Flash_CheckBusy(uint32_t timeout) {
|
||||
WaitUS(WINBOND_WRITE_DELAY);
|
||||
StartCountUS();
|
||||
uint32_t _time = GetCountUS();
|
||||
|
||||
if (g_dbglevel > 3) Dbprintf("Checkbusy in...");
|
||||
|
||||
do {
|
||||
if (!(Flash_ReadStat1() & BUSY)) {
|
||||
return false;
|
||||
}
|
||||
} while ((GetCountUS() - _time) < timeout);
|
||||
|
||||
if (timeout <= (GetCountUS() - _time)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
// read ID out
|
||||
uint8_t Flash_ReadID(void) {
|
||||
|
||||
if (Flash_CheckBusy(BUSY_TIMEOUT)) return 0;
|
||||
|
||||
// Manufacture ID / device ID
|
||||
FlashSendByte(ID);
|
||||
FlashSendByte(0x00);
|
||||
FlashSendByte(0x00);
|
||||
FlashSendByte(0x00);
|
||||
|
||||
uint8_t man_id = FlashSendByte(0xFF);
|
||||
uint8_t dev_id = FlashSendLastByte(0xFF);
|
||||
|
||||
if (g_dbglevel > 3) Dbprintf("Flash ReadID | Man ID %02x | Device ID %02x", man_id, dev_id);
|
||||
|
||||
if ((man_id == WINBOND_MANID) && (dev_id == WINBOND_DEVID))
|
||||
return dev_id;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
// read unique id for chip.
|
||||
void Flash_UniqueID(uint8_t *uid) {
|
||||
|
||||
if (Flash_CheckBusy(BUSY_TIMEOUT)) return;
|
||||
|
||||
// reading unique serial number
|
||||
FlashSendByte(UNIQUE_ID);
|
||||
FlashSendByte(0xFF);
|
||||
FlashSendByte(0xFF);
|
||||
FlashSendByte(0xFF);
|
||||
FlashSendByte(0xFF);
|
||||
|
||||
uid[7] = FlashSendByte(0xFF);
|
||||
uid[6] = FlashSendByte(0xFF);
|
||||
uid[5] = FlashSendByte(0xFF);
|
||||
uid[4] = FlashSendByte(0xFF);
|
||||
uid[3] = FlashSendByte(0xFF);
|
||||
uid[2] = FlashSendByte(0xFF);
|
||||
uid[1] = FlashSendByte(0xFF);
|
||||
uid[0] = FlashSendLastByte(0xFF);
|
||||
}
|
||||
|
||||
uint16_t Flash_ReadData(uint32_t address, uint8_t *out, uint16_t len) {
|
||||
|
||||
if (!FlashInit()) return 0;
|
||||
|
||||
// length should never be zero
|
||||
if (!len || Flash_CheckBusy(BUSY_TIMEOUT)) return 0;
|
||||
|
||||
uint8_t cmd = (FASTFLASH) ? FASTREAD : READDATA;
|
||||
|
||||
FlashSendByte(cmd);
|
||||
Flash_TransferAdresse(address);
|
||||
|
||||
if (FASTFLASH) {
|
||||
FlashSendByte(DUMMYBYTE);
|
||||
}
|
||||
|
||||
uint16_t i = 0;
|
||||
for (; i < (len - 1); i++)
|
||||
out[i] = FlashSendByte(0xFF);
|
||||
|
||||
out[i] = FlashSendLastByte(0xFF);
|
||||
FlashStop();
|
||||
return len;
|
||||
}
|
||||
|
||||
void Flash_TransferAdresse(uint32_t address) {
|
||||
FlashSendByte((address >> 16) & 0xFF);
|
||||
FlashSendByte((address >> 8) & 0xFF);
|
||||
FlashSendByte((address >> 0) & 0xFF);
|
||||
}
|
||||
|
||||
/* This ensures we can ReadData without having to cycle through initialization every time */
|
||||
uint16_t Flash_ReadDataCont(uint32_t address, uint8_t *out, uint16_t len) {
|
||||
|
||||
// length should never be zero
|
||||
if (!len) return 0;
|
||||
|
||||
uint8_t cmd = (FASTFLASH) ? FASTREAD : READDATA;
|
||||
|
||||
FlashSendByte(cmd);
|
||||
Flash_TransferAdresse(address);
|
||||
|
||||
if (FASTFLASH) {
|
||||
FlashSendByte(DUMMYBYTE);
|
||||
}
|
||||
|
||||
uint16_t i = 0;
|
||||
for (; i < (len - 1); i++)
|
||||
out[i] = FlashSendByte(0xFF);
|
||||
|
||||
out[i] = FlashSendLastByte(0xFF);
|
||||
return len;
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////
|
||||
// Write data can only program one page. A page has 256 bytes.
|
||||
// if len > 256, it might wrap around and overwrite pos 0.
|
||||
uint16_t Flash_WriteData(uint32_t address, uint8_t *in, uint16_t len) {
|
||||
|
||||
// length should never be zero
|
||||
if (!len)
|
||||
return 0;
|
||||
|
||||
// Max 256 bytes write
|
||||
if (((address & 0xFF) + len) > 256) {
|
||||
Dbprintf("Flash_WriteData 256 fail [ 0x%02x ] [ %u ]", (address & 0xFF) + len, len);
|
||||
return 0;
|
||||
}
|
||||
|
||||
// out-of-range
|
||||
if (((address >> 16) & 0xFF) > MAX_BLOCKS) {
|
||||
Dbprintf("Flash_WriteData, block out-of-range");
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (!FlashInit()) {
|
||||
if (g_dbglevel > 3) Dbprintf("Flash_WriteData init fail");
|
||||
return 0;
|
||||
}
|
||||
|
||||
Flash_CheckBusy(BUSY_TIMEOUT);
|
||||
|
||||
Flash_WriteEnable();
|
||||
|
||||
FlashSendByte(PAGEPROG);
|
||||
FlashSendByte((address >> 16) & 0xFF);
|
||||
FlashSendByte((address >> 8) & 0xFF);
|
||||
FlashSendByte((address >> 0) & 0xFF);
|
||||
|
||||
uint16_t i = 0;
|
||||
for (; i < (len - 1); i++)
|
||||
FlashSendByte(in[i]);
|
||||
|
||||
FlashSendLastByte(in[i]);
|
||||
|
||||
FlashStop();
|
||||
return len;
|
||||
}
|
||||
|
||||
|
||||
// length should never be zero
|
||||
// Max 256 bytes write
|
||||
// out-of-range
|
||||
uint16_t Flash_WriteDataCont(uint32_t address, uint8_t *in, uint16_t len) {
|
||||
|
||||
if (!len)
|
||||
return 0;
|
||||
|
||||
if (((address & 0xFF) + len) > 256) {
|
||||
Dbprintf("Flash_WriteDataCont 256 fail [ 0x%02x ] [ %u ]", (address & 0xFF) + len, len);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (((address >> 16) & 0xFF) > MAX_BLOCKS) {
|
||||
Dbprintf("Flash_WriteDataCont, block out-of-range");
|
||||
return 0;
|
||||
}
|
||||
|
||||
FlashSendByte(PAGEPROG);
|
||||
FlashSendByte((address >> 16) & 0xFF);
|
||||
FlashSendByte((address >> 8) & 0xFF);
|
||||
FlashSendByte((address >> 0) & 0xFF);
|
||||
|
||||
uint16_t i = 0;
|
||||
for (; i < (len - 1); i++)
|
||||
FlashSendByte(in[i]);
|
||||
|
||||
FlashSendLastByte(in[i]);
|
||||
return len;
|
||||
}
|
||||
|
||||
// assumes valid start 256 based 00 address
|
||||
//
|
||||
uint16_t Flash_Write(uint32_t address, uint8_t *in, uint16_t len) {
|
||||
|
||||
bool isok;
|
||||
uint16_t res, bytes_sent = 0, bytes_remaining = len;
|
||||
uint8_t buf[FLASH_MEM_BLOCK_SIZE];
|
||||
while (bytes_remaining > 0) {
|
||||
|
||||
Flash_CheckBusy(BUSY_TIMEOUT);
|
||||
Flash_WriteEnable();
|
||||
|
||||
uint32_t bytes_in_packet = MIN(FLASH_MEM_BLOCK_SIZE, bytes_remaining);
|
||||
|
||||
memcpy(buf, in + bytes_sent, bytes_in_packet);
|
||||
|
||||
res = Flash_WriteDataCont(address + bytes_sent, buf, bytes_in_packet);
|
||||
|
||||
bytes_remaining -= bytes_in_packet;
|
||||
bytes_sent += bytes_in_packet;
|
||||
|
||||
isok = (res == bytes_in_packet);
|
||||
|
||||
if (!isok)
|
||||
goto out;
|
||||
}
|
||||
|
||||
out:
|
||||
FlashStop();
|
||||
return len;
|
||||
}
|
||||
|
||||
|
||||
bool Flash_WipeMemoryPage(uint8_t page) {
|
||||
if (!FlashInit()) {
|
||||
if (g_dbglevel > 3) Dbprintf("Flash_WriteData init fail");
|
||||
return false;
|
||||
}
|
||||
Flash_ReadStat1();
|
||||
|
||||
// Each block is 64Kb. One block erase takes 1s ( 1000ms )
|
||||
Flash_WriteEnable();
|
||||
Flash_Erase64k(page);
|
||||
Flash_CheckBusy(BUSY_TIMEOUT);
|
||||
|
||||
FlashStop();
|
||||
|
||||
// let spiffs check and update its info post flash erase
|
||||
rdv40_spiffs_check();
|
||||
return true;
|
||||
}
|
||||
// Wipes flash memory completely, fills with 0xFF
|
||||
bool Flash_WipeMemory(void) {
|
||||
if (!FlashInit()) {
|
||||
if (g_dbglevel > 3) Dbprintf("Flash_WriteData init fail");
|
||||
return false;
|
||||
}
|
||||
Flash_ReadStat1();
|
||||
|
||||
// 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);
|
||||
|
||||
FlashStop();
|
||||
return true;
|
||||
}
|
||||
|
||||
// enable the flash write
|
||||
void Flash_WriteEnable(void) {
|
||||
FlashSendLastByte(WRITEENABLE);
|
||||
if (g_dbglevel > 3) Dbprintf("Flash Write enabled");
|
||||
}
|
||||
|
||||
// erase 4K at one time
|
||||
// execution time: 0.8ms / 800us
|
||||
bool Flash_Erase4k(uint8_t block, uint8_t sector) {
|
||||
|
||||
if (block > MAX_BLOCKS || sector > MAX_SECTORS) return false;
|
||||
|
||||
FlashSendByte(SECTORERASE);
|
||||
FlashSendByte(block);
|
||||
FlashSendByte(sector << 4);
|
||||
FlashSendLastByte(00);
|
||||
return true;
|
||||
}
|
||||
|
||||
/*
|
||||
// erase 32K at one time
|
||||
// execution time: 0,3s / 300ms
|
||||
bool Flash_Erase32k(uint32_t address) {
|
||||
if (address & (32*1024 - 1)) {
|
||||
if ( g_dbglevel > 1 ) Dbprintf("Flash_Erase32k : Address is not align at 4096");
|
||||
return false;
|
||||
}
|
||||
FlashSendByte(BLOCK32ERASE);
|
||||
FlashSendByte((address >> 16) & 0xFF);
|
||||
FlashSendByte((address >> 8) & 0xFF);
|
||||
FlashSendLastByte((address >> 0) & 0xFF);
|
||||
return true;
|
||||
}
|
||||
*/
|
||||
|
||||
// erase 64k at one time
|
||||
// since a block is 64kb, and there is four blocks.
|
||||
// we only need block number, as MSB
|
||||
// execution time: 1s / 1000ms
|
||||
// 0x00 00 00 -- 0x 00 FF FF == block 0
|
||||
// 0x01 00 00 -- 0x 01 FF FF == block 1
|
||||
// 0x02 00 00 -- 0x 02 FF FF == block 2
|
||||
// 0x03 00 00 -- 0x 03 FF FF == block 3
|
||||
bool Flash_Erase64k(uint8_t block) {
|
||||
|
||||
if (block > MAX_BLOCKS) return false;
|
||||
|
||||
FlashSendByte(BLOCK64ERASE);
|
||||
FlashSendByte(block);
|
||||
FlashSendByte(0x00);
|
||||
FlashSendLastByte(0x00);
|
||||
return true;
|
||||
}
|
||||
|
||||
/*
|
||||
// Erase chip
|
||||
void Flash_EraseChip(void) {
|
||||
FlashSendLastByte(CHIPERASE);
|
||||
}
|
||||
*/
|
||||
|
||||
void Flashmem_print_status(void) {
|
||||
DbpString(_CYAN_("Flash memory"));
|
||||
Dbprintf(" Baudrate................ " _GREEN_("%d MHz"), FLASHMEM_SPIBAUDRATE / 1000000);
|
||||
|
||||
if (!FlashInit()) {
|
||||
DbpString(" Init.................... " _RED_("FAILED"));
|
||||
return;
|
||||
}
|
||||
DbpString(" Init.................... " _GREEN_("OK"));
|
||||
|
||||
uint8_t dev_id = Flash_ReadID();
|
||||
switch (dev_id) {
|
||||
case 0x11 :
|
||||
DbpString(" Memory size............. " _YELLOW_("2 mbits / 256 kb"));
|
||||
break;
|
||||
case 0x10 :
|
||||
DbpString(" Memory size..... ....... " _YELLOW_("1 mbits / 128 kb"));
|
||||
break;
|
||||
case 0x05 :
|
||||
DbpString(" Memory size............. " _YELLOW_("512 kbits / 64 kb"));
|
||||
break;
|
||||
default :
|
||||
DbpString(" Device ID............... " _YELLOW_(" --> Unknown <--"));
|
||||
break;
|
||||
}
|
||||
|
||||
uint8_t uid[8] = {0, 0, 0, 0, 0, 0, 0, 0};
|
||||
Flash_UniqueID(uid);
|
||||
Dbprintf(" Unique ID............... 0x%02X%02X%02X%02X%02X%02X%02X%02X",
|
||||
uid[7], uid[6], uid[5], uid[4],
|
||||
uid[3], uid[2], uid[1], uid[0]
|
||||
);
|
||||
|
||||
FlashStop();
|
||||
}
|
||||
|
||||
void Flashmem_print_info(void) {
|
||||
|
||||
if (!FlashInit()) return;
|
||||
|
||||
DbpString(_CYAN_("Flash memory dictionary loaded"));
|
||||
|
||||
// load dictionary offsets.
|
||||
uint8_t keysum[2];
|
||||
uint16_t num;
|
||||
|
||||
Flash_CheckBusy(BUSY_TIMEOUT);
|
||||
uint16_t isok = Flash_ReadDataCont(DEFAULT_MF_KEYS_OFFSET, keysum, 2);
|
||||
if (isok == 2) {
|
||||
num = ((keysum[1] << 8) | keysum[0]);
|
||||
if (num != 0xFFFF && num != 0x0)
|
||||
Dbprintf(" Mifare.................. "_YELLOW_("%d")" / "_GREEN_("%d")" keys", num, DEFAULT_MF_KEYS_MAX);
|
||||
}
|
||||
|
||||
Flash_CheckBusy(BUSY_TIMEOUT);
|
||||
isok = Flash_ReadDataCont(DEFAULT_T55XX_KEYS_OFFSET, keysum, 2);
|
||||
if (isok == 2) {
|
||||
num = ((keysum[1] << 8) | keysum[0]);
|
||||
if (num != 0xFFFF && num != 0x0)
|
||||
Dbprintf(" T55x7................... "_YELLOW_("%d")" / "_GREEN_("%d")" keys", num, DEFAULT_T55XX_KEYS_MAX);
|
||||
}
|
||||
|
||||
Flash_CheckBusy(BUSY_TIMEOUT);
|
||||
isok = Flash_ReadDataCont(DEFAULT_ICLASS_KEYS_OFFSET, keysum, 2);
|
||||
if (isok == 2) {
|
||||
num = ((keysum[1] << 8) | keysum[0]);
|
||||
if (num != 0xFFFF && num != 0x0)
|
||||
Dbprintf(" iClass.................. "_YELLOW_("%d")" / "_GREEN_("%d")" keys", num, DEFAULT_ICLASS_KEYS_MAX);
|
||||
}
|
||||
|
||||
FlashStop();
|
||||
}
|
||||
|
||||
|
|
@ -100,17 +100,21 @@
|
|||
|
||||
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~//
|
||||
|
||||
void FlashmemSetSpiBaudrate(uint32_t baudrate);
|
||||
bool FlashInit(void);
|
||||
void FlashSetup(uint32_t baudrate);
|
||||
void Flash_UniqueID(uint8_t *uid);
|
||||
void FlashStop(void);
|
||||
bool Flash_WaitIdle(void);
|
||||
uint8_t Flash_ReadStat1(void);
|
||||
uint8_t Flash_ReadStat2(void);
|
||||
uint16_t FlashSendByte(uint32_t data);
|
||||
void Flash_TransferAdresse(uint32_t address);
|
||||
|
||||
void FlashSetup(uint32_t baudrate);
|
||||
bool Flash_CheckBusy(uint32_t timeout);
|
||||
uint8_t Flash_ReadStat1(void);
|
||||
uint16_t FlashSendByte(uint32_t data);
|
||||
uint16_t FlashSendLastByte(uint32_t data);
|
||||
|
||||
|
||||
#ifndef AS_BOOTROM
|
||||
void FlashmemSetSpiBaudrate(uint32_t baudrate);
|
||||
bool Flash_WaitIdle(void);
|
||||
void Flash_TransferAdresse(uint32_t address);
|
||||
|
||||
void Flash_WriteEnable(void);
|
||||
bool Flash_WipeMemoryPage(uint8_t page);
|
||||
|
@ -119,8 +123,12 @@ bool Flash_Erase4k(uint8_t block, uint8_t sector);
|
|||
//bool Flash_Erase32k(uint32_t address);
|
||||
bool Flash_Erase64k(uint8_t block);
|
||||
|
||||
void Flash_UniqueID(uint8_t *uid);
|
||||
uint8_t Flash_ReadID(void);
|
||||
typedef struct {
|
||||
uint8_t manufacturer_id;
|
||||
uint8_t device_id;
|
||||
} flash_device_type_90_t; // to differentiate from JDEC ID via cmd 9F
|
||||
bool Flash_ReadID_90(flash_device_type_90_t *result);
|
||||
|
||||
uint16_t Flash_ReadData(uint32_t address, uint8_t *out, uint16_t len);
|
||||
uint16_t Flash_ReadDataCont(uint32_t address, uint8_t *out, uint16_t len);
|
||||
uint16_t Flash_Write(uint32_t address, uint8_t *in, uint16_t len);
|
||||
|
@ -128,6 +136,8 @@ uint16_t Flash_WriteData(uint32_t address, uint8_t *in, uint16_t len);
|
|||
uint16_t Flash_WriteDataCont(uint32_t address, uint8_t *in, uint16_t len);
|
||||
void Flashmem_print_status(void);
|
||||
void Flashmem_print_info(void);
|
||||
uint16_t FlashSendLastByte(uint32_t data);
|
||||
|
||||
#endif // #ifndef AS_BOOTROM
|
||||
|
||||
|
||||
#endif
|
|
@ -19,9 +19,13 @@
|
|||
#include "ticks.h"
|
||||
|
||||
#include "proxmark3_arm.h"
|
||||
#ifndef AS_BOOTROM
|
||||
#include "dbprint.h"
|
||||
#endif
|
||||
|
||||
|
||||
#ifndef AS_BOOTROM
|
||||
|
||||
// timer counts in 666ns increments (32/48MHz), rounding applies
|
||||
// WARNING: timer can't measure more than 43ms (666ns * 0xFFFF)
|
||||
void SpinDelayUsPrecision(int us) {
|
||||
|
@ -117,40 +121,6 @@ uint32_t RAMFUNC GetTickCountDelta(uint32_t start_ticks) {
|
|||
return (UINT32_MAX - start_ticks) + stop_ticks;
|
||||
}
|
||||
|
||||
// -------------------------------------------------------------------------
|
||||
// microseconds timer
|
||||
// -------------------------------------------------------------------------
|
||||
void StartCountUS(void) {
|
||||
AT91C_BASE_PMC->PMC_PCER |= (1 << AT91C_ID_TC0) | (1 << AT91C_ID_TC1);
|
||||
AT91C_BASE_TCB->TCB_BMR = AT91C_TCB_TC0XC0S_NONE | AT91C_TCB_TC1XC1S_TIOA0 | AT91C_TCB_TC2XC2S_NONE;
|
||||
|
||||
// fast clock
|
||||
// tick=1.5mks
|
||||
AT91C_BASE_TC0->TC_CCR = AT91C_TC_CLKDIS; // timer disable
|
||||
AT91C_BASE_TC0->TC_CMR = AT91C_TC_CLKS_TIMER_DIV3_CLOCK | // MCK(48MHz) / 32
|
||||
AT91C_TC_WAVE | AT91C_TC_WAVESEL_UP_AUTO | AT91C_TC_ACPA_CLEAR |
|
||||
AT91C_TC_ACPC_SET | AT91C_TC_ASWTRG_SET;
|
||||
AT91C_BASE_TC0->TC_RA = 1;
|
||||
AT91C_BASE_TC0->TC_RC = 0xBFFF + 1; // 0xC000
|
||||
|
||||
AT91C_BASE_TC1->TC_CCR = AT91C_TC_CLKDIS; // timer disable
|
||||
AT91C_BASE_TC1->TC_CMR = AT91C_TC_CLKS_XC1; // from timer 0
|
||||
|
||||
AT91C_BASE_TC0->TC_CCR = AT91C_TC_CLKEN | AT91C_TC_SWTRG;
|
||||
AT91C_BASE_TC1->TC_CCR = AT91C_TC_CLKEN | AT91C_TC_SWTRG;
|
||||
|
||||
// Assert a sync signal. This sets all timers to 0 on next active clock edge
|
||||
AT91C_BASE_TCB->TCB_BCR = 1;
|
||||
|
||||
while (AT91C_BASE_TC1->TC_CV > 0);
|
||||
}
|
||||
|
||||
uint32_t RAMFUNC GetCountUS(void) {
|
||||
//return (AT91C_BASE_TC1->TC_CV * 0x8000) + ((AT91C_BASE_TC0->TC_CV / 15) * 10);
|
||||
// By suggestion from PwPiwi, http://www.proxmark.org/forum/viewtopic.php?pid=17548#p17548
|
||||
return ((uint32_t)AT91C_BASE_TC1->TC_CV) * 0x8000 + (((uint32_t)AT91C_BASE_TC0->TC_CV) * 2) / 3;
|
||||
}
|
||||
|
||||
// -------------------------------------------------------------------------
|
||||
// Timer for iso14443 commands. Uses ssp_clk from FPGA
|
||||
// -------------------------------------------------------------------------
|
||||
|
@ -246,6 +216,47 @@ uint32_t RAMFUNC GetCountSspClkDelta(uint32_t start) {
|
|||
return (UINT32_MAX - start) + stop;
|
||||
}
|
||||
|
||||
void WaitMS(uint32_t ms) {
|
||||
WaitTicks((ms & 0x1FFFFF) * 1500);
|
||||
}
|
||||
|
||||
#endif // #ifndef AS_BOOTROM
|
||||
|
||||
// -------------------------------------------------------------------------
|
||||
// microseconds timer
|
||||
// -------------------------------------------------------------------------
|
||||
void StartCountUS(void) {
|
||||
AT91C_BASE_PMC->PMC_PCER |= (1 << AT91C_ID_TC0) | (1 << AT91C_ID_TC1);
|
||||
AT91C_BASE_TCB->TCB_BMR = AT91C_TCB_TC0XC0S_NONE | AT91C_TCB_TC1XC1S_TIOA0 | AT91C_TCB_TC2XC2S_NONE;
|
||||
|
||||
// fast clock
|
||||
// tick=1.5mks
|
||||
AT91C_BASE_TC0->TC_CCR = AT91C_TC_CLKDIS; // timer disable
|
||||
AT91C_BASE_TC0->TC_CMR = AT91C_TC_CLKS_TIMER_DIV3_CLOCK | // MCK(48MHz) / 32
|
||||
AT91C_TC_WAVE | AT91C_TC_WAVESEL_UP_AUTO | AT91C_TC_ACPA_CLEAR |
|
||||
AT91C_TC_ACPC_SET | AT91C_TC_ASWTRG_SET;
|
||||
AT91C_BASE_TC0->TC_RA = 1;
|
||||
AT91C_BASE_TC0->TC_RC = 0xBFFF + 1; // 0xC000
|
||||
|
||||
AT91C_BASE_TC1->TC_CCR = AT91C_TC_CLKDIS; // timer disable
|
||||
AT91C_BASE_TC1->TC_CMR = AT91C_TC_CLKS_XC1; // from timer 0
|
||||
|
||||
AT91C_BASE_TC0->TC_CCR = AT91C_TC_CLKEN | AT91C_TC_SWTRG;
|
||||
AT91C_BASE_TC1->TC_CCR = AT91C_TC_CLKEN | AT91C_TC_SWTRG;
|
||||
|
||||
// Assert a sync signal. This sets all timers to 0 on next active clock edge
|
||||
AT91C_BASE_TCB->TCB_BCR = 1;
|
||||
|
||||
while (AT91C_BASE_TC1->TC_CV > 0);
|
||||
}
|
||||
|
||||
uint32_t RAMFUNC GetCountUS(void) {
|
||||
//return (AT91C_BASE_TC1->TC_CV * 0x8000) + ((AT91C_BASE_TC0->TC_CV / 15) * 10);
|
||||
// By suggestion from PwPiwi, http://www.proxmark.org/forum/viewtopic.php?pid=17548#p17548
|
||||
return ((uint32_t)AT91C_BASE_TC1->TC_CV) * 0x8000 + (((uint32_t)AT91C_BASE_TC0->TC_CV) * 2) / 3;
|
||||
}
|
||||
|
||||
|
||||
// -------------------------------------------------------------------------
|
||||
// Timer for bitbanging, or LF stuff when you need a very precis timer
|
||||
// 1us = 1.5ticks
|
||||
|
@ -282,7 +293,6 @@ void StartTicks(void) {
|
|||
AT91C_BASE_TC0->TC_CCR = AT91C_TC_SWTRG;
|
||||
while (AT91C_BASE_TC0->TC_CV > 0);
|
||||
}
|
||||
|
||||
uint32_t GetTicks(void) {
|
||||
uint32_t hi, lo;
|
||||
|
||||
|
@ -307,9 +317,6 @@ void WaitTicks(uint32_t ticks) {
|
|||
void WaitUS(uint32_t us) {
|
||||
WaitTicks((us & 0x3FFFFFFF) * 3 / 2);
|
||||
}
|
||||
void WaitMS(uint32_t ms) {
|
||||
WaitTicks((ms & 0x1FFFFF) * 1500);
|
||||
}
|
||||
|
||||
// stop clock
|
||||
void StopTicks(void) {
|
|
@ -26,6 +26,19 @@
|
|||
#define GET_TICKS GetTicks()
|
||||
#endif
|
||||
|
||||
void StartTicks(void);
|
||||
uint32_t GetTicks(void);
|
||||
void WaitUS(uint32_t us);
|
||||
void WaitTicks(uint32_t ticks);
|
||||
void StartCountUS(void);
|
||||
uint32_t RAMFUNC GetCountUS(void);
|
||||
void StopTicks(void);
|
||||
|
||||
|
||||
#ifndef AS_BOOTROM //////////////////////////////////////////////////////////////
|
||||
// Bootrom does not require these functions.
|
||||
// Wrap in #ifndef to avoid accidental bloat of bootrom
|
||||
|
||||
void SpinDelay(int ms);
|
||||
void SpinDelayUs(int us);
|
||||
void SpinDelayUsPrecision(int us); // precision 0.6us , running for 43ms before
|
||||
|
@ -34,8 +47,6 @@ void StartTickCount(void);
|
|||
uint32_t RAMFUNC GetTickCount(void);
|
||||
uint32_t RAMFUNC GetTickCountDelta(uint32_t start_ticks);
|
||||
|
||||
void StartCountUS(void);
|
||||
uint32_t RAMFUNC GetCountUS(void);
|
||||
void ResetUSClock(void);
|
||||
void SpinDelayCountUs(uint32_t us);
|
||||
|
||||
|
@ -44,12 +55,10 @@ void ResetSspClk(void);
|
|||
uint32_t RAMFUNC GetCountSspClk(void);
|
||||
uint32_t RAMFUNC GetCountSspClkDelta(uint32_t start);
|
||||
|
||||
void StartTicks(void);
|
||||
uint32_t GetTicks(void);
|
||||
void WaitTicks(uint32_t ticks);
|
||||
void WaitUS(uint32_t us);
|
||||
void WaitMS(uint32_t ms);
|
||||
|
||||
void StopTicks(void);
|
||||
#endif // #ifndef AS_BOOTROM
|
||||
|
||||
|
||||
|
||||
#endif
|
|
@ -366,11 +366,60 @@ static const char StrProduct[] = {
|
|||
'p', 0, 'r', 0, 'o', 0, 'x', 0, 'm', 0, 'a', 0, 'r', 0, 'k', 0, '3', 0
|
||||
};
|
||||
|
||||
#ifndef WITH_FLASH
|
||||
static const char StrSerialNumber[] = {
|
||||
14, // Length
|
||||
0x03, // Type is string
|
||||
'i', 0, 'c', 0, 'e', 0, 'm', 0, 'a', 0, 'n', 0
|
||||
};
|
||||
#else // WITH_FLASH is defined
|
||||
|
||||
// Manually calculated size of descriptor with unique ID:
|
||||
// offset 0, lengt h 1: total length field
|
||||
// offset 1, length 1: descriptor type field
|
||||
// offset 2, length 12: 6x unicode chars (original string)
|
||||
// offset 14, length 4: 2x unicode chars (underscores) [[ to avoid descriptor being (size % 8) == 0, OS bug workaround ]]
|
||||
// offset 18, length 32: 16x unicode chars (8-byte serial as hex characters)
|
||||
// ============================
|
||||
// total: 50 bytes
|
||||
#define USB_STRING_DESCRIPTOR_SERIAL_NUMBER_LENGTH 50
|
||||
char StrSerialNumber[] = {
|
||||
14, // Length is initially identical to non-unique version ... The length updated at boot, if unique serial is available
|
||||
0x03, // Type is string
|
||||
'i', 0, 'c', 0, 'e', 0, 'm', 0, 'a', 0, 'n', 0,
|
||||
'_', 0, '_', 0,
|
||||
'x', 0, 'x', 0, 'x', 0, 'x', 0, 'x', 0, 'x', 0, 'x', 0, 'x', 0,
|
||||
'x', 0, 'x', 0, 'x', 0, 'x', 0, 'x', 0, 'x', 0, 'x', 0, 'x', 0,
|
||||
};
|
||||
void usb_update_serial(uint64_t newSerialNumber) {
|
||||
static bool configured = false; // TODO: enable by setting to false here...
|
||||
if (configured) {
|
||||
return;
|
||||
}
|
||||
// run this only once per boot... even if it fails to find serial number
|
||||
configured = true;
|
||||
// reject serial number if all-zero or all-ones
|
||||
if ((newSerialNumber == 0x0000000000000000) || (newSerialNumber == 0xFFFFFFFFFFFFFFFF)) {
|
||||
return;
|
||||
}
|
||||
// Descriptor is, effectively, initially identical to non-unique serial
|
||||
// number because it reports the shorter length in the first byte.
|
||||
// Convert uniqueID's eight bytes to 16 unicode characters in the
|
||||
// descriptor and, finally, update the descriptor's length, which
|
||||
// causes the serial number to become visible.
|
||||
for (uint8_t i = 0; i < 8; i++) {
|
||||
// order of nibbles chosen to match display order from `hw status`
|
||||
uint8_t nibble1 = (newSerialNumber >> ((8 * i) + 4)) & 0xFu; // bitmasks [0xF0, 0xF000, 0xF00000, ... 0xF000000000000000]
|
||||
uint8_t nibble2 = (newSerialNumber >> ((8 * i) + 0)) & 0xFu; // bitmasks [0x0F, 0x0F00, 0x0F0000, ... 0x0F00000000000000]
|
||||
char c1 = nibble1 < 10 ? '0' + nibble1 : 'A' + (nibble1 - 10);
|
||||
char c2 = nibble2 < 10 ? '0' + nibble2 : 'A' + (nibble2 - 10);
|
||||
StrSerialNumber[18 + (4 * i) + 0] = c1; // [ 18, 22, .., 42, 46 ]
|
||||
StrSerialNumber[18 + (4 * i) + 2] = c2; // [ 20, 24, .., 44, 48 ]
|
||||
}
|
||||
StrSerialNumber[0] = USB_STRING_DESCRIPTOR_SERIAL_NUMBER_LENGTH;
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
// size includes their own field.
|
||||
static const char StrMS_OSDescriptor[] = {
|
||||
|
|
|
@ -31,6 +31,7 @@ bool usb_poll_validate_length(void);
|
|||
uint32_t usb_read(uint8_t *data, size_t len);
|
||||
int usb_write(const uint8_t *data, const size_t len);
|
||||
uint32_t usb_read_ng(uint8_t *data, size_t len);
|
||||
void usb_update_serial(uint64_t newSerialNumber);
|
||||
|
||||
void SetUSBreconnect(int value);
|
||||
int GetUSBreconnect(void);
|
||||
|
|
|
@ -11507,7 +11507,7 @@
|
|||
},
|
||||
"script help": {
|
||||
"command": "script help",
|
||||
"description": "This is a feature to run Lua/Cmd scripts. You can place scripts within the luascripts/cmdscripts folders. --------------------------------------------------------------------------------------- script list available offline: yes",
|
||||
"description": "This is a feature to run Lua/Cmd/Python scripts. You can place scripts within the luascripts/cmdscripts/pyscripts folders. --------------------------------------------------------------------------------------- script list available offline: yes",
|
||||
"notes": [],
|
||||
"offline": true,
|
||||
"options": [],
|
||||
|
@ -11904,6 +11904,6 @@
|
|||
"metadata": {
|
||||
"commands_extracted": 749,
|
||||
"extracted_by": "PM3Help2JSON v1.00",
|
||||
"extracted_on": "2023-02-11T10:42:29"
|
||||
"extracted_on": "2023-02-18T20:20:19"
|
||||
}
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue