blob: bd7abac9481a40cc4b5d932493f1628fe8efdf93 [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 Richardson60bcbe32010-09-09 14:53:56 -070020/* global variables */
21static int opt_extract = 0;
Che-Liang Chiou305e9e52011-02-17 17:56:16 +080022static char* progname;
23static void* base_of_rom;
Bill Richardson60bcbe32010-09-09 14:53:56 -070024
25
26/* Return 0 if successful */
Che-Liang Chiou305e9e52011-02-17 17:56:16 +080027static int dump_fmap(const void* ptr) {
Bill Richardson60bcbe32010-09-09 14:53:56 -070028 int i,retval = 0;
29 char buf[80]; // DWR: magic number
Che-Liang Chiou305e9e52011-02-17 17:56:16 +080030 const FmapHeader* fmh = (const FmapHeader*) ptr;
31 const FmapAreaHeader* ah = (const FmapAreaHeader*) (ptr + sizeof(FmapHeader));
Bill Richardson60bcbe32010-09-09 14:53:56 -070032
Che-Liang Chiou305e9e52011-02-17 17:56:16 +080033 snprintf(buf, FMAP_SIGNATURE_SIZE+1, "%s", fmh->fmap_signature);
Bill Richardson60bcbe32010-09-09 14:53:56 -070034 printf("fmap_signature %s\n", buf);
35 printf("fmap_version: %d.%d\n", fmh->fmap_ver_major, fmh->fmap_ver_minor);
36 printf("fmap_base: 0x%" PRIx64 "\n", fmh->fmap_base);
37 printf("fmap_size: 0x%08x (%d)\n", fmh->fmap_size, fmh->fmap_size);
38 snprintf(buf, FMAP_NAMELEN+1, "%s", fmh->fmap_name);
39 printf("fmap_name: %s\n", buf);
40 printf("fmap_nareas: %d\n", fmh->fmap_nareas);
41
42 for (i=0; i<fmh->fmap_nareas; i++) {
43 printf("area: %d\n", i+1);
44 printf("area_offset: 0x%08x\n", ah->area_offset);
45 printf("area_size: 0x%08x (%d)\n", ah->area_size, ah->area_size);
46 snprintf(buf, FMAP_NAMELEN+1, "%s", ah->area_name);
47 printf("area_name: %s\n", buf);
48
49 if (opt_extract) {
Che-Liang Chiou305e9e52011-02-17 17:56:16 +080050 char* s;
51 for (s=buf;* s; s++)
Bill Richardson60bcbe32010-09-09 14:53:56 -070052 if (*s == ' ')
Che-Liang Chiou305e9e52011-02-17 17:56:16 +080053 *s = '_';
54 FILE* fp = fopen(buf,"wb");
Bill Richardson60bcbe32010-09-09 14:53:56 -070055 if (!fp) {
56 fprintf(stderr, "%s: can't open %s: %s\n",
57 progname, buf, strerror(errno));
58 retval = 1;
59 } else {
60 if (1 != fwrite(base_of_rom + ah->area_offset, ah->area_size, 1, fp)) {
61 fprintf(stderr, "%s: can't write %s: %s\n",
62 progname, buf, strerror(errno));
63 retval = 1;
64 } else {
65 printf("saved as \"%s\"\n", buf);
66 }
67 fclose(fp);
68 }
69 }
70
71 ah++;
72 }
73
74 return retval;
75}
76
77
Che-Liang Chiou305e9e52011-02-17 17:56:16 +080078int main(int argc, char* argv[]) {
Bill Richardson60bcbe32010-09-09 14:53:56 -070079 int c;
80 int errorcnt = 0;
81 struct stat sb;
82 int fd;
Che-Liang Chiou305e9e52011-02-17 17:56:16 +080083 const char* fmap;
Bill Richardson60bcbe32010-09-09 14:53:56 -070084 int retval = 1;
85
86 progname = strrchr(argv[0], '/');
87 if (progname)
88 progname++;
89 else
90 progname = argv[0];
91
92 opterr = 0; /* quiet, you */
93 while ((c=getopt(argc, argv, ":x")) != -1) {
94 switch (c)
95 {
96 case 'x':
97 opt_extract = 1;
98 break;
99 case '?':
100 fprintf(stderr, "%s: unrecognized switch: -%c\n",
101 progname, optopt);
102 errorcnt++;
103 break;
104 case ':':
105 fprintf(stderr, "%s: missing argument to -%c\n",
106 progname, optopt);
107 errorcnt++;
108 break;
109 default:
110 errorcnt++;
111 break;
112 }
113 }
114
115 if (errorcnt || optind >= argc) {
116 fprintf(stderr,
117 "\nUsage: %s [-x] FLASHIMAGE\n\n"
118 "Display (and extract with -x) the FMAP components from a BIOS image"
119 "\n\n",
120 progname);
121 return 1;
122 }
123
124 if (0 != stat(argv[optind], &sb)) {
125 fprintf(stderr, "%s: can't stat %s: %s\n",
126 progname,
127 argv[optind],
128 strerror(errno));
129 return 1;
130 }
131
132 fd = open(argv[optind], O_RDONLY);
133 if (fd < 0) {
134 fprintf(stderr, "%s: can't open %s: %s\n",
135 progname,
136 argv[optind],
137 strerror(errno));
138 return 1;
139 }
140 printf("opened %s\n", argv[optind]);
141
142 base_of_rom = mmap(0, sb.st_size, PROT_READ, MAP_PRIVATE, fd, 0);
Che-Liang Chiou305e9e52011-02-17 17:56:16 +0800143 if (base_of_rom == (char*)-1) {
Bill Richardson60bcbe32010-09-09 14:53:56 -0700144 fprintf(stderr, "%s: can't mmap %s: %s\n",
145 progname,
146 argv[optind],
147 strerror(errno));
148 close(fd);
149 return 1;
150 }
151 close(fd); /* done with this now */
152
Che-Liang Chiou305e9e52011-02-17 17:56:16 +0800153 fmap = FmapFind((char*) base_of_rom, sb.st_size);
154 if (fmap) {
155 printf("hit at 0x%08x\n", (uint32_t) (fmap - (char*) base_of_rom));
156 retval = dump_fmap(fmap);
Bill Richardson60bcbe32010-09-09 14:53:56 -0700157 }
158
159 if (0 != munmap(base_of_rom, sb.st_size)) {
160 fprintf(stderr, "%s: can't munmap %s: %s\n",
161 progname,
162 argv[optind],
163 strerror(errno));
164 return 1;
165 }
166
167 return retval;
168}