mirror of
https://github.com/Telecominfraproject/OpenCellular.git
synced 2025-11-28 12:13:45 +00:00
The host-side futility tool will need to support all extant vboot
implementations. Some legacy futility commands only support the
original vb1 format, but others ("show" or "sign", for example)
may need to be instructed which formats to expect or emit.
This change adds some global args to specify the preferred
formats. It also cleans up a few [unused AFAICT] one-letter args
to avoid conflicts.
BUG=chromium:231574
BRANCH=none
TEST=make runtests
Nothing makes use of this yet, except the "help" command.
Change-Id: Ib79fa12af72b8860b9494e5d9e90b9572c006107
Signed-off-by: Bill Richardson <wfrichar@chromium.org>
Reviewed-on: https://chromium-review.googlesource.com/246765
Reviewed-by: Randall Spangler <rspangler@chromium.org>
205 lines
4.2 KiB
C
205 lines
4.2 KiB
C
/*
|
|
* Copyright 2014 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 <getopt.h>
|
|
#include <inttypes.h>
|
|
#include <limits.h>
|
|
#include <stddef.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 "fmap.h"
|
|
#include "futility.h"
|
|
|
|
|
|
static const char usage[] = "\n"
|
|
"Usage: " MYNAME " %s [OPTIONS] FILE AREA:file [AREA:file ...]\n"
|
|
"\n"
|
|
"Replace the contents of specific FMAP areas. This is the complement\n"
|
|
"of " MYNAME " dump_fmap -x FILE AREA [AREA ...]\n"
|
|
"\n"
|
|
"Options:\n"
|
|
" -o OUTFILE Write the result to this file, instead of modifying\n"
|
|
" the input file. This is safer, since there are no\n"
|
|
" safeguards against doing something stupid.\n"
|
|
"\n"
|
|
"Example:\n"
|
|
"\n"
|
|
" This will clear the RO_VPD area, and scramble VBLOCK_B:\n"
|
|
"\n"
|
|
" " MYNAME " %s bios.bin RO_VPD:/dev/zero VBLOCK_B:/dev/urandom\n"
|
|
"\n";
|
|
|
|
static void help_and_quit(const char *prog)
|
|
{
|
|
printf(usage, prog, prog);
|
|
}
|
|
|
|
static const struct option long_opts[] = {
|
|
/* name hasarg *flag val */
|
|
{NULL, 0, NULL, 0},
|
|
};
|
|
static char *short_opts = ":o:";
|
|
|
|
|
|
static int copy_to_area(char *file, uint8_t *buf, uint32_t len, char *area)
|
|
{
|
|
FILE *fp;
|
|
int retval = 0;
|
|
int n;
|
|
|
|
fp = fopen(file, "r");
|
|
if (!fp) {
|
|
fprintf(stderr, "area %s: can't open %s for reading: %s\n",
|
|
area, file, strerror(errno));
|
|
return 1;
|
|
}
|
|
|
|
n = fread(buf, 1, len, fp);
|
|
if (n == 0) {
|
|
if (feof(fp))
|
|
fprintf(stderr, "area %s: unexpected EOF on %s\n",
|
|
area, file);
|
|
if (ferror(fp))
|
|
fprintf(stderr, "area %s: can't read from %s: %s\n",
|
|
area, file, strerror(errno));
|
|
retval = 1;
|
|
} else if (n < len) {
|
|
fprintf(stderr, "Warning on area %s: only read %d "
|
|
"(not %d) from %s\n", area, n, len, file);
|
|
}
|
|
|
|
if (0 != fclose(fp)) {
|
|
fprintf(stderr, "area %s: error closing %s: %s\n",
|
|
area, file, strerror(errno));
|
|
retval = 1;
|
|
}
|
|
|
|
return retval;
|
|
}
|
|
|
|
|
|
static int do_load_fmap(int argc, char *argv[])
|
|
{
|
|
char *infile = 0;
|
|
char *outfile = 0;
|
|
uint8_t *buf;
|
|
uint32_t len;
|
|
FmapHeader *fmap;
|
|
FmapAreaHeader *ah;
|
|
int errorcnt = 0;
|
|
int fd, i;
|
|
|
|
opterr = 0; /* quiet, you */
|
|
while ((i = getopt_long(argc, argv, short_opts, long_opts, 0)) != -1) {
|
|
switch (i) {
|
|
case 'o':
|
|
outfile = optarg;
|
|
break;
|
|
case '?':
|
|
if (optopt)
|
|
fprintf(stderr, "Unrecognized option: -%c\n",
|
|
optopt);
|
|
else
|
|
fprintf(stderr, "Unrecognized option\n");
|
|
errorcnt++;
|
|
break;
|
|
case ':':
|
|
fprintf(stderr, "Missing argument to -%c\n", optopt);
|
|
errorcnt++;
|
|
break;
|
|
default:
|
|
DIE;
|
|
}
|
|
}
|
|
|
|
if (errorcnt) {
|
|
help_and_quit(argv[0]);
|
|
return 1;
|
|
}
|
|
|
|
if (argc - optind < 2) {
|
|
fprintf(stderr,
|
|
"You must specify an input file"
|
|
" and at least one AREA:file argument\n");
|
|
help_and_quit(argv[0]);
|
|
return 1;
|
|
}
|
|
|
|
infile = argv[optind++];
|
|
|
|
/* okay, let's do it ... */
|
|
if (outfile)
|
|
futil_copy_file_or_die(infile, outfile);
|
|
else
|
|
outfile = infile;
|
|
|
|
fd = open(outfile, O_RDWR);
|
|
if (fd < 0) {
|
|
fprintf(stderr, "Can't open %s: %s\n",
|
|
outfile, strerror(errno));
|
|
return 1;
|
|
}
|
|
|
|
errorcnt |= futil_map_file(fd, MAP_RW, &buf, &len);
|
|
if (errorcnt)
|
|
goto done_file;
|
|
|
|
fmap = fmap_find(buf, len);
|
|
if (!fmap) {
|
|
fprintf(stderr, "Can't find an FMAP in %s\n", infile);
|
|
errorcnt++;
|
|
goto done_map;
|
|
}
|
|
|
|
for (i = optind; i < argc; i++) {
|
|
char *a = argv[i];
|
|
char *f = strchr(a, ':');
|
|
|
|
if (!f || a == f || *(f+1) == '\0') {
|
|
fprintf(stderr, "argument \"%s\" is bogus\n", a);
|
|
errorcnt++;
|
|
break;
|
|
}
|
|
*f++ = '\0';
|
|
uint8_t *area_buf = fmap_find_by_name(buf, len, fmap, a, &ah);
|
|
if (!area_buf) {
|
|
fprintf(stderr, "Can't find area \"%s\" in FMAP\n", a);
|
|
errorcnt++;
|
|
break;
|
|
}
|
|
|
|
if (0 != copy_to_area(f, area_buf, ah->area_size, a)) {
|
|
errorcnt++;
|
|
break;
|
|
}
|
|
}
|
|
|
|
done_map:
|
|
errorcnt |= futil_unmap_file(fd, 1, buf, len);
|
|
|
|
done_file:
|
|
|
|
if (0 != close(fd)) {
|
|
fprintf(stderr, "Error closing %s: %s\n",
|
|
outfile, strerror(errno));
|
|
errorcnt++;
|
|
}
|
|
|
|
return !!errorcnt;
|
|
}
|
|
|
|
DECLARE_FUTIL_COMMAND(load_fmap, do_load_fmap,
|
|
VBOOT_VERSION_ALL,
|
|
"Replace the contents of specified FMAP areas",
|
|
help_and_quit);
|