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