blob: c478c24e25ae6d38a9fbd0424fe8b15b19ea40ec [file] [log] [blame]
Bill Richardson60bcbe32010-09-09 14:53:56 -07001/*
Che-Liang Chiou305e9e52011-02-17 17:56:16 +08002 * Copyright (c) 2011 The Chromium OS Authors. All rights reserved.
Bill Richardson60bcbe32010-09-09 14:53:56 -07003 * 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 <inttypes.h>
9#include <stdint.h>
10#include <stdio.h>
11#include <stdlib.h>
12#include <string.h>
13#include <sys/mman.h>
14#include <sys/stat.h>
15#include <sys/types.h>
16#include <unistd.h>
17
Che-Liang Chiou305e9e52011-02-17 17:56:16 +080018#include "fmap.h"
19
Bill Richardson77c02432011-07-29 13:05:58 -070020enum { FMT_NORMAL, FMT_PRETTY, FMT_FLASHROM };
21
Bill Richardson60bcbe32010-09-09 14:53:56 -070022/* global variables */
23static int opt_extract = 0;
Bill Richardson77c02432011-07-29 13:05:58 -070024static int opt_format = FMT_NORMAL;
Che-Liang Chiou305e9e52011-02-17 17:56:16 +080025static char* progname;
26static void* base_of_rom;
Bill Richardson60bcbe32010-09-09 14:53:56 -070027
28
29/* Return 0 if successful */
Che-Liang Chiou305e9e52011-02-17 17:56:16 +080030static int dump_fmap(const void* ptr) {
Bill Richardson60bcbe32010-09-09 14:53:56 -070031 int i,retval = 0;
32 char buf[80]; // DWR: magic number
Che-Liang Chiou305e9e52011-02-17 17:56:16 +080033 const FmapHeader* fmh = (const FmapHeader*) ptr;
34 const FmapAreaHeader* ah = (const FmapAreaHeader*) (ptr + sizeof(FmapHeader));
Bill Richardson60bcbe32010-09-09 14:53:56 -070035
Bill Richardson77c02432011-07-29 13:05:58 -070036 if (FMT_NORMAL == opt_format) {
Bill Richardson9a2c3b22011-06-13 12:45:24 -070037 snprintf(buf, FMAP_SIGNATURE_SIZE+1, "%s", fmh->fmap_signature);
38 printf("fmap_signature %s\n", buf);
39 printf("fmap_version: %d.%d\n",
40 fmh->fmap_ver_major, fmh->fmap_ver_minor);
41 printf("fmap_base: 0x%" PRIx64 "\n", fmh->fmap_base);
42 printf("fmap_size: 0x%08x (%d)\n", fmh->fmap_size, fmh->fmap_size);
43 snprintf(buf, FMAP_NAMELEN+1, "%s", fmh->fmap_name);
44 printf("fmap_name: %s\n", buf);
45 printf("fmap_nareas: %d\n", fmh->fmap_nareas);
46 }
Bill Richardson60bcbe32010-09-09 14:53:56 -070047
48 for (i=0; i<fmh->fmap_nareas; i++) {
Bill Richardson77c02432011-07-29 13:05:58 -070049 snprintf(buf, FMAP_NAMELEN+1, "%s", ah->area_name);
50 switch(opt_format)
51 {
52 case FMT_PRETTY:
Bill Richardson9a2c3b22011-06-13 12:45:24 -070053 printf("%s %d %d\n", buf, ah->area_offset, ah->area_size);
Bill Richardson77c02432011-07-29 13:05:58 -070054 break;
55 case FMT_FLASHROM:
56 if (ah->area_size)
57 printf("0x%08x:0x%08x %s\n", ah->area_offset, ah->area_size - 1, buf);
58 break;
59 default:
Bill Richardson9a2c3b22011-06-13 12:45:24 -070060 printf("area: %d\n", i+1);
61 printf("area_offset: 0x%08x\n", ah->area_offset);
62 printf("area_size: 0x%08x (%d)\n", ah->area_size, ah->area_size);
63 printf("area_name: %s\n", buf);
64 }
Bill Richardson60bcbe32010-09-09 14:53:56 -070065
66 if (opt_extract) {
Che-Liang Chiou305e9e52011-02-17 17:56:16 +080067 char* s;
68 for (s=buf;* s; s++)
Bill Richardson60bcbe32010-09-09 14:53:56 -070069 if (*s == ' ')
Bill Richardson9a2c3b22011-06-13 12:45:24 -070070 *s = '_';
Che-Liang Chiou305e9e52011-02-17 17:56:16 +080071 FILE* fp = fopen(buf,"wb");
Bill Richardson60bcbe32010-09-09 14:53:56 -070072 if (!fp) {
73 fprintf(stderr, "%s: can't open %s: %s\n",
74 progname, buf, strerror(errno));
75 retval = 1;
76 } else {
Bill Richardsonccdaa472011-03-03 18:08:18 -080077 if (ah->area_size &&
78 1 != fwrite(base_of_rom + ah->area_offset, ah->area_size, 1, fp)) {
Bill Richardson60bcbe32010-09-09 14:53:56 -070079 fprintf(stderr, "%s: can't write %s: %s\n",
80 progname, buf, strerror(errno));
81 retval = 1;
82 } else {
Bill Richardson77c02432011-07-29 13:05:58 -070083 if (FMT_NORMAL == opt_format)
Bill Richardson9a2c3b22011-06-13 12:45:24 -070084 printf("saved as \"%s\"\n", buf);
Bill Richardson60bcbe32010-09-09 14:53:56 -070085 }
86 fclose(fp);
87 }
88 }
89
90 ah++;
91 }
92
93 return retval;
94}
95
96
Che-Liang Chiou305e9e52011-02-17 17:56:16 +080097int main(int argc, char* argv[]) {
Bill Richardson60bcbe32010-09-09 14:53:56 -070098 int c;
99 int errorcnt = 0;
100 struct stat sb;
101 int fd;
Che-Liang Chiou305e9e52011-02-17 17:56:16 +0800102 const char* fmap;
Bill Richardson60bcbe32010-09-09 14:53:56 -0700103 int retval = 1;
104
105 progname = strrchr(argv[0], '/');
106 if (progname)
107 progname++;
108 else
109 progname = argv[0];
110
111 opterr = 0; /* quiet, you */
Bill Richardson77c02432011-07-29 13:05:58 -0700112 while ((c=getopt(argc, argv, ":xpf")) != -1) {
Bill Richardson60bcbe32010-09-09 14:53:56 -0700113 switch (c)
114 {
115 case 'x':
116 opt_extract = 1;
117 break;
Bill Richardson9a2c3b22011-06-13 12:45:24 -0700118 case 'p':
Bill Richardson77c02432011-07-29 13:05:58 -0700119 opt_format = FMT_PRETTY;
120 break;
121 case 'f':
122 opt_format = FMT_FLASHROM;
Bill Richardson9a2c3b22011-06-13 12:45:24 -0700123 break;
Bill Richardson60bcbe32010-09-09 14:53:56 -0700124 case '?':
125 fprintf(stderr, "%s: unrecognized switch: -%c\n",
126 progname, optopt);
127 errorcnt++;
128 break;
129 case ':':
130 fprintf(stderr, "%s: missing argument to -%c\n",
131 progname, optopt);
132 errorcnt++;
133 break;
134 default:
135 errorcnt++;
136 break;
137 }
138 }
139
140 if (errorcnt || optind >= argc) {
141 fprintf(stderr,
Bill Richardson77c02432011-07-29 13:05:58 -0700142 "\nUsage: %s [-x] [-p|-f] FLASHIMAGE\n\n"
Bill Richardson9a2c3b22011-06-13 12:45:24 -0700143 "Display (and extract with -x) the FMAP components from a BIOS image.\n"
144 "The -p option makes the output easier to parse by scripts.\n"
Bill Richardson77c02432011-07-29 13:05:58 -0700145 "The -f option emits the FMAP in the format used by flashrom\n"
Bill Richardson9a2c3b22011-06-13 12:45:24 -0700146 "\n",
147 progname);
Bill Richardson60bcbe32010-09-09 14:53:56 -0700148 return 1;
149 }
150
151 if (0 != stat(argv[optind], &sb)) {
152 fprintf(stderr, "%s: can't stat %s: %s\n",
153 progname,
154 argv[optind],
155 strerror(errno));
156 return 1;
157 }
158
159 fd = open(argv[optind], O_RDONLY);
160 if (fd < 0) {
161 fprintf(stderr, "%s: can't open %s: %s\n",
162 progname,
163 argv[optind],
164 strerror(errno));
165 return 1;
166 }
Bill Richardson77c02432011-07-29 13:05:58 -0700167 if (FMT_NORMAL == opt_format)
Bill Richardson9a2c3b22011-06-13 12:45:24 -0700168 printf("opened %s\n", argv[optind]);
Bill Richardson60bcbe32010-09-09 14:53:56 -0700169
170 base_of_rom = mmap(0, sb.st_size, PROT_READ, MAP_PRIVATE, fd, 0);
Che-Liang Chiou305e9e52011-02-17 17:56:16 +0800171 if (base_of_rom == (char*)-1) {
Bill Richardson60bcbe32010-09-09 14:53:56 -0700172 fprintf(stderr, "%s: can't mmap %s: %s\n",
173 progname,
174 argv[optind],
175 strerror(errno));
176 close(fd);
177 return 1;
178 }
179 close(fd); /* done with this now */
180
Che-Liang Chiou305e9e52011-02-17 17:56:16 +0800181 fmap = FmapFind((char*) base_of_rom, sb.st_size);
182 if (fmap) {
Bill Richardson77c02432011-07-29 13:05:58 -0700183 if (FMT_NORMAL == opt_format)
Bill Richardson9a2c3b22011-06-13 12:45:24 -0700184 printf("hit at 0x%08x\n", (uint32_t) (fmap - (char*) base_of_rom));
Che-Liang Chiou305e9e52011-02-17 17:56:16 +0800185 retval = dump_fmap(fmap);
Bill Richardson60bcbe32010-09-09 14:53:56 -0700186 }
187
188 if (0 != munmap(base_of_rom, sb.st_size)) {
189 fprintf(stderr, "%s: can't munmap %s: %s\n",
190 progname,
191 argv[optind],
192 strerror(errno));
193 return 1;
194 }
195
196 return retval;
197}