Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(1567)

Unified Diff: utility/load_firmware_test.c

Issue 6465018: Add load_firmware_test utility program (Closed) Base URL: ssh://git@gitrw.chromium.org:9222/vboot_reference.git@master
Patch Set: Created 9 years, 10 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« utility/include/fmap.h ('K') | « utility/include/fmap.h ('k') | no next file » | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: utility/load_firmware_test.c
diff --git a/utility/load_firmware_test.c b/utility/load_firmware_test.c
new file mode 100644
index 0000000000000000000000000000000000000000..b6cf98b6cba28c78e3bf4a62a991624fada2b461
--- /dev/null
+++ b/utility/load_firmware_test.c
@@ -0,0 +1,240 @@
+/* Copyright (c) 2011 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.
+ *
+ * Routines for verifying a firmware image's signature.
+ */
+
+#include <errno.h>
+#include <fcntl.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>
+
+#include "fmap.h"
+#include "gbb_header.h"
+#include "load_firmware_fw.h"
+#include "vboot_struct.h"
+
+
+typedef struct _CallerInternal {
+ struct {
+ uint8_t *fw;
Randall Spangler 2011/02/09 19:42:14 Google style nit: * is next to the type, not the v
Che-Liang Chiou 2011/02/10 09:11:03 Done.
+ uint64_t size;
+ } firmware[2];
+} CallerInternal;
+
+static char *progname = NULL;
+static char *image_path = NULL;
+
+
+/* return -1 on error */
+int area_index(FmapHeader *fh, AreaHeader *ah, const char name[]);
Randall Spangler 2011/02/09 19:42:14 move to fmap.h; add more description
Che-Liang Chiou 2011/02/10 09:11:03 Done.
+/* wrapper of area_index; print error when not found */
+int area_index_or_error(FmapHeader *fh, AreaHeader *ah, const char name[]);
+/* return NULL on error */
+const char *status_string(int status);
+
+int GetFirmwareBody(LoadFirmwareParams *params, uint64_t firmware_index) {
+ CallerInternal* ci = (CallerInternal *) params->caller_internal;
+
+ if (firmware_index != 0 && firmware_index != 1)
+ return 1;
+
+ UpdateFirmwareBodyHash(params,
+ ci->firmware[firmware_index].fw,
+ ci->firmware[firmware_index].size);
+
+ return 0;
+}
+
+/* return zero on success, non-zero on error */
+int drive_load_firmware(void *base_of_rom, void *fmap) {
gauravsh 2011/02/09 19:58:22 comment on arguments and what the function does?
Che-Liang Chiou 2011/02/10 09:11:03 Done.
+ LoadFirmwareParams lfp;
+ CallerInternal ci;
+
+ FmapHeader *fh = (FmapHeader *) fmap;
+ AreaHeader *ah = (AreaHeader *) (fmap + sizeof(FmapHeader));
+ int retval = 1;
+ int i, j, k, status;
+ void *gbb, *kb;
+ GoogleBinaryBlockHeader *gbbh;
+ VbKeyBlockHeader *kbh;
+ VbFirmwarePreambleHeader *fph;
+ const char *status_str;
+
+ const char *key_area_name[2] = {
+ "Firmware A Key",
+ "Firmware B Key"
+ };
+ void **vblock_ptr[2] = {
+ &lfp.verification_block_0,
+ &lfp.verification_block_1
+ };
+ uint64_t *vsize_ptr[2] = {
+ &lfp.verification_size_0,
+ &lfp.verification_size_1
+ };
+
+ const char *data_area_name[2] = {
+ "Firmware A Data",
+ "Firmware B Data"
+ };
+
+ i = area_index_or_error(fh, ah, "GBB Area");
+ if (i < 0)
+ goto EXIT;
+
+ gbb = base_of_rom + ah[i].area_offset;
gauravsh 2011/02/09 19:58:22 2 comments - 1) this method is pretty big. conside
Che-Liang Chiou 2011/02/10 09:11:03 Done.
+ gbbh = (GoogleBinaryBlockHeader *) gbb;
+ lfp.firmware_root_key_blob = gbb + gbbh->rootkey_offset;
+ printf("firmware root key blob at 0x%08" PRIx64 "\n",
+ lfp.firmware_root_key_blob - base_of_rom);
+
+ for (k = 0; k < 2; k ++) {
+ i = area_index_or_error(fh, ah, key_area_name[k]);
+ if (i < 0)
+ goto EXIT;
+
+ j = area_index_or_error(fh, ah, data_area_name[k]);
+ if (j < 0)
+ goto EXIT;
+
+ kb = base_of_rom + ah[i].area_offset;
+
+ *vblock_ptr[k] = kb;
+ printf("verification block %d at 0x%08" PRIx64 "\n", k,
+ *vblock_ptr[k] - base_of_rom);
+
+ kbh = (VbKeyBlockHeader *) kb;
+ fph = (VbFirmwarePreambleHeader *) (kb + kbh->key_block_size);
+
+ *vsize_ptr[k] = kbh->key_block_size + fph->preamble_size;
+ printf("verification block %d size is 0x%08" PRIx64 "\n", k, *vsize_ptr[k]);
+
+ ci.firmware[k].fw = (uint8_t *) (base_of_rom + ah[j].area_offset);
+ printf("firmware %c at 0x%08" PRIx64 "\n", "AB"[k],
+ (void *) ci.firmware[k].fw - base_of_rom);
+
+ ci.firmware[k].size = (uint64_t) fph->body_signature.data_size;
+ printf("firmware %c size is 0x%08" PRIx64 "\n", "AB"[k],
+ ci.firmware[k].size);
+ }
+ lfp.caller_internal = &ci;
+
+ /* remember to free kernel_sign_key_blob before exit */
+ lfp.kernel_sign_key_blob = malloc(LOAD_FIRMWARE_KEY_BLOB_REC_SIZE);
+ lfp.kernel_sign_key_size = LOAD_FIRMWARE_KEY_BLOB_REC_SIZE;
+ printf("kernel sign key size is 0x%08" PRIx64 "\n", lfp.kernel_sign_key_size);
+
+ lfp.boot_flags = 0;
+ printf("boot flags is 0x%08" PRIx64 "\n", lfp.boot_flags);
+
+ status = LoadFirmware(&lfp);
+ status_str = status_string(status);
+ if (status_str)
+ printf("LoadFirmware returns %s\n", status_str);
+ else
+ printf("LoadFirmware returns unknown status code: %d\n", status);
+ if (status == LOAD_FIRMWARE_SUCCESS)
+ printf("firmwiare index is %" PRIu64 "\n", lfp.firmware_index);
+
+ free(lfp.kernel_sign_key_blob);
+ retval = 0;
+
+EXIT:
gauravsh 2011/02/09 19:58:22 in general, we try to avoid goto. refactor to not
Che-Liang Chiou 2011/02/10 09:11:03 Done.
+ return retval;
+}
+
+/* return -1 on error */
+int area_index(FmapHeader *fh, AreaHeader *ah, const char name[]) {
Randall Spangler 2011/02/09 19:42:14 Move these to fmap.c Use Fmap prefix on all funct
Randall Spangler 2011/02/09 19:42:14 const char* name
Che-Liang Chiou 2011/02/10 09:11:03 Done.
Che-Liang Chiou 2011/02/10 09:11:03 Done.
+ size_t len = strlen(name);
Randall Spangler 2011/02/09 19:42:14 Is this just an optimization to save doing the imp
Che-Liang Chiou 2011/02/10 09:11:03 I guess not.
+ int i;
+ for (i = 0; i < fh->fmap_nareas; i++)
+ if (!strncmp((const char *) ah[i].area_name, name, len))
+ return i;
+ return -1;
+}
+
+/* wrap area_index; print error when not found */
+int area_index_or_error(FmapHeader *fh, AreaHeader *ah, const char name[]) {
gauravsh 2011/02/09 19:58:22 this looks like it could be moved to fmap.c
Che-Liang Chiou 2011/02/10 09:11:03 progname is a static global variable of load_firmw
+ int i = area_index(fh, ah, name);
+ if (i < 0)
+ fprintf(stderr, "%s: can't find %s in firmware image\n", progname, name);
+ return i;
+}
+
+/* return NULL on error */
+const char *status_string(int status) {
gauravsh 2011/02/09 19:58:22 comment?
Che-Liang Chiou 2011/02/10 09:11:03 Done.
+ switch (status) {
+ case LOAD_FIRMWARE_SUCCESS:
+ return "LOAD_FIRMWARE_SUCCESS";
+ case LOAD_FIRMWARE_RECOVERY:
+ return "LOAD_FIRMWARE_RECOVERY";
+ case LOAD_FIRMWARE_REBOOT:
+ return "LOAD_FIRMWARE_REBOOT";
+ case LOAD_FIRMWARE_RECOVERY_TPM:
+ return "LOAD_FIRMWARE_RECOVERY_TPM";
+ default:
+ return NULL;
+ }
+}
+
+/* main function and its subroutines */
+
+void error_and_exit(char *action_name) {
+ fprintf(stderr, "%s: can't %s %s: %s\n",
+ progname,
+ action_name,
+ image_path,
+ strerror(errno));
+ exit(1);
+}
+
+int main(int argc, char *argv[]) {
+ int fd, retval = 0;
+ struct stat sb;
+ void *base_of_rom, *fmap;
+
+ progname = argv[0];
+
+ if (argc < 2) {
+ fprintf(stderr, "usage: %s <firmware_image>\n", progname);
+ exit(1);
+ }
+
+ image_path = argv[1];
+
+ if (0 != stat(image_path, &sb))
+ error_and_exit("stat");
+
+ fd = open(image_path, O_RDONLY);
Randall Spangler 2011/02/09 19:42:14 Why not just use ReadFile() from host lib? Code w
Che-Liang Chiou 2011/02/10 09:11:03 Done.
+ if (fd < 0)
+ error_and_exit("open");
+
+ printf("opened %s\n", image_path);
+
+ base_of_rom = mmap(0, sb.st_size, PROT_READ, MAP_PRIVATE, fd, 0);
gauravsh 2011/02/09 19:58:22 i don't think it is really any better to use mmap(
Che-Liang Chiou 2011/02/10 09:11:03 Done.
+ if (base_of_rom == (void *) -1) {
+ close(fd);
+ error_and_exit("mmap");
+ }
+
+ fmap = find_fmap((char *) base_of_rom, sb.st_size);
+
+ retval = drive_load_firmware(base_of_rom, fmap);
+
+ if (0 != munmap(base_of_rom, sb.st_size)) {
+ close(fd);
+ error_and_exit("munmap");
+ }
+
+ if (0 != close(fd))
+ error_and_exit("close");
+
+ return retval;
+}
« utility/include/fmap.h ('K') | « utility/include/fmap.h ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698