cmd_load_fmap.c 4.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211
  1. /*
  2. * Copyright 2014 The Chromium OS Authors. All rights reserved.
  3. * Use of this source code is governed by a BSD-style license that can be
  4. * found in the LICENSE file.
  5. */
  6. #include <errno.h>
  7. #include <fcntl.h>
  8. #include <getopt.h>
  9. #include <inttypes.h>
  10. #include <limits.h>
  11. #include <stddef.h>
  12. #include <stdint.h>
  13. #include <stdio.h>
  14. #include <stdlib.h>
  15. #include <string.h>
  16. #include <sys/stat.h>
  17. #include <sys/types.h>
  18. #include <unistd.h>
  19. #include "fmap.h"
  20. #include "futility.h"
  21. static const char usage[] = "\n"
  22. "Usage: " MYNAME " %s [OPTIONS] FILE AREA:file [AREA:file ...]\n"
  23. "\n"
  24. "Replace the contents of specific FMAP areas. This is the complement\n"
  25. "of " MYNAME " dump_fmap -x FILE AREA [AREA ...]\n"
  26. "\n"
  27. "Options:\n"
  28. " -o OUTFILE Write the result to this file, instead of modifying\n"
  29. " the input file. This is safer, since there are no\n"
  30. " safeguards against doing something stupid.\n"
  31. "\n"
  32. "Example:\n"
  33. "\n"
  34. " This will clear the RO_VPD area, and scramble VBLOCK_B:\n"
  35. "\n"
  36. " " MYNAME " %s bios.bin RO_VPD:/dev/zero VBLOCK_B:/dev/urandom\n"
  37. "\n";
  38. static void print_help(int argc, char *argv[])
  39. {
  40. printf(usage, argv[0], argv[0]);
  41. }
  42. enum {
  43. OPT_HELP = 1000,
  44. };
  45. static const struct option long_opts[] = {
  46. /* name hasarg *flag val */
  47. {"help", 0, NULL, OPT_HELP},
  48. {NULL, 0, NULL, 0},
  49. };
  50. static char *short_opts = ":o:";
  51. static int copy_to_area(char *file, uint8_t *buf, uint32_t len, char *area)
  52. {
  53. FILE *fp;
  54. int retval = 0;
  55. int n;
  56. fp = fopen(file, "r");
  57. if (!fp) {
  58. fprintf(stderr, "area %s: can't open %s for reading: %s\n",
  59. area, file, strerror(errno));
  60. return 1;
  61. }
  62. n = fread(buf, 1, len, fp);
  63. if (n == 0) {
  64. if (feof(fp))
  65. fprintf(stderr, "area %s: unexpected EOF on %s\n",
  66. area, file);
  67. if (ferror(fp))
  68. fprintf(stderr, "area %s: can't read from %s: %s\n",
  69. area, file, strerror(errno));
  70. retval = 1;
  71. } else if (n < len) {
  72. fprintf(stderr, "Warning on area %s: only read %d "
  73. "(not %d) from %s\n", area, n, len, file);
  74. }
  75. if (0 != fclose(fp)) {
  76. fprintf(stderr, "area %s: error closing %s: %s\n",
  77. area, file, strerror(errno));
  78. retval = 1;
  79. }
  80. return retval;
  81. }
  82. static int do_load_fmap(int argc, char *argv[])
  83. {
  84. char *infile = 0;
  85. char *outfile = 0;
  86. uint8_t *buf;
  87. uint32_t len;
  88. FmapHeader *fmap;
  89. FmapAreaHeader *ah;
  90. int errorcnt = 0;
  91. int fd, i;
  92. opterr = 0; /* quiet, you */
  93. while ((i = getopt_long(argc, argv, short_opts, long_opts, 0)) != -1) {
  94. switch (i) {
  95. case 'o':
  96. outfile = optarg;
  97. break;
  98. case OPT_HELP:
  99. print_help(argc, argv);
  100. return !!errorcnt;
  101. case '?':
  102. if (optopt)
  103. fprintf(stderr, "Unrecognized option: -%c\n",
  104. optopt);
  105. else
  106. fprintf(stderr, "Unrecognized option\n");
  107. errorcnt++;
  108. break;
  109. case ':':
  110. fprintf(stderr, "Missing argument to -%c\n", optopt);
  111. errorcnt++;
  112. break;
  113. default:
  114. DIE;
  115. }
  116. }
  117. if (errorcnt) {
  118. print_help(argc, argv);
  119. return 1;
  120. }
  121. if (argc - optind < 2) {
  122. fprintf(stderr,
  123. "You must specify an input file"
  124. " and at least one AREA:file argument\n");
  125. print_help(argc, argv);
  126. return 1;
  127. }
  128. infile = argv[optind++];
  129. /* okay, let's do it ... */
  130. if (outfile)
  131. futil_copy_file_or_die(infile, outfile);
  132. else
  133. outfile = infile;
  134. fd = open(outfile, O_RDWR);
  135. if (fd < 0) {
  136. fprintf(stderr, "Can't open %s: %s\n",
  137. outfile, strerror(errno));
  138. return 1;
  139. }
  140. errorcnt |= futil_map_file(fd, MAP_RW, &buf, &len);
  141. if (errorcnt)
  142. goto done_file;
  143. fmap = fmap_find(buf, len);
  144. if (!fmap) {
  145. fprintf(stderr, "Can't find an FMAP in %s\n", infile);
  146. errorcnt++;
  147. goto done_map;
  148. }
  149. for (i = optind; i < argc; i++) {
  150. char *a = argv[i];
  151. char *f = strchr(a, ':');
  152. if (!f || a == f || *(f+1) == '\0') {
  153. fprintf(stderr, "argument \"%s\" is bogus\n", a);
  154. errorcnt++;
  155. break;
  156. }
  157. *f++ = '\0';
  158. uint8_t *area_buf = fmap_find_by_name(buf, len, fmap, a, &ah);
  159. if (!area_buf) {
  160. fprintf(stderr, "Can't find area \"%s\" in FMAP\n", a);
  161. errorcnt++;
  162. break;
  163. }
  164. if (0 != copy_to_area(f, area_buf, ah->area_size, a)) {
  165. errorcnt++;
  166. break;
  167. }
  168. }
  169. done_map:
  170. errorcnt |= futil_unmap_file(fd, 1, buf, len);
  171. done_file:
  172. if (0 != close(fd)) {
  173. fprintf(stderr, "Error closing %s: %s\n",
  174. outfile, strerror(errno));
  175. errorcnt++;
  176. }
  177. return !!errorcnt;
  178. }
  179. DECLARE_FUTIL_COMMAND(load_fmap, do_load_fmap, VBOOT_VERSION_ALL,
  180. "Replace the contents of specified FMAP areas");