1 /*
2 * Copyright (C) 2011 Intel Corporation
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17 #include <errno.h>
18 #include <fcntl.h>
19 #include <getopt.h>
20 #include <stdio.h>
21 #include <stdlib.h>
22 #include <string.h>
23 #include <sys/stat.h>
24 #include <sys/wait.h>
25 #include <unistd.h>
26 #include <stdint.h>
27
28 #include "fw_version_check.h"
29
30 #define DEVICE_NAME "/sys/kernel/fw_update/fw_info/fw_version"
31 #define FIP_PATTERN 0x50494624
32 #define SCU_IPC_VERSION_LEN_LONG 32
33 #define READ_SZ 256
34
35 struct fip_version_block {
36 uint16_t minor;
37 uint16_t major;
38 uint8_t checksum;
39 uint8_t reserved8;
40 uint16_t reserved16;
41 };
42
43 struct fip_version_block_chxx {
44 uint16_t minor;
45 uint16_t major;
46 uint8_t checksum;
47 uint8_t reserved8;
48 uint16_t reserved16;
49 uint16_t size;
50 uint16_t dest;
51 };
52
53 struct FIP_header {
54 uint32_t FIP_SIG;
55 struct fip_version_block umip_rev;
56 struct fip_version_block spat_rev;
57 struct fip_version_block spct_rev;
58 struct fip_version_block rpch_rev;
59 struct fip_version_block ch00_rev;
60 struct fip_version_block mipd_rev;
61 struct fip_version_block mipn_rev;
62 struct fip_version_block scuc_rev;
63 struct fip_version_block hvm_rev;
64 struct fip_version_block mia_rev;
65 struct fip_version_block ia32_rev;
66 struct fip_version_block oem_rev;
67 struct fip_version_block ved_rev;
68 struct fip_version_block vec_rev;
69 struct fip_version_block mos_rev;
70 struct fip_version_block pos_rev;
71 struct fip_version_block cos_rev;
72 struct fip_version_block_chxx ch01_rev;
73 struct fip_version_block_chxx ch02_rev;
74 struct fip_version_block_chxx ch03_rev;
75 struct fip_version_block_chxx ch04_rev;
76 struct fip_version_block_chxx ch05_rev;
77 struct fip_version_block_chxx ch06_rev;
78 struct fip_version_block_chxx ch07_rev;
79 struct fip_version_block_chxx ch08_rev;
80 struct fip_version_block_chxx ch09_rev;
81 struct fip_version_block_chxx ch10_rev;
82 struct fip_version_block_chxx ch11_rev;
83 struct fip_version_block_chxx ch12_rev;
84 struct fip_version_block_chxx ch13_rev;
85 struct fip_version_block_chxx ch14_rev;
86 struct fip_version_block_chxx ch15_rev;
87 struct fip_version_block dnx_rev;
88 struct fip_version_block reserved0_rev;
89 struct fip_version_block reserved1_rev;
90 struct fip_version_block ifwi_rev;
91 };
92
read_fw_revision(unsigned int * fw_revision,int len)93 static int read_fw_revision(unsigned int *fw_revision, int len)
94 {
95 int i, fw_info, ret;
96 const char *sep = " ";
97 char *p, *save;
98 char buf[READ_SZ];
99
100 fw_info = open(DEVICE_NAME, O_RDONLY);
101 if (fw_info < 0) {
102 fprintf(stderr, "failed to open %s ", DEVICE_NAME);
103 return fw_info;
104 }
105
106 ret = read(fw_info, buf, READ_SZ - 1);
107 if (ret < 0) {
108 fprintf(stderr, "failed to read fw_revision, ret = %d\n", ret);
109 goto err;
110 }
111
112 buf[ret] = 0;
113 p = strtok_r(buf, sep, &save);
114 for (i = 0; p && i < len; i++) {
115 ret = sscanf(p, "%x", &fw_revision[i]);
116 if (ret != 1) {
117 fprintf(stderr, "failed to parse fw_revision, ret = %d\n", ret);
118 goto err;
119 }
120 p = strtok_r(NULL, sep, &save);
121 }
122 ret = 0;
123
124 err:
125 close(fw_info);
126 return ret;
127 }
128
129 /* Bytes in scu_ipc_version after the ioctl():
130
131 * 00 SCU Boot Strap Firmware Minor Revision Low
132 * 01 SCU Boot Strap Firmware Minor Revision High
133 * 02 SCU Boot Strap Firmware Major Revision Low
134 * 03 SCU Boot Strap Firmware Major Revision High
135
136 * 04 SCU Firmware Minor Revision Low
137 * 05 SCU Firmware Minor Revision High
138 * 06 SCU Firmware Major Revision Low
139 * 07 SCU Firmware Major Revision High
140
141 * 08 IA Firmware Minor Revision Low
142 * 09 IA Firmware Minor Revision High
143 * 10 IA Firmware Major Revision Low
144 * 11 IA Firmware Major Revision High
145
146 * 12 Validation Hooks Firmware Minor Revision Low
147 * 13 Validation Hooks Firmware Minor Revision High
148 * 14 Validation Hooks Firmware Major Revision Low
149 * 15 Validation Hooks Firmware Major Revision High
150
151 * 16 IFWI Firmware Minor Revision Low
152 * 17 IFWI Firmware Minor Revision High
153 * 18 IFWI Firmware Major Revision Low
154 * 19 IFWI Firmware Major Revision High
155
156 * 20 Chaabi Firmware Minor Revision Low
157 * 21 Chaabi Firmware Minor Revision High
158 * 22 Chaabi Firmware Major Revision Low
159 * 23 Chaabi Firmware Major Revision High
160
161 * 24 mIA Firmware Minor Revision Low
162 * 25 mIA Firmware Minor Revision High
163 * 26 mIA Firmware Major Revision Low
164 * 27 mIA Firmware Major Revision High
165
166 */
get_current_fw_rev(struct firmware_versions * v)167 int get_current_fw_rev(struct firmware_versions *v)
168 {
169 int ret;
170 unsigned int fw_revision[SCU_IPC_VERSION_LEN_LONG] = { 0 };
171
172 ret = read_fw_revision(fw_revision, SCU_IPC_VERSION_LEN_LONG);
173 if (ret)
174 return ret;
175
176 v->scubootstrap.minor = fw_revision[1] << 8 | fw_revision[0];
177 v->scubootstrap.major = fw_revision[3] << 8 | fw_revision[2];
178 v->scu.minor = fw_revision[5] << 8 | fw_revision[4];
179 v->scu.major = fw_revision[7] << 8 | fw_revision[6];
180 v->ia32.minor = fw_revision[9] << 8 | fw_revision[8];
181 v->ia32.major = fw_revision[11] << 8 | fw_revision[10];
182 v->valhooks.minor = fw_revision[13] << 8 | fw_revision[12];
183 v->valhooks.major = fw_revision[15] << 8 | fw_revision[14];
184 v->ifwi.minor = fw_revision[17] << 8 | fw_revision[16];
185 v->ifwi.major = fw_revision[19] << 8 | fw_revision[18];
186 v->chaabi.minor = fw_revision[21] << 8 | fw_revision[20];
187 v->chaabi.major = fw_revision[23] << 8 | fw_revision[22];
188 v->mia.minor = fw_revision[25] << 8 | fw_revision[24];
189 v->mia.major = fw_revision[27] << 8 | fw_revision[26];
190
191 return ret;
192 }
193
get_image_fw_rev(void * data,unsigned sz,struct firmware_versions * v)194 int get_image_fw_rev(void *data, unsigned sz, struct firmware_versions *v)
195 {
196 struct FIP_header fip;
197 unsigned char *databytes = (unsigned char *)data;
198 int magic;
199 int magic_found = 0;
200
201 if (v == NULL) {
202 fprintf(stderr, "Null pointer !\n");
203 return -1;
204 } else
205 memset((void *)v, 0, sizeof(struct firmware_versions));
206
207 while (sz >= sizeof(fip)) {
208
209 /* Scan for the FIP magic */
210 while (sz >= sizeof(fip)) {
211 memcpy(&magic, databytes, sizeof(magic));
212 if (magic == FIP_PATTERN) {
213 magic_found = 1;
214 break;
215 }
216 databytes += sizeof(magic);
217 sz -= sizeof(magic);
218 }
219
220 if (!magic_found) {
221 fprintf(stderr, "Couldn't find FIP magic in image!\n");
222 return -1;
223 }
224 if (sz < sizeof(fip)) {
225 break;
226 }
227
228 memcpy(&fip, databytes, sizeof(fip));
229
230 /* not available in ifwi file */
231 v->scubootstrap.minor = 0;
232 v->scubootstrap.major = 0;
233
234 /* don't update if null */
235 if (fip.scuc_rev.minor != 0)
236 v->scu.minor = fip.scuc_rev.minor;
237 if (fip.scuc_rev.major != 0)
238 v->scu.major = fip.scuc_rev.major;
239 if (fip.ia32_rev.minor != 0)
240 v->ia32.minor = fip.ia32_rev.minor;
241 if (fip.ia32_rev.major != 0)
242 v->ia32.major = fip.ia32_rev.major;
243 if (fip.oem_rev.minor != 0)
244 v->valhooks.minor = fip.oem_rev.minor;
245 if (fip.oem_rev.major != 0)
246 v->valhooks.major = fip.oem_rev.major;
247 if (fip.ifwi_rev.minor != 0)
248 v->ifwi.minor = fip.ifwi_rev.minor;
249 if (fip.ifwi_rev.major != 0)
250 v->ifwi.major = fip.ifwi_rev.major;
251 if (fip.ch00_rev.minor != 0)
252 v->chaabi.minor = fip.ch00_rev.minor;
253 if (fip.ch00_rev.major != 0)
254 v->chaabi.major = fip.ch00_rev.major;
255 if (fip.mia_rev.minor != 0)
256 v->mia.minor = fip.mia_rev.minor;
257 if (fip.mia_rev.major != 0)
258 v->mia.major = fip.mia_rev.major;
259
260 databytes += sizeof(magic);
261 sz -= sizeof(magic);
262 }
263
264 return 0;
265 }
266