xref: /aosp_15_r20/external/rmi4utils/rmi4update/firmware_image.cpp (revision a248dafd7653b99fc45f9d29e5f139b04f2f28bc)
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 "rmidevice.h"
25 #include "firmware_image.h"
26 
27 using namespace std;
28 
Checksum(unsigned short * data,unsigned long len)29 unsigned long FirmwareImage::Checksum(unsigned short * data, unsigned long len)
30 {
31 	unsigned long checksum = 0xFFFFFFFF;
32 	unsigned long lsw = checksum & 0xFFFF;
33 	unsigned long msw = checksum >> 16;
34 
35 	while (len--) {
36 		lsw += *data++;
37 		msw += lsw;
38 		lsw = (lsw & 0xffff) + (lsw >> 16);
39 		msw = (msw & 0xffff) + (msw >> 16);
40 	}
41 
42 	checksum = msw << 16 | lsw;
43 
44 	return checksum;
45 }
46 
ParseHierarchicalImg()47 void FirmwareImage::ParseHierarchicalImg()
48 {
49 	struct container_descriptor *descriptor;
50 	int numOfCntrs;
51 	int ii;
52 	unsigned int addr;
53 	unsigned int offset;
54 	unsigned int length;
55 	unsigned char *content;
56 	unsigned short container_id;
57 	unsigned int sigature_size;
58 
59 	for (ii = 0; ii < BLv7_MAX; ii++) {
60 		m_signatureInfo[ii].bExisted = false;
61 		m_signatureInfo[ii].size = 0;
62 	}
63 
64 	if (m_bootloaderVersion == RMI_IMG_V10_SIGNATURE_VERSION_NUMBER) {
65 		fprintf (stdout, "has signature\n");
66 	}
67 
68 	m_cntrAddr = extract_long(&m_memBlock[RMI_IMG_V10_CNTR_ADDR_OFFSET]);
69 	descriptor = (struct container_descriptor *)(m_memBlock + m_cntrAddr);
70 	offset = extract_long(descriptor->content_address);
71 	numOfCntrs = extract_long(descriptor->content_length) / 4;
72 
73 	for (ii = 0; ii < numOfCntrs; ii++) {
74 		addr = extract_long(m_memBlock + offset);
75 		offset += 4;
76 		descriptor = (struct container_descriptor *)(m_memBlock + addr);
77 		container_id = descriptor->container_id[0] |
78 				descriptor->container_id[1] << 8;
79 		content = m_memBlock + extract_long(descriptor->content_address);
80 		length = extract_long(descriptor->content_length);
81 		sigature_size = extract_long(descriptor->signature_size);
82 		switch (container_id) {
83 		case BL_CONTAINER:
84 			m_bootloaderVersion = *content;
85 			break;
86 		case UI_CONTAINER:
87 		case CORE_CODE_CONTAINER:
88 			if (sigature_size != 0) {
89 				fprintf(stdout, "CORE CODE signature size : 0x%x\n", sigature_size);
90 				m_signatureInfo[BLv7_CORE_CODE].bExisted = true;
91 				m_signatureInfo[BLv7_CORE_CODE].size = sigature_size;
92 			}
93 			m_firmwareData = content;
94 			m_firmwareSize = length;
95 			break;
96 		case FLASH_CONFIG_CONTAINER:
97 			if (sigature_size != 0) {
98 				fprintf(stdout, "FLASH CONFIG signature size : 0x%x\n", sigature_size);
99 				m_signatureInfo[BLv7_FLASH_CONFIG].bExisted = true;
100 				m_signatureInfo[BLv7_FLASH_CONFIG].size = sigature_size;
101 			}
102 			m_flashConfigData = content;
103 			m_flashConfigSize = length;
104 			break;
105 		case UI_CONFIG_CONTAINER:
106 		case CORE_CONFIG_CONTAINER:
107 			if (sigature_size != 0) {
108 				fprintf(stdout, "CORE CONFIG signature size : 0x%x\n", sigature_size);
109 				m_signatureInfo[BLv7_CORE_CONFIG].bExisted = true;
110 				m_signatureInfo[BLv7_CORE_CONFIG].size = sigature_size;
111 			}
112 			m_configData = content;
113 			m_configSize = length;
114 			break;
115 		case PERMANENT_CONFIG_CONTAINER:
116 		case GUEST_SERIALIZATION_CONTAINER:
117 			m_lockdownData = content;
118 			m_lockdownSize = length;
119 			break;
120 		case GENERAL_INFORMATION_CONTAINER:
121 			m_io = true;
122 			m_packageID = extract_long(content);
123 			m_firmwareBuildID = extract_long(content + 4);
124 			memcpy(m_productID, (content + 0x18), RMI_PRODUCT_ID_LENGTH);
125 			m_productID[RMI_PRODUCT_ID_LENGTH] = 0;
126 			if ((descriptor->major_version == 0) &&
127 				(descriptor->minor_version > 0)) {
128 				m_hasFirmwareVersion = true;
129 				fprintf(stdout, "General Information version : %d.%d\n", descriptor->major_version, descriptor->minor_version);
130 				m_firmwareVersion = *(content + 0x26) << 8 | *(content + 0x27);
131 				fprintf(stdout, "Firmware version : 0x%x\n", m_firmwareVersion);
132 			}
133 			break;
134 		case FIXED_LOCATION_DATA_CONTAINER:
135 			if (sigature_size != 0) {
136 				fprintf(stdout, "FLD signature size : 0x%x\n", sigature_size);
137 				m_signatureInfo[BLv7_FLD].bExisted = true;
138 				m_signatureInfo[BLv7_FLD].size = sigature_size;
139 			}
140 			m_fldData = content;
141 			m_fldSize = length;
142 			break;
143 		case GLOBAL_PARAMETERS_CONTAINER:
144 			m_globalparaData = content;
145 			m_globalparaSize = length;
146 			break;
147 		default:
148 			break;
149 		}
150 	}
151 }
152 
Initialize(const char * filename)153 int FirmwareImage::Initialize(const char * filename)
154 {
155 	if (!filename)
156 		return UPDATE_FAIL_INVALID_PARAMETER;
157 
158 	ifstream ifsFile(filename, ios::in|ios::binary|ios::ate);
159 	if (!ifsFile)
160 		return UPDATE_FAIL_OPEN_FIRMWARE_IMAGE;
161 
162 	ifsFile.seekg(0, ios::end);
163 	m_imageSize = ifsFile.tellg();
164 	if (m_imageSize < 0)
165 		return UPDATE_FAIL_OPEN_FIRMWARE_IMAGE;
166 
167 	m_memBlock = new unsigned char[m_imageSize];
168 	ifsFile.seekg(0, ios::beg);
169 	ifsFile.read((char*)m_memBlock, m_imageSize);
170 
171 	if (m_imageSize < 0x100)
172 		return UPDATE_FAIL_VERIFY_IMAGE;
173 
174 	m_checksum = extract_long(&m_memBlock[RMI_IMG_CHECKSUM_OFFSET]);
175 
176 	unsigned long imageSizeMinusChecksum = m_imageSize - 4;
177 	if ((imageSizeMinusChecksum % 2) != 0)
178 		/*
179 		 * Since the header size is fixed and the firmware is
180 		 * in 16 byte blocks a valid image size should always be
181 		 * divisible by 2.
182 		 */
183 		return UPDATE_FAIL_VERIFY_IMAGE;
184 
185 	unsigned long calculated_checksum = Checksum((uint16_t *)&(m_memBlock[4]),
186 		imageSizeMinusChecksum >> 1);
187 
188 	if (m_checksum != calculated_checksum) {
189 		fprintf(stderr, "Firmware image checksum verification failed, saw 0x%08lX, calculated 0x%08lX\n",
190 			m_checksum, calculated_checksum);
191 		return UPDATE_FAIL_VERIFY_CHECKSUM;
192 	}
193 
194 	m_io = m_memBlock[RMI_IMG_IO_OFFSET];
195 	m_bootloaderVersion = m_memBlock[RMI_IMG_BOOTLOADER_VERSION_OFFSET];
196 	m_firmwareSize = extract_long(&m_memBlock[RMI_IMG_IMAGE_SIZE_OFFSET]);
197 
198 	if ((unsigned long)m_imageSize - RMI_IMG_FW_OFFSET - 1 < m_firmwareSize) {
199 		fprintf(stderr, "Supplied firmware image size too large, goes out of image file size bound\n");
200 		return UPDATE_FAIL_VERIFY_FIRMWARE_SIZE;
201 	}
202 
203 	m_configSize = extract_long(&m_memBlock[RMI_IMG_CONFIG_SIZE_OFFSET]);
204 	if (m_io == 1) {
205 		m_firmwareBuildID = extract_long(&m_memBlock[RMI_IMG_FW_BUILD_ID_OFFSET]);
206 		m_packageID = extract_long(&m_memBlock[RMI_IMG_PACKAGE_ID_OFFSET]);
207 	}
208 	memcpy(m_productID, &m_memBlock[RMI_IMG_PRODUCT_ID_OFFSET], RMI_PRODUCT_ID_LENGTH);
209 	m_productID[RMI_PRODUCT_ID_LENGTH] = 0;
210 	m_productInfo = extract_short(&m_memBlock[RMI_IMG_PRODUCT_INFO_OFFSET]);
211 
212 	m_firmwareData = &m_memBlock[RMI_IMG_FW_OFFSET];
213 	m_configData = &m_memBlock[RMI_IMG_FW_OFFSET + m_firmwareSize];
214 
215 	switch (m_bootloaderVersion) {
216 		case 2:
217 			m_lockdownSize = RMI_IMG_LOCKDOWN_V2_SIZE;
218 			m_lockdownData = &m_memBlock[RMI_IMG_LOCKDOWN_V2_OFFSET];
219 			break;
220 		case 3:
221 		case 4:
222 			m_lockdownSize = RMI_IMG_LOCKDOWN_V3_SIZE;
223 			m_lockdownData = &m_memBlock[RMI_IMG_LOCKDOWN_V3_OFFSET];
224 			break;
225 		case 5:
226 		case 6:
227 			m_lockdownSize = RMI_IMG_LOCKDOWN_V5_SIZE;
228 			m_lockdownData = &m_memBlock[RMI_IMG_LOCKDOWN_V5_OFFSET];
229 			break;
230 		case 16:
231 		case RMI_IMG_V10_SIGNATURE_VERSION_NUMBER:
232 			ParseHierarchicalImg();
233 			break;
234 		default:
235 			return UPDATE_FAIL_UNSUPPORTED_IMAGE_VERSION;
236 	}
237 
238 	fprintf(stdout, "Firmware Header:\n");
239 	PrintHeaderInfo();
240 
241 	return UPDATE_SUCCESS;
242 }
243 
PrintHeaderInfo()244 void FirmwareImage::PrintHeaderInfo()
245 {
246 	fprintf(stdout, "Checksum:\t\t0x%lx\n", m_checksum);
247 	fprintf(stdout, "Firmware Size:\t\t%ld\n", m_firmwareSize);
248 	fprintf(stdout, "Config Size:\t\t%ld\n", m_configSize);
249 	fprintf(stdout, "Lockdown Size:\t\t%ld\n", m_lockdownSize);
250 	fprintf(stdout, "Firmware Build ID:\t%ld\n", m_firmwareBuildID);
251 	fprintf(stdout, "Package ID:\t\t%d\n", m_packageID);
252 	fprintf(stdout, "Bootloader Version:\t%d\n", m_bootloaderVersion);
253 	fprintf(stdout, "Product ID:\t\t%s\n", m_productID);
254 	fprintf(stdout, "Product Info:\t\t%d\n", m_productInfo);
255 	fprintf(stdout, "\n");
256 }
257 
VerifyImageMatchesDevice(unsigned long deviceFirmwareSize,unsigned long deviceConfigSize)258 int FirmwareImage::VerifyImageMatchesDevice(unsigned long deviceFirmwareSize,
259 						unsigned long deviceConfigSize)
260 {
261 	if (m_firmwareSize != deviceFirmwareSize) {
262 		fprintf(stderr, "Firmware image size verfication failed, size in image %ld did "
263 			"not match device size %ld\n", m_firmwareSize, deviceFirmwareSize);
264 		return UPDATE_FAIL_VERIFY_FIRMWARE_SIZE;
265 	}
266 
267 	if (m_configSize != deviceConfigSize) {
268 		fprintf(stderr, "Firmware image size verfication failed, size in image %ld did "
269 			"not match device size %ld\n", m_firmwareSize, deviceConfigSize);
270 		return UPDATE_FAIL_VERIFY_CONFIG_SIZE;
271 	}
272 
273 	return UPDATE_SUCCESS;
274 }
275 
VerifyImageProductID(char * deviceProductID)276 int FirmwareImage::VerifyImageProductID(char* deviceProductID)
277 {
278 	if (strcmp(m_productID, deviceProductID) == 0) {
279 		fprintf(stdout, "image matched\n");
280 		return UPDATE_SUCCESS;
281 	} else {
282 		fprintf (stdout, "image not match, terminated\n");
283 		return UPDATE_FAIL_VERIFY_IMAGE_PRODUCTID_NOT_MATCH;
284 	}
285 }
286 
~FirmwareImage()287 FirmwareImage::~FirmwareImage()
288 {
289 	delete [] m_memBlock;
290 	m_memBlock = NULL;
291 }
292