From 5784c8de77f6cabf4d27c76f412dd3a9b441ff63 Mon Sep 17 00:00:00 2001 From: Henry Gabryjelski Date: Fri, 17 Feb 2023 15:42:46 -0800 Subject: [PATCH] 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);