+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.
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
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 \
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 \
program:
dfu-util --download build/firmware.dfu --alt 0
+
\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
#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
#include "usb_device/usbd_composite.h"\r
#include "usb_device/usbd_msc_storage_sd.h"\r
\r
-\r
-const char* Notice = "Copyright (C) 2019 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
\r
void mainInit()\r
{\r
+ s2s_timeInit();\r
+ s2s_checkHwVersion();\r
+\r
// DISable the ULPI chip\r
- // NO SEE AN4879: CLOCK IS INPUT ONLY YOU IDIOT.\r
HAL_GPIO_WritePin(nULPI_RESET_GPIO_Port, nULPI_RESET_Pin, GPIO_PIN_RESET);\r
\r
- s2s_timeInit();\r
s2s_ledInit();\r
s2s_fpgaInit();\r
\r
#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);
+
/**
* @}
*/
/** @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,
+};
+
/**
* @}
*/
*/
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;
+ }
}
/**
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;
+}
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();
if (dlg.ShowModal() == wxID_CANCEL) return;
std::string filename(dlg.GetPath());
+ wxLogMessage("Attempting firmware update from file %s", filename);
wxWindowPtr<wxGenericProgressDialog> progress(
new wxGenericProgressDialog(
wxPD_AUTO_HIDE | wxPD_CAN_ABORT)
);
mmLogStatus("Searching for bootloader");
+ bool versionChecked = false;
while (true)
{
try
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();
}
+ 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;
}
}
}
+ 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)
return;
}
-
std::stringstream ss;
#ifdef __WINDOWS__
ss << "dfu-util --download \""
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;