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 27 #include "rmi4update.h" 28 29 #define RMI_F34_QUERY_SIZE 7 30 #define RMI_F34_HAS_NEW_REG_MAP (1 << 0) 31 #define RMI_F34_IS_UNLOCKED (1 << 1) 32 #define RMI_F34_HAS_CONFIG_ID (1 << 2) 33 #define RMI_F34_BLOCK_SIZE_OFFSET 1 34 #define RMI_F34_FW_BLOCKS_OFFSET 3 35 #define RMI_F34_CONFIG_BLOCKS_OFFSET 5 36 37 #define RMI_F34_BLOCK_SIZE_V1_OFFSET 0 38 #define RMI_F34_FW_BLOCKS_V1_OFFSET 0 39 #define RMI_F34_CONFIG_BLOCKS_V1_OFFSET 2 40 41 #define RMI_F34_BLOCK_DATA_OFFSET 2 42 #define RMI_F34_BLOCK_DATA_V1_OFFSET 1 43 44 #define RMI_F34_COMMAND_MASK 0x0F 45 #define RMI_F34_STATUS_MASK 0x07 46 #define RMI_F34_STATUS_SHIFT 4 47 #define RMI_F34_ENABLED_MASK 0x80 48 49 #define RMI_F34_COMMAND_V1_MASK 0x3F 50 #define RMI_F34_STATUS_V1_MASK 0x3F 51 #define RMI_F34_ENABLED_V1_MASK 0x80 52 53 #define RMI_F34_WRITE_FW_BLOCK 0x02 54 #define RMI_F34_ERASE_ALL 0x03 55 #define RMI_F34_WRITE_LOCKDOWN_BLOCK 0x04 56 #define RMI_F34_WRITE_CONFIG_BLOCK 0x06 57 #define RMI_F34_ENABLE_FLASH_PROG 0x0f 58 59 #define RMI_F34_ENABLE_WAIT_MS 300 60 #define RMI_F34_ERASE_WAIT_MS (5 * 1000) 61 #define RMI_F34_IDLE_WAIT_MS 500 62 63 /* Most recent device status event */ 64 #define RMI_F01_STATUS_CODE(status) ((status) & 0x0f) 65 /* Indicates that flash programming is enabled (bootloader mode). */ 66 #define RMI_F01_STATUS_BOOTLOADER(status) (!!((status) & 0x40)) 67 /* The device has lost its configuration for some reason. */ 68 #define RMI_F01_STATUS_UNCONFIGURED(status) (!!((status) & 0x80)) 69 70 /* 71 * Sleep mode controls power management on the device and affects all 72 * functions of the device. 73 */ 74 #define RMI_F01_CTRL0_SLEEP_MODE_MASK 0x03 75 76 #define RMI_SLEEP_MODE_NORMAL 0x00 77 #define RMI_SLEEP_MODE_SENSOR_SLEEP 0x01 78 #define RMI_SLEEP_MODE_RESERVED0 0x02 79 #define RMI_SLEEP_MODE_RESERVED1 0x03 80 81 /* 82 * This bit disables whatever sleep mode may be selected by the sleep_mode 83 * field and forces the device to run at full power without sleeping. 84 */ 85 #define RMI_F01_CRTL0_NOSLEEP_BIT (1 << 2) 86 87 int RMI4Update::UpdateFirmware(bool force, bool performLockdown) 88 { 89 struct timespec start; 90 struct timespec end; 91 long long int duration_us = 0; 92 int rc; 93 const unsigned char eraseAll = RMI_F34_ERASE_ALL; 94 95 rc = FindUpdateFunctions(); 96 if (rc != UPDATE_SUCCESS) 97 return rc; 98 99 rc = m_device.QueryBasicProperties(); 100 if (rc < 0) 101 return UPDATE_FAIL_QUERY_BASIC_PROPERTIES; 102 103 if (!force && m_firmwareImage.HasIO()) { 104 if (m_firmwareImage.GetFirmwareID() <= m_device.GetFirmwareID()) { 105 fprintf(stderr, "Firmware image (%ld) is not newer then the firmware on the device (%ld)\n", 106 m_firmwareImage.GetFirmwareID(), m_device.GetFirmwareID()); 107 rc = UPDATE_FAIL_FIRMWARE_IMAGE_IS_OLDER; 108 return rc; 109 } 110 } 111 112 fprintf(stdout, "Device Properties:\n"); 113 m_device.PrintProperties(); 114 115 rc = DisableNonessentialInterupts(); 116 if (rc != UPDATE_SUCCESS) 117 return rc; 118 119 rc = ReadF34Queries(); 120 if (rc != UPDATE_SUCCESS) 121 return rc; 122 123 rc = m_firmwareImage.VerifyImageMatchesDevice(GetFirmwareSize(), GetConfigSize()); 124 if (rc != UPDATE_SUCCESS) 125 return rc; 126 127 rc = EnterFlashProgramming(); 128 if (rc != UPDATE_SUCCESS) { 129 fprintf(stderr, "%s: %s\n", __func__, update_err_to_string(rc)); 130 goto reset; 131 } 132 133 if (performLockdown && m_unlocked) { 134 if (m_firmwareImage.GetLockdownData()) { 135 fprintf(stdout, "Writing lockdown...\n"); 136 clock_gettime(CLOCK_MONOTONIC, &start); 137 rc = WriteBlocks(m_firmwareImage.GetLockdownData(), 138 m_firmwareImage.GetLockdownSize() / 0x10, 139 RMI_F34_WRITE_LOCKDOWN_BLOCK); 140 if (rc != UPDATE_SUCCESS) { 141 fprintf(stderr, "%s: %s\n", __func__, update_err_to_string(rc)); 142 goto reset; 143 } 144 clock_gettime(CLOCK_MONOTONIC, &end); 145 duration_us = diff_time(&start, &end); 146 fprintf(stdout, "Done writing lockdown, time: %lld us.\n", duration_us); 147 } 148 149 rc = EnterFlashProgramming(); 150 if (rc != UPDATE_SUCCESS) { 151 fprintf(stderr, "%s: %s\n", __func__, update_err_to_string(rc)); 152 goto reset; 153 } 154 155 } 156 157 rc = WriteBootloaderID(); 158 if (rc != UPDATE_SUCCESS) { 159 fprintf(stderr, "%s: %s\n", __func__, update_err_to_string(rc)); 160 goto reset; 161 } 162 163 fprintf(stdout, "Erasing FW...\n"); 164 clock_gettime(CLOCK_MONOTONIC, &start); 165 rc = m_device.Write(m_f34StatusAddr, &eraseAll, 1); 166 if (rc != 1) { 167 fprintf(stderr, "%s: %s\n", __func__, update_err_to_string(UPDATE_FAIL_ERASE_ALL)); 168 rc = UPDATE_FAIL_ERASE_ALL; 169 goto reset; 170 } 171 172 rc = WaitForIdle(RMI_F34_ERASE_WAIT_MS); 173 if (rc != UPDATE_SUCCESS) { 174 fprintf(stderr, "%s: %s\n", __func__, update_err_to_string(rc)); 175 goto reset; 176 } 177 clock_gettime(CLOCK_MONOTONIC, &end); 178 duration_us = diff_time(&start, &end); 179 fprintf(stdout, "Erase complete, time: %lld us.\n", duration_us); 180 181 if (m_firmwareImage.GetFirmwareData()) { 182 fprintf(stdout, "Writing firmware...\n"); 183 clock_gettime(CLOCK_MONOTONIC, &start); 184 rc = WriteBlocks(m_firmwareImage.GetFirmwareData(), m_fwBlockCount, 185 RMI_F34_WRITE_FW_BLOCK); 186 if (rc != UPDATE_SUCCESS) { 187 fprintf(stderr, "%s: %s\n", __func__, update_err_to_string(rc)); 188 goto reset; 189 } 190 clock_gettime(CLOCK_MONOTONIC, &end); 191 duration_us = diff_time(&start, &end); 192 fprintf(stdout, "Done writing FW, time: %lld us.\n", duration_us); 193 } 194 195 if (m_firmwareImage.GetConfigData()) { 196 fprintf(stdout, "Writing configuration...\n"); 197 clock_gettime(CLOCK_MONOTONIC, &start); 198 rc = WriteBlocks(m_firmwareImage.GetConfigData(), m_configBlockCount, 199 RMI_F34_WRITE_CONFIG_BLOCK); 200 if (rc != UPDATE_SUCCESS) { 201 fprintf(stderr, "%s: %s\n", __func__, update_err_to_string(rc)); 202 goto reset; 203 } 204 clock_gettime(CLOCK_MONOTONIC, &end); 205 duration_us = diff_time(&start, &end); 206 fprintf(stdout, "Done writing config, time: %lld us.\n", duration_us); 207 } 208 209 reset: 210 m_device.Reset(); 211 m_device.RebindDriver(); 212 return rc; 213 214 } 215 216 int RMI4Update::DisableNonessentialInterupts() 217 { 218 int rc; 219 unsigned char interruptEnabeMask = m_f34.GetInterruptMask() | m_f01.GetInterruptMask(); 220 221 rc = m_device.Write(m_f01.GetControlBase() + 1, &interruptEnabeMask, 1); 222 if (rc != 1) 223 return rc; 224 225 return UPDATE_SUCCESS; 226 } 227 228 int RMI4Update::FindUpdateFunctions() 229 { 230 if (0 > m_device.ScanPDT()) 231 return UPDATE_FAIL_SCAN_PDT; 232 233 if (!m_device.GetFunction(m_f01, 0x01)) 234 return UPDATE_FAIL_NO_FUNCTION_01; 235 236 if (!m_device.GetFunction(m_f34, 0x34)) 237 return UPDATE_FAIL_NO_FUNCTION_34; 238 239 return UPDATE_SUCCESS; 240 } 241 242 int RMI4Update::ReadF34Queries() 243 { 244 int rc; 245 unsigned char idStr[3]; 246 unsigned char buf[8]; 247 unsigned short queryAddr = m_f34.GetQueryBase(); 248 unsigned short f34Version = m_f34.GetFunctionVersion(); 249 unsigned short querySize; 250 251 if (f34Version == 0x1) 252 querySize = 8; 253 else 254 querySize = 2; 255 256 rc = m_device.Read(queryAddr, m_bootloaderID, RMI_BOOTLOADER_ID_SIZE); 257 if (rc != RMI_BOOTLOADER_ID_SIZE) 258 return UPDATE_FAIL_READ_BOOTLOADER_ID; 259 260 if (f34Version == 0x1) 261 ++queryAddr; 262 else 263 queryAddr += querySize; 264 265 if (f34Version == 0x1) { 266 rc = m_device.Read(queryAddr, buf, 1); 267 if (rc != 1) 268 return UPDATE_FAIL_READ_F34_QUERIES; 269 270 m_hasNewRegmap = buf[0] & RMI_F34_HAS_NEW_REG_MAP; 271 m_unlocked = buf[0] & RMI_F34_IS_UNLOCKED;; 272 m_hasConfigID = buf[0] & RMI_F34_HAS_CONFIG_ID; 273 274 ++queryAddr; 275 276 rc = m_device.Read(queryAddr, buf, 2); 277 if (rc != 2) 278 return UPDATE_FAIL_READ_F34_QUERIES; 279 280 m_blockSize = extract_short(buf + RMI_F34_BLOCK_SIZE_V1_OFFSET); 281 282 ++queryAddr; 283 284 rc = m_device.Read(queryAddr, buf, 8); 285 if (rc != 8) 286 return UPDATE_FAIL_READ_F34_QUERIES; 287 288 m_fwBlockCount = extract_short(buf + RMI_F34_FW_BLOCKS_V1_OFFSET); 289 m_configBlockCount = extract_short(buf + RMI_F34_CONFIG_BLOCKS_V1_OFFSET); 290 } else { 291 rc = m_device.Read(queryAddr, buf, RMI_F34_QUERY_SIZE); 292 if (rc != RMI_F34_QUERY_SIZE) 293 return UPDATE_FAIL_READ_F34_QUERIES; 294 295 m_hasNewRegmap = buf[0] & RMI_F34_HAS_NEW_REG_MAP; 296 m_unlocked = buf[0] & RMI_F34_IS_UNLOCKED;; 297 m_hasConfigID = buf[0] & RMI_F34_HAS_CONFIG_ID; 298 m_blockSize = extract_short(buf + RMI_F34_BLOCK_SIZE_OFFSET); 299 m_fwBlockCount = extract_short(buf + RMI_F34_FW_BLOCKS_OFFSET); 300 m_configBlockCount = extract_short(buf + RMI_F34_CONFIG_BLOCKS_OFFSET); 301 } 302 303 idStr[0] = m_bootloaderID[0]; 304 idStr[1] = m_bootloaderID[1]; 305 idStr[2] = 0; 306 307 fprintf(stdout, "F34 bootloader id: %s (%#04x %#04x)\n", idStr, m_bootloaderID[0], 308 m_bootloaderID[1]); 309 fprintf(stdout, "F34 has config id: %d\n", m_hasConfigID); 310 fprintf(stdout, "F34 unlocked: %d\n", m_unlocked); 311 fprintf(stdout, "F34 new reg map: %d\n", m_hasNewRegmap); 312 fprintf(stdout, "F34 block size: %d\n", m_blockSize); 313 fprintf(stdout, "F34 fw blocks: %d\n", m_fwBlockCount); 314 fprintf(stdout, "F34 config blocks: %d\n", m_configBlockCount); 315 fprintf(stdout, "\n"); 316 317 if (f34Version == 0x1) 318 m_f34StatusAddr = m_f34.GetDataBase() + 2; 319 else 320 m_f34StatusAddr = m_f34.GetDataBase() + RMI_F34_BLOCK_DATA_OFFSET + m_blockSize; 321 322 return UPDATE_SUCCESS; 323 } 324 325 int RMI4Update::ReadF34Controls() 326 { 327 int rc; 328 unsigned char buf[2]; 329 330 if (m_f34.GetFunctionVersion() == 0x1) { 331 rc = m_device.Read(m_f34StatusAddr, buf, 2); 332 if (rc != 2) 333 return UPDATE_FAIL_READ_F34_CONTROLS; 334 335 m_f34Command = buf[0] & RMI_F34_COMMAND_V1_MASK; 336 m_f34Status = buf[1] & RMI_F34_STATUS_V1_MASK; 337 m_programEnabled = !!(buf[1] & RMI_F34_ENABLED_MASK); 338 339 } else { 340 rc = m_device.Read(m_f34StatusAddr, buf, 1); 341 if (rc != 1) 342 return UPDATE_FAIL_READ_F34_CONTROLS; 343 344 m_f34Command = buf[0] & RMI_F34_COMMAND_MASK; 345 m_f34Status = (buf[0] >> RMI_F34_STATUS_SHIFT) & RMI_F34_STATUS_MASK; 346 m_programEnabled = !!(buf[0] & RMI_F34_ENABLED_MASK); 347 } 348 349 return UPDATE_SUCCESS; 350 } 351 352 int RMI4Update::WriteBootloaderID() 353 { 354 int rc; 355 int blockDataOffset = RMI_F34_BLOCK_DATA_OFFSET; 356 357 if (m_f34.GetFunctionVersion() == 0x1) 358 blockDataOffset = RMI_F34_BLOCK_DATA_V1_OFFSET; 359 360 rc = m_device.Write(m_f34.GetDataBase() + blockDataOffset, 361 m_bootloaderID, RMI_BOOTLOADER_ID_SIZE); 362 if (rc != RMI_BOOTLOADER_ID_SIZE) 363 return UPDATE_FAIL_WRITE_BOOTLOADER_ID; 364 365 return UPDATE_SUCCESS; 366 } 367 368 int RMI4Update::EnterFlashProgramming() 369 { 370 int rc; 371 unsigned char f01Control_0; 372 const unsigned char enableProg = RMI_F34_ENABLE_FLASH_PROG; 373 374 rc = WriteBootloaderID(); 375 if (rc != UPDATE_SUCCESS) 376 return rc; 377 378 fprintf(stdout, "Enabling flash programming.\n"); 379 rc = m_device.Write(m_f34StatusAddr, &enableProg, 1); 380 if (rc != 1) 381 return UPDATE_FAIL_ENABLE_FLASH_PROGRAMMING; 382 383 Sleep(RMI_F34_ENABLE_WAIT_MS); 384 m_device.RebindDriver(); 385 rc = WaitForIdle(0); 386 if (rc != UPDATE_SUCCESS) 387 return UPDATE_FAIL_NOT_IN_IDLE_STATE; 388 389 if (!m_programEnabled) 390 return UPDATE_FAIL_PROGRAMMING_NOT_ENABLED; 391 392 fprintf(stdout, "Programming is enabled.\n"); 393 rc = FindUpdateFunctions(); 394 if (rc != UPDATE_SUCCESS) 395 return rc; 396 397 rc = m_device.Read(m_f01.GetDataBase(), &m_deviceStatus, 1); 398 if (rc != 1) 399 return UPDATE_FAIL_READ_DEVICE_STATUS; 400 401 if (!RMI_F01_STATUS_BOOTLOADER(m_deviceStatus)) 402 return UPDATE_FAIL_DEVICE_NOT_IN_BOOTLOADER; 403 404 rc = ReadF34Queries(); 405 if (rc != UPDATE_SUCCESS) 406 return rc; 407 408 rc = m_device.Read(m_f01.GetControlBase(), &f01Control_0, 1); 409 if (rc != 1) 410 return UPDATE_FAIL_READ_F01_CONTROL_0; 411 412 f01Control_0 |= RMI_F01_CRTL0_NOSLEEP_BIT; 413 f01Control_0 = (f01Control_0 & ~RMI_F01_CTRL0_SLEEP_MODE_MASK) | RMI_SLEEP_MODE_NORMAL; 414 415 rc = m_device.Write(m_f01.GetControlBase(), &f01Control_0, 1); 416 if (rc != 1) 417 return UPDATE_FAIL_WRITE_F01_CONTROL_0; 418 419 return UPDATE_SUCCESS; 420 } 421 422 int RMI4Update::WriteBlocks(unsigned char *block, unsigned short count, unsigned char cmd) 423 { 424 int blockNum; 425 unsigned char zeros[] = { 0, 0 }; 426 int rc; 427 unsigned short addr; 428 unsigned char *blockWithCmd = (unsigned char *)alloca(m_blockSize + 1); 429 430 if (m_f34.GetFunctionVersion() == 0x1) 431 addr = m_f34.GetDataBase() + RMI_F34_BLOCK_DATA_V1_OFFSET; 432 else 433 addr = m_f34.GetDataBase() + RMI_F34_BLOCK_DATA_OFFSET; 434 435 rc = m_device.Write(m_f34.GetDataBase(), zeros, 2); 436 if (rc != 2) 437 return UPDATE_FAIL_WRITE_INITIAL_ZEROS; 438 439 for (blockNum = 0; blockNum < count; ++blockNum) { 440 if (m_writeBlockWithCmd) { 441 memcpy(blockWithCmd, block, m_blockSize); 442 blockWithCmd[m_blockSize] = cmd; 443 444 rc = m_device.Write(addr, blockWithCmd, m_blockSize + 1); 445 if (rc != m_blockSize + 1) { 446 fprintf(stderr, "failed to write block %d\n", blockNum); 447 return UPDATE_FAIL_WRITE_BLOCK; 448 } 449 } else { 450 rc = m_device.Write(addr, block, m_blockSize); 451 if (rc != m_blockSize) { 452 fprintf(stderr, "failed to write block %d\n", blockNum); 453 return UPDATE_FAIL_WRITE_BLOCK; 454 } 455 456 rc = m_device.Write(m_f34StatusAddr, &cmd, 1); 457 if (rc != 1) { 458 fprintf(stderr, "failed to write command for block %d\n", blockNum); 459 return UPDATE_FAIL_WRITE_FLASH_COMMAND; 460 } 461 } 462 463 rc = WaitForIdle(RMI_F34_IDLE_WAIT_MS, !m_writeBlockWithCmd); 464 if (rc != UPDATE_SUCCESS) { 465 fprintf(stderr, "failed to go into idle after writing block %d\n", blockNum); 466 return UPDATE_FAIL_NOT_IN_IDLE_STATE; 467 } 468 469 block += m_blockSize; 470 } 471 472 return UPDATE_SUCCESS; 473 } 474 475 /* 476 * This is a limited implementation of WaitForIdle which assumes WaitForAttention is supported 477 * this will be true for HID, but other protocols will need to revert polling. Polling 478 * is not implemented yet. 479 */ 480 int RMI4Update::WaitForIdle(int timeout_ms, bool readF34OnSucess) 481 { 482 int rc = 0; 483 struct timeval tv; 484 485 if (timeout_ms > 0) { 486 tv.tv_sec = timeout_ms / 1000; 487 tv.tv_usec = (timeout_ms % 1000) * 1000; 488 489 rc = m_device.WaitForAttention(&tv, m_f34.GetInterruptMask()); 490 if (rc == -ETIMEDOUT) 491 /* 492 * If for some reason we are not getting attention reports for HID devices 493 * then we can still continue after the timeout and read F34 status 494 * but if we have to wait for the timeout to ellapse everytime then this 495 * will be slow. If this message shows up a lot then something is wrong 496 * with receiving attention reports and that should be fixed. 497 */ 498 fprintf(stderr, "Timed out waiting for attn report\n"); 499 } 500 501 if (rc <= 0 || readF34OnSucess) { 502 rc = ReadF34Controls(); 503 if (rc != UPDATE_SUCCESS) 504 return rc; 505 506 if (!m_f34Status && !m_f34Command) { 507 if (!m_programEnabled) { 508 fprintf(stderr, "Bootloader is idle but program_enabled bit isn't set.\n"); 509 return UPDATE_FAIL_PROGRAMMING_NOT_ENABLED; 510 } else { 511 return UPDATE_SUCCESS; 512 } 513 } 514 515 fprintf(stderr, "ERROR: Waiting for idle status.\n"); 516 fprintf(stderr, "Command: %#04x\n", m_f34Command); 517 fprintf(stderr, "Status: %#04x\n", m_f34Status); 518 fprintf(stderr, "Enabled: %d\n", m_programEnabled); 519 fprintf(stderr, "Idle: %d\n", !m_f34Command && !m_f34Status); 520 521 return UPDATE_FAIL_NOT_IN_IDLE_STATE; 522 } 523 524 return UPDATE_SUCCESS; 525 } 526