summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBill Richardson <wfrichar@chromium.org>2015-01-30 12:22:28 -0800
committerChromeOS Commit Bot <chromeos-commit-bot@chromium.org>2015-01-31 05:42:48 +0000
commit2559338dbdacbcbd3ae426337403196135bbc7e8 (patch)
treefb87c9b5b7058e14349f16cac2dc81966942ea87
parent65ce99b3e2c75bbb416b6edf78b5ea0d7f8c3a94 (diff)
downloadvboot-2559338dbdacbcbd3ae426337403196135bbc7e8.tar.gz
futility: refactor file type detection into new files
This moves the what-kind-of-file-is-this logic into a separate file, and makes it work by calling distinct recognizers until one hits. A new "-t" option to the show command prints what it's doing. BUG=chromium:228932 BRANCH=ToT TEST=make runtests Change-Id: Id8f60bdf3fe6a9adf41b4555b3448a261fa52fea Signed-off-by: Bill Richardson <wfrichar@chromium.org> Reviewed-on: https://chromium-review.googlesource.com/245122 Reviewed-by: Randall Spangler <rspangler@chromium.org>
-rw-r--r--Makefile1
-rw-r--r--futility/cmd_show.c44
-rw-r--r--futility/cmd_sign.c13
-rw-r--r--futility/cmd_vbutil_kernel.c3
-rw-r--r--futility/file_type.c123
-rw-r--r--futility/file_type.h50
-rw-r--r--futility/futility.h24
-rw-r--r--futility/misc.c65
-rw-r--r--futility/traversal.c148
-rw-r--r--futility/traversal.h33
-rw-r--r--futility/vb1_helper.c36
11 files changed, 356 insertions, 184 deletions
diff --git a/Makefile b/Makefile
index 3a2f8369..ed4ccf43 100644
--- a/Makefile
+++ b/Makefile
@@ -594,6 +594,7 @@ FUTIL_SRCS = \
futility/cmd_vbutil_kernel.c \
futility/cmd_vbutil_key.c \
futility/cmd_vbutil_keyblock.c \
+ futility/file_type.c \
futility/traversal.c \
futility/vb1_helper.c
diff --git a/futility/cmd_show.c b/futility/cmd_show.c
index 7f0e488f..c6584259 100644
--- a/futility/cmd_show.c
+++ b/futility/cmd_show.c
@@ -17,6 +17,7 @@
#include <unistd.h>
#include "bmpblk_header.h"
+#include "file_type.h"
#include "fmap.h"
#include "futility.h"
#include "gbb_header.h"
@@ -38,6 +39,7 @@ static struct local_data_s {
uint64_t fv_size;
uint32_t padding;
int strict;
+ int t_flag;
} option = {
.padding = 65536,
};
@@ -505,7 +507,7 @@ enum no_short_opts {
};
static const char usage[] = "\n"
- "Usage: " MYNAME " %s [OPTIONS] FILE\n"
+ "Usage: " MYNAME " %s [OPTIONS] FILE [...]\n"
"\n"
"Where FILE could be a\n"
"\n"
@@ -516,6 +518,7 @@ static const char usage[] = "\n"
" kernel partition (/dev/sda2, /dev/mmcblk0p2)\n"
"\n"
"Options:\n"
+ " -t Just show the type of each file\n"
" -k|--publickey FILE"
" Use this public key for validation\n"
" -f|--fv FILE Verify this payload (FW_MAIN_A/B)\n"
@@ -544,7 +547,34 @@ static const struct option long_opts[] = {
{"debug", 0, &debugging_enabled, 1},
{NULL, 0, NULL, 0},
};
-static char *short_opts = ":f:k:";
+static char *short_opts = ":f:k:t";
+
+
+static void show_type(char *filename)
+{
+ enum futil_file_err err;
+ enum futil_file_type type;
+ err = futil_file_type(filename, &type);
+ switch (err) {
+ case FILE_ERR_NONE:
+ printf("%s:\t%s\n", filename, futil_file_type_str(type));
+ break;
+ case FILE_ERR_DIR:
+ printf("%s:\t%s\n", filename, "directory");
+ break;
+ case FILE_ERR_CHR:
+ printf("%s:\t%s\n", filename, "character special");
+ break;
+ case FILE_ERR_FIFO:
+ printf("%s:\t%s\n", filename, "FIFO");
+ break;
+ case FILE_ERR_SOCK:
+ printf("%s:\t%s\n", filename, "socket");
+ break;
+ default:
+ break;
+ }
+}
static int do_show(int argc, char *argv[])
{
@@ -574,6 +604,9 @@ static int do_show(int argc, char *argv[])
errorcnt++;
}
break;
+ case 't':
+ option.t_flag = 1;
+ break;
case OPT_PADDING:
option.padding = strtoul(optarg, &e, 0);
if (!*optarg || (e && *e)) {
@@ -613,6 +646,12 @@ static int do_show(int argc, char *argv[])
return 1;
}
+ if (option.t_flag) {
+ for (i = optind; i < argc; i++)
+ show_type(argv[i]);
+ goto done;
+ }
+
for (i = optind; i < argc; i++) {
infile = argv[i];
ifd = open(infile, O_RDONLY);
@@ -646,6 +685,7 @@ boo:
}
}
+done:
if (option.k)
free(option.k);
if (option.fv)
diff --git a/futility/cmd_sign.c b/futility/cmd_sign.c
index f256b00e..a960abd6 100644
--- a/futility/cmd_sign.c
+++ b/futility/cmd_sign.c
@@ -18,6 +18,7 @@
#include <unistd.h>
#include "bmpblk_header.h"
+#include "file_type.h"
#include "fmap.h"
#include "futility.h"
#include "gbb_header.h"
@@ -889,7 +890,10 @@ static int do_sign(int argc, char *argv[])
}
/* What are we looking at? */
- type = futil_what_file_type(infile);
+ if (futil_file_type(infile, &type)) {
+ errorcnt++;
+ goto done;
+ }
/* We may be able to infer the type based on the other args */
if (type == FILE_TYPE_UNKNOWN) {
@@ -900,7 +904,7 @@ static int do_sign(int argc, char *argv[])
type = FILE_TYPE_RAW_FIRMWARE;
}
- Debug("type=%s\n", futil_file_type_str[type]);
+ Debug("type=%s\n", futil_file_type_str(type));
/* Check the arguments for the type of thing we want to sign */
switch (type) {
@@ -972,6 +976,11 @@ static int do_sign(int argc, char *argv[])
errorcnt += no_opt_if(!option.config_data, "config");
errorcnt += no_opt_if(option.arch == ARCH_UNSPECIFIED, "arch");
break;
+ case FILE_TYPE_CHROMIUMOS_DISK:
+ fprintf(stderr, "Signing a %s is not yet supported\n",
+ futil_file_type_str(type));
+ errorcnt++;
+ break;
default:
DIE;
}
diff --git a/futility/cmd_vbutil_kernel.c b/futility/cmd_vbutil_kernel.c
index 40deba9e..65a9af39 100644
--- a/futility/cmd_vbutil_kernel.c
+++ b/futility/cmd_vbutil_kernel.c
@@ -18,6 +18,7 @@
#include <sys/stat.h>
#include <unistd.h>
+#include "file_type.h"
#include "futility.h"
#include "host_common.h"
#include "kernel_blob.h"
@@ -464,7 +465,7 @@ static int do_vbutil_kernel(int argc, char *argv[])
/* Make sure we have a kernel partition */
if (FILE_TYPE_KERN_PREAMBLE !=
- futil_what_file_type_buf(kpart_data, kpart_size))
+ futil_file_type_buf(kpart_data, kpart_size))
Fatal("%s is not a kernel blob\n", oldfile);
kblob_data = UnpackKPart(kpart_data, kpart_size, opt_pad,
diff --git a/futility/file_type.c b/futility/file_type.c
new file mode 100644
index 00000000..0c915865
--- /dev/null
+++ b/futility/file_type.c
@@ -0,0 +1,123 @@
+/*
+ * Copyright 2015 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 <stdint.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sys/stat.h>
+#include <sys/types.h>
+#include <unistd.h>
+
+#include "file_type.h"
+#include "futility.h"
+#include "gbb_header.h"
+
+/* Human-readable strings */
+static const char * const type_strings[] = {
+ "unknown",
+ "VbPublicKey",
+ "VbKeyBlock",
+ "VbFirmwarePreamble",
+ "GBB",
+ "Chrome OS BIOS image",
+ "Cr-48 Chrome OS BIOS image",
+ "VbKernelPreamble",
+ "raw firmware",
+ "raw kernel",
+ "chromiumos disk image",
+};
+BUILD_ASSERT(ARRAY_SIZE(type_strings) == NUM_FILE_TYPES);
+
+const char * const futil_file_type_str(enum futil_file_type type)
+{
+ if (type < 0 || type >= NUM_FILE_TYPES)
+ type = FILE_TYPE_UNKNOWN;
+
+ return type_strings[type];
+}
+
+/* Try these in order so we recognize the larger objects first */
+enum futil_file_type (*recognizers[])(uint8_t *buf, uint32_t len) = {
+ &recognize_gpt,
+ &recognize_bios_image,
+ &recognize_gbb,
+ &recognize_vblock1,
+};
+
+/* Try to figure out what we're looking at */
+enum futil_file_type futil_file_type_buf(uint8_t *buf, uint32_t len)
+{
+ enum futil_file_type type;
+ int i;
+
+ for (i = 0; i < ARRAY_SIZE(recognizers); i++) {
+ type = recognizers[i](buf, len);
+ if (type != FILE_TYPE_UNKNOWN)
+ return type;
+ }
+
+ return FILE_TYPE_UNKNOWN;
+}
+
+enum futil_file_err futil_file_type(const char *filename,
+ enum futil_file_type *type)
+{
+ int ifd;
+ uint8_t *buf;
+ uint32_t buf_len;
+ struct stat sb;
+ enum futil_file_err err = FILE_ERR_NONE;
+
+ *type = FILE_TYPE_UNKNOWN;
+
+ ifd = open(filename, O_RDONLY);
+ if (ifd < 0) {
+ fprintf(stderr, "Can't open %s: %s\n",
+ filename, strerror(errno));
+ return FILE_ERR_OPEN;
+ }
+
+ if (0 != fstat(ifd, &sb)) {
+ fprintf(stderr, "Can't stat input file: %s\n",
+ strerror(errno));
+ return FILE_ERR_STAT;
+ }
+
+ if (S_ISREG(sb.st_mode) || S_ISBLK(sb.st_mode)) {
+ err = futil_map_file(ifd, MAP_RO, &buf, &buf_len);
+ if (err) {
+ close(ifd);
+ return err;
+ }
+
+ *type = futil_file_type_buf(buf, buf_len);
+
+ err = futil_unmap_file(ifd, MAP_RO, buf, buf_len);
+ if (err) {
+ close(ifd);
+ return err;
+ }
+ } else if (S_ISDIR(sb.st_mode)) {
+ err = FILE_ERR_DIR;
+ } else if (S_ISCHR(sb.st_mode)) {
+ err = FILE_ERR_CHR;
+ } else if (S_ISFIFO(sb.st_mode)) {
+ err = FILE_ERR_FIFO;
+ } else if (S_ISSOCK(sb.st_mode)) {
+ err = FILE_ERR_SOCK;
+ }
+
+ if (close(ifd)) {
+ fprintf(stderr, "Error when closing %s: %s\n",
+ filename, strerror(errno));
+ return FILE_ERR_CLOSE;
+ }
+
+ return err;
+}
diff --git a/futility/file_type.h b/futility/file_type.h
new file mode 100644
index 00000000..f8aa97e7
--- /dev/null
+++ b/futility/file_type.h
@@ -0,0 +1,50 @@
+/*
+ * Copyright (c) 2013 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.
+ */
+#ifndef VBOOT_REFERENCE_FUTILITY_FILE_TYPE_H_
+#define VBOOT_REFERENCE_FUTILITY_FILE_TYPE_H_
+
+/* What type of things do I know how to handle? */
+enum futil_file_type {
+ FILE_TYPE_UNKNOWN,
+ FILE_TYPE_PUBKEY, /* VbPublicKey */
+ FILE_TYPE_KEYBLOCK, /* VbKeyBlockHeader */
+ FILE_TYPE_FW_PREAMBLE, /* VbFirmwarePreambleHeader */
+ FILE_TYPE_GBB, /* GoogleBinaryBlockHeader */
+ FILE_TYPE_BIOS_IMAGE, /* Chrome OS BIOS image */
+ FILE_TYPE_OLD_BIOS_IMAGE, /* Old Chrome OS BIOS image */
+ FILE_TYPE_KERN_PREAMBLE, /* VbKernelPreambleHeader */
+
+ /* These are FILE_TYPE_UNKNOWN, but we've been told more about them */
+ FILE_TYPE_RAW_FIRMWARE, /* FW_MAIN_A, etc. */
+ FILE_TYPE_RAW_KERNEL, /* vmlinuz, *.uimg, etc. */
+
+ FILE_TYPE_CHROMIUMOS_DISK, /* At least it has a GPT */
+
+ NUM_FILE_TYPES
+};
+
+/* Names for them */
+const char * const futil_file_type_str(enum futil_file_type type);
+
+/*
+ * This tries to match the buffer content to one of the known file types.
+ */
+enum futil_file_type futil_file_type_buf(uint8_t *buf, uint32_t len);
+
+/*
+ * This opens a file and tries to match it to one of the known file types.
+ * It's not an error if it returns FILE_TYPE_UKNOWN.
+ */
+enum futil_file_err futil_file_type(const char *filename,
+ enum futil_file_type *type);
+
+/* Routines to identify particular file types. */
+enum futil_file_type recognize_bios_image(uint8_t *buf, uint32_t len);
+enum futil_file_type recognize_gbb(uint8_t *buf, uint32_t len);
+enum futil_file_type recognize_vblock1(uint8_t *buf, uint32_t len);
+enum futil_file_type recognize_gpt(uint8_t *buf, uint32_t len);
+
+#endif /* VBOOT_REFERENCE_FUTILITY_FILE_TYPE_H_ */
diff --git a/futility/futility.h b/futility/futility.h
index 652b5fbc..5f9a5b78 100644
--- a/futility/futility.h
+++ b/futility/futility.h
@@ -85,11 +85,29 @@ int print_hwid_digest(GoogleBinaryBlockHeader *gbb,
/* Copies a file or dies with an error message */
void futil_copy_file_or_die(const char *infile, const char *outfile);
-/* Wrapper for mmap/munmap. Returns 0 on success. Skips stupidly large files. */
+/* Possible file operation errors */
+enum futil_file_err {
+ FILE_ERR_NONE,
+ FILE_ERR_STAT,
+ FILE_ERR_SIZE,
+ FILE_ERR_MMAP,
+ FILE_ERR_MSYNC,
+ FILE_ERR_MUNMAP,
+ FILE_ERR_OPEN,
+ FILE_ERR_CLOSE,
+ FILE_ERR_DIR,
+ FILE_ERR_CHR,
+ FILE_ERR_FIFO,
+ FILE_ERR_SOCK,
+};
+
+/* Wrapper for mmap/munmap. Skips stupidly large files. */
#define MAP_RO 0
#define MAP_RW 1
-int futil_map_file(int fd, int writeable, uint8_t **buf, uint32_t *len);
-int futil_unmap_file(int fd, int writeable, uint8_t *buf, uint32_t len);
+enum futil_file_err futil_map_file(int fd, int writeable,
+ uint8_t **buf, uint32_t *len);
+enum futil_file_err futil_unmap_file(int fd, int writeable,
+ uint8_t *buf, uint32_t len);
/* The CPU architecture is occasionally important */
enum arch_t {
diff --git a/futility/misc.c b/futility/misc.c
index 4d8d762e..183edcc2 100644
--- a/futility/misc.c
+++ b/futility/misc.c
@@ -18,6 +18,8 @@
#include <sys/wait.h>
#include <unistd.h>
+#include "cgptlib_internal.h"
+#include "file_type.h"
#include "futility.h"
#include "gbb_header.h"
@@ -49,17 +51,19 @@ static inline uint32_t max(uint32_t a, uint32_t b)
return a > b ? a : b;
}
-int futil_looks_like_gbb(GoogleBinaryBlockHeader *gbb, uint32_t len)
+enum futil_file_type recognize_gbb(uint8_t *buf, uint32_t len)
{
+ GoogleBinaryBlockHeader *gbb = (GoogleBinaryBlockHeader *)buf;
+
if (memcmp(gbb->signature, GBB_SIGNATURE, GBB_SIGNATURE_SIZE))
- return 0;
+ return FILE_TYPE_UNKNOWN;
if (gbb->major_version > GBB_MAJOR_VER)
- return 0;
+ return FILE_TYPE_UNKNOWN;
if (sizeof(GoogleBinaryBlockHeader) > len)
- return 0;
+ return FILE_TYPE_UNKNOWN;
/* close enough */
- return 1;
+ return FILE_TYPE_GBB;
}
int futil_valid_gbb_header(GoogleBinaryBlockHeader *gbb, uint32_t len,
@@ -221,7 +225,8 @@ void futil_copy_file_or_die(const char *infile, const char *outfile)
}
-int futil_map_file(int fd, int writeable, uint8_t **buf, uint32_t *len)
+enum futil_file_err futil_map_file(int fd, int writeable,
+ uint8_t **buf, uint32_t *len)
{
struct stat sb;
void *mmap_ptr;
@@ -230,7 +235,7 @@ int futil_map_file(int fd, int writeable, uint8_t **buf, uint32_t *len)
if (0 != fstat(fd, &sb)) {
fprintf(stderr, "Can't stat input file: %s\n",
strerror(errno));
- return 1;
+ return FILE_ERR_STAT;
}
if (S_ISBLK(sb.st_mode))
@@ -239,7 +244,7 @@ int futil_map_file(int fd, int writeable, uint8_t **buf, uint32_t *len)
/* If the image is larger than 2^32 bytes, it's wrong. */
if (sb.st_size < 0 || sb.st_size > UINT32_MAX) {
fprintf(stderr, "Image size is unreasonable\n");
- return 1;
+ return FILE_ERR_SIZE;
}
reasonable_len = (uint32_t)sb.st_size;
@@ -254,30 +259,60 @@ int futil_map_file(int fd, int writeable, uint8_t **buf, uint32_t *len)
fprintf(stderr, "Can't mmap %s file: %s\n",
writeable ? "output" : "input",
strerror(errno));
- return 1;
+ return FILE_ERR_MMAP;
}
*buf = (uint8_t *)mmap_ptr;
*len = reasonable_len;
- return 0;
+ return FILE_ERR_NONE;
}
-int futil_unmap_file(int fd, int writeable, uint8_t *buf, uint32_t len)
+enum futil_file_err futil_unmap_file(int fd, int writeable,
+ uint8_t *buf, uint32_t len)
{
void *mmap_ptr = buf;
- int errorcnt = 0;
+ enum futil_file_err err = FILE_ERR_NONE;
if (writeable &&
(0 != msync(mmap_ptr, len, MS_SYNC|MS_INVALIDATE))) {
fprintf(stderr, "msync failed: %s\n", strerror(errno));
- errorcnt++;
+ err = FILE_ERR_MSYNC;
}
if (0 != munmap(mmap_ptr, len)) {
fprintf(stderr, "Can't munmap pointer: %s\n",
strerror(errno));
- errorcnt++;
+ if (err == FILE_ERR_NONE)
+ err = FILE_ERR_MUNMAP;
}
- return errorcnt;
+ return err;
+}
+
+
+#define DISK_SECTOR_SIZE 512
+enum futil_file_type recognize_gpt(uint8_t *buf, uint32_t len)
+{
+ GptHeader *h;
+
+ /* GPT header starts at sector 1, is one sector long */
+ if (len < 2 * DISK_SECTOR_SIZE)
+ return FILE_TYPE_UNKNOWN;
+
+ h = (GptHeader *)(buf + DISK_SECTOR_SIZE);
+
+ if (memcmp(h->signature, GPT_HEADER_SIGNATURE,
+ GPT_HEADER_SIGNATURE_SIZE) &&
+ memcmp(h->signature, GPT_HEADER_SIGNATURE2,
+ GPT_HEADER_SIGNATURE_SIZE))
+ return FILE_TYPE_UNKNOWN;
+ if (h->revision != GPT_HEADER_REVISION)
+ return FILE_TYPE_UNKNOWN;
+ if (h->size < MIN_SIZE_OF_HEADER || h->size > MAX_SIZE_OF_HEADER)
+ return FILE_TYPE_UNKNOWN;
+
+ if (HeaderCrc(h) != h->header_crc32)
+ return FILE_TYPE_UNKNOWN;
+
+ return FILE_TYPE_CHROMIUMOS_DISK;
}
diff --git a/futility/traversal.c b/futility/traversal.c
index ef60fde2..aa9988a7 100644
--- a/futility/traversal.c
+++ b/futility/traversal.c
@@ -4,20 +4,12 @@
* found in the LICENSE file.
*/
-#include <errno.h>
-#include <fcntl.h>
#include <stdint.h>
#include <stdio.h>
-#include <string.h>
-#include <sys/stat.h>
-#include <sys/types.h>
-#include <unistd.h>
+#include "file_type.h"
#include "fmap.h"
#include "futility.h"
-#include "gbb_header.h"
-#include "host_common.h"
-#include "host_key.h"
#include "traversal.h"
/* What functions do we invoke for a particular operation and component? */
@@ -84,6 +76,7 @@ static const struct {
{CB_KERN_PREAMBLE, "Kernel Preamble"}, /* FILE_TYPE_KERN_PREAMBLE */
{CB_RAW_FIRMWARE, "raw firmware"}, /* FILE_TYPE_RAW_FIRMWARE */
{CB_RAW_KERNEL, "raw kernel"}, /* FILE_TYPE_RAW_KERNEL */
+ {0, "chromiumos disk"}, /* FILE_TYPE_CHROMIUMOS_DISK */
};
BUILD_ASSERT(ARRAY_SIZE(direct_callback) == NUM_FILE_TYPES);
@@ -116,7 +109,6 @@ static const struct bios_area_s old_bios_area[] = {
{0, 0}
};
-
static int has_all_areas(uint8_t *buf, uint32_t len, FmapHeader *fmap,
const struct bios_area_s *area)
{
@@ -129,19 +121,17 @@ static int has_all_areas(uint8_t *buf, uint32_t len, FmapHeader *fmap,
return 1;
}
-const char * const futil_file_type_str[] = {
- "FILE_TYPE_UNKNOWN",
- "FILE_TYPE_PUBKEY",
- "FILE_TYPE_KEYBLOCK",
- "FILE_TYPE_FW_PREAMBLE",
- "FILE_TYPE_GBB",
- "FILE_TYPE_BIOS_IMAGE",
- "FILE_TYPE_OLD_BIOS_IMAGE",
- "FILE_TYPE_KERN_PREAMBLE",
- "FILE_TYPE_RAW_FIRMWARE",
- "FILE_TYPE_RAW_KERNEL",
-};
-BUILD_ASSERT(ARRAY_SIZE(futil_file_type_str) == NUM_FILE_TYPES);
+enum futil_file_type recognize_bios_image(uint8_t *buf, uint32_t len)
+{
+ FmapHeader *fmap = fmap_find(buf, len);
+ if (fmap) {
+ if (has_all_areas(buf, len, fmap, bios_area))
+ return FILE_TYPE_BIOS_IMAGE;
+ if (has_all_areas(buf, len, fmap, old_bios_area))
+ return FILE_TYPE_OLD_BIOS_IMAGE;
+ }
+ return FILE_TYPE_UNKNOWN;
+}
const char * const futil_cb_component_str[] = {
"CB_BEGIN_TRAVERSAL",
@@ -191,93 +181,6 @@ static int invoke_callback(struct futil_traverse_state_s *state,
return 0;
}
-enum futil_file_type futil_what_file_type_buf(uint8_t *buf, uint32_t len)
-{
- VbPublicKey *pubkey = (VbPublicKey *)buf;
- VbKeyBlockHeader *key_block = (VbKeyBlockHeader *)buf;
- GoogleBinaryBlockHeader *gbb = (GoogleBinaryBlockHeader *)buf;
- VbFirmwarePreambleHeader *fw_preamble;
- VbKernelPreambleHeader *kern_preamble;
- RSAPublicKey *rsa;
- FmapHeader *fmap;
-
- /*
- * Complex structs may begin with simpler structs first, so try them
- * in reverse order.
- */
-
- fmap = fmap_find(buf, len);
- if (fmap) {
- if (has_all_areas(buf, len, fmap, bios_area))
- return FILE_TYPE_BIOS_IMAGE;
- if (has_all_areas(buf, len, fmap, old_bios_area))
- return FILE_TYPE_OLD_BIOS_IMAGE;
- }
-
- if (futil_looks_like_gbb(gbb, len))
- return FILE_TYPE_GBB;
-
- if (VBOOT_SUCCESS == KeyBlockVerify(key_block, len, NULL, 1)) {
- rsa = PublicKeyToRSA(&key_block->data_key);
- uint32_t more = key_block->key_block_size;
-
- /* and firmware preamble too? */
- fw_preamble = (VbFirmwarePreambleHeader *)(buf + more);
- if (VBOOT_SUCCESS ==
- VerifyFirmwarePreamble(fw_preamble, len - more, rsa))
- return FILE_TYPE_FW_PREAMBLE;
-
- /* or maybe kernel preamble? */
- kern_preamble = (VbKernelPreambleHeader *)(buf + more);
- if (VBOOT_SUCCESS ==
- VerifyKernelPreamble(kern_preamble, len - more, rsa))
- return FILE_TYPE_KERN_PREAMBLE;
-
- /* no, just keyblock */
- return FILE_TYPE_KEYBLOCK;
- }
-
- if (PublicKeyLooksOkay(pubkey, len))
- return FILE_TYPE_PUBKEY;
-
- return FILE_TYPE_UNKNOWN;
-}
-
-enum futil_file_type futil_what_file_type(const char *filename)
-{
- enum futil_file_type type;
- int ifd;
- uint8_t *buf;
- uint32_t buf_len;
-
- ifd = open(filename, O_RDONLY);
- if (ifd < 0) {
- fprintf(stderr, "Can't open %s: %s\n",
- filename, strerror(errno));
- exit(1);
- }
-
- if (0 != futil_map_file(ifd, MAP_RO, &buf, &buf_len)) {
- close(ifd);
- exit(1);
- }
-
- type = futil_what_file_type_buf(buf, buf_len);
-
- if (0 != futil_unmap_file(ifd, MAP_RO, buf, buf_len)) {
- close(ifd);
- exit(1);
- }
-
- if (close(ifd)) {
- fprintf(stderr, "Error when closing %s: %s\n",
- filename, strerror(errno));
- exit(1);
- }
-
- return type;
-}
-
int futil_traverse(uint8_t *buf, uint32_t len,
struct futil_traverse_state_s *state,
enum futil_file_type type)
@@ -293,7 +196,7 @@ int futil_traverse(uint8_t *buf, uint32_t len,
}
if (type == FILE_TYPE_UNKNOWN)
- type = futil_what_file_type_buf(buf, len);
+ type = futil_file_type_buf(buf, len);
state->in_type = type;
state->errors = retval;
@@ -302,20 +205,6 @@ int futil_traverse(uint8_t *buf, uint32_t len,
state->errors = retval;
switch (type) {
- case FILE_TYPE_PUBKEY:
- case FILE_TYPE_KEYBLOCK:
- case FILE_TYPE_FW_PREAMBLE:
- case FILE_TYPE_GBB:
- case FILE_TYPE_KERN_PREAMBLE:
- case FILE_TYPE_RAW_FIRMWARE:
- case FILE_TYPE_RAW_KERNEL:
- retval |= invoke_callback(state,
- direct_callback[type].component,
- direct_callback[type].name,
- 0, buf, len);
- state->errors = retval;
- break;
-
case FILE_TYPE_BIOS_IMAGE:
/* We've already checked, so we know this will work. */
fmap = fmap_find(buf, len);
@@ -349,9 +238,12 @@ int futil_traverse(uint8_t *buf, uint32_t len,
break;
default:
- Debug("%s:%d unhandled type %s\n", __FILE__, __LINE__,
- futil_file_type_str[type]);
- retval = 1;
+ retval |= invoke_callback(state,
+ direct_callback[type].component,
+ direct_callback[type].name,
+ 0, buf, len);
+ state->errors = retval;
+ break;
}
retval |= invoke_callback(state, CB_END_TRAVERSAL, "<end>",
diff --git a/futility/traversal.h b/futility/traversal.h
index faf8d27c..e22b231e 100644
--- a/futility/traversal.h
+++ b/futility/traversal.h
@@ -8,27 +8,6 @@
#include <stdint.h>
-/* What type of things do I know how to handle? */
-enum futil_file_type {
- FILE_TYPE_UNKNOWN,
- FILE_TYPE_PUBKEY, /* 1 VbPublicKey */
- FILE_TYPE_KEYBLOCK, /* 2 VbKeyBlockHeader */
- FILE_TYPE_FW_PREAMBLE, /* 3 VbFirmwarePreambleHeader */
- FILE_TYPE_GBB, /* 4 GoogleBinaryBlockHeader */
- FILE_TYPE_BIOS_IMAGE, /* 5 Chrome OS BIOS image */
- FILE_TYPE_OLD_BIOS_IMAGE, /* 6 Old Chrome OS BIOS image */
- FILE_TYPE_KERN_PREAMBLE, /* 7 VbKernelPreambleHeader */
-
- /* These are FILE_TYPE_UNKNOWN, but we've been told more about them */
- FILE_TYPE_RAW_FIRMWARE, /* 8 FW_MAIN_A, etc. */
- FILE_TYPE_RAW_KERNEL, /* 9 vmlinuz, *.uimg, etc. */
-
- NUM_FILE_TYPES
-};
-
-/* Names for them */
-extern const char * const futil_file_type_str[];
-
/* What are we trying to accomplish? */
enum futil_op_type {
FUTIL_OP_SHOW,
@@ -91,18 +70,6 @@ struct futil_traverse_state_s {
/*
- * This tries to match the buffer content to one of the known file types.
- */
-enum futil_file_type futil_what_file_type_buf(uint8_t *buf, uint32_t len);
-
-/*
- * This opens a file and tries to match it to one of the known file types. It
- * fails only if it can't open and scan the file. It's not an error if it
- * returns FILE_TYPE_UKNOWN.
- */
-enum futil_file_type futil_what_file_type(const char *filename);
-
-/*
* Traverse the buffer using the provided state, which should be initialized
* before calling. Returns nonzero (but no details) if there were any errors.
*/
diff --git a/futility/vb1_helper.c b/futility/vb1_helper.c
index dd219ef8..292a0f24 100644
--- a/futility/vb1_helper.c
+++ b/futility/vb1_helper.c
@@ -10,6 +10,7 @@
#include <string.h>
#include <unistd.h>
+#include "file_type.h"
#include "futility.h"
#include "host_common.h"
#include "kernel_blob.h"
@@ -701,3 +702,38 @@ uint8_t *CreateKernelBlob(uint8_t *vmlinuz_buf, uint64_t vmlinuz_size,
*blob_size_ptr = g_kernel_blob_size;
return g_kernel_blob_data;
}
+
+enum futil_file_type recognize_vblock1(uint8_t *buf, uint32_t len)
+{
+ VbKeyBlockHeader *key_block = (VbKeyBlockHeader *)buf;
+ VbPublicKey *pubkey = (VbPublicKey *)buf;
+ VbFirmwarePreambleHeader *fw_preamble;
+ VbKernelPreambleHeader *kern_preamble;
+ RSAPublicKey *rsa;
+
+ if (VBOOT_SUCCESS == KeyBlockVerify(key_block, len, NULL, 1)) {
+ rsa = PublicKeyToRSA(&key_block->data_key);
+ uint32_t more = key_block->key_block_size;
+
+ /* and firmware preamble too? */
+ fw_preamble = (VbFirmwarePreambleHeader *)(buf + more);
+ if (VBOOT_SUCCESS ==
+ VerifyFirmwarePreamble(fw_preamble, len - more, rsa))
+ return FILE_TYPE_FW_PREAMBLE;
+
+ /* or maybe kernel preamble? */
+ kern_preamble = (VbKernelPreambleHeader *)(buf + more);
+ if (VBOOT_SUCCESS ==
+ VerifyKernelPreamble(kern_preamble, len - more, rsa))
+ return FILE_TYPE_KERN_PREAMBLE;
+
+ /* no, just keyblock */
+ return FILE_TYPE_KEYBLOCK;
+ }
+
+ /* Maybe just a VbPublicKey? */
+ if (PublicKeyLooksOkay(pubkey, len))
+ return FILE_TYPE_PUBKEY;
+
+ return FILE_TYPE_UNKNOWN;
+}