From: Michael McMaster Date: Sun, 19 Apr 2020 04:36:08 +0000 (+1000) Subject: Add hardware version checks, and embed version marker in the one-time-programmable... X-Git-Tag: v6.3.1-2020~1 X-Git-Url: http://git.codesrc.com/gitweb.cgi?a=commitdiff_plain;h=e66766d115fe2504e5b74e556e29d011e5b5e0d5;p=SCSI2SD-V6.git Add hardware version checks, and embed version marker in the one-time-programmable flash memory --- diff --git a/CHANGELOG b/CHANGELOG index ccc5e9e7..e6dccb96 100644 --- 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. diff --git a/Makefile b/Makefile index 5529f3c1..df9d40c6 100644 --- a/Makefile +++ b/Makefile @@ -40,6 +40,8 @@ build/stm32cubemx/usbd_conf.o: STM32CubeMX/SCSI2SD-V6/Src/usbd_conf.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 @@ -73,6 +75,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 \ @@ -116,6 +120,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 \ @@ -171,3 +176,4 @@ clean: program: dfu-util --download build/firmware.dfu --alt 0 + diff --git a/src/firmware/config.c b/src/firmware/config.c index ce771ef7..46ef3d7b 100755 --- a/src/firmware/config.c +++ b/src/firmware/config.c @@ -37,7 +37,7 @@ #include -static const uint16_t FIRMWARE_VERSION = 0x0630; +static const uint16_t FIRMWARE_VERSION = 0x0631; // Optional static config extern uint8_t* __fixed_config; diff --git a/src/firmware/main.c b/src/firmware/main.c index 8a8e3653..6392c4fb 100755 --- a/src/firmware/main.c +++ b/src/firmware/main.c @@ -21,6 +21,7 @@ #include "bsp.h" #include "disk.h" #include "fpga.h" +#include "hwversion.h" #include "led.h" #include "sd.h" #include "scsi.h" @@ -31,8 +32,7 @@ #include "usb_device/usbd_composite.h" #include "usb_device/usbd_msc_storage_sd.h" - -const char* Notice = "Copyright (C) 2019 Michael McMaster "; +const char* Notice = "Copyright (C) 2020 Michael McMaster "; uint32_t lastSDPoll; static int isUsbStarted; @@ -45,11 +45,12 @@ void mainEarlyInit() void mainInit() { + s2s_timeInit(); + s2s_checkHwVersion(); + // DISable the ULPI chip - // NO SEE AN4879: CLOCK IS INPUT ONLY YOU IDIOT. HAL_GPIO_WritePin(nULPI_RESET_GPIO_Port, nULPI_RESET_Pin, GPIO_PIN_RESET); - s2s_timeInit(); s2s_ledInit(); s2s_fpgaInit(); diff --git a/src/firmware/usb_device/usbd_desc.c b/src/firmware/usb_device/usbd_desc.c index a9e71482..9f81fb01 100755 --- a/src/firmware/usb_device/usbd_desc.c +++ b/src/firmware/usb_device/usbd_desc.c @@ -60,10 +60,7 @@ #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" @@ -74,6 +71,10 @@ /** @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; + } } /** diff --git a/src/scsi2sd-util6/SCSI2SD_HID.cc b/src/scsi2sd-util6/SCSI2SD_HID.cc index 94db8b51..7560c90e 100644 --- a/src/scsi2sd-util6/SCSI2SD_HID.cc +++ b/src/scsi2sd-util6/SCSI2SD_HID.cc @@ -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; +} diff --git a/src/scsi2sd-util6/SCSI2SD_HID.hh b/src/scsi2sd-util6/SCSI2SD_HID.hh index d22a4a3a..315e7d0d 100644 --- a/src/scsi2sd-util6/SCSI2SD_HID.hh +++ b/src/scsi2sd-util6/SCSI2SD_HID.hh @@ -68,6 +68,9 @@ public: bool readSCSIDebugInfo(std::vector& buf); + std::string getSerialNumber(); + std::string getHardwareVersion(); + bool isCorrectFirmware(const std::string& path); private: HID(hid_device_info* hidInfo); void destroy(); diff --git a/src/scsi2sd-util6/scsi2sd-util.cc b/src/scsi2sd-util6/scsi2sd-util.cc index ebdc8f74..ddd10919 100644 --- a/src/scsi2sd-util6/scsi2sd-util.cc +++ b/src/scsi2sd-util6/scsi2sd-util.cc @@ -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 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(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 csd(myHID->getSD_CSD()); std::vector cid(myHID->getSD_CID()); std::stringstream sdinfo;