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