Add hardware version checks, and embed version marker in the one-time-programmable...
authorMichael McMaster <michael@codesrc.com>
Sun, 19 Apr 2020 04:36:08 +0000 (14:36 +1000)
committerMichael McMaster <michael@codesrc.com>
Sun, 19 Apr 2020 09:01:01 +0000 (19:01 +1000)
CHANGELOG
Makefile
src/firmware/config.c
src/firmware/main.c
src/firmware/usb_device/usbd_desc.c
src/scsi2sd-util6/SCSI2SD_HID.cc
src/scsi2sd-util6/SCSI2SD_HID.hh
src/scsi2sd-util6/scsi2sd-util.cc

index ccc5e9e..e6dccb9 100644 (file)
--- a/CHANGELOG
+++ b/CHANGELOG
@@ -1,3 +1,8 @@
+20200419               6.3.1
+       - Added checks to ensure the correct firmware version is loaded.
+       V6 Rev.f and older boards need the "firmware.V6.revF.dfu" firmware updates.
+       V6 2020c and newer boards need the "firmware.V6.2020.dfu" firmware updates.
+
 20200216               6.3.0
        - Breaking change: Firmware updates on windows now require the UsbDK
        driver to be installed.
index b81734a..812b3ae 100644 (file)
--- a/Makefile
+++ b/Makefile
@@ -43,6 +43,8 @@ build/stm32cubemx/usb_host.o: STM32CubeMX/SCSI2SD-V6/Src/usb_host.c
 build/stm32cubemx/stm32f2xx_hal.o: STM32CubeMX/SCSI2SD-V6/Drivers/STM32F2xx_HAL_Driver/Src/stm32f2xx_hal.c
 build/stm32cubemx/stm32f2xx_hal_cortex.o: STM32CubeMX/SCSI2SD-V6/Drivers/STM32F2xx_HAL_Driver/Src/stm32f2xx_hal_cortex.c
 build/stm32cubemx/stm32f2xx_hal_dma.o: STM32CubeMX/SCSI2SD-V6/Drivers/STM32F2xx_HAL_Driver/Src/stm32f2xx_hal_dma.c
+build/stm32cubemx/stm32f2xx_hal_flash.o: STM32CubeMX/SCSI2SD-V6/Drivers/STM32F2xx_HAL_Driver/Src/stm32f2xx_hal_flash.c
+build/stm32cubemx/stm32f2xx_hal_flash_ex.o: STM32CubeMX/SCSI2SD-V6/Drivers/STM32F2xx_HAL_Driver/Src/stm32f2xx_hal_flash_ex.c
 build/stm32cubemx/stm32f2xx_hal_gpio.o: STM32CubeMX/SCSI2SD-V6/Drivers/STM32F2xx_HAL_Driver/Src/stm32f2xx_hal_gpio.c
 build/stm32cubemx/stm32f2xx_hal_hcd.o: STM32CubeMX/SCSI2SD-V6/Drivers/STM32F2xx_HAL_Driver/Src/stm32f2xx_hal_hcd.c
 build/stm32cubemx/stm32f2xx_hal_pcd.o: STM32CubeMX/SCSI2SD-V6/Drivers/STM32F2xx_HAL_Driver/Src/stm32f2xx_hal_pcd.c
@@ -86,6 +88,8 @@ STM32OBJS = \
        build/stm32cubemx/stm32f2xx_hal.o \
        build/stm32cubemx/stm32f2xx_hal_cortex.o \
        build/stm32cubemx/stm32f2xx_hal_dma.o \
+       build/stm32cubemx/stm32f2xx_hal_flash.o \
+       build/stm32cubemx/stm32f2xx_hal_flash_ex.o \
        build/stm32cubemx/stm32f2xx_hal_gpio.o \
        build/stm32cubemx/stm32f2xx_hal_hcd.o \
        build/stm32cubemx/stm32f2xx_hal_pcd.o \
