Procházet zdrojové kódy

Add hardware version checks, and embed version marker in the one-time-programmable flash memory

Michael McMaster před 5 roky
rodič
revize
39de641376

+ 5 - 0
lib/SCSI2SD/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.

+ 6 - 0
lib/SCSI2SD/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
+

+ 1 - 1
lib/SCSI2SD/src/firmware/config.c

@@ -37,7 +37,7 @@
 
 #include <string.h>
 
-static const uint16_t FIRMWARE_VERSION = 0x0630;
+static const uint16_t FIRMWARE_VERSION = 0x0631;
 
 // Optional static config
 extern uint8_t* __fixed_config;

+ 5 - 4
lib/SCSI2SD/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 <michael@codesrc.com>";
+const char* Notice = "Copyright (C) 2020 Michael McMaster <michael@codesrc.com>";
 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();
 

+ 75 - 13
lib/SCSI2SD/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;
+	}
 }
 
 /**

+ 91 - 0
lib/SCSI2SD/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;
+}
 

+ 3 - 0
lib/SCSI2SD/src/scsi2sd-util6/SCSI2SD_HID.hh

@@ -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();

+ 119 - 2
lib/SCSI2SD/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<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;