1 /*
2 * Copyright (C) 2015 The Android Open Source Project
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 /* Vboot/crossystem interface */
17
18 #define LOG_TAG "fwtool"
19
20 #include <endian.h>
21 #include <errno.h>
22 #include <stdint.h>
23 #include <stdlib.h>
24 #include <string.h>
25 #include <unistd.h>
26
27 #include "ec_commands.h"
28 #include "flash_device.h"
29 #include "fmap.h"
30 #include "update_log.h"
31 #include "vboot_struct.h"
32 #include "gbb_header.h"
33
34 /* ---- VBoot information passed by the firmware through the device-tree ---- */
35
36 /* Base name for firmware FDT files */
37 #define FDT_BASE_PATH "/proc/device-tree/firmware/chromeos"
38
fdt_read_string(const char * prop)39 char *fdt_read_string(const char *prop)
40 {
41 char filename[PATH_MAX];
42 FILE *file;
43 size_t size;
44 char *data;
45
46 snprintf(filename, sizeof(filename), FDT_BASE_PATH "/%s", prop);
47 file = fopen(filename, "r");
48 if (!file) {
49 ALOGD("Unable to open FDT property %s\n", prop);
50 return NULL;
51 }
52 fseek(file, 0, SEEK_END);
53 size = ftell(file);
54 data = malloc(size + 1);
55 if (!data) {
56 goto out_close;
57 }
58 data[size] = '\0';
59
60 rewind(file);
61 if (fread(data, 1, size, file) != size) {
62 ALOGD("Unable to read FDT property %s\n", prop);
63 goto out_free;
64 }
65 fclose(file);
66
67 return data;
68
69 out_free:
70 free(data);
71
72 out_close:
73 fclose(file);
74 return NULL;
75 }
76
fdt_read_u32(const char * prop)77 uint32_t fdt_read_u32(const char *prop)
78 {
79 char filename[PATH_MAX];
80 FILE *file;
81 int data = 0;
82
83 snprintf(filename, sizeof(filename), FDT_BASE_PATH "/%s", prop);
84 file = fopen(filename, "r");
85 if (!file) {
86 ALOGD("Unable to open FDT property %s\n", prop);
87 return -1U;
88 }
89 if (fread(&data, 1, sizeof(data), file) != sizeof(data)) {
90 ALOGD("Unable to read FDT property %s\n", prop);
91 fclose(file);
92 return -1U;
93 }
94 fclose(file);
95
96 return ntohl(data); /* FDT is network byte order */
97 }
98
vboot_get_mainfw_act(void)99 char vboot_get_mainfw_act(void)
100 {
101 VbSharedDataHeader *shd = (void *)fdt_read_string("vboot-shared-data");
102 char v;
103
104 if (!shd || shd->magic != VB_SHARED_DATA_MAGIC) {
105 ALOGD("Cannot retrieve VBoot shared data\n");
106 if (shd)
107 free(shd);
108 return 'E'; /* Error */
109 }
110
111 switch(shd->firmware_index) {
112 case 0:
113 v = 'A'; /* RW_A in use */
114 break;
115 case 1:
116 v = 'B'; /* RW_B in use */
117 break;
118 case 0xFF:
119 v = 'R'; /* Recovery/RO in use */
120 break;
121 default:
122 ALOGD("Invalid firmware index : %02x\n", shd->firmware_index);
123 v = 'E'; /* Error */
124 }
125
126 free(shd);
127 return v;
128 }
129
130 /* ---- Flash Maps handling ---- */
131
fmap_scan_offset(struct flash_device * dev,off_t end)132 off_t fmap_scan_offset(struct flash_device *dev, off_t end)
133 {
134 struct fmap h;
135 uint32_t off = end - (end % 64); /* start on a 64-byte boundary */
136 int res;
137
138 /*
139 * Try to find the FMAP signature at 64-byte boundaries
140 * starting from the end.
141 */
142 do {
143 off -= 64;
144 res = flash_read(dev, off, &h, sizeof(h.signature));
145 if (res)
146 break;
147 if (!memcmp(&h.signature, FMAP_SIGNATURE, sizeof(h.signature)))
148 break;
149 } while (off);
150
151 return off;
152 }
153
fmap_load(struct flash_device * dev,off_t offset)154 struct fmap *fmap_load(struct flash_device *dev, off_t offset)
155 {
156 struct fmap hdr;
157 struct fmap *fmap;
158 size_t size;
159 int res;
160
161 ALOGD("Searching FMAP @0x%08lx\n", offset);
162 res = flash_read(dev, offset, &hdr, sizeof(hdr));
163 if (res) {
164 ALOGD("Cannot read FMAP header\n");
165 return NULL;
166 }
167
168 if (memcmp(&hdr.signature, FMAP_SIGNATURE, sizeof(hdr.signature))) {
169 ALOGD("Cannot find FMAP\n");
170 return NULL;
171 }
172
173 size = sizeof(struct fmap) + hdr.nareas * sizeof(struct fmap_area);
174 fmap = malloc(size);
175
176 res = flash_read(dev, offset, fmap, size);
177 if (res) {
178 ALOGD("Cannot read FMAP\n");
179 free(fmap);
180 return NULL;
181 }
182
183 return fmap;
184 }
185
fmap_get_section_offset(struct flash_device * dev,const char * name,off_t * offset)186 int fmap_get_section_offset(struct flash_device *dev, const char *name,
187 off_t *offset)
188 {
189 int i;
190 struct fmap *fmap = flash_get_fmap(dev);
191 if (!fmap)
192 return -1;
193
194 if (name) {
195 for (i = 0; i < fmap->nareas; i++)
196 if (!strcmp(name, (const char*)fmap->areas[i].name))
197 break;
198
199 if (i == fmap->nareas) {
200 ALOGD("Cannot find section '%s'\n", name);
201 return -1;
202 }
203
204 *offset = fmap->areas[i].offset;
205 } else {
206 *offset = 0;
207 }
208
209 return 0;
210 }
211
fmap_read_section(struct flash_device * dev,const char * name,size_t * size,off_t * offset)212 void *fmap_read_section(struct flash_device *dev,
213 const char *name, size_t *size, off_t *offset)
214 {
215 int i, r;
216 struct fmap *fmap = flash_get_fmap(dev);
217 void *data;
218 off_t start_offset;
219
220 if (!fmap)
221 return NULL;
222
223 if (name) {
224 for (i = 0; i < fmap->nareas; i++)
225 if (!strcmp(name, (const char*)fmap->areas[i].name))
226 break;
227 if (i == fmap->nareas) {
228 ALOGD("Cannot find section '%s'\n", name);
229 return NULL;
230 }
231 *size = fmap->areas[i].size;
232 start_offset = fmap->areas[i].offset;
233 } else {
234 *size = flash_get_size(dev);
235 start_offset = 0;
236 }
237
238 data = malloc(*size);
239 if (!data)
240 return NULL;
241
242 r = flash_read(dev, start_offset, data, *size);
243 if (r) {
244 ALOGD("Cannot read section '%s'\n", name);
245 free(data);
246 return NULL;
247 }
248 if (offset)
249 *offset = start_offset;
250
251 return data;
252 }
253
254 /* ---- Google Binary Block (GBB) ---- */
255
gbb_get_rootkey(struct flash_device * dev,size_t * size)256 uint8_t *gbb_get_rootkey(struct flash_device *dev, size_t *size)
257 {
258 size_t gbb_size;
259 uint8_t *gbb = flash_get_gbb(dev, &gbb_size);
260 GoogleBinaryBlockHeader *hdr = (void *)gbb;
261
262 if (!gbb || memcmp(hdr->signature, GBB_SIGNATURE, GBB_SIGNATURE_SIZE) ||
263 gbb_size < sizeof(*hdr))
264 return NULL;
265
266 if (hdr->rootkey_offset + hdr->rootkey_size > gbb_size)
267 return NULL;
268
269 if (size)
270 *size = hdr->rootkey_size;
271
272 return gbb + hdr->rootkey_offset;
273 }
274
275 /* ---- VBoot NVRAM (stored in SPI flash) ---- */
276
277 /* bits definition in NVRAM */
278
279 enum {
280 VB_HEADER_OFFSET = 0,
281 VB_BOOT_OFFSET = 1,
282 VB_RECOVERY_OFFSET = 2,
283 VB_LOCALIZATION_OFFSET = 3,
284 VB_DEV_OFFSET = 4,
285 VB_TPM_OFFSET = 5,
286 VB_RECVOERY_SUBCODE_OFFSET = 6,
287 VB_BOOT2_OFFSET = 7,
288 VB_MISC_OFFSET = 8,
289 VB_KERNEL_OFFSET = 11,
290 VB_CRC_OFFSET = 15,
291 VB_NVDATA_SIZE = 16
292 };
293
294 #define VB_DEFAULT_MASK 0x01
295
296 /* HEADER_OFFSET */
297 #define VB_HEADER_WIPEOUT_SHIFT 3
298 #define VB_HEADER_KERNEL_SETTINGS_RESET_SHIFT 4
299 #define VB_HEADER_FW_SETTINGS_RESET_SHIFT 5
300 #define VB_HEADER_SIGNATURE_SHIFT 6
301
302 /* BOOT_OFFSET */
303 #define VB_BOOT_TRY_COUNT_MASK 0xf
304 #define VB_BOOT_TRY_COUNT_SHIFT 0
305 #define VB_BOOT_BACKUP_NVRAM_SHIFT 4
306 #define VB_BOOT_OPROM_NEEDED_SHIFT 5
307 #define VB_BOOT_DISABLE_DEV_SHIFT 6
308 #define VB_BOOT_DEBUG_RESET_SHIFT 7
309
310 /* RECOVERY_OFFSET */
311 #define VB_RECOVERY_REASON_SHIFT 0
312 #define VB_RECOVERY_REASON_MASK 0xff
313
314 /* BOOT2_OFFSET */
315 #define VB_BOOT2_RESULT_MASK 0x3
316 #define VB_BOOT2_RESULT_SHIFT 0
317 #define VB_BOOT2_TRIED_SHIFT 2
318 #define VB_BOOT2_TRY_NEXT_SHIFT 3
319 #define VB_BOOT2_PREV_RESULT_MASK 0x3
320 #define VB_BOOT2_PREV_RESULT_SHIFT 4
321 #define VB_BOOT2_PREV_TRIED_SHIFT 6
322
323 /* DEV_OFFSET */
324 #define VB_DEV_FLAG_USB_SHIFT 0
325 #define VB_DEV_FLAG_SIGNED_ONLY_SHIFT 1
326 #define VB_DEV_FLAG_LEGACY_SHIFT 2
327 #define VB_DEV_FLAG_FASTBOOT_FULL_CAP_SHIFT 3
328
329 /* TPM_OFFSET */
330 #define VB_TPM_CLEAR_OWNER_REQUEST_SHIFT 0
331 #define VB_TPM_CLEAR_OWNER_DONE_SHIFT 1
332
333 /* MISC_OFFSET */
334 #define VB_MISC_UNLOCK_FASTBOOT_SHIFT 0
335 #define VB_MISC_BOOT_ON_AC_DETECT_SHIFT 1
336
337 typedef enum {
338 VBNV_DEFAULT_FLAG = 0x00,
339 VBNV_WRITABLE = 0x01,
340 } vbnv_param_flags_t;
341
342 typedef struct vbnv_param {
343 char *name;
344 vbnv_param_flags_t flags;
345 int offset;
346 int shift;
347 int mask;
348 } vbnv_param_t;
349
350 static const vbnv_param_t param_table[] = {
351 {"try_count", VBNV_WRITABLE, VB_BOOT_OFFSET, VB_BOOT_TRY_COUNT_SHIFT,
352 VB_BOOT_TRY_COUNT_MASK},
353 {"backup_nvram", VBNV_WRITABLE, VB_BOOT_OFFSET,
354 VB_BOOT_BACKUP_NVRAM_SHIFT, VB_DEFAULT_MASK},
355 {"oprom_needed", VBNV_WRITABLE, VB_BOOT_OFFSET,
356 VB_BOOT_OPROM_NEEDED_SHIFT, VB_DEFAULT_MASK},
357 {"disable_dev", VBNV_WRITABLE, VB_BOOT_OFFSET,
358 VB_BOOT_DISABLE_DEV_SHIFT, VB_DEFAULT_MASK},
359 {"debug_reset", VBNV_WRITABLE, VB_BOOT_OFFSET,
360 VB_BOOT_DEBUG_RESET_SHIFT, VB_DEFAULT_MASK},
361 {"boot_result", VBNV_WRITABLE, VB_BOOT2_OFFSET, VB_BOOT2_RESULT_SHIFT,
362 VB_BOOT2_RESULT_MASK},
363 {"fw_tried", VBNV_DEFAULT_FLAG, VB_BOOT2_OFFSET, VB_BOOT2_TRIED_SHIFT,
364 VB_DEFAULT_MASK},
365 {"fw_try_next", VBNV_WRITABLE, VB_BOOT2_OFFSET, VB_BOOT2_TRY_NEXT_SHIFT,
366 VB_DEFAULT_MASK},
367 {"fw_prev_result", VBNV_DEFAULT_FLAG, VB_BOOT2_OFFSET,
368 VB_BOOT2_PREV_RESULT_SHIFT, VB_BOOT2_PREV_RESULT_MASK},
369 {"prev_tried", VBNV_DEFAULT_FLAG, VB_BOOT2_OFFSET,
370 VB_BOOT2_PREV_TRIED_SHIFT, VB_DEFAULT_MASK},
371 {"dev_boot_usb", VBNV_WRITABLE, VB_DEV_OFFSET, VB_DEV_FLAG_USB_SHIFT,
372 VB_DEFAULT_MASK},
373 {"dev_boot_signed_only", VBNV_WRITABLE, VB_DEV_OFFSET,
374 VB_DEV_FLAG_SIGNED_ONLY_SHIFT, VB_DEFAULT_MASK},
375 {"dev_boot_legacy", VBNV_WRITABLE, VB_DEV_OFFSET,
376 VB_DEV_FLAG_LEGACY_SHIFT, VB_DEFAULT_MASK},
377 {"dev_boot_fastboot_full_cap", VBNV_WRITABLE, VB_DEV_OFFSET,
378 VB_DEV_FLAG_FASTBOOT_FULL_CAP_SHIFT, VB_DEFAULT_MASK},
379 {"tpm_clear_owner_request", VBNV_WRITABLE, VB_TPM_OFFSET,
380 VB_TPM_CLEAR_OWNER_REQUEST_SHIFT, VB_DEFAULT_MASK},
381 {"tpm_clear_owner_done", VBNV_WRITABLE, VB_TPM_OFFSET,
382 VB_TPM_CLEAR_OWNER_DONE_SHIFT, VB_DEFAULT_MASK},
383 {"unlock_fastboot", VBNV_WRITABLE, VB_MISC_OFFSET,
384 VB_MISC_UNLOCK_FASTBOOT_SHIFT, VB_DEFAULT_MASK},
385 {"boot_on_ac_detect", VBNV_WRITABLE, VB_MISC_OFFSET,
386 VB_MISC_BOOT_ON_AC_DETECT_SHIFT, VB_DEFAULT_MASK},
387 {"recovery_reason", VBNV_WRITABLE, VB_RECOVERY_OFFSET,
388 VB_RECOVERY_REASON_SHIFT, VB_RECOVERY_REASON_MASK},
389 };
390
crc8(const uint8_t * data,int len)391 static uint8_t crc8(const uint8_t *data, int len)
392 {
393 uint32_t crc = 0;
394 int i, j;
395
396 for (j = len; j; j--, data++) {
397 crc ^= (*data << 8);
398 for(i = 8; i; i--) {
399 if (crc & 0x8000)
400 crc ^= (0x1070 << 3);
401 crc <<= 1;
402 }
403 }
404
405 return (uint8_t)(crc >> 8);
406 }
407
can_overwrite(uint8_t current,uint8_t new)408 static inline int can_overwrite(uint8_t current, uint8_t new)
409 {
410 return (current & new) == new;
411 }
412
vbnv_readwrite(struct flash_device * spi,const vbnv_param_t * param,uint8_t * value,int write)413 int vbnv_readwrite(struct flash_device *spi, const vbnv_param_t *param,
414 uint8_t *value, int write)
415 {
416 int i;
417 int res;
418 size_t size;
419 off_t offset;
420 uint8_t *block, *nvram, *end, *curr;
421 uint8_t dummy[VB_NVDATA_SIZE];
422
423 int off = param->offset;
424 uint8_t mask = param->mask << param->shift;
425
426 if (off >= VB_NVDATA_SIZE) {
427 ALOGW("ERROR: Incorrect offset %d for NvStorage\n", off);
428 return -EIO;
429 }
430
431 /* Read NVRAM. */
432 nvram = fmap_read_section(spi, "RW_NVRAM", &size, &offset);
433 /*
434 * Ensure NVRAM is found, size is at least 1 block and total size is
435 * multiple of VB_NVDATA_SIZE.
436 */
437 if ((nvram == NULL) || (size < VB_NVDATA_SIZE) ||
438 (size % VB_NVDATA_SIZE)) {
439 ALOGW("ERROR: NVRAM not found\n");
440 return -EIO;
441 }
442
443 /* Create an empty dummy block to compare. */
444 memset(dummy, 0xFF, sizeof(dummy));
445
446 /*
447 * Loop until the last used block in NVRAM.
448 * 1. All blocks will not be empty since we just booted up fine.
449 * 2. If all blocks are used, select the last block.
450 */
451 block = nvram;
452 end = block + size;
453 for (curr = block; curr < end; curr += VB_NVDATA_SIZE) {
454 if (memcmp(curr, dummy, VB_NVDATA_SIZE) == 0)
455 break;
456 block = curr;
457 }
458
459 if (write) {
460 uint8_t flag_value = (*value & param->mask) << param->shift;
461
462 /* Copy last used block to make modifications. */
463 memcpy(dummy, block, VB_NVDATA_SIZE);
464
465 dummy[off] = (dummy[off] & ~mask) | (flag_value & mask);
466 dummy[VB_CRC_OFFSET] = crc8(dummy, VB_CRC_OFFSET);
467
468 /* Check if new block can be overwritten */
469 for (i = 0; i < VB_NVDATA_SIZE; i++) {
470 if (!can_overwrite(block[i], dummy[i])) {
471 if (curr != end)
472 offset += (curr - nvram);
473 else if (flash_erase(spi, offset, size)) {
474 ALOGW("ERROR: Cannot erase flash\n");
475 return -EIO;
476 }
477 break;
478 }
479 }
480
481 /* Block can be overwritten. */
482 if (i == VB_NVDATA_SIZE)
483 offset += (block - nvram);
484
485 ALOGI("Writing new entry into NVRAM @ 0x%lx\n", offset);
486
487 /* Write new entry into NVRAM. */
488 if (flash_write(spi, offset, dummy, VB_NVDATA_SIZE)) {
489 ALOGW("ERROR: Cannot update NVRAM\n");
490 return -EIO;
491 }
492
493 ALOGD("NVRAM updated.\n");
494 } else {
495 *value = (block[off] & mask) >> param->shift;
496 }
497
498 return 0;
499 }
500
501 #define ARRAY_SIZE(arr) (sizeof(arr)/sizeof(arr[0]))
vbnv_set_flag(struct flash_device * spi,const char * param,uint8_t value)502 int vbnv_set_flag(struct flash_device *spi, const char *param, uint8_t value)
503 {
504 size_t i;
505 for (i = 0; i < ARRAY_SIZE(param_table); i++) {
506 if (!strcmp(param, param_table[i].name)) {
507 if (param_table[i].flags & VBNV_WRITABLE)
508 return vbnv_readwrite(spi, ¶m_table[i],
509 &value, 1);
510
511 fprintf(stderr, "ERROR: Cannot write this flag.\n");
512 return -EIO;
513 }
514 }
515 fprintf(stderr, "Error: Unknown param\n");
516 return -EIO;
517 }
518
vbnv_get_flag(struct flash_device * spi,const char * param,uint8_t * value)519 int vbnv_get_flag(struct flash_device *spi, const char *param, uint8_t *value)
520 {
521 size_t i;
522 for (i = 0; i < ARRAY_SIZE(param_table); i++) {
523 if (!strcmp(param, param_table[i].name))
524 return vbnv_readwrite(spi, ¶m_table[i], value, 0);
525 }
526 fprintf(stderr, "Error: Unknown param\n");
527 return -EIO;
528 }
529
vbnv_usage(int write)530 void vbnv_usage(int write)
531 {
532 size_t i;
533 for (i = 0; i < ARRAY_SIZE(param_table); i++)
534 if ((write == 0) || (write &&
535 (param_table[i].flags & VBNV_WRITABLE)))
536 printf(" %s\n", param_table[i].name);
537 }
538
539 /* ---- Vital Product Data handling ---- */
540