blob: 0b88029b66999a9e80b0b7649429c632cabe026b [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)
Louis Yung-Chieh Lo9462e3e2011-08-24 12:53:43 +080057 printf("0x%08x:0x%08x %s\n", ah->area_offset,
58 ah->area_offset + ah->area_size - 1, buf);
Bill Richardson77c02432011-07-29 13:05:58 -070059 break;
60 default:
Bill Richardson9a2c3b22011-06-13 12:45:24 -070061 printf("area: %d\n", i+1);
62 printf("area_offset: 0x%08x\n", ah->area_offset);
63 printf("area_size: 0x%08x (%d)\n", ah->area_size, ah->area_size);
64 printf("area_name: %s\n", buf);
65 }
Bill Richardson60bcbe32010-09-09 14:53:56 -070066
67 if (opt_extract) {
Che-Liang Chiou305e9e52011-02-17 17:56:16 +080068 char* s;
69 for (s=buf;* s; s++)
Bill Richardson60bcbe32010-09-09 14:53:56 -070070 if (*s == ' ')
Bill Richardson9a2c3b22011-06-13 12:45:24 -070071 *s = '_';
Che-Liang Chiou305e9e52011-02-17 17:56:16 +080072 FILE* fp = fopen(buf,"wb");
Bill Richardson60bcbe32010-09-09 14:53:56 -070073 if (!fp) {
74 fprintf(stderr, "%s: can't open %s: %s\n",
75 progname, buf, strerror(errno));
76 retval = 1;
77 } else {
Bill Richardsonccdaa472011-03-03 18:08:18 -080078 if (ah->area_size &&
79 1 != fwrite(base_of_rom + ah->area_offset, ah->area_size, 1, fp)) {
Bill Richardson60bcbe32010-09-09 14:53:56 -070080 fprintf(stderr, "%s: can't write %s: %s\n",
81 progname, buf, strerror(errno));
82 retval = 1;
83 } else {
Bill Richardson77c02432011-07-29 13:05:58 -070084 if (FMT_NORMAL == opt_format)
Bill Richardson9a2c3b22011-06-13 12:45:24 -070085 printf("saved as \"%s\"\n", buf);
Bill Richardson60bcbe32010-09-09 14:53:56 -070086 }
87 fclose(fp);
88 }
89 }
90
91 ah++;
92 }
93
94 return retval;
95}
96
97
Che-Liang Chiou305e9e52011-02-17 17:56:16 +080098int main(int argc, char* argv[]) {
Bill Richardson60bcbe32010-09-09 14:53:56 -070099 int c;
100 int errorcnt = 0;
101 struct stat sb;
102 int fd;
Che-Liang Chiou305e9e52011-02-17 17:56:16 +0800103 const char* fmap;
Bill Richardson60bcbe32010-09-09 14:53:56 -0700104 int retval = 1;
105
106 progname = strrchr(argv[0], '/');
107 if (progname)
108 progname++;
109 else
110 progname = argv[0];
111
112 opterr = 0; /* quiet, you */
Bill Richardson77c02432011-07-29 13:05:58 -0700113 while ((c=getopt(argc, argv, ":xpf")) != -1) {
Bill Richardson60bcbe32010-09-09 14:53:56 -0700114 switch (c)
115 {
116 case 'x':
117 opt_extract = 1;
118 break;
Bill Richardson9a2c3b22011-06-13 12:45:24 -0700119 case 'p':
Bill Richardson77c02432011-07-29 13:05:58 -0700120 opt_format = FMT_PRETTY;
121 break;
122 case 'f':
123 opt_format = FMT_FLASHROM;
Bill Richardson9a2c3b22011-06-13 12:45:24 -0700124 break;
Bill Richardson60bcbe32010-09-09 14:53:56 -0700125 case '?':
126 fprintf(stderr, "%s: unrecognized switch: -%c\n",
127 progname, optopt);
128 errorcnt++;
129 break;
130 case ':':
131 fprintf(stderr, "%s: missing argument to -%c\n",
132 progname, optopt);
133 errorcnt++;
134 break;
135 default:
136 errorcnt++;
137 break;
138 }
139 }
140
141 if (errorcnt || optind >= argc) {
142 fprintf(stderr,
Bill Richardson77c02432011-07-29 13:05:58 -0700143 "\nUsage: %s [-x] [-p|-f] FLASHIMAGE\n\n"
Bill Richardson9a2c3b22011-06-13 12:45:24 -0700144 "Display (and extract with -x) the FMAP components from a BIOS image.\n"
145 "The -p option makes the output easier to parse by scripts.\n"
Bill Richardson77c02432011-07-29 13:05:58 -0700146 "The -f option emits the FMAP in the format used by flashrom\n"
Bill Richardson9a2c3b22011-06-13 12:45:24 -0700147 "\n",
148 progname);
Bill Richardson60bcbe32010-09-09 14:53:56 -0700149 return 1;
150 }
151
152 if (0 != stat(argv[optind], &sb)) {
153 fprintf(stderr, "%s: can't stat %s: %s\n",
154 progname,
155 argv[optind],
156 strerror(errno));
157 return 1;
158 }
159
160 fd = open(argv[optind], O_RDONLY);
161 if (fd < 0) {
162 fprintf(stderr, "%s: can't open %s: %s\n",
163 progname,
164 argv[optind],
165 strerror(errno));
166 return 1;
167 }
Bill Richardson77c02432011-07-29 13:05:58 -0700168 if (FMT_NORMAL == opt_format)
Bill Richardson9a2c3b22011-06-13 12:45:24 -0700169 printf("opened %s\n", argv[optind]);
Bill Richardson60bcbe32010-09-09 14:53:56 -0700170
171 base_of_rom = mmap(0, sb.st_size, PROT_READ, MAP_PRIVATE, fd, 0);
Che-Liang Chiou305e9e52011-02-17 17:56:16 +0800172 if (base_of_rom == (char*)-1) {
Bill Richardson60bcbe32010-09-09 14:53:56 -0700173 fprintf(stderr, "%s: can't mmap %s: %s\n",
174 progname,
175 argv[optind],
176 strerror(errno));
177 close(fd);
178 return 1;
179 }
180 close(fd); /* done with this now */
181
Che-Liang Chiou305e9e52011-02-17 17:56:16 +0800182 fmap = FmapFind((char*) base_of_rom, sb.st_size);
183 if (fmap) {
Bill Richardson77c02432011-07-29 13:05:58 -0700184 if (FMT_NORMAL == opt_format)
Bill Richardson9a2c3b22011-06-13 12:45:24 -0700185 printf("hit at 0x%08x\n", (uint32_t) (fmap - (char*) base_of_rom));
Che-Liang Chiou305e9e52011-02-17 17:56:16 +0800186 retval = dump_fmap(fmap);
Bill Richardson60bcbe32010-09-09 14:53:56 -0700187 }
188
189 if (0 != munmap(base_of_rom, sb.st_size)) {
190 fprintf(stderr, "%s: can't munmap %s: %s\n",
191 progname,
192 argv[optind],
193 strerror(errno));
194 return 1;
195 }
196
197 return retval;
198}