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