123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211 |
- /*
- * 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 print_help(int argc, char *argv[])
- {
- printf(usage, argv[0], argv[0]);
- }
- enum {
- OPT_HELP = 1000,
- };
- static const struct option long_opts[] = {
- /* name hasarg *flag val */
- {"help", 0, NULL, OPT_HELP},
- {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 OPT_HELP:
- print_help(argc, argv);
- return !!errorcnt;
- 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) {
- print_help(argc, argv);
- return 1;
- }
- if (argc - optind < 2) {
- fprintf(stderr,
- "You must specify an input file"
- " and at least one AREA:file argument\n");
- print_help(argc, argv);
- 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");
|