1 /*
2  * HidUpdateManager.h
3  *
4  * Recovery for broken eZ-FETs and MSP-FET Debuggers
5  *
6  * Copyright (C) 2007 - 2011 Texas Instruments Incorporated - http://www.ti.com/
7  *
8  *
9  *  Redistribution and use in source and binary forms, with or without
10  *  modification, are permitted provided that the following conditions
11  *  are met:
12  *
13  *    Redistributions of source code must retain the above copyright
14  *    notice, this list of conditions and the following disclaimer.
15  *
16  *    Redistributions in binary form must reproduce the above copyright
17  *    notice, this list of conditions and the following disclaimer in the
18  *    documentation and/or other materials provided with the
19  *    distribution.
20  *
21  *    Neither the name of Texas Instruments Incorporated nor the names of
22  *    its contributors may be used to endorse or promote products derived
23  *    from this software without specific prior written permission.
24  *
25  *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
26  *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
27  *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
28  *  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
29  *  OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
30  *  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
31  *  LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
32  *  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
33  *  THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
34  *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
35  *  OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
36  */
37 
38 #include <pch.h>
39 #include "HidUpdateManager.h"
40 
41 #include <hidapi.h>
42 
43 #include <BSL430_DLL/Connections/MSPBSL_Connection5xxUSB.h>
44 #include <BSL430_DLL/MSPBSL_Factory.h>
45 #include <BSL430_DLL/Utility_Classes/MSPBSL_CRCEngine.h>
46 
47 #include "MemoryContent.h"
48 
49 #include "../../../../Bios/include/eZ_FetCore.h"
50 #include "../../../../Bios/include/MSP_FetCore.h"
51 
52 using namespace TI::DLL430;
53 using namespace std;
54 
55 struct BslFetWrapper
56 {
BslFetWrapperBslFetWrapper57 	explicit BslFetWrapper(MSPBSL_Connection5xxUSB *ptr) : ptr_(ptr)
58 	{
59 	}
60 
operator =BslFetWrapper61 	BslFetWrapper& operator=(BslFetWrapper& bsl)
62 	{
63 		return *this;
64 	}
65 
~BslFetWrapperBslFetWrapper66 	~BslFetWrapper()
67 	{
68 		if (ptr_)
69 		{
70 			ptr_->closeBslconnection();
71 			delete ptr_;
72 		}
73 
74 		ptr_ = nullptr;
75 
76 		hid_exit();
77 	}
78 
getBslFetWrapper79 	MSPBSL_Connection5xxUSB* get()
80 	{
81 		return ptr_;
82 	}
83 
isNullBslFetWrapper84 	bool isNull() const
85 	{
86 		return ptr_ == nullptr;
87 	}
88 
89 	MSPBSL_Connection5xxUSB *ptr_;
90 };
91 
countHidDevices(uint16_t productId)92 uint32_t HidUpdateManager::countHidDevices(uint16_t productId)
93 {
94 	hid_device_info *hidDevices = hid_enumerate(MSPBSL_STANDARD_USB_VID, productId);
95 	hid_device_info *hidDevicesIt = hidDevices;
96 
97 	uint32_t count = 0;
98 	while (hidDevicesIt != nullptr)
99 	{
100 		count++;
101 		hidDevicesIt =  hidDevicesIt->next;
102 	}
103 	hid_free_enumeration(hidDevices);
104 	hid_exit();
105 
106 	return count;
107 }
108 
109 
HidUpdateManager()110 HidUpdateManager::HidUpdateManager ()
111 {
112 }
113 
~HidUpdateManager()114 HidUpdateManager::~HidUpdateManager (){}
115 
hid_firmWareUpdate(const char * fname,UpdateNotifyCallback callback)116 bool HidUpdateManager::hid_firmWareUpdate(const char * fname, UpdateNotifyCallback callback)
117 {
118 	bool returnValue = false;
119 	try
120 	{
121 		const bool eZRecoveryNeeded = (HidUpdateManager::countHidDevices(MSPBSL_EZ_FET_USB_PID) > 0);
122 		const bool mspFetRecoveryNeeded = (HidUpdateManager::countHidDevices(MSPBSL_MSP_FET_USB_PID) > 0);
123 
124 		uint16_t currentPid = 0;
125 		if (eZRecoveryNeeded)
126 		{
127 			currentPid = MSPBSL_EZ_FET_USB_PID;
128 		}
129 		else if (mspFetRecoveryNeeded)
130 		{
131 			currentPid = MSPBSL_MSP_FET_USB_PID;
132 		}
133 
134 		//------------------------------------------------------------------------------------------
135 		BslFetWrapper bslWrapper(hid_enumerateBSL(currentPid));
136 
137 		if (bslWrapper.isNull())
138 		{
139 			return false;
140 		}
141 
142 		uint32_t requiredUpdates = 3;
143 		const uint32_t percent = 100/requiredUpdates;
144 
145 		if (callback)
146 		{
147 			callback(BL_INIT, 0, 0);
148 			callback(BL_PROGRAM_FIRMWARE, 0, 0);
149 			callback(BL_DATA_BLOCK_PROGRAMMED, 0, 0);
150 		}
151 
152 		MemoryContent firmware;
153 
154 		if (eZRecoveryNeeded)
155 		{
156 			uint16_t toolIdBSL = hid_getBSLToolId(bslWrapper.get());
157 			if (toolIdBSL == eZ_FET_WITH_DCDC || toolIdBSL == eZ_FET_WITH_DCDC_0X3FF || toolIdBSL == eZ_FET_NO_DCDC || toolIdBSL == eZ_FET_WITH_DCDC_NO_FLOWCT || toolIdBSL == eZ_FET_WITH_DCDC_V2x)
158 			{
159 				//load eZ-FET CORE imag ewith TOOL ID 0xAAAA -> DCDC Sub mcu is present
160 				firmware.fromSRec(eZ_FetCoreImage, eZ_FetCoreImage_address, eZ_FetCoreImage_length_of_sections, eZ_FetCoreImage_sections);
161 			}
162 		}
163 		else if (mspFetRecoveryNeeded)
164 		{
165 			uint16_t toolIdBSL = hid_getBSLToolId(bslWrapper.get());
166 			if (toolIdBSL == MSP_FET_WITH_DCDC || toolIdBSL == MSP_FET_WITH_DCDC_V2x)
167 			{
168 				firmware.fromSRec(MSP_FetCoreImage, MSP_FetCoreImage_address, MSP_FetCoreImage_length_of_sections, MSP_FetCoreImage_sections);
169 			}
170 		}
171 
172 		if (callback)
173 		{
174 			callback(BL_DATA_BLOCK_PROGRAMMED, (100-(--requiredUpdates)*percent), 0);
175 		}
176 
177 		returnValue = hid_updateCore(firmware, bslWrapper.get());
178 
179 		if (callback)
180 		{
181 			callback(BL_DATA_BLOCK_PROGRAMMED, (100-(--requiredUpdates)*percent), 0);
182 		}
183 	}
184 	catch (...)
185 	{
186 		returnValue = false;
187 	}
188 
189 	if (callback)
190 	{
191 		callback(BL_DATA_BLOCK_PROGRAMMED, 100, 0);
192 		callback(BL_UPDATE_DONE, 0, 0);
193 		callback(BL_EXIT, 0, 0);
194 	}
195 	return returnValue;
196 }
197 
hid_getBSLToolId(MSPBSL_Connection5xxUSB * bsl)198 uint16_t HidUpdateManager::hid_getBSLToolId(MSPBSL_Connection5xxUSB* bsl)
199 {
200 	uint8_t data[2];
201 	// read tool-ID stored in BSL memory
202 	bsl->TX_DataBlock(data, 0x100e, 2);
203 	uint16_t toolId = data[1];
204 	toolId = toolId<<8;
205 	toolId |= static_cast<uint16_t>(data[0]);
206 	return toolId;
207 }
208 
hid_enumerateBSL(uint16_t currentPid)209 MSPBSL_Connection5xxUSB* HidUpdateManager::hid_enumerateBSL(uint16_t currentPid)
210 {
211 	string currentDevice = "";
212 
213 	if (currentPid == MSPBSL_MSP_FET_USB_PID)
214 	{
215 		currentDevice = "MSP430F6638";
216 	}
217 	if (currentPid == MSPBSL_EZ_FET_USB_PID)
218 	{
219 		currentDevice = "MSP430F5528";
220 	}
221 
222 	MSPBSL_Connection5xxUSB* BslFet = dynamic_cast<MSPBSL_Connection5xxUSB*>(MSPBSL_Factory::getMSPBSL_Connection("DEVICE:" + currentDevice + " VID:0x2047 PID:0x"+ convertPid(currentPid) +"")); // works for 6638 and 5528 because of generic usb bsl
223 
224 	if (BslFet)
225 	{
226 		if (BslFet->loadRAM_BSL(currentPid) != 0)
227 		{
228 			//Reset FET
229 			BslFet->closeBslconnection();
230 			delete BslFet;
231 			return 0;
232 		}
233 		string verString = "BUG";
234 		BslFet->TX_BSL_Version(verString);
235 	}
236 
237 	return BslFet;
238 }
239 
hid_updateCore(const MemoryContent & firmware,MSPBSL_Connection5xxUSB * BslFet) const240 bool HidUpdateManager::hid_updateCore(const MemoryContent &firmware, MSPBSL_Connection5xxUSB* BslFet) const
241 {
242 	// erase reset vector of core
243 	BslFet->massErase();
244 	BslFet->eraseSegment(0x197F);
245 	BslFet->eraseSegment(0x18FF);
246 	BslFet->eraseSegment(0x187F);
247 
248 	// Info A hanlding -> unlock it
249 	BslFet->toggleInfo();
250 	// erase Info A
251 	BslFet->eraseSegment(0x19FF);
252 
253 	if (firmware.segments.empty())
254 	{
255 		return false;
256 	}
257 
258 	for (size_t i = 0; i < firmware.segments.size(); i++)
259 	{
260 		const DataSegment& seg = firmware.segments[i];
261 
262 		vector<uint8_t> Buffer(seg.data.size());
263 
264 		MSPBSL_CRCEngine crcEngine("5xx_CRC");
265 		crcEngine.initEngine(0xFFFF);
266 
267 		for (uint32_t n=0; n < seg.data.size(); n++)
268 		{
269 			Buffer[n]= (seg.data[n] & 0xff);
270 			crcEngine.addByte(seg.data[n] & 0xff);
271 		}
272 
273 		BslFet->RX_DataBlockFast(&Buffer[0], (uint32_t)seg.startAddress&0xfffffffe, (uint16_t)seg.data.size());
274 
275 		uint16_t currentCoreCRC[1];
276 		BslFet->CRC_Check(currentCoreCRC, (uint32_t)seg.startAddress & 0xfffffffe, static_cast<uint16_t>(seg.data.size()));
277 
278 		uint32_t expectedCoreCRC = crcEngine.getHighByte()<<8;
279 		expectedCoreCRC |= static_cast<uint32_t>(crcEngine.getLowByte());
280 
281 		if (expectedCoreCRC != currentCoreCRC[0])
282 		{
283 			if (i != 0)// just debug exeption
284 			{
285 				BslFet->closeBslconnection();
286 				return false;
287 			}
288 		}
289 
290 	}
291 	return true;
292 }
293