blob: 010ab1026499d37c2a14b263979cf2ff49834366 [file] [log] [blame]
Andrew Duggan4e811252014-04-03 15:17:57 -07001//===========================================================================
2// Copyright (c) 2012 Synaptics Incorporated. All rights reserved.
3//===========================================================================
4
5#include <iostream>
6#include <fstream>
7#include <string.h>
8#include <stdint.h>
9
10#include "firmware_image.h"
11
12using namespace std;
13
14unsigned long FirmwareImage::Checksum(unsigned short * data, unsigned long len)
15{
16 unsigned long checksum = 0xFFFFFFFF;
17 unsigned long lsw = checksum & 0xFFFF;
18 unsigned long msw = checksum >> 16;
19
20 while (len--) {
21 lsw += *data++;
22 msw += lsw;
23 lsw = (lsw & 0xffff) + (lsw >> 16);
24 msw = (msw & 0xffff) + (msw >> 16);
25 }
26
27 checksum = msw << 16 | lsw;
28
29 return checksum;
30}
31
32int FirmwareImage::Initialize(const char * filename)
33{
34 int rc;
35
36 if (!filename)
37 return UPDATE_FAIL_INVALID_PARAMETER;
38
39 ifstream ifsFile(filename, ios::in|ios::binary|ios::ate);
40 if (!ifsFile)
41 return UPDATE_FAIL_OPEN_FIRMWARE_IMAGE;
42
43 m_imageSize = (unsigned long)ifsFile.tellg();
44 m_memBlock = new unsigned char[m_imageSize];
45 ifsFile.seekg(0, ios::beg);
46 ifsFile.read((char*)m_memBlock, m_imageSize);
47
48 rc = ExtractHeader();
49 if (rc != UPDATE_SUCCESS)
50 return rc;
51
52 fprintf(stdout, "Firmware Header:\n");
53 PrintHeaderInfo();
54
55 return UPDATE_SUCCESS;
56}
57
58int FirmwareImage::ExtractHeader()
59{
60 m_checksum = extract_long(&m_memBlock[RMI_IMG_CHECKSUM_OFFSET]);
61 m_io = m_memBlock[RMI_IMG_IO_OFFSET];
62 m_bootloaderVersion = m_memBlock[RMI_IMG_BOOTLOADER_VERSION_OFFSET];
63 m_firmwareSize = extract_long(&m_memBlock[RMI_IMG_IMAGE_SIZE_OFFSET]);
64 m_configSize = extract_long(&m_memBlock[RMI_IMG_CONFIG_SIZE_OFFSET]);
65 if (m_io == 1) {
66 m_firmwareBuildID = extract_long(&m_memBlock[RMI_IMG_FW_BUILD_ID_OFFSET]);
67 m_packageID = extract_long(&m_memBlock[RMI_IMG_PACKAGE_ID_OFFSET]);
68 }
69 memcpy(m_productID, &m_memBlock[RMI_IMG_PRODUCT_ID_OFFSET], RMI_PRODUCT_ID_LENGTH);
70 m_productID[RMI_PRODUCT_ID_LENGTH] = 0;
71 memcpy(m_productInfo, &m_memBlock[RMI_IMG_PRODUCT_INFO_OFFSET], RMI_IMG_PRODUCT_INFO_LENGTH);
72
73 m_firmwareData = &m_memBlock[RMI_IMG_FW_OFFSET];
74 m_configData = &m_memBlock[RMI_IMG_FW_OFFSET + m_firmwareSize];
75
76 switch (m_bootloaderVersion) {
77 case 2:
78 m_lockdownSize = RMI_IMG_LOCKDOWN_V2_SIZE;
79 m_lockdownData = &m_memBlock[RMI_IMG_LOCKDOWN_V2_OFFSET];
80 break;
81 case 3:
82 case 4:
83 m_lockdownSize = RMI_IMG_LOCKDOWN_V3_SIZE;
84 m_lockdownData = &m_memBlock[RMI_IMG_LOCKDOWN_V3_OFFSET];
85 break;
86 case 5:
87 m_lockdownSize = RMI_IMG_LOCKDOWN_V5_SIZE;
88 m_lockdownData = &m_memBlock[RMI_IMG_LOCKDOWN_V5_OFFSET];
89 break;
90 case 6:
91 // TODO: Add support for V6
92 default:
93 return UPDATE_FAIL_UNSUPPORTED_IMAGE_VERSION;
94 }
95
96 return UPDATE_SUCCESS;
97}
98
99void FirmwareImage::PrintHeaderInfo()
100{
101 fprintf(stdout, "Checksum:\t\t0x%lx\n", m_checksum);
102 fprintf(stdout, "Firmware Size:\t\t%ld\n", m_firmwareSize);
103 fprintf(stdout, "Config Size:\t\t%ld\n", m_configSize);
104 fprintf(stdout, "Lockdown Size:\t\t%ld\n", m_lockdownSize);
105 fprintf(stdout, "Firmware Build ID:\t%ld\n", m_firmwareBuildID);
106 fprintf(stdout, "Package ID:\t\t%d\n", *((unsigned short*)&m_packageID));
107 fprintf(stdout, "Bootloader Version:\t%d\n", m_bootloaderVersion);
108 fprintf(stdout, "Product ID:\t\t%s\n", m_productID);
109 fprintf(stdout, "Product Info:\t\t%d\n", *((unsigned short*)&m_productInfo));
110 fprintf(stdout, "\n");
111}
112
113int FirmwareImage::VerifyImage(unsigned short deviceFirmwareSize, unsigned short deviceConfigSize)
114{
115 if (m_imageSize < 0x100)
116 return UPDATE_FAIL_VERIFY_IMAGE;
117
118 unsigned long calculated_checksum = Checksum((uint16_t *)&(m_memBlock[4]),
119 (unsigned short)(m_imageSize - 4) >> 1);
120
121 if (m_checksum != calculated_checksum) {
122 fprintf(stderr, "Firmware image checksum verification failed, saw 0x%08lX, calculated 0x%08lX\n",
123 m_checksum, calculated_checksum);
124 return UPDATE_FAIL_VERIFY_CHECKSUM;
125 }
126
127 if (m_firmwareSize != deviceFirmwareSize) {
128 fprintf(stderr, "Firmware image size verfication failed, size in image %ld did "
129 "not match device size %d\n", m_firmwareSize, deviceFirmwareSize);
130 return UPDATE_FAIL_VERIFY_FIRMWARE_SIZE;
131 }
132
133 if (m_configSize != deviceConfigSize) {
134 fprintf(stderr, "Firmware image size verfication failed, size in image %ld did "
135 "not match device size %d\n", m_firmwareSize, deviceConfigSize);
136 return UPDATE_FAIL_VERIFY_CONFIG_SIZE;
137 }
138
139 return UPDATE_SUCCESS;
140}
141
142FirmwareImage::~FirmwareImage()
143{
144 delete [] m_memBlock;
145 m_memBlock = NULL;
146}