From 5784c8de77f6cabf4d27c76f412dd3a9b441ff63 Mon Sep 17 00:00:00 2001 From: Henry Gabryjelski Date: Fri, 17 Feb 2023 15:42:46 -0800 Subject: [PATCH 1/6] Update USB Serial Number from SPI flash's uniqueID Also allow flash to be separately enabled via PLATFORM_EXTRAS. NOTE: this does *NOT* enable the serial number in the bootrom. Still investigating options there. --- Makefile.platform.sample | 2 ++ armsrc/appmain.c | 16 +++++++++++++- armsrc/flashmem.c | 8 +++---- common_arm/Makefile.hal | 4 ++++ common_arm/usb_cdc.c | 45 ++++++++++++++++++++++++++++++++++++++++ common_arm/usb_cdc.h | 1 + 6 files changed, 71 insertions(+), 5 deletions(-) diff --git a/Makefile.platform.sample b/Makefile.platform.sample index 21fb2137e..aeb541cee 100644 --- a/Makefile.platform.sample +++ b/Makefile.platform.sample @@ -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 diff --git a/armsrc/appmain.c b/armsrc/appmain.c index bc22f1834..f3a42ed09 100644 --- a/armsrc/appmain.c +++ b/armsrc/appmain.c @@ -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 diff --git a/armsrc/flashmem.c b/armsrc/flashmem.c index ba882eaa7..4b6d39b91 100644 --- a/armsrc/flashmem.c +++ b/armsrc/flashmem.c @@ -22,7 +22,7 @@ #include "ticks.h" #include "dbprint.h" #include "string.h" -#include "spiffs.h" +#include "usb_cdc.h" /* here: use NCPS2 @ PA10: */ #define SPI_CSR_NUM 2 @@ -436,7 +436,9 @@ out: 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"); @@ -451,8 +453,6 @@ bool Flash_WipeMemoryPage(uint8_t page) { FlashStop(); - // let spiffs check and update its info post flash erase - rdv40_spiffs_check(); return true; } // Wipes flash memory completely, fills with 0xFF diff --git a/common_arm/Makefile.hal b/common_arm/Makefile.hal index 0e9dd455b..a65514784 100644 --- a/common_arm/Makefile.hal +++ b/common_arm/Makefile.hal @@ -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))) diff --git a/common_arm/usb_cdc.c b/common_arm/usb_cdc.c index 0ccf25aef..f805d1797 100644 --- a/common_arm/usb_cdc.c +++ b/common_arm/usb_cdc.c @@ -366,11 +366,56 @@ 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; + 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 < 16; i++) { + uint8_t nibble = (uint8_t)((newSerialNumber >> (60 - (4*i))) & 0xFu); + char c = nibble < 10 ? '0' + nibble : 'A' + (nibble-10); + StrSerialNumber[18+(2*i)] = c; // [ 18, 20, 22, .., 46, 48 ] + } + StrSerialNumber[0] = USB_STRING_DESCRIPTOR_SERIAL_NUMBER_LENGTH; +} +#endif + // size includes their own field. static const char StrMS_OSDescriptor[] = { diff --git a/common_arm/usb_cdc.h b/common_arm/usb_cdc.h index a09d3fc33..e7f6f3d09 100644 --- a/common_arm/usb_cdc.h +++ b/common_arm/usb_cdc.h @@ -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); From 44676bde724fb8718a6ddf6eaa7af3bdbbc259b6 Mon Sep 17 00:00:00 2001 From: Henry Gabryjelski Date: Fri, 17 Feb 2023 16:59:00 -0800 Subject: [PATCH 2/6] Bootrom: Enable serial number from flash * Add `.ramfunc` section to bootrom loader script * exclude spiffs functionality from flashmem.h/flashmem.c (allows bootrom to use flashmem) * hide unused tick.h / flashmem.h functions from bootrom (not technically necessary; see comments) * bootrom: add source files, include path, and defines when `PLATFORM_DEFS` defines `WITH_FLASH` * Define `AS_BOOTROM` to indicate code is building for bootrom --- armsrc/appmain.c | 2 +- bootrom/Makefile | 8 +- bootrom/bootrom.c | 16 +- bootrom/ldscript-flash | 1 + {armsrc => common_arm}/flashmem.c | 431 +++++++++++++++--------------- {armsrc => common_arm}/flashmem.h | 65 ++++- {armsrc => common_arm}/ticks.c | 85 +++--- {armsrc => common_arm}/ticks.h | 23 +- common_arm/usb_cdc.c | 14 +- 9 files changed, 373 insertions(+), 272 deletions(-) rename {armsrc => common_arm}/flashmem.c (98%) rename {armsrc => common_arm}/flashmem.h (76%) rename {armsrc => common_arm}/ticks.c (99%) rename {armsrc => common_arm}/ticks.h (89%) diff --git a/armsrc/appmain.c b/armsrc/appmain.c index f3a42ed09..90681c324 100644 --- a/armsrc/appmain.c +++ b/armsrc/appmain.c @@ -2684,7 +2684,7 @@ void __attribute__((noreturn)) AppMain(void) { 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)); + Flash_UniqueID((uint8_t*)(&flash_uniqueID)); } FlashStop(); usb_update_serial(flash_uniqueID); diff --git a/bootrom/Makefile b/bootrom/Makefile index edb0cc990..cad3e17d1 100644 --- a/bootrom/Makefile +++ b/bootrom/Makefile @@ -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 diff --git a/bootrom/bootrom.c b/bootrom/bootrom.c index 93c4d605e..c94c23481 100644 --- a/bootrom/bootrom.c +++ b/bootrom/bootrom.c @@ -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(); diff --git a/bootrom/ldscript-flash b/bootrom/ldscript-flash index 5d63f9689..374c2d6c7 100644 --- a/bootrom/ldscript-flash +++ b/bootrom/ldscript-flash @@ -53,6 +53,7 @@ SECTIONS *(.rodata.*) *(.data) *(.data.*) + *(.ramfunc) . = ALIGN(4); } >ram AT>bootphase2 :phase2 diff --git a/armsrc/flashmem.c b/common_arm/flashmem.c similarity index 98% rename from armsrc/flashmem.c rename to common_arm/flashmem.c index 4b6d39b91..0a60d43c0 100644 --- a/armsrc/flashmem.c +++ b/common_arm/flashmem.c @@ -20,7 +20,11 @@ #include "proxmark3_arm.h" #include "ticks.h" + +#ifndef AS_BOOTROM #include "dbprint.h" +#endif // AS_BOOTROM + #include "string.h" #include "usb_cdc.h" @@ -37,197 +41,13 @@ 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); } -// initialize -bool FlashInit(void) { - FlashSetup(FLASHMEM_SPIBAUDRATE); - - StartTicks(); - - if (Flash_CheckBusy(BUSY_TIMEOUT)) { - StopTicks(); - return false; - } - - return true; -} - -void FlashSetup(uint32_t baudrate) { - //WDT_DISABLE - AT91C_BASE_WDTC->WDTC_WDMR = AT91C_WDTC_WDDIS; - - // PA10 -> SPI_NCS2 chip select (FLASHMEM) - // PA11 -> SPI_NCS0 chip select (FPGA) - // PA12 -> SPI_MISO Master-In Slave-Out - // PA13 -> SPI_MOSI Master-Out Slave-In - // PA14 -> SPI_SPCK Serial Clock - - // Disable PIO control of the following pins, allows use by the SPI peripheral - AT91C_BASE_PIOA->PIO_PDR |= (GPIO_NCS0 | GPIO_MISO | GPIO_MOSI | GPIO_SPCK | GPIO_NCS2); - - // Pull-up Enable - AT91C_BASE_PIOA->PIO_PPUER |= (GPIO_NCS0 | GPIO_MISO | GPIO_MOSI | GPIO_SPCK | GPIO_NCS2); - - // Peripheral A - AT91C_BASE_PIOA->PIO_ASR |= (GPIO_NCS0 | GPIO_MISO | GPIO_MOSI | GPIO_SPCK); - - // Peripheral B - AT91C_BASE_PIOA->PIO_BSR |= GPIO_NCS2; - - //enable the SPI Peripheral clock - AT91C_BASE_PMC->PMC_PCER = (1 << AT91C_ID_SPI); - - - //reset spi needs double SWRST, see atmel's errata on this case - AT91C_BASE_SPI->SPI_CR = AT91C_SPI_SWRST; - AT91C_BASE_SPI->SPI_CR = AT91C_SPI_SWRST; - - // Enable SPI - AT91C_BASE_SPI->SPI_CR = AT91C_SPI_SPIEN; - - // NPCS2 Mode 0 - AT91C_BASE_SPI->SPI_MR = - (0 << 24) | // Delay between chip selects = DYLBCS/MCK BUT: - // If DLYBCS is less than or equal to six, six MCK periods - // will be inserted by default. - SPI_PCS(SPI_CSR_NUM) | // Peripheral Chip Select (selects SPI_NCS2 or PA10) - (0 << 7) | // Disable LLB (1=MOSI2MISO test mode) - (1 << 4) | // Disable ModeFault Protection - (0 << 3) | // makes spi operate at MCK (1 is MCK/2) - (0 << 2) | // Chip selects connected directly to peripheral - AT91C_SPI_PS_FIXED | // Fixed Peripheral Select - AT91C_SPI_MSTR; // Master Mode - - uint8_t csaat = 1; - uint32_t dlybct = 0; - uint8_t ncpha = 1; - uint8_t cpol = 0; - if (baudrate > FLASH_MINFAST) { - baudrate = FLASH_FASTBAUD; - //csaat = 0; - dlybct = 1500; - ncpha = 0; - cpol = 0; - } - - AT91C_BASE_SPI->SPI_CSR[2] = - SPI_DLYBCT(dlybct, MCK) | // Delay between Consecutive Transfers (32 MCK periods) - SPI_DLYBS(0, MCK) | // Delay Beforce SPCK CLock - SPI_SCBR(baudrate, MCK) | // SPI Baudrate Selection - AT91C_SPI_BITS_8 | // Bits per Transfer (8 bits) - //AT91C_SPI_CSAAT | // Chip Select inactive after transfer - // 40.4.6.2 SPI: Bad tx_ready Behavior when CSAAT = 1 and SCBR = 1 - // If the SPI is programmed with CSAAT = 1, SCBR(baudrate) = 1 and two transfers are performed consecutively on - // the same slave with an IDLE state between them, the tx_ready signal does not rise after the second data has been - // transferred in the shifter. This can imply for example, that the second data is sent twice. - // COLIN :: For now we STILL use CSAAT=1 to avoid having to (de)assert NPCS manually via PIO lines and we deal with delay - (csaat << 3) | - /* Spi modes: - Mode CPOL CPHA NCPHA - 0 0 0 1 clock normally low read on rising edge - 1 0 1 0 clock normally low read on falling edge - 2 1 0 1 clock normally high read on falling edge - 3 1 1 0 clock normally high read on rising edge - However, page 512 of the AT91SAM7Sx datasheet say "Note that in SPI - master mode the ATSAM7S512/256/128/64/321/32 does not sample the data - (MISO) on the opposite edge where data clocks out (MOSI) but the same - edge is used as shown in Figure 36-3 and Figure 36-4." Figure 36-3 - shows that CPOL=NCPHA=0 or CPOL=NCPHA=1 samples on the rising edge and - that the data changes sometime after the rising edge (about 2 ns). To - be consistent with normal SPI operation, it is probably safe to say - that the data changes on the falling edge and should be sampled on the - rising edge. Therefore, it appears that NCPHA should be treated the - same as CPHA. Thus: - Mode CPOL CPHA NCPHA - 0 0 0 0 clock normally low read on rising edge - 1 0 1 1 clock normally low read on falling edge - 2 1 0 0 clock normally high read on falling edge - 3 1 1 1 clock normally high read on rising edge - Update: for 24MHz, writing is more stable with ncpha=1, else bitflips occur. - */ - (ncpha << 1) | // Clock Phase data captured on leading edge, changes on following edge - (cpol << 0); // Clock Polarity inactive state is logic 0 - - // read first, empty buffer - 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; - - // 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; - - if (g_dbglevel > 3) Dbprintf("FlashStop"); - - StopTicks(); -} - -// send one byte over SPI -uint16_t FlashSendByte(uint32_t data) { - - // wait until SPI is ready for transfer - //if you are checking for incoming data returned then the TXEMPTY flag is redundant - //while ((AT91C_BASE_SPI->SPI_SR & AT91C_SPI_TXEMPTY) == 0) {}; - - // send the data - AT91C_BASE_SPI->SPI_TDR = data; - - //while ((AT91C_BASE_SPI->SPI_SR & AT91C_SPI_TDRE) == 0){}; - - // wait receive transfer is complete - while ((AT91C_BASE_SPI->SPI_SR & AT91C_SPI_RDRF) == 0) {}; - - // reading incoming data - return ((AT91C_BASE_SPI->SPI_RDR) & 0xFFFF); -} - -// send last byte over SPI -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) { @@ -250,28 +70,6 @@ uint8_t Flash_ReadID(void) { 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; @@ -326,7 +124,6 @@ uint16_t Flash_ReadDataCont(uint32_t address, uint8_t *out, uint16_t len) { 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. @@ -372,7 +169,6 @@ uint16_t Flash_WriteData(uint32_t address, uint8_t *in, uint16_t len) { return len; } - // length should never be zero // Max 256 bytes write // out-of-range @@ -571,7 +367,7 @@ void Flashmem_print_status(void) { 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", + Dbprintf( " Unique ID............... " _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] ); @@ -616,4 +412,217 @@ void Flashmem_print_info(void) { FlashStop(); } +#endif // #ifndef AS_BOOTROM + +// initialize +bool FlashInit(void) { + FlashSetup(FLASHMEM_SPIBAUDRATE); + + StartTicks(); + + if (Flash_CheckBusy(BUSY_TIMEOUT)) { + StopTicks(); + return false; + } + + 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; + + // PA10 -> SPI_NCS2 chip select (FLASHMEM) + // PA11 -> SPI_NCS0 chip select (FPGA) + // PA12 -> SPI_MISO Master-In Slave-Out + // PA13 -> SPI_MOSI Master-Out Slave-In + // PA14 -> SPI_SPCK Serial Clock + + // Disable PIO control of the following pins, allows use by the SPI peripheral + AT91C_BASE_PIOA->PIO_PDR |= (GPIO_NCS0 | GPIO_MISO | GPIO_MOSI | GPIO_SPCK | GPIO_NCS2); + + // Pull-up Enable + AT91C_BASE_PIOA->PIO_PPUER |= (GPIO_NCS0 | GPIO_MISO | GPIO_MOSI | GPIO_SPCK | GPIO_NCS2); + + // Peripheral A + AT91C_BASE_PIOA->PIO_ASR |= (GPIO_NCS0 | GPIO_MISO | GPIO_MOSI | GPIO_SPCK); + + // Peripheral B + AT91C_BASE_PIOA->PIO_BSR |= GPIO_NCS2; + + //enable the SPI Peripheral clock + AT91C_BASE_PMC->PMC_PCER = (1 << AT91C_ID_SPI); + + + //reset spi needs double SWRST, see atmel's errata on this case + AT91C_BASE_SPI->SPI_CR = AT91C_SPI_SWRST; + AT91C_BASE_SPI->SPI_CR = AT91C_SPI_SWRST; + + // Enable SPI + AT91C_BASE_SPI->SPI_CR = AT91C_SPI_SPIEN; + + // NPCS2 Mode 0 + AT91C_BASE_SPI->SPI_MR = + (0 << 24) | // Delay between chip selects = DYLBCS/MCK BUT: + // If DLYBCS is less than or equal to six, six MCK periods + // will be inserted by default. + SPI_PCS(SPI_CSR_NUM) | // Peripheral Chip Select (selects SPI_NCS2 or PA10) + (0 << 7) | // Disable LLB (1=MOSI2MISO test mode) + (1 << 4) | // Disable ModeFault Protection + (0 << 3) | // makes spi operate at MCK (1 is MCK/2) + (0 << 2) | // Chip selects connected directly to peripheral + AT91C_SPI_PS_FIXED | // Fixed Peripheral Select + AT91C_SPI_MSTR; // Master Mode + + uint8_t csaat = 1; + uint32_t dlybct = 0; + uint8_t ncpha = 1; + uint8_t cpol = 0; + if (baudrate > FLASH_MINFAST) { + baudrate = FLASH_FASTBAUD; + //csaat = 0; + dlybct = 1500; + ncpha = 0; + cpol = 0; + } + + AT91C_BASE_SPI->SPI_CSR[2] = + SPI_DLYBCT(dlybct, MCK) | // Delay between Consecutive Transfers (32 MCK periods) + SPI_DLYBS(0, MCK) | // Delay Beforce SPCK CLock + SPI_SCBR(baudrate, MCK) | // SPI Baudrate Selection + AT91C_SPI_BITS_8 | // Bits per Transfer (8 bits) + //AT91C_SPI_CSAAT | // Chip Select inactive after transfer + // 40.4.6.2 SPI: Bad tx_ready Behavior when CSAAT = 1 and SCBR = 1 + // If the SPI is programmed with CSAAT = 1, SCBR(baudrate) = 1 and two transfers are performed consecutively on + // the same slave with an IDLE state between them, the tx_ready signal does not rise after the second data has been + // transferred in the shifter. This can imply for example, that the second data is sent twice. + // COLIN :: For now we STILL use CSAAT=1 to avoid having to (de)assert NPCS manually via PIO lines and we deal with delay + (csaat << 3) | + /* Spi modes: + Mode CPOL CPHA NCPHA + 0 0 0 1 clock normally low read on rising edge + 1 0 1 0 clock normally low read on falling edge + 2 1 0 1 clock normally high read on falling edge + 3 1 1 0 clock normally high read on rising edge + However, page 512 of the AT91SAM7Sx datasheet say "Note that in SPI + master mode the ATSAM7S512/256/128/64/321/32 does not sample the data + (MISO) on the opposite edge where data clocks out (MOSI) but the same + edge is used as shown in Figure 36-3 and Figure 36-4." Figure 36-3 + shows that CPOL=NCPHA=0 or CPOL=NCPHA=1 samples on the rising edge and + that the data changes sometime after the rising edge (about 2 ns). To + be consistent with normal SPI operation, it is probably safe to say + that the data changes on the falling edge and should be sampled on the + rising edge. Therefore, it appears that NCPHA should be treated the + same as CPHA. Thus: + Mode CPOL CPHA NCPHA + 0 0 0 0 clock normally low read on rising edge + 1 0 1 1 clock normally low read on falling edge + 2 1 0 0 clock normally high read on falling edge + 3 1 1 1 clock normally high read on rising edge + Update: for 24MHz, writing is more stable with ncpha=1, else bitflips occur. + */ + (ncpha << 1) | // Clock Phase data captured on leading edge, changes on following edge + (cpol << 0); // Clock Polarity inactive state is logic 0 + + // read first, empty buffer + if (AT91C_BASE_SPI->SPI_RDR == 0) {}; +} + +bool Flash_CheckBusy(uint32_t timeout) { + WaitUS(WINBOND_WRITE_DELAY); + StartCountUS(); + uint32_t _time = GetCountUS(); + +#ifndef AS_BOOTROM + if (g_dbglevel > 3) Dbprintf("Checkbusy in..."); +#endif // AS_BOOTROM + + do { + if (!(Flash_ReadStat1() & BUSY)) { + return false; + } + } while ((GetCountUS() - _time) < timeout); + + if (timeout <= (GetCountUS() - _time)) { + return true; + } + + return false; +} + +// read state register 1 +uint8_t Flash_ReadStat1(void) { + FlashSendByte(READSTAT1); + return FlashSendLastByte(0xFF); +} + +// send one byte over SPI +uint16_t FlashSendByte(uint32_t data) { + + // wait until SPI is ready for transfer + //if you are checking for incoming data returned then the TXEMPTY flag is redundant + //while ((AT91C_BASE_SPI->SPI_SR & AT91C_SPI_TXEMPTY) == 0) {}; + + // send the data + AT91C_BASE_SPI->SPI_TDR = data; + + //while ((AT91C_BASE_SPI->SPI_SR & AT91C_SPI_TDRE) == 0){}; + + // wait receive transfer is complete + while ((AT91C_BASE_SPI->SPI_SR & AT91C_SPI_RDRF) == 0) {}; + + // reading incoming data + return ((AT91C_BASE_SPI->SPI_RDR) & 0xFFFF); +} + +// send last byte over SPI +uint16_t FlashSendLastByte(uint32_t data) { + return FlashSendByte(data | AT91C_SPI_LASTXFER); +} diff --git a/armsrc/flashmem.h b/common_arm/flashmem.h similarity index 76% rename from armsrc/flashmem.h rename to common_arm/flashmem.h index 2b829c378..3578fa933 100644 --- a/armsrc/flashmem.h +++ b/common_arm/flashmem.h @@ -100,17 +100,67 @@ //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~// -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); + +void FlashSetup(uint32_t baudrate); +bool Flash_CheckBusy(uint32_t timeout); uint8_t Flash_ReadStat1(void); -uint8_t Flash_ReadStat2(void); uint16_t FlashSendByte(uint32_t data); +uint16_t FlashSendLastByte(uint32_t data); + + +#ifndef AS_BOOTROM + // Bootrom does not require these functions. + // Wrap in #ifndef to avoid accidental bloat of bootrom + // Bootrom needs only enough to get uniqueID from flash. + // It calls three functions. Full call trees listed: + // + // FlashInit() + // | + // \____ FlashSetup() + // | \____ leaf + // | + // \____ StartTicks() + // | \____ leaf + // | + // \____ Flash_CheckBusy() [*] + // | \____ WaitUS() + // | | \____ WaitTicks() + // | | \____ leaf + // | | + // | \____ StartCountUS() + // | | \____ leaf + // | | + // | \____ GetCountUS() + // | | \____ leaf + // | | + // | \____ Flash_ReadStat1() + // | \____ FlashSendByte() + // | | \____ leaf + // | | + // | \____ FlashSendLastByte() + // | \____ FlashSendByte() + // | \____ leaf + // | + // \____ StopTicks() + // \____ leaf + // + // Flash_UniqueID() + // \____ FlashCheckBusy() (see FlashInit) + // \____ FlashSendByteByte() (see FlashInit) + // \____ FlashSendByteLastByte() (see FlashInit) + // + // + // FlashStop() [*] + + + +void FlashmemSetSpiBaudrate(uint32_t baudrate); +bool Flash_WaitIdle(void); void Flash_TransferAdresse(uint32_t address); -bool Flash_CheckBusy(uint32_t timeout); void Flash_WriteEnable(void); bool Flash_WipeMemoryPage(uint8_t page); @@ -119,7 +169,6 @@ 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); 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); @@ -128,6 +177,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 diff --git a/armsrc/ticks.c b/common_arm/ticks.c similarity index 99% rename from armsrc/ticks.c rename to common_arm/ticks.c index 3cf2c54dc..34c480061 100644 --- a/armsrc/ticks.c +++ b/common_arm/ticks.c @@ -19,9 +19,13 @@ #include "ticks.h" #include "proxmark3_arm.h" -#include "dbprint.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) { diff --git a/armsrc/ticks.h b/common_arm/ticks.h similarity index 89% rename from armsrc/ticks.h rename to common_arm/ticks.h index 7ad4486fa..4a2276268 100644 --- a/armsrc/ticks.h +++ b/common_arm/ticks.h @@ -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 diff --git a/common_arm/usb_cdc.c b/common_arm/usb_cdc.c index f805d1797..82fc6d0e1 100644 --- a/common_arm/usb_cdc.c +++ b/common_arm/usb_cdc.c @@ -382,7 +382,6 @@ static const char StrSerialNumber[] = { // 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 @@ -399,6 +398,7 @@ void usb_update_serial(uint64_t newSerialNumber) { } // 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; } @@ -407,10 +407,14 @@ void usb_update_serial(uint64_t newSerialNumber) { // 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 < 16; i++) { - uint8_t nibble = (uint8_t)((newSerialNumber >> (60 - (4*i))) & 0xFu); - char c = nibble < 10 ? '0' + nibble : 'A' + (nibble-10); - StrSerialNumber[18+(2*i)] = c; // [ 18, 20, 22, .., 46, 48 ] + 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[46-(4*i)] = c1; // [ 46, 42, .., 22, 18 ] + StrSerialNumber[48-(4*i)] = c2; // [ 48, 44, .., 24, 20 ] } StrSerialNumber[0] = USB_STRING_DESCRIPTOR_SERIAL_NUMBER_LENGTH; } From 6eea476076ff0aad0eb2c2cb2a2058e9e35c92ee Mon Sep 17 00:00:00 2001 From: Henry Gabryjelski Date: Fri, 17 Feb 2023 17:19:01 -0800 Subject: [PATCH 3/6] Add changelog --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 668e2c32c..e865190c1 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -3,6 +3,7 @@ All notable changes to this project will be documented in this file. This project uses the changelog in accordance with [keepchangelog](http://keepachangelog.com/). Please use this to write notable changes, which is not the same as git commit log... ## [unreleased][unreleased] + - 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) From 48ca513a964d3d76b22f1207b37132f2e0863827 Mon Sep 17 00:00:00 2001 From: Henry Gabryjelski Date: Fri, 17 Feb 2023 17:27:07 -0800 Subject: [PATCH 4/6] updates from `make style` --- armsrc/appmain.c | 2 +- bootrom/bootrom.c | 2 +- client/src/cmdhficlass.c | 2 +- common_arm/flashmem.c | 2 +- common_arm/flashmem.h | 46 ---------------------------------------- common_arm/ticks.c | 2 +- common_arm/usb_cdc.c | 14 ++++++------ doc/commands.json | 9 ++++---- 8 files changed, 16 insertions(+), 63 deletions(-) diff --git a/armsrc/appmain.c b/armsrc/appmain.c index 90681c324..66d1380b5 100644 --- a/armsrc/appmain.c +++ b/armsrc/appmain.c @@ -2684,7 +2684,7 @@ void __attribute__((noreturn)) AppMain(void) { 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)); + Flash_UniqueID((uint8_t *)(&flash_uniqueID)); } FlashStop(); usb_update_serial(flash_uniqueID); diff --git a/bootrom/bootrom.c b/bootrom/bootrom.c index c94c23481..9ca0dc430 100644 --- a/bootrom/bootrom.c +++ b/bootrom/bootrom.c @@ -225,7 +225,7 @@ static void flash_mode(void) { #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); + Flash_UniqueID((uint8_t *)&flash_uniqueID); FlashStop(); usb_update_serial(flash_uniqueID); } diff --git a/client/src/cmdhficlass.c b/client/src/cmdhficlass.c index 84a6e563d..53bb483ec 100644 --- a/client/src/cmdhficlass.c +++ b/client/src/cmdhficlass.c @@ -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; } diff --git a/common_arm/flashmem.c b/common_arm/flashmem.c index 0a60d43c0..a81576c5f 100644 --- a/common_arm/flashmem.c +++ b/common_arm/flashmem.c @@ -367,7 +367,7 @@ void Flashmem_print_status(void) { uint8_t uid[8] = {0, 0, 0, 0, 0, 0, 0, 0}; Flash_UniqueID(uid); - Dbprintf( " Unique ID............... " _YELLOW_("0x%02X%02X%02X%02X%02X%02X%02X%02X"), + Dbprintf(" Unique ID............... " _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] ); diff --git a/common_arm/flashmem.h b/common_arm/flashmem.h index 3578fa933..b2456ac76 100644 --- a/common_arm/flashmem.h +++ b/common_arm/flashmem.h @@ -112,56 +112,10 @@ uint16_t FlashSendLastByte(uint32_t data); #ifndef AS_BOOTROM - // Bootrom does not require these functions. - // Wrap in #ifndef to avoid accidental bloat of bootrom - // Bootrom needs only enough to get uniqueID from flash. - // It calls three functions. Full call trees listed: - // - // FlashInit() - // | - // \____ FlashSetup() - // | \____ leaf - // | - // \____ StartTicks() - // | \____ leaf - // | - // \____ Flash_CheckBusy() [*] - // | \____ WaitUS() - // | | \____ WaitTicks() - // | | \____ leaf - // | | - // | \____ StartCountUS() - // | | \____ leaf - // | | - // | \____ GetCountUS() - // | | \____ leaf - // | | - // | \____ Flash_ReadStat1() - // | \____ FlashSendByte() - // | | \____ leaf - // | | - // | \____ FlashSendLastByte() - // | \____ FlashSendByte() - // | \____ leaf - // | - // \____ StopTicks() - // \____ leaf - // - // Flash_UniqueID() - // \____ FlashCheckBusy() (see FlashInit) - // \____ FlashSendByteByte() (see FlashInit) - // \____ FlashSendByteLastByte() (see FlashInit) - // - // - // FlashStop() [*] - - - 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); bool Flash_WipeMemory(void); diff --git a/common_arm/ticks.c b/common_arm/ticks.c index 34c480061..342aa3cab 100644 --- a/common_arm/ticks.c +++ b/common_arm/ticks.c @@ -20,7 +20,7 @@ #include "proxmark3_arm.h" #ifndef AS_BOOTROM - #include "dbprint.h" +#include "dbprint.h" #endif diff --git a/common_arm/usb_cdc.c b/common_arm/usb_cdc.c index 82fc6d0e1..8a17c4f89 100644 --- a/common_arm/usb_cdc.c +++ b/common_arm/usb_cdc.c @@ -405,16 +405,16 @@ void usb_update_serial(uint64_t newSerialNumber) { // 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 + // 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[46-(4*i)] = c1; // [ 46, 42, .., 22, 18 ] - StrSerialNumber[48-(4*i)] = c2; // [ 48, 44, .., 24, 20 ] + 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[46 - (4 * i)] = c1; // [ 46, 42, .., 22, 18 ] + StrSerialNumber[48 - (4 * i)] = c2; // [ 48, 44, .., 24, 20 ] } StrSerialNumber[0] = USB_STRING_DESCRIPTOR_SERIAL_NUMBER_LENGTH; } diff --git a/doc/commands.json b/doc/commands.json index cb68d6069..b8e7be6be 100644 --- a/doc/commands.json +++ b/doc/commands.json @@ -3099,10 +3099,9 @@ "--fc facility code", "--cn card number", "-w, --wiegand see `wiegand list` for available formats", - "--shallow use shallow (ASK) reader modulation instead of OOK", - "-v verbose (print encoded blocks)" + "--shallow use shallow (ASK) reader modulation instead of OOK" ], - "usage": "hf iclass encode [-hv] [--bin ] --ki [--credit] [--elite] [--raw] [--enckey ] [--fc ] [--cn ] [-w ] [--shallow]" + "usage": "hf iclass encode [-h] [--bin ] --ki [--credit] [--elite] [--raw] [--enckey ] [--fc ] [--cn ] [-w ] [--shallow]" }, "hf iclass encrypt": { "command": "hf iclass encrypt", @@ -11507,7 +11506,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 +11903,6 @@ "metadata": { "commands_extracted": 749, "extracted_by": "PM3Help2JSON v1.00", - "extracted_on": "2023-02-11T10:42:29" + "extracted_on": "2023-02-18T01:26:44" } } \ No newline at end of file From 229454963b1bd46d97ba5c927800fd0657782577 Mon Sep 17 00:00:00 2001 From: Henry Gabryjelski Date: Sat, 18 Feb 2023 12:16:50 -0800 Subject: [PATCH 5/6] standardize flash uniqueID to big-endian --- common_arm/flashmem.c | 54 +++++++++++++++++++++---------------------- common_arm/flashmem.h | 7 +++++- common_arm/usb_cdc.c | 4 ++-- 3 files changed, 34 insertions(+), 31 deletions(-) diff --git a/common_arm/flashmem.c b/common_arm/flashmem.c index a81576c5f..eae8f3bef 100644 --- a/common_arm/flashmem.c +++ b/common_arm/flashmem.c @@ -49,9 +49,9 @@ void FlashmemSetSpiBaudrate(uint32_t baudrate) { } // read ID out -uint8_t Flash_ReadID(void) { +bool Flash_ReadID_90(flash_device_type_90_t* result) { - if (Flash_CheckBusy(BUSY_TIMEOUT)) return 0; + if (Flash_CheckBusy(BUSY_TIMEOUT)) return false; // Manufacture ID / device ID FlashSendByte(ID); @@ -59,15 +59,10 @@ uint8_t Flash_ReadID(void) { FlashSendByte(0x00); FlashSendByte(0x00); - uint8_t man_id = FlashSendByte(0xFF); - uint8_t dev_id = FlashSendLastByte(0xFF); + result->manufacturer_id = FlashSendByte(0xFF); + result->device_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; + return true; } uint16_t Flash_ReadData(uint32_t address, uint8_t *out, uint16_t len) { @@ -349,29 +344,32 @@ void Flashmem_print_status(void) { } 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; + // 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............... " _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] + 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(); } diff --git a/common_arm/flashmem.h b/common_arm/flashmem.h index b2456ac76..72cc3e8b7 100644 --- a/common_arm/flashmem.h +++ b/common_arm/flashmem.h @@ -123,7 +123,12 @@ bool Flash_Erase4k(uint8_t block, uint8_t sector); //bool Flash_Erase32k(uint32_t address); bool Flash_Erase64k(uint8_t block); -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); diff --git a/common_arm/usb_cdc.c b/common_arm/usb_cdc.c index 8a17c4f89..6e758c8aa 100644 --- a/common_arm/usb_cdc.c +++ b/common_arm/usb_cdc.c @@ -413,8 +413,8 @@ void usb_update_serial(uint64_t newSerialNumber) { 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[46 - (4 * i)] = c1; // [ 46, 42, .., 22, 18 ] - StrSerialNumber[48 - (4 * i)] = c2; // [ 48, 44, .., 24, 20 ] + 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; } From c531bd0f65576d560738d808ef08acf9402d6483 Mon Sep 17 00:00:00 2001 From: Henry Gabryjelski Date: Sat, 18 Feb 2023 12:20:43 -0800 Subject: [PATCH 6/6] make style updates --- common_arm/flashmem.c | 16 ++++++++-------- common_arm/flashmem.h | 2 +- common_arm/usb_cdc.c | 4 ++-- doc/commands.json | 7 ++++--- 4 files changed, 15 insertions(+), 14 deletions(-) diff --git a/common_arm/flashmem.c b/common_arm/flashmem.c index eae8f3bef..5a115da1a 100644 --- a/common_arm/flashmem.c +++ b/common_arm/flashmem.c @@ -49,7 +49,7 @@ void FlashmemSetSpiBaudrate(uint32_t baudrate) { } // read ID out -bool Flash_ReadID_90(flash_device_type_90_t* result) { +bool Flash_ReadID_90(flash_device_type_90_t *result) { if (Flash_CheckBusy(BUSY_TIMEOUT)) return false; @@ -354,20 +354,20 @@ void Flashmem_print_status(void) { DbpString(" Memory size............. " _GREEN_("2 mbits / 256 kb")); } else { Dbprintf(" Device ID............... " _YELLOW_("%02X / %02X (unknown)"), - device_type.manufacturer_id, device_type.device_id ); + 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] + 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] + 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(); diff --git a/common_arm/flashmem.h b/common_arm/flashmem.h index 72cc3e8b7..f60b73c58 100644 --- a/common_arm/flashmem.h +++ b/common_arm/flashmem.h @@ -127,7 +127,7 @@ 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); +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); diff --git a/common_arm/usb_cdc.c b/common_arm/usb_cdc.c index 6e758c8aa..cb2d0c64a 100644 --- a/common_arm/usb_cdc.c +++ b/common_arm/usb_cdc.c @@ -413,8 +413,8 @@ void usb_update_serial(uint64_t newSerialNumber) { 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[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; } diff --git a/doc/commands.json b/doc/commands.json index b8e7be6be..3b1ac6aca 100644 --- a/doc/commands.json +++ b/doc/commands.json @@ -3099,9 +3099,10 @@ "--fc facility code", "--cn card number", "-w, --wiegand see `wiegand list` for available formats", - "--shallow use shallow (ASK) reader modulation instead of OOK" + "--shallow use shallow (ASK) reader modulation instead of OOK", + "-v verbose (print encoded blocks)" ], - "usage": "hf iclass encode [-h] [--bin ] --ki [--credit] [--elite] [--raw] [--enckey ] [--fc ] [--cn ] [-w ] [--shallow]" + "usage": "hf iclass encode [-hv] [--bin ] --ki [--credit] [--elite] [--raw] [--enckey ] [--fc ] [--cn ] [-w ] [--shallow]" }, "hf iclass encrypt": { "command": "hf iclass encrypt", @@ -11903,6 +11904,6 @@ "metadata": { "commands_extracted": 749, "extracted_by": "PM3Help2JSON v1.00", - "extracted_on": "2023-02-18T01:26:44" + "extracted_on": "2023-02-18T20:20:19" } } \ No newline at end of file