xref: /aosp_15_r20/external/rmi4utils/rmi4update/rmi4update.cpp (revision a248dafd7653b99fc45f9d29e5f139b04f2f28bc)
1 /*
2  * Copyright (C) 2014 Andrew Duggan
3  * Copyright (C) 2014 Synaptics Inc
4  *
5  * Licensed under the Apache License, Version 2.0 (the "License");
6  * you may not use this file except in compliance with the License.
7  * You may obtain a copy of the License at
8  *
9  *      http://www.apache.org/licenses/LICENSE-2.0
10  *
11  * Unless required by applicable law or agreed to in writing, software
12  * distributed under the License is distributed on an "AS IS" BASIS,
13  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14  * See the License for the specific language governing permissions and
15  * limitations under the License.
16  */
17 
18 #include <alloca.h>
19 #include <time.h>
20 #include <stdint.h>
21 #include <stdio.h>
22 #include <unistd.h>
23 #include <string.h>
24 #include <stdlib.h>
25 #include <errno.h>
26 #include <fcntl.h>
27 #include <linux/input.h>
28 #include "rmi4update.h"
29 
30 #define RMI_F34_QUERY_SIZE		7
31 #define RMI_F34_HAS_NEW_REG_MAP		(1 << 0)
32 #define RMI_F34_IS_UNLOCKED		(1 << 1)
33 #define RMI_F34_HAS_CONFIG_ID		(1 << 2)
34 #define RMI_F34_BLOCK_SIZE_OFFSET	1
35 #define RMI_F34_FW_BLOCKS_OFFSET	3
36 #define RMI_F34_CONFIG_BLOCKS_OFFSET	5
37 
38 #define RMI_F34_BLOCK_SIZE_V1_OFFSET	0
39 #define RMI_F34_FW_BLOCKS_V1_OFFSET	0
40 #define RMI_F34_CONFIG_BLOCKS_V1_OFFSET	2
41 
42 #define RMI_F34_BLOCK_DATA_OFFSET	2
43 #define RMI_F34_BLOCK_DATA_V1_OFFSET	1
44 
45 #define RMI_F34_COMMAND_MASK		0x0F
46 #define RMI_F34_STATUS_MASK		0x07
47 #define RMI_F34_STATUS_SHIFT		4
48 #define RMI_F34_ENABLED_MASK		0x80
49 
50 #define RMI_F34_COMMAND_V1_MASK		0x3F
51 #define RMI_F34_STATUS_V1_MASK		0x3F
52 #define RMI_F34_ENABLED_V1_MASK		0x80
53 
54 #define RMI_F34_WRITE_FW_BLOCK        0x02
55 #define RMI_F34_ERASE_ALL             0x03
56 #define RMI_F34_WRITE_LOCKDOWN_BLOCK  0x04
57 #define RMI_F34_WRITE_CONFIG_BLOCK    0x06
58 #define RMI_F34_ENABLE_FLASH_PROG     0x0f
59 
60 #define RMI_F34_ENABLE_WAIT_MS 300
61 #define RMI_F34_ERASE_WAIT_MS (5 * 1000)
62 #define RMI_F34_ERASE_V8_WAIT_MS (10000)
63 #define RMI_F34_IDLE_WAIT_MS 500
64 #define RMI_F34_PARTITION_READ_WAIT_MS 20
65 
66 /* Most recent device status event */
67 #define RMI_F01_STATUS_CODE(status)		((status) & 0x0f)
68 /* Indicates that flash programming is enabled (bootloader mode). */
69 #define RMI_F01_STATUS_BOOTLOADER(status)	(!!((status) & 0x40))
70 /* The device has lost its configuration for some reason. */
71 #define RMI_F01_STATUS_UNCONFIGURED(status)	(!!((status) & 0x80))
72 
73 /* Indicates that flash programming is enabled V7(bootloader mode). */
74 #define RMI_F01_STATUS_BOOTLOADER_v7(status) (!!((status) & 0x80))
75 
76 /*
77  * Sleep mode controls power management on the device and affects all
78  * functions of the device.
79  */
80 #define RMI_F01_CTRL0_SLEEP_MODE_MASK	0x03
81 
82 #define RMI_SLEEP_MODE_NORMAL		0x00
83 #define RMI_SLEEP_MODE_SENSOR_SLEEP	0x01
84 #define RMI_SLEEP_MODE_RESERVED0	0x02
85 #define RMI_SLEEP_MODE_RESERVED1	0x03
86 
87 /*
88  * This bit disables whatever sleep mode may be selected by the sleep_mode
89  * field and forces the device to run at full power without sleeping.
90  */
91 #define RMI_F01_CRTL0_NOSLEEP_BIT	(1 << 2)
92 
UpdateFirmware(bool force,bool performLockdown)93 int RMI4Update::UpdateFirmware(bool force, bool performLockdown)
94 {
95 	struct timespec start;
96 	struct timespec end;
97 	long long int duration_us = 0;
98 	int rc;
99 	const unsigned char eraseAll = RMI_F34_ERASE_ALL;
100 
101 	// Clear all interrupts before parsing to avoid unexpected interrupts.
102 	m_device.ToggleInterruptMask(false);
103 	rc = FindUpdateFunctions();
104 	if (rc != UPDATE_SUCCESS) {
105 		m_device.ToggleInterruptMask(true);
106 		return rc;
107 	}
108 
109 	rc = m_device.QueryBasicProperties();
110 	if (rc < 0) {
111 		m_device.ToggleInterruptMask(true);
112 		return UPDATE_FAIL_QUERY_BASIC_PROPERTIES;
113 	}
114 	// Restore the interrupts
115 	m_device.ToggleInterruptMask(true);
116 
117 	if (!force && m_firmwareImage.HasIO()) {
118 		if (m_firmwareImage.GetFirmwareID() <= m_device.GetFirmwareID()) {
119 			fprintf(stderr, "Firmware image (%ld) is not newer then the firmware on the device (%ld)\n",
120 				m_firmwareImage.GetFirmwareID(), m_device.GetFirmwareID());
121 			rc = UPDATE_FAIL_FIRMWARE_IMAGE_IS_OLDER;
122 			return rc;
123 		}
124 	}
125 
126 	fprintf(stdout, "Device Properties:\n");
127 	m_device.PrintProperties();
128 	if (m_device.GetDeviceType() == RMI_DEVICE_TYPE_TOUCHPAD) {
129 		rc = m_firmwareImage.VerifyImageProductID(m_device.GetProductID());
130 		if (rc != UPDATE_SUCCESS)
131 			return rc;
132 	} else {
133 		fprintf(stdout, "not touchpad, skip checking product ID\n");
134 	}
135 
136 
137 	rc = DisableNonessentialInterupts();
138 	if (rc != UPDATE_SUCCESS)
139 		return rc;
140 
141 	rc = ReadF34Queries();
142 	if (rc != UPDATE_SUCCESS)
143 		return rc;
144 
145 	if (m_bootloaderID[1] < 10) {
146 		// Checking size alignment for the device prior to BL v10.
147 		rc = m_firmwareImage.VerifyImageMatchesDevice(GetFirmwareSize(), GetConfigSize());
148 		if (rc != UPDATE_SUCCESS)
149 			return rc;
150 	}
151 
152 	if (m_f34.GetFunctionVersion() == 0x02) {
153 		fprintf(stdout, "Enable Flash V7+...\n");
154 		rc = EnterFlashProgrammingV7();
155 		if (rc != UPDATE_SUCCESS) {
156 			fprintf(stderr, "%s: %s\n", __func__, update_err_to_string(rc));
157 			goto reset;
158 		}
159 		fprintf(stdout, "Enable Flash done V7+...\n");
160 
161 		if (IsBLv87()) {
162 			if (m_firmwareImage.IsImageHasFirmwareVersion()) {
163 				rc = ReadMSL();
164 				if (rc != UPDATE_SUCCESS) {
165 					fprintf(stderr, "%s: %s\n", __func__, update_err_to_string(rc));
166 					goto reset;
167 				}
168 				fprintf(stdout, "MSL : 0x%x\n", m_MSL);
169 				if (m_MSL > m_firmwareImage.GetFirmwareVersion()) {
170 					fprintf(stdout, "MSL checking failed. device(0x%x) > image(0x%x)\n",
171 						m_MSL, m_firmwareImage.GetFirmwareVersion());
172 					rc = UPDATE_FAIL_MSL_CHECKING;
173 					goto reset;
174 				} else {
175 					fprintf(stdout, "Passing MSL checking\n");
176 				}
177 			}
178 		}
179 
180 		if (m_bootloaderID[1] >= 10) {
181 			fprintf(stdout, "Writing FLD V10...\n");
182 			rc = WriteFLDV7();
183 			if (rc != UPDATE_SUCCESS) {
184 				fprintf(stderr, "%s: %s\n", __func__, update_err_to_string(rc));
185 				goto reset;
186 			}
187 			fprintf(stdout, "Writing FLD done V10...\n");
188 
189 			fprintf(stdout, "Erasing Flash Config V10...\n");
190 			rc = EraseFlashConfigV10();
191 			if (rc != UPDATE_SUCCESS) {
192 				fprintf(stderr, "%s: %s\n", __func__, update_err_to_string(rc));
193 				goto reset;
194 			}
195 			fprintf(stdout, "Erasing Flash Config done V10...\n");
196 
197 			if (m_firmwareImage.GetFlashConfigData()) {
198 				fprintf(stdout, "Writing flash configuration V10...\n");
199 				rc = WriteFlashConfigV7();
200 				if (rc != UPDATE_SUCCESS) {
201 					fprintf(stderr, "%s: %s\n", __func__, update_err_to_string(rc));
202 					goto reset;
203 				}
204 				fprintf(stdout, "Writing flash config done V10...\n");
205 			}
206 
207 			fprintf(stdout, "Erasing Core Code V10...\n");
208 			rc = EraseCoreCodeV10();
209 			if (rc != UPDATE_SUCCESS) {
210 				fprintf(stderr, "%s: %s\n", __func__, update_err_to_string(rc));
211 				goto reset;
212 			}
213 			fprintf(stdout, "Erasing Core Code done V10...\n");
214 
215 			if (m_firmwareImage.GetFirmwareData()) {
216 				fprintf(stdout, "Writing Core Code V10...\n");
217 				rc = WriteFirmwareV7();
218 				if (rc != UPDATE_SUCCESS) {
219 					fprintf(stderr, "%s: %s\n", __func__, update_err_to_string(rc));
220 					goto reset;
221 				}
222 				fprintf(stdout, "Writing Core Code done V10...\n");
223 			}
224 
225 			if (m_firmwareImage.GetConfigData()) {
226 				fprintf(stdout, "Writing Core Config V10...\n");
227 				rc = WriteCoreConfigV7();
228 				if (rc != UPDATE_SUCCESS) {
229 					fprintf(stderr, "%s: %s\n", __func__, update_err_to_string(rc));
230 					goto reset;
231 				}
232 				fprintf(stdout, "Writing Core Config done V10...\n");
233 				goto reset;
234 			}
235 
236 			if (m_firmwareImage.GetGlobalParametersSize() && m_hasGlobalParameters) {
237 				fprintf(stdout, "Writing Global Parameters V10...\n");
238 				rc = WriteGlobalParametersV7();
239 				if (rc != UPDATE_SUCCESS) {
240 					fprintf(stderr, "%s: %s\n", __func__, update_err_to_string(rc));
241 					goto reset;
242 				}
243 				fprintf(stdout, "Writing Global Parameters done V10...\n");
244 				goto reset;
245 			}
246 
247 
248 		} else {
249 			if (!m_IsErased){
250 				fprintf(stdout, "Erasing FW V7+...\n");
251 				rc = EraseFirmwareV7();
252 				if (rc != UPDATE_SUCCESS) {
253 					fprintf(stderr, "%s: %s\n", __func__, update_err_to_string(rc));
254 					goto reset;
255 				}
256 				fprintf(stdout, "Erasing FW done V7+...\n");
257 			}
258 			if(m_bootloaderID[1] == 8){
259 				if (m_firmwareImage.GetFlashConfigData()) {
260 					fprintf(stdout, "Writing flash configuration V8...\n");
261 					rc = WriteFlashConfigV7();
262 					if (rc != UPDATE_SUCCESS) {
263 						fprintf(stderr, "%s: %s\n", __func__, update_err_to_string(rc));
264 						goto reset;
265 					}
266 					fprintf(stdout, "Writing flash config done V8...\n");
267 				}
268 			}
269 			if (m_firmwareImage.GetFirmwareData()) {
270 				fprintf(stdout, "Writing firmware V7+...\n");
271 				rc = WriteFirmwareV7();
272 				if (rc != UPDATE_SUCCESS) {
273 					fprintf(stderr, "%s: %s\n", __func__, update_err_to_string(rc));
274 					goto reset;
275 				}
276 				fprintf(stdout, "Writing firmware done V7+...\n");
277 			}
278 			if (m_firmwareImage.GetConfigData()) {
279 				fprintf(stdout, "Writing core configuration V7+...\n");
280 				rc = WriteCoreConfigV7();
281 				if (rc != UPDATE_SUCCESS) {
282 					fprintf(stderr, "%s: %s\n", __func__, update_err_to_string(rc));
283 					goto reset;
284 				}
285 				fprintf(stdout, "Writing core config done V7+...\n");
286 				goto reset;
287 			}
288 		}
289 
290 
291 	} else {
292 		rc = EnterFlashProgramming();
293 		if (rc != UPDATE_SUCCESS) {
294 			fprintf(stderr, "%s: %s\n", __func__, update_err_to_string(rc));
295 			goto reset;
296 		}
297 	}
298 
299 	if (performLockdown && m_unlocked) {
300 		if (m_firmwareImage.GetLockdownData()) {
301 			fprintf(stdout, "Writing lockdown...\n");
302 			clock_gettime(CLOCK_MONOTONIC, &start);
303 			rc = WriteBlocks(m_firmwareImage.GetLockdownData(),
304 					m_firmwareImage.GetLockdownSize() / 0x10,
305 					RMI_F34_WRITE_LOCKDOWN_BLOCK);
306 			if (rc != UPDATE_SUCCESS) {
307 				fprintf(stderr, "%s: %s\n", __func__, update_err_to_string(rc));
308 				goto reset;
309 			}
310 			clock_gettime(CLOCK_MONOTONIC, &end);
311 			duration_us = diff_time(&start, &end);
312 			fprintf(stdout, "Done writing lockdown, time: %lld us.\n", duration_us);
313 		}
314 
315 		rc = EnterFlashProgramming();
316 		if (rc != UPDATE_SUCCESS) {
317 			fprintf(stderr, "%s: %s\n", __func__, update_err_to_string(rc));
318 			goto reset;
319 		}
320 	}
321 
322 	rc = WriteBootloaderID();
323 	if (rc != UPDATE_SUCCESS) {
324 		fprintf(stderr, "%s: %s\n", __func__, update_err_to_string(rc));
325 		goto reset;
326 	}
327 
328 	fprintf(stdout, "Erasing FW...\n");
329 	clock_gettime(CLOCK_MONOTONIC, &start);
330 	rc = m_device.Write(m_f34StatusAddr, &eraseAll, 1);
331 	if (rc != 1) {
332 		fprintf(stderr, "%s: %s\n", __func__, update_err_to_string(UPDATE_FAIL_ERASE_ALL));
333 		rc = UPDATE_FAIL_ERASE_ALL;
334 		goto reset;
335 	}
336 
337 	rc = WaitForIdle(RMI_F34_ERASE_WAIT_MS);
338 	if (rc != UPDATE_SUCCESS) {
339 		fprintf(stderr, "%s: %s\n", __func__, update_err_to_string(rc));
340 		goto reset;
341 	}
342 	clock_gettime(CLOCK_MONOTONIC, &end);
343 	duration_us = diff_time(&start, &end);
344 	fprintf(stdout, "Erase complete, time: %lld us.\n", duration_us);
345 
346 	if (m_firmwareImage.GetFirmwareData()) {
347 		fprintf(stdout, "Writing firmware...\n");
348 		clock_gettime(CLOCK_MONOTONIC, &start);
349 		rc = WriteBlocks(m_firmwareImage.GetFirmwareData(), m_fwBlockCount,
350 						RMI_F34_WRITE_FW_BLOCK);
351 		if (rc != UPDATE_SUCCESS) {
352 			fprintf(stderr, "%s: %s\n", __func__, update_err_to_string(rc));
353 			goto reset;
354 		}
355 		clock_gettime(CLOCK_MONOTONIC, &end);
356 		duration_us = diff_time(&start, &end);
357 		fprintf(stdout, "Done writing FW, time: %lld us.\n", duration_us);
358 	}
359 
360 	if (m_firmwareImage.GetConfigData()) {
361 		fprintf(stdout, "Writing configuration...\n");
362 		clock_gettime(CLOCK_MONOTONIC, &start);
363 		rc = WriteBlocks(m_firmwareImage.GetConfigData(), m_configBlockCount,
364 				RMI_F34_WRITE_CONFIG_BLOCK);
365 		if (rc != UPDATE_SUCCESS) {
366 			fprintf(stderr, "%s: %s\n", __func__, update_err_to_string(rc));
367 			goto reset;
368 		}
369 		clock_gettime(CLOCK_MONOTONIC, &end);
370 		duration_us = diff_time(&start, &end);
371 		fprintf(stdout, "Done writing config, time: %lld us.\n", duration_us);
372 	}
373 
374 reset:
375 	m_device.Reset();
376 rebind:
377 	if (m_bootloaderID[1] >= 10) {
378 		Sleep(5000);
379 	}
380 	m_device.RebindDriver();
381 	if(!m_device.CheckABSEvent())
382 	{
383 		goto rebind;
384 	}
385 
386 	// In order to print out new PR
387 	rc = FindUpdateFunctions();
388 	if (rc != UPDATE_SUCCESS)
389 		return rc;
390 
391 	rc = m_device.QueryBasicProperties();
392 	if (rc < 0)
393 		return UPDATE_FAIL_QUERY_BASIC_PROPERTIES;
394 	fprintf(stdout, "Device Properties:\n");
395 	m_device.PrintProperties();
396 
397 	return rc;
398 
399 }
400 
DisableNonessentialInterupts()401 int RMI4Update::DisableNonessentialInterupts()
402 {
403 	int rc;
404 	unsigned char interruptEnabeMask = m_f34.GetInterruptMask() | m_f01.GetInterruptMask();
405 
406 	rc = m_device.Write(m_f01.GetControlBase() + 1, &interruptEnabeMask, 1);
407 	if (rc != 1)
408 		return rc;
409 
410 	return UPDATE_SUCCESS;
411 }
412 
FindUpdateFunctions()413 int RMI4Update::FindUpdateFunctions()
414 {
415 	if (0 > m_device.ScanPDT())
416 		return UPDATE_FAIL_SCAN_PDT;
417 
418 	if (!m_device.GetFunction(m_f01, 0x01))
419 		return UPDATE_FAIL_NO_FUNCTION_01;
420 
421 	if (!m_device.GetFunction(m_f34, 0x34))
422 		return UPDATE_FAIL_NO_FUNCTION_34;
423 
424 	return UPDATE_SUCCESS;
425 }
426 
rmi4update_poll()427 int RMI4Update::rmi4update_poll()
428 {
429 	unsigned char f34_status;
430 	unsigned short dataAddr = m_f34.GetDataBase();
431 	int rc;
432 
433 	rc = m_device.Read(dataAddr, &f34_status, sizeof(unsigned char));
434 	if (rc != sizeof(unsigned char))
435 		return UPDATE_FAIL_WRITE_FLASH_COMMAND;
436 
437 	m_flashStatus = f34_status & 0x1F;
438 	m_inBLmode = f34_status & 0x80;
439 	if(!m_flashStatus)
440 		rc = m_device.Read(dataAddr + 4, &m_flashCmd, sizeof(unsigned char));
441 
442 	return 0;
443 }
444 
ReadFlashConfig()445 int RMI4Update::ReadFlashConfig()
446 {
447 	int rc;
448 	int transaction_count, remain_block;
449 	unsigned char *flash_cfg;
450 	int transfer_leng = 0;
451 	int read_leng = 0;
452 	int offset = 0;
453 	unsigned char trans_leng_buf[2];
454 	unsigned char cmd_buf[1];
455 	unsigned char off[2] = {0, 0};
456 	unsigned char partition_id = FLASH_CONFIG_PARTITION;
457 	unsigned short dataAddr = m_f34.GetDataBase();
458 	int i;
459 	int retry = 0;
460 	unsigned char *data_temp;
461 	struct partition_tbl *partition_temp;
462 
463 	flash_cfg = (unsigned char *)malloc(m_blockSize * m_flashConfigLength);
464 	memset(flash_cfg, 0, m_blockSize * m_flashConfigLength);
465 	partition_temp = (partition_tbl *)malloc(sizeof(struct partition_tbl));
466 	memset(partition_temp, 0, sizeof(struct partition_tbl));
467 	/* calculate the count */
468 	remain_block = (m_flashConfigLength % m_payloadLength);
469 	transaction_count = (m_flashConfigLength / m_payloadLength);
470 
471 	if (remain_block > 0)
472 		transaction_count++;
473 
474 	/* set partition id for bootloader 7 */
475 	rc = m_device.Write(dataAddr + 1, &partition_id, sizeof(partition_id));
476 	if (rc != sizeof(partition_id))
477 		return UPDATE_FAIL_WRITE_FLASH_COMMAND;
478 	rc = m_device.Write(dataAddr + 2, off, sizeof(off));
479 	if (rc != sizeof(off))
480 		return UPDATE_FAIL_WRITE_INITIAL_ZEROS;
481 
482 	for (i = 0; i < transaction_count; i++)
483 	{
484 		if ((i == (transaction_count -1)) && (remain_block > 0))
485 			transfer_leng = remain_block;
486 		else
487 			transfer_leng = m_payloadLength;
488 
489 		// Set Transfer Length
490 		trans_leng_buf[0] = (unsigned char)(transfer_leng & 0xFF);
491 		trans_leng_buf[1] = (unsigned char)((transfer_leng & 0xFF00) >> 8);
492 		rc = m_device.Write(dataAddr + 3, trans_leng_buf, sizeof(trans_leng_buf));
493 		if (rc != sizeof(trans_leng_buf))
494 			return UPDATE_FAIL_WRITE_FLASH_COMMAND;
495 
496 		// Set Command to Read
497 		cmd_buf[0] = (unsigned char)CMD_V7_READ;
498 		rc = m_device.Write(dataAddr + 4, cmd_buf, sizeof(cmd_buf));
499 		if (rc != sizeof(cmd_buf))
500 			return UPDATE_FAIL_WRITE_FLASH_COMMAND;
501 
502 		if(m_device.GetDeviceType() == RMI_DEVICE_TYPE_TOUCHPAD)  {
503 			// Sleep 20 ms and wait for attention for touchpad only.
504 			Sleep(20);
505 			rc = WaitForIdle(RMI_F34_PARTITION_READ_WAIT_MS, false);
506 			if (rc != UPDATE_SUCCESS) {
507 				fprintf(stderr, "%s: %s\n", __func__, update_err_to_string(rc));
508 				return UPDATE_FAIL_TIMEOUT_WAITING_FOR_ATTN;
509 			}
510 			fprintf(stdout, "Got attention\n");
511 		}
512 
513 		//Wait for completion
514 		do {
515 			Sleep(20);
516 			rmi4update_poll();
517 			if (m_flashStatus == SUCCESS){
518 				break;
519 			}
520 			retry++;
521 		} while(retry < 20);
522 
523 		read_leng = transfer_leng * m_blockSize;
524 		data_temp = (unsigned char *) malloc(sizeof(char) * read_leng);
525 		rc = m_device.Read(dataAddr + 5, data_temp, sizeof(char) * read_leng);
526 		if (rc != ((ssize_t)sizeof(char) * read_leng))
527 			return UPDATE_FAIL_READ_F34_QUERIES;
528 
529 		memcpy(flash_cfg + offset, data_temp, sizeof(char) * read_leng);
530 		offset += read_leng;
531 		free(data_temp);
532 	}
533 
534 	// Initialize as NULL here to avoid segmentation fault.
535 	m_partitionConfig = NULL;
536 	m_partitionCore = NULL;
537 	m_partitionGuest = NULL;
538 
539 	/* parse the config length */
540 	for (i = 2; i < m_blockSize * m_flashConfigLength; i = i + 8)
541 	{
542 		memcpy(partition_temp->data ,flash_cfg + i, sizeof(struct partition_tbl));
543 		if (partition_temp->partition_id == CORE_CONFIG_PARTITION)
544 		{
545 			m_partitionConfig = (partition_tbl *) malloc(sizeof(struct partition_tbl));
546 			memcpy(m_partitionConfig ,partition_temp, sizeof(struct partition_tbl));
547 			memset(partition_temp, 0, sizeof(struct partition_tbl));
548 			fprintf(stdout, "CORE_CONFIG_PARTITION is found\n");
549 		}
550 		else if (partition_temp->partition_id == CORE_CODE_PARTITION)
551 		{
552 			m_partitionCore = (partition_tbl *) malloc(sizeof(struct partition_tbl));
553 			memcpy(m_partitionCore ,partition_temp, sizeof(struct partition_tbl));
554 			memset(partition_temp, 0, sizeof(struct partition_tbl));
555 			fprintf(stdout, "CORE_CODE_PARTITION is found\n");
556 		}
557 		else if (partition_temp->partition_id == GUEST_CODE_PARTITION)
558 		{
559 			m_partitionGuest = (partition_tbl *) malloc(sizeof(struct partition_tbl));
560 			memcpy(m_partitionGuest ,partition_temp, sizeof(struct partition_tbl));
561 			memset(partition_temp, 0, sizeof(struct partition_tbl));
562 			fprintf(stdout, "GUEST_CODE_PARTITION is found\n");
563 		}
564 		else if (partition_temp->partition_id == NONE_PARTITION)
565 			break;
566 	}
567 
568 	if (flash_cfg)
569 		free(flash_cfg);
570 
571 	if (partition_temp)
572 		free(partition_temp);
573 
574 	m_fwBlockCount = m_partitionCore ? m_partitionCore->partition_len : 0;
575 	m_configBlockCount = m_partitionConfig ? m_partitionConfig->partition_len : 0;
576 	m_guestBlockCount = m_partitionGuest ? m_partitionGuest->partition_len : 0;
577 	fprintf(stdout, "F34 fw blocks:     %d\n", m_fwBlockCount);
578 	fprintf(stdout, "F34 config blocks: %d\n", m_configBlockCount);
579 	fprintf(stdout, "F34 guest blocks:     %d\n", m_guestBlockCount);
580 	fprintf(stdout, "\n");
581 
582 	m_guestData = (unsigned char *) malloc(m_guestBlockCount * m_blockSize);
583 	memset(m_guestData, 0, m_guestBlockCount * m_blockSize);
584 	memset(m_guestData + m_guestBlockCount * m_blockSize -4, 0, 4);
585 	return UPDATE_SUCCESS;
586 }
587 
ReadF34QueriesV7()588 int RMI4Update::ReadF34QueriesV7()
589 {
590 	int rc;
591 	struct f34_v7_query_0 query_0;
592 	struct f34_v7_query_1_7 query_1_7;
593 	unsigned char idStr[3];
594 	unsigned short queryAddr = m_f34.GetQueryBase();
595 	unsigned char offset;
596 
597 	rc = m_device.Read(queryAddr, query_0.data, sizeof(query_0.data));
598 	if (rc != sizeof(query_0.data))
599 		return UPDATE_FAIL_READ_BOOTLOADER_ID;
600 
601 	offset = query_0.subpacket_1_size + 1;
602 	rc = m_device.Read(queryAddr + offset, query_1_7.data, sizeof(query_1_7.data));
603 	if (rc != sizeof(query_1_7.data))
604 		return UPDATE_FAIL_READ_BOOTLOADER_ID;
605 
606 	m_bootloaderID[0] = query_1_7.bl_minor_revision;
607 	m_bootloaderID[1] = query_1_7.bl_major_revision;
608 	m_hasConfigID = query_0.has_config_id;
609 	m_blockSize = query_1_7.block_size_15_8 << 8 |
610 			query_1_7.block_size_7_0;
611 	m_flashConfigLength = query_1_7.flash_config_length_15_8 << 8 |
612 				query_1_7.flash_config_length_7_0;
613 	m_payloadLength = query_1_7.payload_length_15_8 << 8 |
614 			query_1_7.payload_length_7_0;
615 	m_buildID = query_1_7.bl_fw_id_7_0 |
616 			query_1_7.bl_fw_id_15_8 << 8 |
617 			query_1_7.bl_fw_id_23_16 << 16 |
618 			query_1_7.bl_fw_id_31_24 << 24;
619 
620 	idStr[0] = m_bootloaderID[0];
621 	idStr[1] = m_bootloaderID[1];
622 	idStr[2] = 0;
623 
624 	m_hasCoreCode = query_1_7.has_core_code;
625 	m_hasCoreConfig = query_1_7.has_core_config;
626 	m_hasFlashConfig = query_1_7.has_flash_config;
627 	m_hasFLD = query_1_7.has_fld;
628 	m_hasGlobalParameters = query_1_7.has_global_parameters;
629 
630 	fprintf(stdout, "F34 has CoreCode: %d\n", m_hasCoreCode);
631 	fprintf(stdout, "F34 has CoreConfig: %d\n", m_hasCoreConfig);
632 	fprintf(stdout, "F34 has FlashConfig: %d\n", m_hasFlashConfig);
633 	fprintf(stdout, "F34 has FLD: %d\n", m_hasFLD);
634 
635 	fprintf(stdout, "F34 bootloader id: %s (%#04x %#04x)\n", idStr, m_bootloaderID[0],
636 		m_bootloaderID[1]);
637 	fprintf(stdout, "F34 has config id: %d\n", m_hasConfigID);
638 	fprintf(stdout, "F34 unlocked:      %d\n", m_unlocked);
639 	fprintf(stdout, "F34 block size:    %d\n", m_blockSize);
640 	fprintf(stdout, "F34 flash cfg leng:%d\n", m_flashConfigLength);
641 	fprintf(stdout, "F34 payload length:%d\n", m_payloadLength);
642 	fprintf(stdout, "F34 build id:      %lu\n", m_buildID);
643 
644 	if ((m_device.GetDeviceType() == RMI_DEVICE_TYPE_TOUCHPAD) && (m_bootloaderID[1] == 10)) {
645 		// FW size would be different from the one in image file in bootloader v10,
646 		// we use size parsing in image file instead.
647 		return UPDATE_SUCCESS;
648 	} else
649 		return ReadFlashConfig();
650 }
651 
ReadF34Queries()652 int RMI4Update::ReadF34Queries()
653 {
654 	int rc;
655 	unsigned char idStr[3];
656 	unsigned char buf[8];
657 	unsigned short queryAddr = m_f34.GetQueryBase();
658 	unsigned short f34Version = m_f34.GetFunctionVersion();
659 	unsigned short querySize;
660 
661 	if (f34Version == 0x2)
662 		return ReadF34QueriesV7();
663 	else if (f34Version == 0x1)
664 		querySize = 8;
665 	else
666 		querySize = 2;
667 
668 	rc = m_device.Read(queryAddr, m_bootloaderID, RMI_BOOTLOADER_ID_SIZE);
669 	if (rc != RMI_BOOTLOADER_ID_SIZE)
670 		return UPDATE_FAIL_READ_BOOTLOADER_ID;
671 
672 	if (f34Version == 0x1)
673 		++queryAddr;
674 	else
675 		queryAddr += querySize;
676 
677 	if (f34Version == 0x1) {
678 		rc = m_device.Read(queryAddr, buf, 1);
679 		if (rc != 1)
680 			return UPDATE_FAIL_READ_F34_QUERIES;
681 
682 		m_hasNewRegmap = buf[0] & RMI_F34_HAS_NEW_REG_MAP;
683 		m_unlocked = buf[0] & RMI_F34_IS_UNLOCKED;;
684 		m_hasConfigID = buf[0] & RMI_F34_HAS_CONFIG_ID;
685 
686 		++queryAddr;
687 
688 		rc = m_device.Read(queryAddr, buf, 2);
689 		if (rc != 2)
690 			return UPDATE_FAIL_READ_F34_QUERIES;
691 
692 		m_blockSize = extract_short(buf + RMI_F34_BLOCK_SIZE_V1_OFFSET);
693 
694 		++queryAddr;
695 
696 		rc = m_device.Read(queryAddr, buf, 8);
697 		if (rc != 8)
698 			return UPDATE_FAIL_READ_F34_QUERIES;
699 
700 		m_fwBlockCount = extract_short(buf + RMI_F34_FW_BLOCKS_V1_OFFSET);
701 		m_configBlockCount = extract_short(buf + RMI_F34_CONFIG_BLOCKS_V1_OFFSET);
702 	} else {
703 		rc = m_device.Read(queryAddr, buf, RMI_F34_QUERY_SIZE);
704 		if (rc != RMI_F34_QUERY_SIZE)
705 			return UPDATE_FAIL_READ_F34_QUERIES;
706 
707 		m_hasNewRegmap = buf[0] & RMI_F34_HAS_NEW_REG_MAP;
708 		m_unlocked = buf[0] & RMI_F34_IS_UNLOCKED;;
709 		m_hasConfigID = buf[0] & RMI_F34_HAS_CONFIG_ID;
710 		m_blockSize = extract_short(buf + RMI_F34_BLOCK_SIZE_OFFSET);
711 		m_fwBlockCount = extract_short(buf + RMI_F34_FW_BLOCKS_OFFSET);
712 		m_configBlockCount = extract_short(buf + RMI_F34_CONFIG_BLOCKS_OFFSET);
713 	}
714 
715 	idStr[0] = m_bootloaderID[0];
716 	idStr[1] = m_bootloaderID[1];
717 	idStr[2] = 0;
718 
719 	fprintf(stdout, "F34 bootloader id: %s (%#04x %#04x)\n", idStr, m_bootloaderID[0],
720 		m_bootloaderID[1]);
721 	fprintf(stdout, "F34 has config id: %d\n", m_hasConfigID);
722 	fprintf(stdout, "F34 unlocked:      %d\n", m_unlocked);
723 	fprintf(stdout, "F34 new reg map:   %d\n", m_hasNewRegmap);
724 	fprintf(stdout, "F34 block size:    %d\n", m_blockSize);
725 	fprintf(stdout, "F34 fw blocks:     %d\n", m_fwBlockCount);
726 	fprintf(stdout, "F34 config blocks: %d\n", m_configBlockCount);
727 	fprintf(stdout, "\n");
728 
729 	if (f34Version == 0x1)
730 		m_f34StatusAddr = m_f34.GetDataBase() + 2;
731 	else
732 		m_f34StatusAddr = m_f34.GetDataBase() + RMI_F34_BLOCK_DATA_OFFSET + m_blockSize;
733 
734 	return UPDATE_SUCCESS;
735 }
736 
ReadF34Controls()737 int RMI4Update::ReadF34Controls()
738 {
739 	int rc;
740 	unsigned char buf[2];
741 
742 	if (m_f34.GetFunctionVersion() == 0x1) {
743 		rc = m_device.Read(m_f34StatusAddr, buf, 2);
744 		if (rc != 2)
745 			return UPDATE_FAIL_READ_F34_CONTROLS;
746 
747 		m_f34Command = buf[0] & RMI_F34_COMMAND_V1_MASK;
748 		m_f34Status = buf[1] & RMI_F34_STATUS_V1_MASK;
749 		m_programEnabled = !!(buf[1] & RMI_F34_ENABLED_MASK);
750 
751 	} else {
752 		rc = m_device.Read(m_f34StatusAddr, buf, 1);
753 		if (rc != 1)
754 			return UPDATE_FAIL_READ_F34_CONTROLS;
755 
756 		m_f34Command = buf[0] & RMI_F34_COMMAND_MASK;
757 		m_f34Status = (buf[0] >> RMI_F34_STATUS_SHIFT) & RMI_F34_STATUS_MASK;
758 		m_programEnabled = !!(buf[0] & RMI_F34_ENABLED_MASK);
759 	}
760 
761 	return UPDATE_SUCCESS;
762 }
763 
WriteBootloaderID()764 int RMI4Update::WriteBootloaderID()
765 {
766 	int rc;
767 	int blockDataOffset = RMI_F34_BLOCK_DATA_OFFSET;
768 
769 	if (m_f34.GetFunctionVersion() == 0x1)
770 		blockDataOffset = RMI_F34_BLOCK_DATA_V1_OFFSET;
771 
772 	rc = m_device.Write(m_f34.GetDataBase() + blockDataOffset,
773 				m_bootloaderID, RMI_BOOTLOADER_ID_SIZE);
774 	if (rc != RMI_BOOTLOADER_ID_SIZE)
775 		return UPDATE_FAIL_WRITE_BOOTLOADER_ID;
776 
777 	return UPDATE_SUCCESS;
778 }
779 
WriteFirmwareV7()780 int RMI4Update::WriteFirmwareV7()
781 {
782 	int transaction_count, remain_block;
783 	int transfer_leng = 0;
784 	int offset = 0;
785 	unsigned char trans_leng_buf[2];
786 	unsigned char cmd_buf[1];
787 	unsigned char off[2] = {0, 0};
788 	unsigned char partition_id;
789 	int i;
790 	int retry = 0;
791 	unsigned char *data_temp;
792 	int rc;
793 	unsigned short left_bytes;
794 	unsigned short write_size;
795 	unsigned short max_write_size;
796 	unsigned short dataAddr = m_f34.GetDataBase();
797 
798 	if (m_bootloaderID[1] == 10) {
799 		m_fwBlockCount = m_firmwareImage.GetFirmwareSize() / m_blockSize;
800 	}
801 
802 	/* calculate the count */
803 	partition_id = CORE_CODE_PARTITION;
804 
805 	remain_block = (m_fwBlockCount % m_payloadLength);
806 	transaction_count = (m_fwBlockCount / m_payloadLength);
807 
808 	if (remain_block > 0)
809 		transaction_count++;
810 
811 	/* set partition id for bootloader 7 */
812 	rc = m_device.Write(dataAddr + 1, &partition_id, sizeof(partition_id));
813 	if (rc != sizeof(partition_id))
814 		return UPDATE_FAIL_WRITE_FLASH_COMMAND;
815 
816 	rc = m_device.Write(dataAddr + 2, off, sizeof(off));
817 	if (rc != sizeof(off))
818 		return UPDATE_FAIL_WRITE_INITIAL_ZEROS;
819 
820 	for (i = 0; i < transaction_count; i++)
821 	{
822 		if ((i == (transaction_count -1)) && (remain_block > 0))
823 			transfer_leng = remain_block;
824 		else
825 			transfer_leng = m_payloadLength;
826 
827 		// Set Transfer Length
828 		trans_leng_buf[0] = (unsigned char)(transfer_leng & 0xFF);
829 		trans_leng_buf[1] = (unsigned char)((transfer_leng & 0xFF00) >> 8);
830 
831 		rc = m_device.Write(dataAddr + 3, trans_leng_buf, sizeof(trans_leng_buf));
832 		if (rc != sizeof(trans_leng_buf))
833 			return UPDATE_FAIL_WRITE_FLASH_COMMAND;
834 
835 		// Set Command to Write
836 		cmd_buf[0] = (unsigned char)CMD_V7_WRITE;
837 		rc = m_device.Write(dataAddr + 4, cmd_buf, sizeof(cmd_buf));
838 		if (rc != sizeof(cmd_buf))
839 			return UPDATE_FAIL_WRITE_FLASH_COMMAND;
840 
841 		max_write_size = 16;
842 		if (max_write_size >= transfer_leng * m_blockSize)
843 			max_write_size = transfer_leng * m_blockSize;
844 		else if (max_write_size > m_blockSize)
845 			max_write_size -= max_write_size % m_blockSize;
846 		else
847 			max_write_size = m_blockSize;
848 
849 		left_bytes = transfer_leng * m_blockSize;
850 		do {
851 			if (left_bytes / max_write_size)
852 				write_size = max_write_size;
853 			else
854 				write_size = left_bytes;
855 
856 			data_temp = (unsigned char *) malloc(sizeof(unsigned char) * write_size);
857 			memcpy(data_temp, m_firmwareImage.GetFirmwareData() + offset, sizeof(char) * write_size);
858 			rc = m_device.Write(dataAddr + 5, data_temp, sizeof(char) * write_size);
859 			if (rc != ((ssize_t)sizeof(char) * write_size)) {
860 				fprintf(stdout, "err write_size = %d; rc = %d\n", write_size, rc);
861 				return UPDATE_FAIL_READ_F34_QUERIES;
862 			}
863 
864 			offset += write_size;
865 			left_bytes -= write_size;
866 			free(data_temp);
867 		} while (left_bytes);
868 
869 		if(m_device.GetDeviceType() == RMI_DEVICE_TYPE_TOUCHPAD)  {
870 			// Sleep 100 ms and wait for attention for touchpad only.
871 			Sleep(100);
872 			rc = WaitForIdle(RMI_F34_IDLE_WAIT_MS, false);
873 			if (rc != UPDATE_SUCCESS) {
874 				fprintf(stderr, "%s: %s\n", __func__, update_err_to_string(rc));
875 				return UPDATE_FAIL_TIMEOUT_WAITING_FOR_ATTN;
876 			}
877 		}
878 
879 
880 		//Wait for completion
881 		do {
882 			Sleep(20);
883 			rmi4update_poll();
884 			if (m_flashStatus == SUCCESS){
885 				break;
886 
887 			}
888 			retry++;
889 		} while(retry < 20);
890 
891 		if (m_flashStatus != SUCCESS) {
892 			fprintf(stdout, "err flash_status = %d\n", m_flashStatus);
893 			return UPDATE_FAIL_WRITE_F01_CONTROL_0;
894 		}
895 
896 	}
897 
898 	if(m_device.GetDeviceType() == RMI_DEVICE_TYPE_TOUCHPAD)  {
899 		if (m_firmwareImage.GetSignatureInfo()[BLv7_CORE_CODE].bExisted) {
900 			// Write signature.
901 			rc = WriteSignatureV7(BLv7_CORE_CODE, m_firmwareImage.GetFirmwareData(), offset);
902 			if (rc != UPDATE_SUCCESS) {
903 				fprintf(stderr, "%s: %s\n", __func__, update_err_to_string(rc));
904 				return rc;
905 			}
906 		}
907 	}
908 
909 	return UPDATE_SUCCESS;
910 }
911 
WriteCoreConfigV7()912 int RMI4Update::WriteCoreConfigV7()
913 {
914 	int transaction_count, remain_block;
915 	int transfer_leng = 0;
916 	int offset = 0;
917 	unsigned char trans_leng_buf[2];
918 	unsigned char cmd_buf[1];
919 	unsigned char off[2] = {0, 0};
920 	unsigned char partition_id;
921 	unsigned short dataAddr = m_f34.GetDataBase();
922 	unsigned short left_bytes;
923 	unsigned short write_size;
924 	unsigned short max_write_size;
925 	int rc;
926 	int i;
927 	int retry = 0;
928 	unsigned char *data_temp;
929 	if (m_bootloaderID[1] == 10) {
930 		m_configBlockCount = m_firmwareImage.GetConfigSize() / m_blockSize;
931 	}
932 
933 	/* calculate the count */
934 	partition_id = CORE_CONFIG_PARTITION;
935 
936 	remain_block = (m_configBlockCount % m_payloadLength);
937 	transaction_count = (m_configBlockCount / m_payloadLength);
938 
939 	if (remain_block > 0)
940 		transaction_count++;
941 
942 	/* set partition id for bootloader 7 */
943 	rc = m_device.Write(dataAddr + 1, &partition_id, sizeof(partition_id));
944 	if (rc != sizeof(partition_id))
945 		return UPDATE_FAIL_WRITE_FLASH_COMMAND;
946 
947 	rc = m_device.Write(dataAddr + 2, off, sizeof(off));
948 	if (rc != sizeof(off))
949 		return UPDATE_FAIL_WRITE_INITIAL_ZEROS;
950 
951 	for (i = 0; i < transaction_count; i++)
952 	{
953 		if ((i == (transaction_count -1)) && (remain_block > 0))
954 			transfer_leng = remain_block;
955 		else
956 			transfer_leng = m_payloadLength;
957 
958 		// Set Transfer Length
959 		trans_leng_buf[0] = (unsigned char)(transfer_leng & 0xFF);
960 		trans_leng_buf[1] = (unsigned char)((transfer_leng & 0xFF00) >> 8);
961 
962 		rc = m_device.Write(dataAddr + 3, trans_leng_buf, sizeof(trans_leng_buf));
963 		if (rc != sizeof(trans_leng_buf))
964 			return UPDATE_FAIL_WRITE_FLASH_COMMAND;
965 
966 		// Set Command to Write
967 		cmd_buf[0] = (unsigned char)CMD_V7_WRITE;
968 		rc = m_device.Write(dataAddr + 4, cmd_buf, sizeof(cmd_buf));
969 		if (rc != sizeof(cmd_buf))
970 			return UPDATE_FAIL_WRITE_FLASH_COMMAND;
971 
972 		max_write_size = 16;
973 		if (max_write_size >= transfer_leng * m_blockSize)
974 			max_write_size = transfer_leng * m_blockSize;
975 		else if (max_write_size > m_blockSize)
976 			max_write_size -= max_write_size % m_blockSize;
977 		else
978 			max_write_size = m_blockSize;
979 
980 		left_bytes = transfer_leng * m_blockSize;
981 
982 		do {
983 			if (left_bytes / max_write_size)
984 				write_size = max_write_size;
985 			else
986 				write_size = left_bytes;
987 
988 			data_temp = (unsigned char *) malloc(sizeof(unsigned char) * write_size);
989 			memcpy(data_temp, m_firmwareImage.GetConfigData() + offset, sizeof(char) * write_size);
990 			rc = m_device.Write(dataAddr + 5, data_temp, sizeof(char) * write_size);
991 			if (rc != ((ssize_t)sizeof(char) * write_size)) {
992 				return UPDATE_FAIL_READ_F34_QUERIES;
993 			}
994 
995 			offset += write_size;
996 			left_bytes -= write_size;
997 			free(data_temp);
998 		} while (left_bytes);
999 
1000 		if(m_device.GetDeviceType() == RMI_DEVICE_TYPE_TOUCHPAD)  {
1001 			// Wait for attention for touchpad only.
1002 			rc = WaitForIdle(RMI_F34_IDLE_WAIT_MS, false);
1003 			if (rc != UPDATE_SUCCESS) {
1004 				fprintf(stderr, "%s: %s\n", __func__, update_err_to_string(rc));
1005 				return UPDATE_FAIL_TIMEOUT_WAITING_FOR_ATTN;
1006 			}
1007 		}
1008 
1009 		//Wait for completion
1010 		do {
1011 			Sleep(20);
1012 			rmi4update_poll();
1013 			if (m_flashStatus == SUCCESS){
1014 				break;
1015 			}
1016 			retry++;
1017 		} while(retry < 20);
1018 
1019 		if (m_flashStatus != SUCCESS) {
1020 			fprintf(stdout, "err flash_status = %d\n", m_flashStatus);
1021 			return UPDATE_FAIL_WRITE_F01_CONTROL_0;
1022 		}
1023 
1024 	}
1025 
1026 	if(m_device.GetDeviceType() == RMI_DEVICE_TYPE_TOUCHPAD)  {
1027 		if (m_firmwareImage.GetSignatureInfo()[BLv7_CORE_CONFIG].bExisted) {
1028 			// Write signature.
1029 			rc = WriteSignatureV7(BLv7_CORE_CONFIG, m_firmwareImage.GetConfigData(), offset);
1030 			if (rc != UPDATE_SUCCESS) {
1031 				fprintf(stderr, "%s: %s\n", __func__, update_err_to_string(rc));
1032 				return rc;
1033 			}
1034 		}
1035 	}
1036 
1037 	return UPDATE_SUCCESS;
1038 }
1039 
WriteFlashConfigV7()1040 int RMI4Update::WriteFlashConfigV7()
1041 {
1042 	int transaction_count, remain_block;
1043 	int transfer_leng = 0;
1044 	int offset = 0;
1045 	unsigned char trans_leng_buf[2];
1046 	unsigned char cmd_buf[1];
1047 	unsigned char off[2] = {0, 0};
1048 	unsigned char partition_id;
1049 	unsigned short dataAddr = m_f34.GetDataBase();
1050 	unsigned short left_bytes;
1051 	unsigned short write_size;
1052 	unsigned short max_write_size;
1053 	int rc;
1054 	int i;
1055 	int retry = 0;
1056 	unsigned char *data_temp;
1057 	unsigned short FlashConfigBlockCount;
1058 
1059 	/* calculate the count */
1060 	partition_id = FLASH_CONFIG_PARTITION;
1061 
1062 	FlashConfigBlockCount = m_firmwareImage.GetFlashConfigSize() / m_blockSize;
1063 
1064 	remain_block = (FlashConfigBlockCount % m_payloadLength);
1065 	transaction_count = (FlashConfigBlockCount / m_payloadLength);
1066 	if (remain_block > 0)
1067 		transaction_count++;
1068 
1069 	/* set partition id for bootloader 7 */
1070 	rc = m_device.Write(dataAddr + 1, &partition_id, sizeof(partition_id));
1071 	if (rc != sizeof(partition_id))
1072 		return UPDATE_FAIL_WRITE_FLASH_COMMAND;
1073 
1074 	rc = m_device.Write(dataAddr + 2, off, sizeof(off));
1075 	if (rc != sizeof(off))
1076 		return UPDATE_FAIL_WRITE_INITIAL_ZEROS;
1077 
1078 	for (i = 0; i < transaction_count; i++)
1079 	{
1080 		if ((i == (transaction_count -1)) && (remain_block > 0))
1081 			transfer_leng = remain_block;
1082 		else
1083 			transfer_leng = m_payloadLength;
1084 
1085 		// Set Transfer Length
1086 		trans_leng_buf[0] = (unsigned char)(transfer_leng & 0xFF);
1087 		trans_leng_buf[1] = (unsigned char)((transfer_leng & 0xFF00) >> 8);
1088 
1089 		rc = m_device.Write(dataAddr + 3, trans_leng_buf, sizeof(trans_leng_buf));
1090 		if (rc != sizeof(trans_leng_buf))
1091 			return UPDATE_FAIL_WRITE_FLASH_COMMAND;
1092 
1093 		// Set Command to Write
1094 		cmd_buf[0] = (unsigned char)CMD_V7_WRITE;
1095 		rc = m_device.Write(dataAddr + 4, cmd_buf, sizeof(cmd_buf));
1096 		if (rc != sizeof(cmd_buf))
1097 			return UPDATE_FAIL_WRITE_FLASH_COMMAND;
1098 
1099 		max_write_size = 16;
1100 		if (max_write_size >= transfer_leng * m_blockSize)
1101 			max_write_size = transfer_leng * m_blockSize;
1102 		else if (max_write_size > m_blockSize)
1103 			max_write_size -= max_write_size % m_blockSize;
1104 		else
1105 			max_write_size = m_blockSize;
1106 
1107 		left_bytes = transfer_leng * m_blockSize;
1108 
1109 		do {
1110 			if (left_bytes / max_write_size)
1111 				write_size = max_write_size;
1112 			else
1113 				write_size = left_bytes;
1114 
1115 			data_temp = (unsigned char *) malloc(sizeof(unsigned char) * write_size);
1116 			memcpy(data_temp, m_firmwareImage.GetFlashConfigData() + offset, sizeof(char) * write_size);
1117 			rc = m_device.Write(dataAddr + 5, data_temp, sizeof(char) * write_size);
1118 			if (rc != ((ssize_t)sizeof(char) * write_size)) {
1119 				fprintf(stdout, "err write_size = %d; rc = %d\n", write_size, rc);
1120 				return UPDATE_FAIL_READ_F34_QUERIES;
1121 			}
1122 
1123 			offset += write_size;
1124 			left_bytes -= write_size;
1125 			free(data_temp);
1126 		} while (left_bytes);
1127 
1128 		if(m_device.GetDeviceType() == RMI_DEVICE_TYPE_TOUCHPAD)  {
1129 			// Wair for attention for touchpad only.
1130 			rc = WaitForIdle(RMI_F34_IDLE_WAIT_MS, false);
1131 			if (rc != UPDATE_SUCCESS) {
1132 				fprintf(stderr, "%s: %s\n", __func__, update_err_to_string(rc));
1133 				return UPDATE_FAIL_TIMEOUT_WAITING_FOR_ATTN;
1134 			}
1135 		}
1136 
1137 		//Wait for completion
1138 		do {
1139 			Sleep(20);
1140 			rmi4update_poll();
1141 			if (IsBLv87()) {
1142 				if (m_flashStatus == WRITE_PROTECTION)
1143 					return UPDATE_FAIL_WRITE_PROTECTED;
1144 			}
1145 			if (m_flashStatus == SUCCESS){
1146 				break;
1147 			}
1148 			retry++;
1149 		} while(retry < 20);
1150 
1151 		if (m_flashStatus != SUCCESS) {
1152 			fprintf(stdout, "err flash_status = %d\n", m_flashStatus);
1153 			return UPDATE_FAIL_WRITE_F01_CONTROL_0;
1154 		}
1155 
1156 	}
1157 
1158 	if(m_device.GetDeviceType() == RMI_DEVICE_TYPE_TOUCHPAD)  {
1159 		if (m_firmwareImage.GetSignatureInfo()[BLv7_FLASH_CONFIG].bExisted) {
1160 			// Write signature.
1161 			rc = WriteSignatureV7(BLv7_FLASH_CONFIG, m_firmwareImage.GetFlashConfigData(), offset);
1162 			if (rc != UPDATE_SUCCESS) {
1163 				fprintf(stderr, "%s: %s\n", __func__, update_err_to_string(rc));
1164 				return rc;
1165 			}
1166 		}
1167 	}
1168 
1169 	return UPDATE_SUCCESS;
1170 }
1171 
WriteFLDV7()1172 int RMI4Update::WriteFLDV7()
1173 {
1174 	int transaction_count, remain_block;
1175 	int transfer_leng = 0;
1176 	int offset = 0;
1177 	unsigned char trans_leng_buf[2];
1178 	unsigned char cmd_buf[1];
1179 	unsigned char off[2] = {0, 0};
1180 	unsigned char partition_id;
1181 	int i;
1182 	int retry = 0;
1183 	unsigned char *data_temp;
1184 	int rc;
1185 	unsigned short left_bytes;
1186 	unsigned short write_size;
1187 	unsigned short max_write_size;
1188 	unsigned short dataAddr = m_f34.GetDataBase();
1189 	unsigned short fldBlockCount = m_firmwareImage.GetFLDSize() / m_blockSize;
1190 
1191 	if (m_bootloaderID[1] < 10) {
1192 		// Not support writing FLD before bootloader v10
1193 		return UPDATE_SUCCESS;
1194 	}
1195 
1196 	/* calculate the count */
1197 	partition_id = FIXED_LOCATION_DATA_PARTITION;
1198 
1199 	remain_block = (fldBlockCount % m_payloadLength);
1200 	transaction_count = (fldBlockCount / m_payloadLength);
1201 
1202 	if (remain_block > 0)
1203 		transaction_count++;
1204 
1205 	/* set partition id for bootloader 7 */
1206 	rc = m_device.Write(dataAddr + 1, &partition_id, sizeof(partition_id));
1207 	if (rc != sizeof(partition_id))
1208 		return UPDATE_FAIL_WRITE_FLASH_COMMAND;
1209 
1210 	rc = m_device.Write(dataAddr + 2, off, sizeof(off));
1211 	if (rc != sizeof(off))
1212 		return UPDATE_FAIL_WRITE_INITIAL_ZEROS;
1213 
1214 	for (i = 0; i < transaction_count; i++)
1215 	{
1216 		if ((i == (transaction_count -1)) && (remain_block > 0))
1217 			transfer_leng = remain_block;
1218 		else
1219 			transfer_leng = m_payloadLength;
1220 
1221 		// Set Transfer Length
1222 		trans_leng_buf[0] = (unsigned char)(transfer_leng & 0xFF);
1223 		trans_leng_buf[1] = (unsigned char)((transfer_leng & 0xFF00) >> 8);
1224 
1225 		rc = m_device.Write(dataAddr + 3, trans_leng_buf, sizeof(trans_leng_buf));
1226 		if (rc != sizeof(trans_leng_buf))
1227 			return UPDATE_FAIL_WRITE_FLASH_COMMAND;
1228 
1229 		// Set Command to Write
1230 		cmd_buf[0] = (unsigned char)CMD_V7_WRITE;
1231 		rc = m_device.Write(dataAddr + 4, cmd_buf, sizeof(cmd_buf));
1232 		if (rc != sizeof(cmd_buf))
1233 			return UPDATE_FAIL_WRITE_FLASH_COMMAND;
1234 
1235 		max_write_size = 16;
1236 		if (max_write_size >= transfer_leng * m_blockSize)
1237 			max_write_size = transfer_leng * m_blockSize;
1238 		else if (max_write_size > m_blockSize)
1239 			max_write_size -= max_write_size % m_blockSize;
1240 		else
1241 			max_write_size = m_blockSize;
1242 
1243 		left_bytes = transfer_leng * m_blockSize;
1244 		do {
1245 			if (left_bytes / max_write_size)
1246 				write_size = max_write_size;
1247 			else
1248 				write_size = left_bytes;
1249 
1250 			data_temp = (unsigned char *) malloc(sizeof(unsigned char) * write_size);
1251 			memcpy(data_temp, m_firmwareImage.GetFLDData() + offset, sizeof(char) * write_size);
1252 			rc = m_device.Write(dataAddr + 5, data_temp, sizeof(char) * write_size);
1253 			if (rc != ((ssize_t)sizeof(char) * write_size)) {
1254 				fprintf(stdout, "err write_size = %d; rc = %d\n", write_size, rc);
1255 				return UPDATE_FAIL_READ_F34_QUERIES;
1256 			}
1257 
1258 			offset += write_size;
1259 			left_bytes -= write_size;
1260 			free(data_temp);
1261 		} while (left_bytes);
1262 
1263 		if(m_device.GetDeviceType() == RMI_DEVICE_TYPE_TOUCHPAD)  {
1264 			// Sleep 100 ms and wait for attention for touchpad only.
1265 			Sleep(100);
1266 			rc = WaitForIdle(RMI_F34_IDLE_WAIT_MS, false);
1267 			if (rc != UPDATE_SUCCESS) {
1268 				fprintf(stderr, "%s: %s\n", __func__, update_err_to_string(rc));
1269 				return UPDATE_FAIL_TIMEOUT_WAITING_FOR_ATTN;
1270 			}
1271 		}
1272 
1273 
1274 		//Wait for completion
1275 		do {
1276 			Sleep(20);
1277 			rmi4update_poll();
1278 			if (IsBLv87()) {
1279 				if (m_flashStatus == WRITE_PROTECTION)
1280 					return UPDATE_FAIL_WRITE_PROTECTED;
1281 			}
1282 			if (m_flashStatus == SUCCESS){
1283 				break;
1284 
1285 			}
1286 			retry++;
1287 		} while(retry < 20);
1288 
1289 		if (m_flashStatus != SUCCESS) {
1290 			fprintf(stdout, "err flash_status = %d\n", m_flashStatus);
1291 			return UPDATE_FAIL_WRITE_F01_CONTROL_0;
1292 		}
1293 
1294 	}
1295 
1296 	if(m_device.GetDeviceType() == RMI_DEVICE_TYPE_TOUCHPAD)  {
1297 		if (m_firmwareImage.GetSignatureInfo()[BLv7_FLD].bExisted) {
1298 			// Write signature.
1299 			rc = WriteSignatureV7(BLv7_FLD, m_firmwareImage.GetFLDData(), offset);
1300 			if (rc != UPDATE_SUCCESS) {
1301 				fprintf(stderr, "%s: %s\n", __func__, update_err_to_string(rc));
1302 				return rc;
1303 			}
1304 		}
1305 	}
1306 
1307 	return UPDATE_SUCCESS;
1308 }
1309 
WriteGlobalParametersV7()1310 int RMI4Update::WriteGlobalParametersV7()
1311 {
1312 	int transaction_count, remain_block;
1313 	int transfer_leng = 0;
1314 	int offset = 0;
1315 	unsigned char trans_leng_buf[2];
1316 	unsigned char cmd_buf[1];
1317 	unsigned char off[2] = {0, 0};
1318 	unsigned char partition_id;
1319 	int i;
1320 	int retry = 0;
1321 	unsigned char *data_temp;
1322 	int rc;
1323 	unsigned short left_bytes;
1324 	unsigned short write_size;
1325 	unsigned short max_write_size;
1326 	unsigned short dataAddr = m_f34.GetDataBase();
1327 	unsigned short glpBlockCount = m_firmwareImage.GetGlobalParametersSize() / m_blockSize;
1328 
1329 	/* calculate the count */
1330 	partition_id = GLOBAL_PARAMETERS_PARTITION;
1331 
1332 	remain_block = (glpBlockCount % m_payloadLength);
1333 	transaction_count = (glpBlockCount / m_payloadLength);
1334 
1335 	if (remain_block > 0)
1336 		transaction_count++;
1337 
1338 	/* set partition id for bootloader 7 */
1339 	rc = m_device.Write(dataAddr + 1, &partition_id, sizeof(partition_id));
1340 	if (rc != sizeof(partition_id))
1341 		return UPDATE_FAIL_WRITE_FLASH_COMMAND;
1342 
1343 	rc = m_device.Write(dataAddr + 2, off, sizeof(off));
1344 	if (rc != sizeof(off))
1345 		return UPDATE_FAIL_WRITE_INITIAL_ZEROS;
1346 
1347 	for (i = 0; i < transaction_count; i++)
1348 	{
1349 		if ((i == (transaction_count -1)) && (remain_block > 0))
1350 			transfer_leng = remain_block;
1351 		else
1352 			transfer_leng = m_payloadLength;
1353 
1354 		// Set Transfer Length
1355 		trans_leng_buf[0] = (unsigned char)(transfer_leng & 0xFF);
1356 		trans_leng_buf[1] = (unsigned char)((transfer_leng & 0xFF00) >> 8);
1357 
1358 		rc = m_device.Write(dataAddr + 3, trans_leng_buf, sizeof(trans_leng_buf));
1359 		if (rc != sizeof(trans_leng_buf))
1360 			return UPDATE_FAIL_WRITE_FLASH_COMMAND;
1361 
1362 		// Set Command to Write
1363 		cmd_buf[0] = (unsigned char)CMD_V7_WRITE;
1364 		rc = m_device.Write(dataAddr + 4, cmd_buf, sizeof(cmd_buf));
1365 		if (rc != sizeof(cmd_buf))
1366 			return UPDATE_FAIL_WRITE_FLASH_COMMAND;
1367 
1368 		max_write_size = 16;
1369 		if (max_write_size >= transfer_leng * m_blockSize)
1370 			max_write_size = transfer_leng * m_blockSize;
1371 		else if (max_write_size > m_blockSize)
1372 			max_write_size -= max_write_size % m_blockSize;
1373 		else
1374 			max_write_size = m_blockSize;
1375 
1376 		left_bytes = transfer_leng * m_blockSize;
1377 		do {
1378 			if (left_bytes / max_write_size)
1379 				write_size = max_write_size;
1380 			else
1381 				write_size = left_bytes;
1382 
1383 			data_temp = (unsigned char *) malloc(sizeof(unsigned char) * write_size);
1384 			memcpy(data_temp, m_firmwareImage.GetFLDData() + offset, sizeof(char) * write_size);
1385 			rc = m_device.Write(dataAddr + 5, data_temp, sizeof(char) * write_size);
1386 			if (rc != ((ssize_t)sizeof(char) * write_size)) {
1387 				fprintf(stdout, "err write_size = %d; rc = %d\n", write_size, rc);
1388 				return UPDATE_FAIL_READ_F34_QUERIES;
1389 			}
1390 
1391 			offset += write_size;
1392 			left_bytes -= write_size;
1393 			free(data_temp);
1394 		} while (left_bytes);
1395 
1396 		if(m_device.GetDeviceType() == RMI_DEVICE_TYPE_TOUCHPAD)  {
1397 			// Sleep 100 ms and wait for attention for touchpad only.
1398 			Sleep(100);
1399 			rc = WaitForIdle(RMI_F34_IDLE_WAIT_MS, false);
1400 			if (rc != UPDATE_SUCCESS) {
1401 				fprintf(stderr, "%s: %s\n", __func__, update_err_to_string(rc));
1402 				return UPDATE_FAIL_TIMEOUT_WAITING_FOR_ATTN;
1403 			}
1404 		}
1405 
1406 
1407 		//Wait for completion
1408 		do {
1409 			Sleep(20);
1410 			rmi4update_poll();
1411 			if (m_flashStatus == SUCCESS){
1412 				break;
1413 
1414 			}
1415 			retry++;
1416 		} while(retry < 20);
1417 
1418 		if (m_flashStatus != SUCCESS) {
1419 			fprintf(stdout, "err flash_status = %d\n", m_flashStatus);
1420 			return UPDATE_FAIL_WRITE_F01_CONTROL_0;
1421 		}
1422 
1423 	}
1424 
1425 	return UPDATE_SUCCESS;
1426 }
1427 
EraseFlashConfigV10()1428 int RMI4Update::EraseFlashConfigV10()
1429 {
1430 	unsigned char erase_cmd[8] = {0, 0, 0, 0, 0, 0, 0, 0};
1431 	int retry = 0;
1432 	int rc;
1433 
1434 	/* set partition id for bootloader 10 */
1435 	erase_cmd[0] = FLASH_CONFIG_PARTITION;
1436 	/* write bootloader id */
1437 	erase_cmd[6] = m_bootloaderID[0];
1438 	erase_cmd[7] = m_bootloaderID[1];
1439 	erase_cmd[5] = (unsigned char)CMD_V7_ERASE;
1440 
1441 	fprintf(stdout, "Erase command : ");
1442 	for(int i = 0 ;i<8;i++){
1443 		fprintf(stdout, "%d ", erase_cmd[i]);
1444 	}
1445 	fprintf(stdout, "\n");
1446 
1447 	rmi4update_poll();
1448 	if (!m_inBLmode)
1449 		return UPDATE_FAIL_DEVICE_NOT_IN_BOOTLOADER;
1450 
1451 	// For BL8 device, we need hold 1 seconds after querying
1452 	// F34 status to avoid not get attention by following giving
1453 	// erase command.
1454 	Sleep(1000);
1455 
1456 	rc = m_device.Write(m_f34.GetDataBase() + 1, erase_cmd, sizeof(erase_cmd));
1457 	if (rc != sizeof(erase_cmd))
1458 		return UPDATE_FAIL_WRITE_F01_CONTROL_0;
1459 
1460 	Sleep(100);
1461 
1462 	//Wait from ATTN
1463 	rc = WaitForIdle(RMI_F34_ERASE_V8_WAIT_MS, false);
1464 	if (rc != UPDATE_SUCCESS) {
1465 		fprintf(stderr, "%s: %s\n", __func__, update_err_to_string(rc));
1466 		return UPDATE_FAIL_TIMEOUT_WAITING_FOR_ATTN;
1467 	}
1468 
1469 	do {
1470 		Sleep(20);
1471 		rmi4update_poll();
1472 		if (IsBLv87()) {
1473 			if (m_flashStatus == WRITE_PROTECTION)
1474 				return UPDATE_FAIL_WRITE_PROTECTED;
1475 		}
1476 		if (m_flashStatus == SUCCESS){
1477 			break;
1478 		}
1479 		retry++;
1480 	} while(retry < 20);
1481 
1482 	if (m_flashStatus != SUCCESS) {
1483 		fprintf(stdout, "err flash_status = %d\n", m_flashStatus);
1484 		return UPDATE_FAIL_WRITE_F01_CONTROL_0;
1485 	}
1486 
1487 	return UPDATE_SUCCESS;
1488 }
1489 
EraseCoreCodeV10()1490 int RMI4Update::EraseCoreCodeV10()
1491 {
1492 	unsigned char erase_cmd[8] = {0, 0, 0, 0, 0, 0, 0, 0};
1493 	int retry = 0;
1494 	int rc;
1495 
1496 	/* set partition id for bootloader 10 */
1497 	erase_cmd[0] = CORE_CODE_PARTITION;
1498 	/* write bootloader id */
1499 	erase_cmd[6] = m_bootloaderID[0];
1500 	erase_cmd[7] = m_bootloaderID[1];
1501 	erase_cmd[5] = (unsigned char)CMD_V7_ERASE_AP;
1502 
1503 	fprintf(stdout, "Erase command : ");
1504 	for(int i = 0 ;i<8;i++){
1505 		fprintf(stdout, "%d ", erase_cmd[i]);
1506 	}
1507 	fprintf(stdout, "\n");
1508 
1509 	rmi4update_poll();
1510 	if (!m_inBLmode)
1511 		return UPDATE_FAIL_DEVICE_NOT_IN_BOOTLOADER;
1512 
1513 	// For BL8 device, we need hold 1 seconds after querying
1514 	// F34 status to avoid not get attention by following giving
1515 	// erase command.
1516 	Sleep(1000);
1517 
1518 	rc = m_device.Write(m_f34.GetDataBase() + 1, erase_cmd, sizeof(erase_cmd));
1519 	if (rc != sizeof(erase_cmd))
1520 		return UPDATE_FAIL_WRITE_F01_CONTROL_0;
1521 
1522 	Sleep(100);
1523 
1524 	//Wait from ATTN
1525 	rc = WaitForIdle(RMI_F34_ERASE_V8_WAIT_MS, false);
1526 	if (rc != UPDATE_SUCCESS) {
1527 		fprintf(stderr, "%s: %s\n", __func__, update_err_to_string(rc));
1528 		return UPDATE_FAIL_TIMEOUT_WAITING_FOR_ATTN;
1529 	}
1530 
1531 	do {
1532 		Sleep(20);
1533 		rmi4update_poll();
1534 		if (m_flashStatus == SUCCESS){
1535 			break;
1536 		}
1537 		retry++;
1538 	} while(retry < 20);
1539 
1540 	if (m_flashStatus != SUCCESS) {
1541 		fprintf(stdout, "err flash_status = %d\n", m_flashStatus);
1542 		return UPDATE_FAIL_WRITE_F01_CONTROL_0;
1543 	}
1544 
1545 	return UPDATE_SUCCESS;
1546 }
1547 
EraseFirmwareV7()1548 int RMI4Update::EraseFirmwareV7()
1549 {
1550 	unsigned char erase_cmd[8] = {0, 0, 0, 0, 0, 0, 0, 0};
1551 	int retry = 0;
1552 	int rc;
1553 
1554 	/* set partition id for bootloader 7 */
1555 	erase_cmd[0] = CORE_CODE_PARTITION;
1556 	/* write bootloader id */
1557 	erase_cmd[6] = m_bootloaderID[0];
1558 	erase_cmd[7] = m_bootloaderID[1];
1559 	if(m_bootloaderID[1] == 8){
1560 		/* Set Command to Erase AP for BL8*/
1561 		erase_cmd[5] = (unsigned char)CMD_V7_ERASE_AP;
1562 	} else {
1563 		/* Set Command to Erase AP for BL7*/
1564 		erase_cmd[5] = (unsigned char)CMD_V7_ERASE;
1565 	}
1566 
1567 	fprintf(stdout, "Erase command : ");
1568 	for(int i = 0 ;i<8;i++){
1569 		fprintf(stdout, "%d ", erase_cmd[i]);
1570 	}
1571 	fprintf(stdout, "\n");
1572 
1573 	rmi4update_poll();
1574 	if (!m_inBLmode)
1575 		return UPDATE_FAIL_DEVICE_NOT_IN_BOOTLOADER;
1576 	if(m_bootloaderID[1] == 8){
1577 		// For BL8 device, we need hold 1 seconds after querying
1578 		// F34 status to avoid not get attention by following giving
1579 		// erase command.
1580 		Sleep(1000);
1581 	}
1582 
1583 	rc = m_device.Write(m_f34.GetDataBase() + 1, erase_cmd, sizeof(erase_cmd));
1584 	if (rc != sizeof(erase_cmd))
1585 		return UPDATE_FAIL_WRITE_F01_CONTROL_0;
1586 
1587 	Sleep(100);
1588 
1589 	//Wait from ATTN
1590 	if(m_bootloaderID[1] == 8){
1591 		if(m_device.GetDeviceType() == RMI_DEVICE_TYPE_TOUCHPAD)  {
1592 			// Wait for attention for BL8 touchpad.
1593 			rc = WaitForIdle(RMI_F34_ERASE_V8_WAIT_MS, false);
1594 			if (rc != UPDATE_SUCCESS) {
1595 				fprintf(stderr, "%s: %s\n", __func__, update_err_to_string(rc));
1596 				return UPDATE_FAIL_TIMEOUT_WAITING_FOR_ATTN;
1597 			}
1598 		}
1599 	}
1600 	do {
1601 		Sleep(20);
1602 		rmi4update_poll();
1603 		if (IsBLv87()) {
1604 			if (m_flashStatus == WRITE_PROTECTION)
1605 				return UPDATE_FAIL_WRITE_PROTECTED;
1606 		}
1607 		if (m_flashStatus == SUCCESS){
1608 			break;
1609 		}
1610 		retry++;
1611 	} while(retry < 20);
1612 
1613 	if (m_flashStatus != SUCCESS) {
1614 		fprintf(stdout, "err flash_status = %d\n", m_flashStatus);
1615 		return UPDATE_FAIL_WRITE_F01_CONTROL_0;
1616 	}
1617 
1618 	if(m_bootloaderID[1] == 7){
1619 		// For BL7, we need erase config partition.
1620 		fprintf(stdout, "Start to erase config\n");
1621 		erase_cmd[0] = CORE_CONFIG_PARTITION;
1622 		erase_cmd[6] = m_bootloaderID[0];
1623 		erase_cmd[7] = m_bootloaderID[1];
1624 		erase_cmd[5] = (unsigned char)CMD_V7_ERASE;
1625 
1626 		Sleep(100);
1627 		rmi4update_poll();
1628 		if (!m_inBLmode)
1629 		  return UPDATE_FAIL_DEVICE_NOT_IN_BOOTLOADER;
1630 
1631 		rc = m_device.Write(m_f34.GetDataBase() + 1, erase_cmd, sizeof(erase_cmd));
1632 		if (rc != sizeof(erase_cmd))
1633 			return UPDATE_FAIL_WRITE_F01_CONTROL_0;
1634 
1635 		if(m_device.GetDeviceType() == RMI_DEVICE_TYPE_TOUCHPAD)  {
1636 			//Wait from ATTN for touchpad only.
1637 			Sleep(100);
1638 
1639 			rc = WaitForIdle(RMI_F34_ERASE_WAIT_MS, true);
1640 			if (rc != UPDATE_SUCCESS) {
1641 				fprintf(stderr, "%s: %s\n", __func__, update_err_to_string(rc));
1642 				return UPDATE_FAIL_TIMEOUT_WAITING_FOR_ATTN;
1643 			}
1644 		}
1645 
1646 
1647 		do {
1648 			Sleep(20);
1649 			rmi4update_poll();
1650 			if (m_flashStatus == SUCCESS){
1651 				break;
1652 			}
1653 			retry++;
1654 		} while(retry < 20);
1655 
1656 		if (m_flashStatus != SUCCESS) {
1657 			fprintf(stdout, "err flash_status = %d\n", m_flashStatus);
1658 			return UPDATE_FAIL_WRITE_F01_CONTROL_0;
1659 		}
1660 	}
1661 
1662 	return UPDATE_SUCCESS;
1663 }
1664 
EnterFlashProgrammingV7()1665 int RMI4Update::EnterFlashProgrammingV7()
1666 {
1667 	int rc;
1668 	unsigned char f34_status;
1669 	rc = m_device.Read(m_f34.GetDataBase(), &f34_status, sizeof(unsigned char));
1670 	m_inBLmode = f34_status & 0x80;
1671 	if(!m_inBLmode){
1672 		fprintf(stdout, "Not in BL mode, going to BL mode...\n");
1673 		unsigned char EnterCmd[8] = {0, 0, 0, 0, 0, 0, 0, 0};
1674 		int retry = 0;
1675 
1676 		/* set partition id for bootloader 7 */
1677 		EnterCmd[0] = BOOTLOADER_PARTITION;
1678 
1679 		/* write bootloader id */
1680 		EnterCmd[6] = m_bootloaderID[0];
1681 		EnterCmd[7] = m_bootloaderID[1];
1682 
1683 		// Set Command to EnterBL
1684 		EnterCmd[5] = (unsigned char)CMD_V7_ENTER_BL;
1685 
1686 		rc = m_device.Write(m_f34.GetDataBase() + 1, EnterCmd, sizeof(EnterCmd));
1687 		if (rc != sizeof(EnterCmd))
1688 			return UPDATE_FAIL_WRITE_F01_CONTROL_0;
1689 
1690 		if(m_device.GetDeviceType() == RMI_DEVICE_TYPE_TOUCHPAD)  {
1691 			rc = WaitForIdle(RMI_F34_ENABLE_WAIT_MS, false);
1692 			if (rc != UPDATE_SUCCESS) {
1693 				fprintf(stderr, "%s: %s\n", __func__, update_err_to_string(rc));
1694 				return UPDATE_FAIL_TIMEOUT_WAITING_FOR_ATTN;
1695 			}
1696 		}
1697 
1698 		//Wait from ATTN
1699 		do {
1700 			Sleep(20);
1701 			rmi4update_poll();
1702 			if (m_flashStatus == SUCCESS){
1703 				break;
1704 			}
1705 			retry++;
1706 		} while(retry < 20);
1707 
1708 		if (m_flashStatus != SUCCESS) {
1709 			fprintf(stdout, "err flash_status = %d\n", m_flashStatus);
1710 			return UPDATE_FAIL_WRITE_F01_CONTROL_0;
1711 		}
1712 
1713 		Sleep(RMI_F34_ENABLE_WAIT_MS);
1714 
1715 		fprintf(stdout, "%s\n", __func__);
1716 		rmi4update_poll();
1717 		if (!m_inBLmode)
1718 			return UPDATE_FAIL_DEVICE_NOT_IN_BOOTLOADER;
1719 
1720 	} else
1721 		fprintf(stdout, "Already in BL mode, skip...\n");
1722 
1723 	if(m_device.GetDeviceType() != RMI_DEVICE_TYPE_TOUCHPAD) {
1724 		// workaround for touchscreen only
1725 		fprintf(stdout, "Erase in BL mode\n");
1726 		rc = EraseFirmwareV7();
1727 		if (rc != UPDATE_SUCCESS) {
1728 			fprintf(stderr, "%s: %s\n", __func__, update_err_to_string(rc));
1729 			return UPDATE_FAIL_ERASE_ALL;
1730 		}
1731 		fprintf(stdout, "Erase in BL mode end\n");
1732 		m_device.RebindDriver();
1733 	}
1734 
1735 	Sleep(RMI_F34_ENABLE_WAIT_MS);
1736 
1737 	rc = FindUpdateFunctions();
1738 	if (rc != UPDATE_SUCCESS)
1739 		return rc;
1740 
1741 	rc = ReadF34Queries();
1742 	if (rc != UPDATE_SUCCESS)
1743 		return rc;
1744 
1745 	return UPDATE_SUCCESS;
1746 }
1747 
EnterFlashProgramming()1748 int RMI4Update::EnterFlashProgramming()
1749 {
1750 	int rc;
1751 	unsigned char f01Control_0;
1752 	const unsigned char enableProg = RMI_F34_ENABLE_FLASH_PROG;
1753 
1754 	rc = WriteBootloaderID();
1755 	if (rc != UPDATE_SUCCESS)
1756 		return rc;
1757 
1758 	fprintf(stdout, "Enabling flash programming.\n");
1759 	rc = m_device.Write(m_f34StatusAddr, &enableProg, 1);
1760 	if (rc != 1)
1761 		return UPDATE_FAIL_ENABLE_FLASH_PROGRAMMING;
1762 
1763 
1764 	if(m_device.GetDeviceType() != RMI_DEVICE_TYPE_TOUCHPAD) {
1765 		fprintf(stdout, "not TouchPad, rebind driver here\n");
1766 		Sleep(RMI_F34_ENABLE_WAIT_MS);
1767 		m_device.RebindDriver();
1768 		rc = WaitForIdle(0);
1769 		if (rc != UPDATE_SUCCESS)
1770 			return UPDATE_FAIL_NOT_IN_IDLE_STATE;
1771 	} else {
1772 		// For TouchPad
1773 		rc = WaitForIdle(RMI_F34_ENABLE_WAIT_MS);
1774 		if (rc != UPDATE_SUCCESS)
1775 			return UPDATE_FAIL_NOT_IN_IDLE_STATE;
1776 	}
1777 
1778 	if (!m_programEnabled)
1779 		return UPDATE_FAIL_PROGRAMMING_NOT_ENABLED;
1780 
1781 	fprintf(stdout, "Programming is enabled.\n");
1782 	rc = FindUpdateFunctions();
1783 	if (rc != UPDATE_SUCCESS)
1784 		return rc;
1785 
1786 	rc = m_device.Read(m_f01.GetDataBase(), &m_deviceStatus, 1);
1787 	if (rc != 1)
1788 		return UPDATE_FAIL_READ_DEVICE_STATUS;
1789 
1790 	if(m_f34.GetFunctionVersion() > 0x1){
1791 		if (!RMI_F01_STATUS_BOOTLOADER_v7(m_deviceStatus))
1792 			return UPDATE_FAIL_DEVICE_NOT_IN_BOOTLOADER;
1793 		fprintf(stdout, "Already in BL mode V7\n");
1794 	} else {
1795 		if (!RMI_F01_STATUS_BOOTLOADER(m_deviceStatus))
1796 			return UPDATE_FAIL_DEVICE_NOT_IN_BOOTLOADER;
1797 		fprintf(stdout, "Already in BL mode\n");
1798 	}
1799 
1800 	rc = ReadF34Queries();
1801 	if (rc != UPDATE_SUCCESS)
1802 		return rc;
1803 
1804 	rc = m_device.Read(m_f01.GetControlBase(), &f01Control_0, 1);
1805 	if (rc != 1)
1806 		return UPDATE_FAIL_READ_F01_CONTROL_0;
1807 
1808 	f01Control_0 |= RMI_F01_CRTL0_NOSLEEP_BIT;
1809 	f01Control_0 = (f01Control_0 & ~RMI_F01_CTRL0_SLEEP_MODE_MASK) | RMI_SLEEP_MODE_NORMAL;
1810 
1811 	rc = m_device.Write(m_f01.GetControlBase(), &f01Control_0, 1);
1812 	if (rc != 1)
1813 		return UPDATE_FAIL_WRITE_F01_CONTROL_0;
1814 
1815 	return UPDATE_SUCCESS;
1816 }
1817 
WriteBlocks(unsigned char * block,unsigned short count,unsigned char cmd)1818 int RMI4Update::WriteBlocks(unsigned char *block, unsigned short count, unsigned char cmd)
1819 {
1820 	int blockNum;
1821 	unsigned char zeros[] = { 0, 0 };
1822 	int rc;
1823 	unsigned short addr;
1824 	unsigned char *blockWithCmd = (unsigned char *)alloca(m_blockSize + 1);
1825 
1826 	if (m_f34.GetFunctionVersion() == 0x1)
1827 		addr = m_f34.GetDataBase() + RMI_F34_BLOCK_DATA_V1_OFFSET;
1828 	else
1829 		addr = m_f34.GetDataBase() + RMI_F34_BLOCK_DATA_OFFSET;
1830 
1831 	rc = m_device.Write(m_f34.GetDataBase(), zeros, 2);
1832 	if (rc != 2)
1833 		return UPDATE_FAIL_WRITE_INITIAL_ZEROS;
1834 
1835 	for (blockNum = 0; blockNum < count; ++blockNum) {
1836 		if (m_writeBlockWithCmd) {
1837 			memcpy(blockWithCmd, block, m_blockSize);
1838 			blockWithCmd[m_blockSize] = cmd;
1839 
1840 			rc = m_device.Write(addr, blockWithCmd, m_blockSize + 1);
1841 			if (rc != m_blockSize + 1) {
1842 				fprintf(stderr, "failed to write block %d\n", blockNum);
1843 				return UPDATE_FAIL_WRITE_BLOCK;
1844 			}
1845 		} else {
1846 			rc = m_device.Write(addr, block, m_blockSize);
1847 			if (rc != m_blockSize) {
1848 				fprintf(stderr, "failed to write block %d\n", blockNum);
1849 				return UPDATE_FAIL_WRITE_BLOCK;
1850 			}
1851 
1852 			rc = m_device.Write(m_f34StatusAddr, &cmd, 1);
1853 			if (rc != 1) {
1854 				fprintf(stderr, "failed to write command for block %d\n", blockNum);
1855 				return UPDATE_FAIL_WRITE_FLASH_COMMAND;
1856 			}
1857 		}
1858 
1859 		rc = WaitForIdle(RMI_F34_IDLE_WAIT_MS, !m_writeBlockWithCmd);
1860 		if (rc != UPDATE_SUCCESS) {
1861 			fprintf(stderr, "failed to go into idle after writing block %d\n", blockNum);
1862 			return UPDATE_FAIL_NOT_IN_IDLE_STATE;
1863 		}
1864 
1865 		block += m_blockSize;
1866 	}
1867 
1868 	return UPDATE_SUCCESS;
1869 }
1870 
WriteSignatureV7(enum signature_BLv7 signature_partition,unsigned char * data,int offset)1871 int RMI4Update::WriteSignatureV7(enum signature_BLv7 signature_partition, unsigned char* data, int offset)
1872 {
1873 	fprintf(stdout, "Write Signature...\n");
1874 	int rc;
1875 	unsigned char off[2] = {0, 0};
1876 	unsigned char cmd_buf[1];
1877 	unsigned short dataAddr = m_f34.GetDataBase();
1878 	int transfer_leng = 0;
1879 	signature_info signature = m_firmwareImage.GetSignatureInfo()[signature_partition];
1880 	unsigned char trans_leng_buf[2];
1881 	unsigned short left_bytes;
1882 	unsigned short write_size;
1883 	unsigned short max_write_size;
1884 	unsigned char *data_temp;
1885 	int retry = 0;
1886 	rc = m_device.Write(dataAddr + 2, off, sizeof(off));
1887 	if (rc != sizeof(off))
1888 		return UPDATE_FAIL_WRITE_INITIAL_ZEROS;
1889 
1890 	// Set Transfer Length
1891 	transfer_leng = signature.size / m_blockSize;
1892 	trans_leng_buf[0] = (unsigned char)(transfer_leng & 0xFF);
1893 	trans_leng_buf[1] = (unsigned char)((transfer_leng & 0xFF00) >> 8);
1894 
1895 	rc = m_device.Write(dataAddr + 3, trans_leng_buf, sizeof(trans_leng_buf));
1896 	if (rc != sizeof(trans_leng_buf))
1897 		return UPDATE_FAIL_WRITE_FLASH_COMMAND;
1898 
1899 	// Set Command to Signature
1900 	cmd_buf[0] = (unsigned char)CMD_V7_SIGNATURE;
1901 	rc = m_device.Write(dataAddr + 4, cmd_buf, sizeof(cmd_buf));
1902 	if (rc != sizeof(cmd_buf))
1903 		return UPDATE_FAIL_WRITE_FLASH_COMMAND;
1904 
1905 	max_write_size = 16;
1906 	if (max_write_size >= transfer_leng * m_blockSize)
1907 		max_write_size = transfer_leng * m_blockSize;
1908 	else if (max_write_size > m_blockSize)
1909 		max_write_size -= max_write_size % m_blockSize;
1910 	else
1911 		max_write_size = m_blockSize;
1912 
1913 	left_bytes = transfer_leng * m_blockSize;
1914 
1915 	do {
1916 		if (left_bytes / max_write_size)
1917 			write_size = max_write_size;
1918 		else
1919 			write_size = left_bytes;
1920 
1921 		data_temp = (unsigned char *) malloc(sizeof(unsigned char) * write_size);
1922 		memcpy(data_temp, data + offset, sizeof(char) * write_size);
1923 		rc = m_device.Write(dataAddr + 5, data_temp, sizeof(char) * write_size);
1924 		if (rc != ((ssize_t)sizeof(char) * write_size)) {
1925 			fprintf(stdout, "err write_size = %d; rc = %d\n", write_size, rc);
1926 			return UPDATE_FAIL_WRITE_BLOCK;
1927 		}
1928 
1929 		offset += write_size;
1930 		left_bytes -= write_size;
1931 		free(data_temp);
1932 	} while (left_bytes);
1933 
1934 	// Wair for attention for touchpad only.
1935 	rc = WaitForIdle(RMI_F34_IDLE_WAIT_MS, false);
1936 	if (rc != UPDATE_SUCCESS) {
1937 		fprintf(stderr, "%s: %s\n", __func__, update_err_to_string(rc));
1938 		return UPDATE_FAIL_TIMEOUT_WAITING_FOR_ATTN;
1939 	}
1940 
1941 	//Wait for completion
1942 	do {
1943 		Sleep(20);
1944 		rmi4update_poll();
1945 		if (m_flashStatus == SUCCESS){
1946 			break;
1947 		}
1948 		retry++;
1949 	} while(retry < 20);
1950 
1951 	if (m_flashStatus != SUCCESS) {
1952 		fprintf(stdout, "err flash_status = %d\n", m_flashStatus);
1953 		return UPDATE_FAIL_WRITE_F01_CONTROL_0;
1954 	}
1955 	return UPDATE_SUCCESS;
1956 }
1957 
1958 /*
1959  * This is a limited implementation of WaitForIdle which assumes WaitForAttention is supported
1960  * this will be true for HID, but other protocols will need to revert polling. Polling
1961  * is not implemented yet.
1962  */
WaitForIdle(int timeout_ms,bool readF34OnSucess)1963 int RMI4Update::WaitForIdle(int timeout_ms, bool readF34OnSucess)
1964 {
1965 	int rc = 0;
1966 	struct timeval tv;
1967 
1968 	if (timeout_ms > 0) {
1969 		tv.tv_sec = timeout_ms / 1000;
1970 		tv.tv_usec = (timeout_ms % 1000) * 1000;
1971 
1972 		rc = m_device.WaitForAttention(&tv, m_f34.GetInterruptMask());
1973 		if (rc == -ETIMEDOUT){
1974 			/*
1975 			 * If for some reason we are not getting attention reports for HID devices
1976 			 * then we can still continue after the timeout and read F34 status
1977 			 * but if we have to wait for the timeout to ellapse everytime then this
1978 			 * will be slow. If this message shows up a lot then something is wrong
1979 			 * with receiving attention reports and that should be fixed.
1980 			 */
1981 			fprintf(stderr, "RMI4Update::WaitForIdle Timed out waiting for attn report\n");
1982 		}
1983 	}
1984 
1985 	if (rc <= 0 || readF34OnSucess) {
1986 		rc = ReadF34Controls();
1987 		if (rc != UPDATE_SUCCESS)
1988 			return rc;
1989 
1990 		if (!m_f34Status && !m_f34Command) {
1991 			if (!m_programEnabled) {
1992 				fprintf(stderr, "RMI4Update::WaitForIdle Bootloader is idle but program_enabled bit isn't set.\n");
1993 				return UPDATE_FAIL_PROGRAMMING_NOT_ENABLED;
1994 			} else {
1995 				return UPDATE_SUCCESS;
1996 			}
1997 		}
1998 		fprintf(stderr, "RMI4Update::WaitForIdle\n");
1999 		fprintf(stderr, "  ERROR: Waiting for idle status.\n");
2000 		fprintf(stderr, "  Command: %#04x\n", m_f34Command);
2001 		fprintf(stderr, "  Status:  %#04x\n", m_f34Status);
2002 		fprintf(stderr, "  Enabled: %d\n", m_programEnabled);
2003 		fprintf(stderr, "  Idle:    %d\n", !m_f34Command && !m_f34Status);
2004 
2005 		return UPDATE_FAIL_NOT_IN_IDLE_STATE;
2006 	}
2007 
2008 	return UPDATE_SUCCESS;
2009 }
2010 
IsBLv87()2011 bool RMI4Update::IsBLv87()
2012 {
2013 	if ((m_bootloaderID[1] >= 10) ||
2014 		((m_bootloaderID[1] == 8) && (m_bootloaderID[0] >= 7))){
2015 		return true;
2016 	} else
2017 		return false;
2018 }
2019 
ReadMSL()2020 int RMI4Update::ReadMSL()
2021 {
2022 	int rc;
2023 	unsigned char idStr[3];
2024 	unsigned short query9Addr = m_f34.GetQueryBase() + 9;
2025 	unsigned char offset;
2026 	unsigned char MSL[2];
2027 
2028 	rc = m_device.Read(query9Addr, MSL, sizeof(MSL));
2029 	if (rc != sizeof(MSL))
2030 		return UPDATE_FAIL_READ_F34_QUERIES;
2031 
2032 	m_MSL = MSL[0] << 8 | MSL[1];
2033 	return UPDATE_SUCCESS;
2034 }
2035