New tools to help debug vboot failures.
This adds some tools to help us figure out why a particular kernel isn't
booting. Often we suspect it's because it was signed with the wrong keys, or
has flags restricting its use to certain boot modes. This change adds some
tools to extract and display all the keys from the BIOS, and try them on the
various kernels. We also display the sha1sum of all the keys we find, to
make comparing them easier.
Change-Id: I38e447bf95cb6c3a0b87aa949611bb135f2f94b4
BUG=chromeos-partner:888
TEST=manual
To test, obtain a root shell, and run dev_debug_vboot. You should see lots
of useful information go by.
Review URL: http://codereview.chromium.org/3303018
diff --git a/utility/dump_fmap.c b/utility/dump_fmap.c
new file mode 100644
index 0000000..a0d24de
--- /dev/null
+++ b/utility/dump_fmap.c
@@ -0,0 +1,192 @@
+/*
+ * Copyright (c) 2010 The Chromium OS Authors. All rights reserved.
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+#include <errno.h>
+#include <fcntl.h>
+#include <inttypes.h>
+#include <stdint.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sys/mman.h>
+#include <sys/stat.h>
+#include <sys/types.h>
+#include <unistd.h>
+
+/* global variables */
+static int opt_extract = 0;
+static char *progname;
+static void *base_of_rom;
+
+/* FMAP structs. See http://code.google.com/p/flashmap/wiki/FmapSpec */
+#define FMAP_SIGLEN 8
+#define FMAP_NAMELEN 32
+#define FMAP_SEARCH_STRIDE 4
+typedef struct _FmapHeader {
+ char fmap_signature[FMAP_SIGLEN]; /* avoiding endian issues */
+ uint8_t fmap_ver_major;
+ uint8_t fmap_ver_minor;
+ uint64_t fmap_base;
+ uint32_t fmap_size;
+ char fmap_name[FMAP_NAMELEN];
+ uint16_t fmap_nareas;
+} __attribute__((packed)) FmapHeader;
+
+typedef struct _AreaHeader {
+ uint32_t area_offset;
+ uint32_t area_size;
+ char area_name[FMAP_NAMELEN];
+ uint16_t area_flags;
+} __attribute__((packed)) AreaHeader;
+
+
+/* Return 0 if successful */
+static int dump_fmap(void *ptr) {
+ int i,retval = 0;
+ char buf[80]; // DWR: magic number
+ FmapHeader *fmh = (FmapHeader *)ptr;
+ AreaHeader *ah = (AreaHeader *)(ptr + sizeof(FmapHeader));
+
+ snprintf(buf, FMAP_SIGLEN+1, "%s", fmh->fmap_signature);
+ printf("fmap_signature %s\n", buf);
+ printf("fmap_version: %d.%d\n", fmh->fmap_ver_major, fmh->fmap_ver_minor);
+ printf("fmap_base: 0x%" PRIx64 "\n", fmh->fmap_base);
+ printf("fmap_size: 0x%08x (%d)\n", fmh->fmap_size, fmh->fmap_size);
+ snprintf(buf, FMAP_NAMELEN+1, "%s", fmh->fmap_name);
+ printf("fmap_name: %s\n", buf);
+ printf("fmap_nareas: %d\n", fmh->fmap_nareas);
+
+ for (i=0; i<fmh->fmap_nareas; i++) {
+ printf("area: %d\n", i+1);
+ printf("area_offset: 0x%08x\n", ah->area_offset);
+ printf("area_size: 0x%08x (%d)\n", ah->area_size, ah->area_size);
+ snprintf(buf, FMAP_NAMELEN+1, "%s", ah->area_name);
+ printf("area_name: %s\n", buf);
+
+ if (opt_extract) {
+ char *s;
+ for (s=buf; *s; s++)
+ if (*s == ' ')
+ *s = '_';
+ FILE *fp = fopen(buf,"wb");
+ if (!fp) {
+ fprintf(stderr, "%s: can't open %s: %s\n",
+ progname, buf, strerror(errno));
+ retval = 1;
+ } else {
+ if (1 != fwrite(base_of_rom + ah->area_offset, ah->area_size, 1, fp)) {
+ fprintf(stderr, "%s: can't write %s: %s\n",
+ progname, buf, strerror(errno));
+ retval = 1;
+ } else {
+ printf("saved as \"%s\"\n", buf);
+ }
+ fclose(fp);
+ }
+ }
+
+ ah++;
+ }
+
+ return retval;
+}
+
+
+int main(int argc, char *argv[]) {
+ int c;
+ int errorcnt = 0;
+ struct stat sb;
+ int fd;
+ char *s;
+ size_t i;
+ int retval = 1;
+
+ progname = strrchr(argv[0], '/');
+ if (progname)
+ progname++;
+ else
+ progname = argv[0];
+
+ opterr = 0; /* quiet, you */
+ while ((c=getopt(argc, argv, ":x")) != -1) {
+ switch (c)
+ {
+ case 'x':
+ opt_extract = 1;
+ break;
+ case '?':
+ fprintf(stderr, "%s: unrecognized switch: -%c\n",
+ progname, optopt);
+ errorcnt++;
+ break;
+ case ':':
+ fprintf(stderr, "%s: missing argument to -%c\n",
+ progname, optopt);
+ errorcnt++;
+ break;
+ default:
+ errorcnt++;
+ break;
+ }
+ }
+
+ if (errorcnt || optind >= argc) {
+ fprintf(stderr,
+ "\nUsage: %s [-x] FLASHIMAGE\n\n"
+ "Display (and extract with -x) the FMAP components from a BIOS image"
+ "\n\n",
+ progname);
+ return 1;
+ }
+
+ if (0 != stat(argv[optind], &sb)) {
+ fprintf(stderr, "%s: can't stat %s: %s\n",
+ progname,
+ argv[optind],
+ strerror(errno));
+ return 1;
+ }
+
+ fd = open(argv[optind], O_RDONLY);
+ if (fd < 0) {
+ fprintf(stderr, "%s: can't open %s: %s\n",
+ progname,
+ argv[optind],
+ strerror(errno));
+ return 1;
+ }
+ printf("opened %s\n", argv[optind]);
+
+ base_of_rom = mmap(0, sb.st_size, PROT_READ, MAP_PRIVATE, fd, 0);
+ if (base_of_rom == (char *)-1) {
+ fprintf(stderr, "%s: can't mmap %s: %s\n",
+ progname,
+ argv[optind],
+ strerror(errno));
+ close(fd);
+ return 1;
+ }
+ close(fd); /* done with this now */
+
+ s = (char *)base_of_rom;
+ for (i=0; i<sb.st_size; i += FMAP_SEARCH_STRIDE) {
+ if (0 == strncmp(s, "__FMAP__", 8)) {
+ printf("hit at 0x%08x\n", (uint32_t)i);
+ retval = dump_fmap(s);
+ break;
+ }
+ s++;
+ }
+
+ if (0 != munmap(base_of_rom, sb.st_size)) {
+ fprintf(stderr, "%s: can't munmap %s: %s\n",
+ progname,
+ argv[optind],
+ strerror(errno));
+ return 1;
+ }
+
+ return retval;
+}