@@ -136,6 +140,7 @@ SRC = \
        src/firmware/fpga.c \
        src/firmware/geometry.c \
        src/firmware/hidpacket.c \
+       src/firmware/hwversion.c \
        src/firmware/inquiry.c \
        src/firmware/led.c \
        src/firmware/main.c \
@@ -190,3 +195,4 @@ clean:
 
 program:
        dfu-util --download build/firmware.dfu --alt 0
+
index ce771ef..46ef3d7 100755 (executable)
@@ -37,7 +37,7 @@
 \r
 #include <string.h>\r
 \r
-static const uint16_t FIRMWARE_VERSION = 0x0630;\r
+static const uint16_t FIRMWARE_VERSION = 0x0631;\r
 \r
 // Optional static config\r
 extern uint8_t* __fixed_config;\r
index ed37b5c..a67460b 100755 (executable)
@@ -21,6 +21,7 @@
 #include "bsp.h"\r
 #include "disk.h"\r
 #include "fpga.h"\r
+#include "hwversion.h"\r
 #include "led.h"\r
 #include "sd.h"\r
 #include "scsi.h"\r
@@ -31,8 +32,7 @@
 #include "usb_device/usbd_composite.h"\r
 #include "usb_device/usbd_msc_storage_sd.h"\r
 \r
-\r
-const char* Notice = "Copyright (C) 2016 Michael McMaster <michael@codesrc.com>";\r
+const char* Notice = "Copyright (C) 2020 Michael McMaster <michael@codesrc.com>";\r
 uint32_t lastSDPoll;\r
 \r
 static int isUsbStarted;\r
