summaryrefslogtreecommitdiff
path: root/futility/cmd_gbb_utility.c
diff options
context:
space:
mode:
Diffstat (limited to 'futility/cmd_gbb_utility.c')
-rw-r--r--futility/cmd_gbb_utility.c240
1 files changed, 195 insertions, 45 deletions
diff --git a/futility/cmd_gbb_utility.c b/futility/cmd_gbb_utility.c
index c0e5fc51..3ca93b94 100644
--- a/futility/cmd_gbb_utility.c
+++ b/futility/cmd_gbb_utility.c
@@ -16,17 +16,34 @@
#include <unistd.h>
#include "futility.h"
+#include "updater.h"
#include "updater_utils.h"
+#ifdef USE_FLASHROM
+#define FLASH_ARG_HELP \
+ " --flash \tRead from and write to flash" \
+ ", ignore file arguments.\n"
+#define FLASH_MORE_HELP \
+ "In GET and SET mode, the following options modify the " \
+ "behaviour of flashing. Presence of any of these implies " \
+ "--flash.\n" \
+ SHARED_FLASH_ARGS_HELP \
+ "\n"
+#else
+#define FLASH_ARG_HELP
+#define FLASH_MORE_HELP
+#endif /* USE_FLASHROM */
+
static void print_help(int argc, char *argv[])
{
printf("\n"
"Usage: " MYNAME " %s [-g|-s|-c] [OPTIONS] "
- "bios_file [output_file]\n"
+ "[bios_file] [output_file]\n"
"\n"
"GET MODE:\n"
- "-g, --get (default)\tGet (read) from bios_file, "
+ "-g, --get (default)\tGet (read) from bios_file or flash, "
"with following options:\n"
+ FLASH_ARG_HELP
" --hwid \tReport hardware id (default).\n"
" --flags \tReport header flags.\n"
" --digest \tReport digest of hwid (>= v1.2)\n"
@@ -35,8 +52,9 @@ static void print_help(int argc, char *argv[])
" -r --recoverykey=FILE\tFile name to export Recovery Key.\n"
"\n"
"SET MODE:\n"
- "-s, --set \tSet (write) to bios_file, "
+ "-s, --set \tSet (write) to flash or file, "
"with following options:\n"
+ FLASH_ARG_HELP
" -o, --output=FILE \tNew file name for ouptput.\n"
" --hwid=HWID \tThe new hardware id to be changed.\n"
" --flags=FLAGS \tThe new (numeric) flags value.\n"
@@ -47,7 +65,8 @@ static void print_help(int argc, char *argv[])
"CREATE MODE:\n"
"-c, --create=hwid_size,rootkey_size,bmpfv_size,"
"recoverykey_size\n"
- " \tCreate a GBB blob by given size list.\n"
+ " \tCreate a GBB blob by given size list.\n\n"
+ FLASH_MORE_HELP
"SAMPLE:\n"
" %s -g bios.bin\n"
" %s --set --hwid='New Model' -k key.bin"
@@ -57,14 +76,16 @@ static void print_help(int argc, char *argv[])
}
enum {
- OPT_HWID = 1000,
+ OPT_HWID = 0x1000,
OPT_FLAGS,
OPT_DIGEST,
+ OPT_FLASH,
OPT_HELP,
};
/* Command line options */
static struct option long_opts[] = {
+ SHARED_FLASH_ARGS_LONGOPTS
/* name has_arg *flag val */
{"get", 0, NULL, 'g'},
{"set", 0, NULL, 's'},
@@ -76,11 +97,12 @@ static struct option long_opts[] = {
{"hwid", 0, NULL, OPT_HWID},
{"flags", 0, NULL, OPT_FLAGS},
{"digest", 0, NULL, OPT_DIGEST},
+ {"flash", 0, NULL, OPT_FLASH},
{"help", 0, NULL, OPT_HELP},
{NULL, 0, NULL, 0},
};
-static const char *short_opts = ":gsc:o:k:b:r:";
+static const char *short_opts = ":gsc:o:k:b:r:" SHARED_FLASH_ARGS_SHORTOPTS;
/* Change the has_arg field of a long_opts entry */
static void opt_has_arg(const char *name, int val)
@@ -167,9 +189,9 @@ static uint8_t *create_gbb(const char *desc, off_t *sizeptr)
size, strerror(errno));
free(sizes);
return NULL;
- } else if (sizeptr) {
- *sizeptr = size;
}
+ if (sizeptr)
+ *sizeptr = size;
gbb = (struct vb2_gbb_header *) buf;
memcpy(gbb->signature, VB2_GBB_SIGNATURE, VB2_GBB_SIGNATURE_SIZE);
@@ -317,6 +339,96 @@ done_close:
return r;
}
+/*
+ * Prepare for flashrom interaction. Setup cfg from args and put servo into
+ * flash mode if servo is in use. If this succeeds teardown_flash must be
+ * called.
+ */
+static int setup_flash(struct updater_config **cfg,
+ struct updater_config_arguments *args,
+ const char **prepare_ctrl_name)
+{
+#ifdef USE_FLASHROM
+ *prepare_ctrl_name = NULL;
+ *cfg = updater_new_config();
+ if (!*cfg) {
+ fprintf(stderr, "\nERROR: Out of memory\n");
+ return 1;
+ }
+ if (args->detect_servo) {
+ char *servo_programmer = host_detect_servo(prepare_ctrl_name);
+
+ if (!servo_programmer) {
+ fprintf(stderr,
+ "\nERROR: Problem communicating with servo\n");
+ goto errdelete;
+ }
+
+ if (!args->programmer)
+ args->programmer = servo_programmer;
+ else
+ free(servo_programmer);
+ }
+ int ignored;
+ if (updater_setup_config(*cfg, args, &ignored)) {
+ fprintf(stderr, "\nERROR: Bad servo options\n");
+ goto errdelete;
+ }
+ prepare_servo_control(*prepare_ctrl_name, 1);
+ return 0;
+errdelete:
+ updater_delete_config(*cfg);
+ *cfg = NULL;
+ return 1;
+#else
+ return 1;
+#endif /* USE_FLASHROM */
+}
+
+/* Cleanup objects created in setup_flash and release servo from flash mode. */
+static void teardown_flash(struct updater_config *cfg,
+ const char *prepare_ctrl_name,
+ char *servo_programmer)
+{
+#ifdef USE_FLASHROM
+ prepare_servo_control(prepare_ctrl_name, 0);
+ free(servo_programmer);
+ updater_delete_config(cfg);
+#endif /* USE_FLASHROM */
+}
+
+/* Read firmware from flash. */
+static uint8_t *read_from_flash(struct updater_config *cfg, off_t *filesize)
+{
+#ifdef USE_FLASHROM
+ if (load_system_firmware(cfg, &cfg->image_current))
+ return NULL;
+ uint8_t *ret = cfg->image_current.data;
+ cfg->image_current.data = NULL;
+ *filesize = cfg->image_current.size;
+ cfg->image_current.size = 0;
+ return ret;
+#else
+ return NULL;
+#endif /* USE_FLASHROM */
+}
+
+/* Write firmware to flash. Takes ownership of inbuf and outbuf data. */
+static int write_to_flash(struct updater_config *cfg, uint8_t *outbuf,
+ off_t filesize)
+{
+#ifdef USE_FLASHROM
+ cfg->image.data = outbuf;
+ cfg->image.size = filesize;
+ int ret = write_firmware(cfg, &cfg->image, FMAP_RO_GBB);
+ cfg->image.data = NULL;
+ cfg->image.size = 0;
+ return ret;
+#else
+ return 1;
+#endif /* USE_FLASHROM */
+}
+
static int do_gbb(int argc, char *argv[])
{
enum do_what_now { DO_GET, DO_SET, DO_CREATE } mode = DO_GET;
@@ -337,9 +449,17 @@ static int do_gbb(int argc, char *argv[])
struct vb2_gbb_header *gbb;
uint8_t *gbb_base;
int i;
+ struct updater_config *cfg = NULL;
+ struct updater_config_arguments args = {0};
+ const char *prepare_ctrl_name = NULL;
+ char *servo_programmer = NULL;
opterr = 0; /* quiet, you */
while ((i = getopt_long(argc, argv, short_opts, long_opts, 0)) != -1) {
+#ifdef USE_FLASHROM
+ if (handle_flash_argument(&args, i, optarg))
+ continue;
+#endif
switch (i) {
case 'g':
mode = DO_GET;
@@ -380,6 +500,14 @@ static int do_gbb(int argc, char *argv[])
case OPT_DIGEST:
sel_digest = 1;
break;
+ case OPT_FLASH:
+#ifndef USE_FLASHROM
+ fprintf(stderr, "ERROR: futility was built without "
+ "flashrom support\n");
+ return 1;
+#endif
+ args.use_flash = 1;
+ break;
case OPT_HELP:
print_help(argc, argv);
return !!errorcnt;
@@ -422,16 +550,34 @@ static int do_gbb(int argc, char *argv[])
return 1;
}
+ if (args.use_flash) {
+ if (setup_flash(&cfg, &args, &prepare_ctrl_name)) {
+ fprintf(stderr,
+ "ERROR: error while preparing flash\n");
+ return 1;
+ }
+ }
+
/* Now try to do something */
switch (mode) {
case DO_GET:
- if (argc - optind < 1) {
- fprintf(stderr, "\nERROR: missing input filename\n");
- print_help(argc, argv);
- errorcnt++;
- break;
+ if (args.use_flash) {
+ inbuf = read_from_flash(cfg, &filesize);
} else {
+ if (argc - optind < 1) {
+ fprintf(stderr,
+ "\nERROR: missing input filename\n");
+ print_help(argc, argv);
+ errorcnt++;
+ break;
+ }
infile = argv[optind++];
+ inbuf = read_entire_file(infile, &filesize);
+
+ }
+ if (!inbuf) {
+ errorcnt++;
+ break;
}
/* With no args, show the HWID */
@@ -439,12 +585,6 @@ static int do_gbb(int argc, char *argv[])
&& !sel_flags && !sel_digest)
sel_hwid = 1;
- inbuf = read_entire_file(infile, &filesize);
- if (!inbuf) {
- errorcnt++;
- break;
- }
-
gbb = FindGbbHeader(inbuf, filesize);
if (!gbb) {
fprintf(stderr, "ERROR: No GBB found in %s\n", infile);
@@ -491,15 +631,26 @@ static int do_gbb(int argc, char *argv[])
break;
case DO_SET:
- if (argc - optind < 1) {
- fprintf(stderr, "\nERROR: missing input filename\n");
- print_help(argc, argv);
+ if (args.use_flash) {
+ inbuf = read_from_flash(cfg, &filesize);
+ } else {
+ if (argc - optind < 1) {
+ fprintf(stderr,
+ "\nERROR: missing input filename\n");
+ print_help(argc, argv);
+ errorcnt++;
+ break;
+ }
+ infile = argv[optind++];
+ inbuf = read_entire_file(infile, &filesize);
+ if (!outfile)
+ outfile = (argc - optind < 1) ? infile
+ : argv[optind++];
+ }
+ if (!inbuf) {
errorcnt++;
break;
}
- infile = argv[optind++];
- if (!outfile)
- outfile = (argc - optind < 1) ? infile : argv[optind++];
if (sel_hwid && !opt_hwid) {
fprintf(stderr, "\nERROR: missing new HWID value\n");
@@ -514,13 +665,6 @@ static int do_gbb(int argc, char *argv[])
break;
}
- /* With no args, we'll either copy it unchanged or do nothing */
- inbuf = read_entire_file(infile, &filesize);
- if (!inbuf) {
- errorcnt++;
- break;
- }
-
gbb = FindGbbHeader(inbuf, filesize);
if (!gbb) {
fprintf(stderr, "ERROR: No GBB found in %s\n", infile);
@@ -557,14 +701,13 @@ static int do_gbb(int argc, char *argv[])
gbb->hwid_size);
errorcnt++;
break;
- } else {
- /* Wipe data before writing new value. */
- memset(gbb_base + gbb->hwid_offset, 0,
- gbb->hwid_size);
- strcpy((char *)(gbb_base + gbb->hwid_offset),
- opt_hwid);
- update_hwid_digest(gbb);
}
+ /* Wipe data before writing new value. */
+ memset(gbb_base + gbb->hwid_offset, 0,
+ gbb->hwid_size);
+ strcpy((char *)(gbb_base + gbb->hwid_offset),
+ opt_hwid);
+ update_hwid_digest(gbb);
}
if (opt_flags) {
@@ -577,9 +720,8 @@ static int do_gbb(int argc, char *argv[])
opt_flags);
errorcnt++;
break;
- } else {
- gbb->flags = val;
}
+ gbb->flags = val;
}
if (opt_rootkey) {
@@ -606,13 +748,19 @@ static int do_gbb(int argc, char *argv[])
}
/* Write it out if there are no problems. */
- if (!errorcnt)
- if (write_to_file("successfully saved new image to:",
- outfile, outbuf, filesize)) {
+ if (!errorcnt) {
+ if (args.use_flash) {
+ if (write_to_flash(cfg, outbuf, filesize)) {
+ errorcnt++;
+ break;
+ }
+ } else if (write_to_file(
+ "successfully saved new image to:",
+ outfile, outbuf, filesize)) {
errorcnt++;
break;
}
-
+ }
break;
case DO_CREATE:
@@ -645,6 +793,8 @@ static int do_gbb(int argc, char *argv[])
break;
}
+ if (args.use_flash)
+ teardown_flash(cfg, prepare_ctrl_name, servo_programmer);
if (inbuf)
free(inbuf);
if (outbuf)