1 /* 2 * Copyright (C) 2012 - 2014 Andrew Duggan 3 * Copyright (C) 2012 - 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 <iostream> 19 #include <fstream> 20 #include <string.h> 21 #include <stdint.h> 22 #include <stdlib.h> 23 24 #include "firmware_image.h" 25 26 using namespace std; 27 28 unsigned long FirmwareImage::Checksum(unsigned short * data, unsigned long len) 29 { 30 unsigned long checksum = 0xFFFFFFFF; 31 unsigned long lsw = checksum & 0xFFFF; 32 unsigned long msw = checksum >> 16; 33 34 while (len--) { 35 lsw += *data++; 36 msw += lsw; 37 lsw = (lsw & 0xffff) + (lsw >> 16); 38 msw = (msw & 0xffff) + (msw >> 16); 39 } 40 41 checksum = msw << 16 | lsw; 42 43 return checksum; 44 } 45 46 int FirmwareImage::Initialize(const char * filename) 47 { 48 if (!filename) 49 return UPDATE_FAIL_INVALID_PARAMETER; 50 51 ifstream ifsFile(filename, ios::in|ios::binary|ios::ate); 52 if (!ifsFile) 53 return UPDATE_FAIL_OPEN_FIRMWARE_IMAGE; 54 55 ifsFile.seekg(0, ios::end); 56 m_imageSize = ifsFile.tellg(); 57 if (m_imageSize < 0) 58 return UPDATE_FAIL_OPEN_FIRMWARE_IMAGE; 59 60 m_memBlock = new unsigned char[m_imageSize]; 61 ifsFile.seekg(0, ios::beg); 62 ifsFile.read((char*)m_memBlock, m_imageSize); 63 64 if (m_imageSize < 0x100) 65 return UPDATE_FAIL_VERIFY_IMAGE; 66 67 m_checksum = extract_long(&m_memBlock[RMI_IMG_CHECKSUM_OFFSET]); 68 69 unsigned long imageSizeMinusChecksum = m_imageSize - 4; 70 if ((imageSizeMinusChecksum % 2) != 0) 71 /* 72 * Since the header size is fixed and the firmware is 73 * in 16 byte blocks a valid image size should always be 74 * divisible by 2. 75 */ 76 return UPDATE_FAIL_VERIFY_IMAGE; 77 78 unsigned long calculated_checksum = Checksum((uint16_t *)&(m_memBlock[4]), 79 imageSizeMinusChecksum >> 1); 80 81 if (m_checksum != calculated_checksum) { 82 fprintf(stderr, "Firmware image checksum verification failed, saw 0x%08lX, calculated 0x%08lX\n", 83 m_checksum, calculated_checksum); 84 return UPDATE_FAIL_VERIFY_CHECKSUM; 85 } 86 87 m_io = m_memBlock[RMI_IMG_IO_OFFSET]; 88 m_bootloaderVersion = m_memBlock[RMI_IMG_BOOTLOADER_VERSION_OFFSET]; 89 m_firmwareSize = extract_long(&m_memBlock[RMI_IMG_IMAGE_SIZE_OFFSET]); 90 m_configSize = extract_long(&m_memBlock[RMI_IMG_CONFIG_SIZE_OFFSET]); 91 if (m_io == 1) { 92 m_firmwareBuildID = extract_long(&m_memBlock[RMI_IMG_FW_BUILD_ID_OFFSET]); 93 m_packageID = extract_long(&m_memBlock[RMI_IMG_PACKAGE_ID_OFFSET]); 94 } 95 memcpy(m_productID, &m_memBlock[RMI_IMG_PRODUCT_ID_OFFSET], RMI_PRODUCT_ID_LENGTH); 96 m_productID[RMI_PRODUCT_ID_LENGTH] = 0; 97 m_productInfo = extract_short(&m_memBlock[RMI_IMG_PRODUCT_INFO_OFFSET]); 98 99 m_firmwareData = &m_memBlock[RMI_IMG_FW_OFFSET]; 100 m_configData = &m_memBlock[RMI_IMG_FW_OFFSET + m_firmwareSize]; 101 102 switch (m_bootloaderVersion) { 103 case 2: 104 m_lockdownSize = RMI_IMG_LOCKDOWN_V2_SIZE; 105 m_lockdownData = &m_memBlock[RMI_IMG_LOCKDOWN_V2_OFFSET]; 106 break; 107 case 3: 108 case 4: 109 m_lockdownSize = RMI_IMG_LOCKDOWN_V3_SIZE; 110 m_lockdownData = &m_memBlock[RMI_IMG_LOCKDOWN_V3_OFFSET]; 111 break; 112 case 5: 113 case 6: 114 m_lockdownSize = RMI_IMG_LOCKDOWN_V5_SIZE; 115 m_lockdownData = &m_memBlock[RMI_IMG_LOCKDOWN_V5_OFFSET]; 116 break; 117 default: 118 return UPDATE_FAIL_UNSUPPORTED_IMAGE_VERSION; 119 } 120 121 fprintf(stdout, "Firmware Header:\n"); 122 PrintHeaderInfo(); 123 124 return UPDATE_SUCCESS; 125 } 126 127 void FirmwareImage::PrintHeaderInfo() 128 { 129 fprintf(stdout, "Checksum:\t\t0x%lx\n", m_checksum); 130 fprintf(stdout, "Firmware Size:\t\t%ld\n", m_firmwareSize); 131 fprintf(stdout, "Config Size:\t\t%ld\n", m_configSize); 132 fprintf(stdout, "Lockdown Size:\t\t%ld\n", m_lockdownSize); 133 fprintf(stdout, "Firmware Build ID:\t%ld\n", m_firmwareBuildID); 134 fprintf(stdout, "Package ID:\t\t%d\n", m_packageID); 135 fprintf(stdout, "Bootloader Version:\t%d\n", m_bootloaderVersion); 136 fprintf(stdout, "Product ID:\t\t%s\n", m_productID); 137 fprintf(stdout, "Product Info:\t\t%d\n", m_productInfo); 138 fprintf(stdout, "\n"); 139 } 140 141 int FirmwareImage::VerifyImageMatchesDevice(unsigned long deviceFirmwareSize, 142 unsigned long deviceConfigSize) 143 { 144 if (m_firmwareSize != deviceFirmwareSize) { 145 fprintf(stderr, "Firmware image size verfication failed, size in image %ld did " 146 "not match device size %ld\n", m_firmwareSize, deviceFirmwareSize); 147 return UPDATE_FAIL_VERIFY_FIRMWARE_SIZE; 148 } 149 150 if (m_configSize != deviceConfigSize) { 151 fprintf(stderr, "Firmware image size verfication failed, size in image %ld did " 152 "not match device size %ld\n", m_firmwareSize, deviceConfigSize); 153 return UPDATE_FAIL_VERIFY_CONFIG_SIZE; 154 } 155 156 return UPDATE_SUCCESS; 157 } 158 159 FirmwareImage::~FirmwareImage() 160 { 161 delete [] m_memBlock; 162 m_memBlock = NULL; 163 } 164