@@ -46,6 +46,8 @@ void mainEarlyInit()
 void mainInit()\r
 {\r
        s2s_timeInit();\r
+       s2s_checkHwVersion();\r
+\r
        s2s_ledInit();\r
        s2s_fpgaInit();\r
 \r
index f7b30d3..3aa984b 100755 (executable)
 #define USBD_LANGID_STRING               1033
 #define USBD_MANUFACTURER_STRING         (uint8_t*)"codesrc.com"
 #define USBD_PID_FS                      0x0BD4
-#define USBD_PRODUCT_STRING_FS           (uint8_t*)"SCSI2SD"
-/* USER CODE BEGIN SERIALNUMBER_STRING_FS */
-#define USBD_SERIALNUMBER_STRING_FS      (uint8_t*)"000000000000"
-/* USER CODE END SERIALNUMBER_STRING_FS */
+#define USBD_PRODUCT_STRING_FS           (uint8_t*)"SCSI2SD 2020"
 #define USBD_CONFIGURATION_STRING_FS     (uint8_t*)"SCSI2SD Config"
 #define USBD_INTERFACE_STRING_FS         (uint8_t*)"SCSI2SD Interface"
 
 /** @defgroup USBD_DESC_Private_Macros
   * @{
   */ 
+
+static void Get_SerialNum(void);
+static void IntToUnicode(uint32_t value, uint8_t * pbuf, uint8_t len);
+
 /**
   * @}
   */ 
@@ -155,6 +156,13 @@ __ALIGN_BEGIN uint8_t USBD_StrDesc[USBD_MAX_STR_DESC_SIZ] __ALIGN_END;
 /** @defgroup USBD_DESC_Private_FunctionPrototypes
   * @{
   */ 
+
+#define  USB_SIZ_STRING_SERIAL       0x1A
+__ALIGN_BEGIN uint8_t USBD_StringSerial[USB_SIZ_STRING_SERIAL] __ALIGN_END = {
+  USB_SIZ_STRING_SERIAL,
+  USB_DESC_TYPE_STRING,
+};
+
 /**
   * @}
   */ 
@@ -231,15 +239,69 @@ uint8_t *  USBD_FS_ManufacturerStrDescriptor( USBD_SpeedTypeDef speed , uint16_t
 */
 uint8_t *  USBD_FS_SerialStrDescriptor( USBD_SpeedTypeDef speed , uint16_t *length)
 {
-  if(speed  == USBD_SPEED_HIGH)
-  {    
-    USBD_GetString (USBD_SERIALNUMBER_STRING_FS, USBD_StrDesc, length);
-  }
-  else
-  {
-    USBD_GetString (USBD_SERIALNUMBER_STRING_FS, USBD_StrDesc, length);    
-  }
-  return USBD_StrDesc;
+       *length = USB_SIZ_STRING_SERIAL;
+
+       // Update the serial number string descriptor with the data from the unique
+       // ID
+       Get_SerialNum();
+
+       return (uint8_t *) USBD_StringSerial;
+}
+
+/**
+ * @brief  Create the serial number string descriptor
+ * @param  None
+ * @retval None
+ */
+static void Get_SerialNum(void)
+{
+       uint32_t deviceserial0, deviceserial1, deviceserial2;
+
+// UID_BASE good for STM32F2 and F4
+#define                UID_BASE                        0x1FFF7A10
+#define         DEVICE_ID1          (UID_BASE)
+#define         DEVICE_ID2          (UID_BASE + 0x4)
+#define         DEVICE_ID3          (UID_BASE + 0x8)
+
+       deviceserial0 = *(uint32_t *) DEVICE_ID1;
+       deviceserial1 = *(uint32_t *) DEVICE_ID2;
+       deviceserial2 = *(uint32_t *) DEVICE_ID3;
+
+       deviceserial0 += deviceserial2;
+
+       if (deviceserial0 != 0)
+       {
+               IntToUnicode(deviceserial0, &USBD_StringSerial[2], 8);
+               IntToUnicode(deviceserial1, &USBD_StringSerial[18], 4);
+       }
+}
+
+/**
+ * @brief  Convert Hex 32Bits value into char
+ * @param  value: value to convert
+ * @param  pbuf: pointer to the buffer
+ * @param  len: buffer length
+ * @retval None
+ */
+static void IntToUnicode(uint32_t value, uint8_t * pbuf, uint8_t len)
+{
+       uint8_t idx = 0;
+
+       for (idx = 0; idx < len; idx++)
+       {
+               if (((value >> 28)) < 0xA)
+               {
+                       pbuf[2 * idx] = (value >> 28) + '0';
+               }
+               else
+               {
+                       pbuf[2 * idx] = (value >> 28) + 'A' - 10;
+               }
+
+               value = value << 4;
+
+               pbuf[2 * idx + 1] = 0;
+       }
 }
 
 /**
index 94db8b5..7560c90 100644 (file)
@@ -334,4 +334,95 @@ HID::sendHIDPacket(
                resp + respLen);
 }
 
+std::string
+HID::getHardwareVersion()
+{
+       if (myFirmwareVersion < 0x0630)
+       {
+               // Definitely the 2020c or newer hardware.
+               return "V6, Rev F or older";
+       }
+       else if (myFirmwareVersion == 0x0630)
+       {
+               return "V6, unknown.";
+       }
+       else
+       {
+               const size_t maxUsbString = 255;
+               wchar_t wstr[maxUsbString];
+               int res = hid_get_product_string(myConfigHandle, wstr, maxUsbString);
+               if (res == 0)
+               {
+                       std::wstring prodStr(wstr);
+                       if (prodStr.find(L"2020") != std::string::npos)
+                       {
+                               // Definitely the 2020c or newer hardware.
+                               return "V6, 2020c or newer";
+                       }
+                       else
+                       {
+                               return "V6, Rev F or older";
+                       }
+               }
+       }
+
+       return "Unknown";
+}
+
+std::string
+HID::getSerialNumber()
+{
+       const size_t maxUsbString = 255;
+       wchar_t wstr[maxUsbString];
+       int res = hid_get_serial_number_string(myConfigHandle, wstr, maxUsbString);
+       if (res == 0)
+       {
+               std::wstring wideString(wstr);
+               return std::string(wideString.begin(), wideString.end());
+       }
+
+       return std::string();
+}
+
+
+bool
+HID::isCorrectFirmware(const std::string& path)
+{
+       if (myFirmwareVersion < 0x0630)
+       {
+               // Definitely the 2020c or newer hardware.
+               return path.rfind("firmware.V6.revF.dfu") != std::string::npos ||
+                       path.rfind("firmware.dfu") != std::string::npos;
+       }
+       else if (myFirmwareVersion == 0x0630)
+       {
+               // We don't know which. :-( Initial batch of 2020 boards loaded with
+               // v6.3.0
+               // So for now we CANNOT bundle ? User will need to selet the correct
+               // file.
+               return true;
+       }
+       else
+       {
+               const size_t maxUsbString = 255;
+               wchar_t wstr[maxUsbString];
+               int res = hid_get_product_string(myConfigHandle, wstr, maxUsbString);
+               if (res == 0)
+               {
+                       std::wstring prodStr(wstr);
+                       if (prodStr.find(L"2020") != std::string::npos)
+                       {
+                               // Definitely the 2020c or newer hardware.
+                               return path.rfind("firmware.V6.2020.dfu") != std::string::npos;
+                       }
+                       else
+                       {
+                               return path.rfind("firmware.V6.revF.dfu") != std::string::npos ||
+                                       path.rfind("firmware.dfu") != std::string::npos;
+                       }
+               }
+       }
+
+       return false;
+}
 
index d22a4a3..315e7d0 100644 (file)
@@ -68,6 +68,9 @@ public:
 
        bool readSCSIDebugInfo(std::vector<uint8_t>& buf);
 
+       std::string getSerialNumber();
+       std::string getHardwareVersion();
+       bool isCorrectFirmware(const std::string& path);
 private:
        HID(hid_device_info* hidInfo);
        void destroy();
index ebdc8f7..ddd1091 100644 (file)
@@ -475,6 +475,7 @@ private:
                if (dlg.ShowModal() == wxID_CANCEL) return;
 
                std::string filename(dlg.GetPath());
+               wxLogMessage("Attempting firmware update from file %s", filename);
 
                wxWindowPtr<wxGenericProgressDialog> progress(
                        new wxGenericProgressDialog(
@@ -485,6 +486,7 @@ private:
                                wxPD_AUTO_HIDE | wxPD_CAN_ABORT)
                                );
                mmLogStatus("Searching for bootloader");
+               bool versionChecked = false;
                while (true)
                {
                        try
@@ -492,6 +494,16 @@ private:
                                if (!myHID) myHID.reset(HID::Open());
                                if (myHID)
                                {
+                                       if (!myHID->isCorrectFirmware(filename))
+                                       {
+                                               wxMessageBox(
+                                                       "Firmware does not match device hardware",
+                                                       "Wrong filename",
+                                                       wxOK | wxICON_ERROR);
+                                               return;
+                                       }
+                                       versionChecked = true;
+
                                        mmLogStatus("Resetting SCSI2SD into bootloader");
 
                                        myHID->enterBootloader();
@@ -499,10 +511,25 @@ private:
                                }
 
 
+                               if (myDfu.hasDevice() && !versionChecked)
+                               {
+                                       mmLogStatus("STM DFU Bootloader found, checking compatibility");
+                                       progress->Show(0);
+                                       if (!checkVersionMarker(filename))
+                                       {
+                                               wxMessageBox(
+                                                       "Firmware does not match device hardware",
+                                                       "Wrong filename",
+                                                       wxOK | wxICON_ERROR);
+                                               return;
+                                       }
+                                       versionChecked = true;
+                               }
+
                                if (myDfu.hasDevice())
                                {
                                        mmLogStatus("STM DFU Bootloader found");
-                                       progress->Show(0);
+                                       progress->Show(10);
                                        doDFUUpdate(filename);
                                        return;
                                }
@@ -520,6 +547,90 @@ private:
                }
        }
 
+       bool checkVersionMarker(const std::string& firmware)
+       {
+               std::stringstream ss;
+#ifdef __WINDOWS__
+               ss << "dfu-util ";
+#else
+               if (wxExecute("which dfu-util", wxEXEC_SYNC) == 0)
+               {
+                       ss << "dfu-util ";
+               } else {
+                       wxFileName exePath(wxStandardPaths::Get().GetExecutablePath());
+                       ss << '"' << exePath.GetPathWithSep() << "dfu-util\" ";
+               }
+#endif
+
+               std::string tmpFile =
+                       wxFileName::CreateTempFileName(
+                               _("SCSI2SD_MARKER"), static_cast<wxFile*>(NULL));
+               wxRemoveFile(tmpFile); // dfu-util won't overwrite.
+
+               ss << "--alt 2 -s 0x1FFF7800:4 -U \"" << tmpFile << "\"";
+
+               wxLogMessage("Running: %s", ss.str());
+
+               std::string cmd = ss.str();
+               long result = wxExecute(
+                       cmd.c_str(),
+                       wxEXEC_SYNC
+                       );
+               if (result != 0)
+               {
+                       wxLogMessage("OTP Version check failed.");
+                       return false;
+               }
+
+               // Ok, we now have a file with 8 bytes in it.
+               wxFile file(tmpFile);
+               if (file.Length() != 4)
+               {
+                       wxLogMessage("OTP Version check file isn't 4 bytes.");
+                       return false;
+               }
+
+               uint8_t data[4];
+               if (file.Read(data, sizeof(data)) != sizeof(data))
+               {
+                       wxMessageBox(
+                               "Couldn't read file",
+                               "Couldn't read file",
+                               wxOK | wxICON_ERROR);
+                       return false;
+               }
+               wxRemoveFile(tmpFile);
+
+               uint32_t value =
+                       (((uint32_t)(data[0]))) |
+                       (((uint32_t)(data[1])) << 8) |
+                       (((uint32_t)(data[2])) << 16) |
+                       (((uint32_t)(data[3])) << 24);
+               if (value == 0xFFFFFFFF)
+               {
+                       // Not set, ignore.
+                       wxLogMessage("OTP Hardware version not set. Ignoring.");
+                       return true;
+               }
+               else if (value == 0x06002020)
+               {
+                       wxLogMessage("Found V6 2020 hardware marker");
+                       return firmware.rfind("firmware.V6.2020.dfu") != std::string::npos;
+               }
+               else if (value == 0x06002019)
+               {
+                       wxLogMessage("Found V6 revF hardware marker");
+                       return firmware.rfind("firmware.V6.revF.dfu") != std::string::npos ||
+                               firmware.rfind("firmware.dfu") != std::string::npos;
+               }
+               else
+               {
+                       wxLogMessage("Found unknown hardware marker: %u", value);
+                       return false; // Some unknown version.
+               }
+       }
+
+
        void doDFUUpdate(const std::string& filename)
        {
                if (filename.find(".dfu") == std::string::npos)
@@ -531,7 +642,6 @@ private:
                        return;
                }
 
-
                std::stringstream ss;
 #ifdef __WINDOWS__
                ss << "dfu-util --download \""
@@ -697,6 +807,13 @@ private:
                                                myHID->getFirmwareVersionStr();
                                        mmLogStatus(msg.str());
 
+                                       std::stringstream devInfo;
+                                       devInfo << "Hardware version: " <<
+                                               myHID->getHardwareVersion() << std::endl <<
+                                               "Serial Number: " <<
+                                               myHID->getSerialNumber();
+                                       wxLogMessage(this, "%s", devInfo.str());
+
                                        std::vector<uint8_t> csd(myHID->getSD_CSD());
                                        std::vector<uint8_t> cid(myHID->getSD_CID());
                                        std::stringstream sdinfo;