blob: 6b520628f1414d7eaf67e47446dcc364563f4681 [file] [log] [blame]
Ronald G. Minnich5d01ec02009-03-31 11:57:36 +00001/*
Patrick Georgib7b56dd82009-09-14 13:29:27 +00002 * cbfstool, CLI utility for CBFS file manipulation
Ronald G. Minnich5d01ec02009-03-31 11:57:36 +00003 *
Patrick Georgib7b56dd82009-09-14 13:29:27 +00004 * Copyright (C) 2009 coresystems GmbH
5 * written by Patrick Georgi <patrick.georgi@coresystems.de>
David Hendricks90ca3b62012-11-16 14:48:22 -08006 * Copyright (C) 2012 Google, Inc.
Ronald G. Minnich5d01ec02009-03-31 11:57:36 +00007 *
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation; version 2 of the License.
11 *
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License
18 * along with this program; if not, write to the Free Software
19 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA, 02110-1301 USA
20 */
21
Patrick Georgib7b56dd82009-09-14 13:29:27 +000022#include <stdio.h>
Stefan Reinauera1e48242011-10-21 14:24:57 -070023#include <stdlib.h>
Stefan Reinauer336daa72009-12-21 15:09:01 +000024#include <string.h>
Stefan Reinauera1e48242011-10-21 14:24:57 -070025#include <ctype.h>
Stefan Reinauer63217582012-10-29 16:52:36 -070026#include <unistd.h>
27#include <getopt.h>
Patrick Georgib7b56dd82009-09-14 13:29:27 +000028#include "common.h"
29#include "cbfs.h"
Ronald G. Minnich5d01ec02009-03-31 11:57:36 +000030
Stefan Reinauer3fec29c2009-09-22 15:58:19 +000031struct command {
Stefan Reinauer3fec29c2009-09-22 15:58:19 +000032 const char *name;
Stefan Reinauer63217582012-10-29 16:52:36 -070033 const char *optstring;
34 int (*function) (void);
Stefan Reinauer3fec29c2009-09-22 15:58:19 +000035};
36
Stefan Reinauer63217582012-10-29 16:52:36 -070037int verbose = 0;
38static char *cbfs_name = NULL;
39static char *rom_name = NULL;
40static char *rom_filename = NULL;
41static char *rom_bootblock = NULL;
42static uint32_t rom_type = 0;
43static uint32_t rom_baseaddress = 0;
44static uint32_t rom_loadaddress = 0;
45static uint32_t rom_entrypoint = 0;
46static uint32_t rom_size = 0;
47static uint32_t rom_alignment = 0;
48static uint32_t rom_offset = 0;
49static comp_algo rom_algo = CBFS_COMPRESS_NONE;
50
51static int cbfs_add(void)
Ronald G. Minnich5d01ec02009-03-31 11:57:36 +000052{
Patrick Georgib7b56dd82009-09-14 13:29:27 +000053 uint32_t filesize = 0;
Stefan Reinauer63217582012-10-29 16:52:36 -070054 void *rom, *filedata, *cbfsfile;
55
56 if (!rom_filename) {
57 fprintf(stderr, "E: You need to specify -f/--filename.\n");
58 return 1;
59 }
60
61 if (!rom_name) {
62 fprintf(stderr, "E: You need to specify -n/--name.\n");
63 return 1;
64 }
65
66 if (rom_type == 0) {
67 fprintf(stderr, "E: You need to specify a valid -t/--type.\n");
68 return 1;
69 }
70
71 rom = loadrom(cbfs_name);
72 if (rom == NULL) {
73 fprintf(stderr, "E: Could not load ROM image '%s'.\n",
74 cbfs_name);
75 return 1;
76 }
77
78 filedata = loadfile(rom_filename, &filesize, 0, SEEK_SET);
Patrick Georgi45d8a832009-09-15 08:21:46 +000079 if (filedata == NULL) {
Stefan Reinauer63217582012-10-29 16:52:36 -070080 fprintf(stderr, "E: Could not load file '%s'.\n",
81 rom_filename);
82 free(rom);
Patrick Georgi45d8a832009-09-15 08:21:46 +000083 return 1;
84 }
Ronald G. Minnich5d01ec02009-03-31 11:57:36 +000085
Stefan Reinauer63217582012-10-29 16:52:36 -070086 cbfsfile = create_cbfs_file(rom_name, filedata, &filesize,
87 rom_type, &rom_baseaddress);
88 free(filedata);
Patrick Georgib7b56dd82009-09-14 13:29:27 +000089
Stefan Reinauer63217582012-10-29 16:52:36 -070090 if (add_file_to_cbfs(cbfsfile, filesize, rom_baseaddress)) {
91 fprintf(stderr, "E: Adding file '%s' failed.\n", rom_filename);
92 free(cbfsfile);
93 free(rom);
Stefan Reinauer3fec29c2009-09-22 15:58:19 +000094 return 1;
95 }
Stefan Reinauer63217582012-10-29 16:52:36 -070096 if (writerom(cbfs_name, rom, romsize)) {
97 free(cbfsfile);
98 free(rom);
Patrick Georgi56f5fb72009-09-30 11:21:18 +000099 return 1;
Stefan Reinauerfbadc492011-10-14 12:44:14 -0700100 }
Stefan Reinauer63217582012-10-29 16:52:36 -0700101
102 free(cbfsfile);
103 free(rom);
Stefan Reinauer3fec29c2009-09-22 15:58:19 +0000104 return 0;
105}
106
Stefan Reinauer63217582012-10-29 16:52:36 -0700107static int cbfs_add_payload(void)
Stefan Reinauer3fec29c2009-09-22 15:58:19 +0000108{
Stefan Reinauercf5aaaf2012-12-11 17:35:30 -0800109 int32_t filesize = 0;
Stefan Reinauer63217582012-10-29 16:52:36 -0700110 void *rom, *filedata, *cbfsfile;
Stefan Reinauer3fec29c2009-09-22 15:58:19 +0000111 unsigned char *payload;
Stefan Reinauer63217582012-10-29 16:52:36 -0700112
113 if (!rom_filename) {
114 fprintf(stderr, "E: You need to specify -f/--filename.\n");
Patrick Georgi56f5fb72009-09-30 11:21:18 +0000115 return 1;
Stefan Reinauerfbadc492011-10-14 12:44:14 -0700116 }
Stefan Reinauer63217582012-10-29 16:52:36 -0700117
118 if (!rom_name) {
119 fprintf(stderr, "E: You need to specify -n/--name.\n");
Stefan Reinauer9bb043852010-06-24 13:37:59 +0000120 return 1;
Stefan Reinauer63217582012-10-29 16:52:36 -0700121 }
Stefan Reinauer3fec29c2009-09-22 15:58:19 +0000122
Stefan Reinauer63217582012-10-29 16:52:36 -0700123 rom = loadrom(cbfs_name);
Stefan Reinauer3fec29c2009-09-22 15:58:19 +0000124 if (rom == NULL) {
Stefan Reinauer63217582012-10-29 16:52:36 -0700125 fprintf(stderr, "E: Could not load ROM image '%s'.\n",
126 cbfs_name);
Stefan Reinauer3fec29c2009-09-22 15:58:19 +0000127 return 1;
128 }
129
Stefan Reinauer63217582012-10-29 16:52:36 -0700130 filedata = loadfile(rom_filename, &filesize, 0, SEEK_SET);
Stefan Reinauer3fec29c2009-09-22 15:58:19 +0000131 if (filedata == NULL) {
Stefan Reinauer63217582012-10-29 16:52:36 -0700132 fprintf(stderr, "E: Could not load file '%s'.\n",
133 rom_filename);
134 free(rom);
Stefan Reinauer3fec29c2009-09-22 15:58:19 +0000135 return 1;
136 }
137
Stefan Reinauer63217582012-10-29 16:52:36 -0700138 filesize = parse_elf_to_payload(filedata, &payload, rom_algo);
Stefan Reinauercf5aaaf2012-12-11 17:35:30 -0800139 if (filesize <= 0) {
140 fprintf(stderr, "E: Adding payload '%s' failed.\n",
141 rom_filename);
142 free(rom);
143 return 1;
144 }
Stefan Reinauer3fec29c2009-09-22 15:58:19 +0000145
Stefan Reinauer63217582012-10-29 16:52:36 -0700146 cbfsfile = create_cbfs_file(rom_name, payload, &filesize,
147 CBFS_COMPONENT_PAYLOAD, &rom_baseaddress);
Stefan Reinauer3fec29c2009-09-22 15:58:19 +0000148
Stefan Reinauer63217582012-10-29 16:52:36 -0700149 free(filedata);
150 free(payload);
151
152 if (add_file_to_cbfs(cbfsfile, filesize, rom_baseaddress)) {
153 fprintf(stderr, "E: Adding payload '%s' failed.\n",
154 rom_filename);
155 free(cbfsfile);
156 free(rom);
Patrick Georgi56f5fb72009-09-30 11:21:18 +0000157 return 1;
Stefan Reinauerfbadc492011-10-14 12:44:14 -0700158 }
Stefan Reinauer63217582012-10-29 16:52:36 -0700159
160 if (writerom(cbfs_name, rom, romsize)) {
161 free(cbfsfile);
162 free(rom);
Stefan Reinauer9bb043852010-06-24 13:37:59 +0000163 return 1;
Stefan Reinauer63217582012-10-29 16:52:36 -0700164 }
165
166 free(cbfsfile);
167 free(rom);
Patrick Georgib7b56dd82009-09-14 13:29:27 +0000168 return 0;
Ronald G. Minnich5d01ec02009-03-31 11:57:36 +0000169}
Stefan Reinauer3fec29c2009-09-22 15:58:19 +0000170
Stefan Reinauer63217582012-10-29 16:52:36 -0700171static int cbfs_add_stage(void)
Stefan Reinauer20848ee2012-10-22 16:04:13 -0700172{
Stefan Reinauer63217582012-10-29 16:52:36 -0700173 uint32_t filesize = 0;
174 void *rom, *filedata, *cbfsfile;
175 unsigned char *stage;
Stefan Reinauer20848ee2012-10-22 16:04:13 -0700176
Stefan Reinauer63217582012-10-29 16:52:36 -0700177 if (!rom_filename) {
178 fprintf(stderr, "E: You need to specify -f/--filename.\n");
179 return 1;
180 }
181
182 if (!rom_name) {
183 fprintf(stderr, "E: You need to specify -n/--name.\n");
184 return 1;
185 }
186
187 rom = loadrom(cbfs_name);
Stefan Reinauer20848ee2012-10-22 16:04:13 -0700188 if (rom == NULL) {
Stefan Reinauer63217582012-10-29 16:52:36 -0700189 fprintf(stderr, "E: Could not load ROM image '%s'.\n",
190 cbfs_name);
Stefan Reinauer20848ee2012-10-22 16:04:13 -0700191 return 1;
192 }
193
Stefan Reinauer63217582012-10-29 16:52:36 -0700194 filedata = loadfile(rom_filename, &filesize, 0, SEEK_SET);
195 if (filedata == NULL) {
196 fprintf(stderr, "E: Could not load file '%s'.\n",
197 rom_filename);
198 free(rom);
Stefan Reinauer20848ee2012-10-22 16:04:13 -0700199 return 1;
200 }
201
Stefan Reinauer63217582012-10-29 16:52:36 -0700202 filesize = parse_elf_to_stage(filedata, &stage, rom_algo, &rom_baseaddress);
Stefan Reinauer20848ee2012-10-22 16:04:13 -0700203
Stefan Reinauer63217582012-10-29 16:52:36 -0700204 cbfsfile = create_cbfs_file(rom_name, stage, &filesize,
205 CBFS_COMPONENT_STAGE, &rom_baseaddress);
Stefan Reinauer20848ee2012-10-22 16:04:13 -0700206
Stefan Reinauer63217582012-10-29 16:52:36 -0700207 free(filedata);
208 free(stage);
209
210 if (add_file_to_cbfs(cbfsfile, filesize, rom_baseaddress)) {
211 fprintf(stderr, "E: Adding stage '%s' failed.\n",
212 rom_filename);
213 free(cbfsfile);
214 free(rom);
215 return 1;
Stefan Reinauer20848ee2012-10-22 16:04:13 -0700216 }
Stefan Reinauer63217582012-10-29 16:52:36 -0700217
218 if (writerom(cbfs_name, rom, romsize)) {
219 free(cbfsfile);
220 free(rom);
221 return 1;
Stefan Reinauer20848ee2012-10-22 16:04:13 -0700222 }
Stefan Reinauer63217582012-10-29 16:52:36 -0700223
224 free(cbfsfile);
225 free(rom);
226 return 0;
227}
228
229static int cbfs_add_flat_binary(void)
230{
231 uint32_t filesize = 0;
232 uint32_t final_size;
233 void *rom, *filedata, *cbfsfile;
234 unsigned char *payload;
235 comp_func_ptr compress;
236 struct cbfs_payload_segment *segs;
237 int doffset, len = 0;
238
239 if (!rom_filename) {
240 fprintf(stderr, "E: You need to specify -f/--filename.\n");
241 return 1;
242 }
243
244 if (!rom_name) {
245 fprintf(stderr, "E: You need to specify -n/--name.\n");
246 return 1;
247 }
248
249 if (rom_loadaddress == 0) {
250 fprintf(stderr, "E: You need to specify a valid "
251 "-l/--load-address.\n");
252 return 1;
253 }
254
255 if (rom_entrypoint == 0) {
Stefan Reinauer0a977592012-11-30 11:21:05 -0800256 fprintf(stderr, "E: You need to specify a valid "
Stefan Reinauer63217582012-10-29 16:52:36 -0700257 "-e/--entry-point.\n");
258 return 1;
259 }
260
261 compress = compression_function(rom_algo);
Stefan Reinauer20848ee2012-10-22 16:04:13 -0700262 if (!compress)
263 return 1;
264
Stefan Reinauer63217582012-10-29 16:52:36 -0700265 rom = loadrom(cbfs_name);
266 if (rom == NULL) {
Stefan Reinauer0a977592012-11-30 11:21:05 -0800267 fprintf(stderr, "E: Could not load ROM image '%s'.\n",
Stefan Reinauer63217582012-10-29 16:52:36 -0700268 cbfs_name);
Stefan Reinauer20848ee2012-10-22 16:04:13 -0700269 return 1;
270 }
271
Stefan Reinauer63217582012-10-29 16:52:36 -0700272 filedata = loadfile(rom_filename, &filesize, 0, SEEK_SET);
273 if (filedata == NULL) {
274 fprintf(stderr, "E: Could not load file '%s'.\n",
275 rom_filename);
276 free(rom);
277 return 1;
278 }
279
280 /* FIXME compressed file size might be bigger than original file */
Stefan Reinauer20848ee2012-10-22 16:04:13 -0700281 payload = calloc((2 * sizeof(struct cbfs_payload_segment)) + filesize, 1);
282 if (payload == NULL) {
Stefan Reinauer63217582012-10-29 16:52:36 -0700283 fprintf(stderr, "E: Could not allocate memory.\n");
284 free(filedata);
285 free(rom);
Stefan Reinauer20848ee2012-10-22 16:04:13 -0700286 return 1;
287 }
288
Stefan Reinauer20848ee2012-10-22 16:04:13 -0700289 segs = (struct cbfs_payload_segment *)payload;
Stefan Reinauer63217582012-10-29 16:52:36 -0700290 doffset = (2 * sizeof(struct cbfs_payload_segment));
Stefan Reinauer20848ee2012-10-22 16:04:13 -0700291
Stefan Reinauer63217582012-10-29 16:52:36 -0700292 /* Prepare code segment */
Stefan Reinauer20848ee2012-10-22 16:04:13 -0700293 segs[0].type = PAYLOAD_SEGMENT_CODE;
Stefan Reinauer63217582012-10-29 16:52:36 -0700294 segs[0].load_addr = (uint64_t)htonll(rom_loadaddress);
Stefan Reinauer20848ee2012-10-22 16:04:13 -0700295 segs[0].mem_len = (uint32_t)htonl(filesize);
Stefan Reinauer63217582012-10-29 16:52:36 -0700296 segs[0].offset = (uint32_t)htonl(doffset);
Stefan Reinauer20848ee2012-10-22 16:04:13 -0700297
298 compress(filedata, filesize, (char *)(payload + doffset), &len);
Stefan Reinauer63217582012-10-29 16:52:36 -0700299 segs[0].compression = htonl(rom_algo);
Stefan Reinauer20848ee2012-10-22 16:04:13 -0700300 segs[0].len = htonl(len);
301
Stefan Reinauer63217582012-10-29 16:52:36 -0700302 if ((unsigned int)len >= filesize) {
Stefan Reinauer20848ee2012-10-22 16:04:13 -0700303 segs[0].compression = 0;
304 segs[0].len = htonl(filesize);
305 memcpy((char *)(payload + doffset), filedata, filesize);
306 }
Stefan Reinauer20848ee2012-10-22 16:04:13 -0700307
Stefan Reinauer63217582012-10-29 16:52:36 -0700308 /* prepare entry point segment */
Stefan Reinauer20848ee2012-10-22 16:04:13 -0700309 segs[1].type = PAYLOAD_SEGMENT_ENTRY;
Stefan Reinauer63217582012-10-29 16:52:36 -0700310 segs[1].load_addr = (uint64_t)htonll(rom_entrypoint);
Stefan Reinauer20848ee2012-10-22 16:04:13 -0700311
Stefan Reinauer63217582012-10-29 16:52:36 -0700312 final_size = doffset + ntohl(segs[0].len);
Stefan Reinauer20848ee2012-10-22 16:04:13 -0700313 cbfsfile =
Stefan Reinauer63217582012-10-29 16:52:36 -0700314 create_cbfs_file(rom_name, payload, &final_size,
315 CBFS_COMPONENT_PAYLOAD, &rom_baseaddress);
316
317 free(filedata);
318 free(payload);
319
320 if (add_file_to_cbfs(cbfsfile, final_size, rom_baseaddress)) {
321 fprintf(stderr, "E: Adding payload '%s' failed.\n",
322 rom_filename);
323 free(cbfsfile);
324 free(rom);
Stefan Reinauer20848ee2012-10-22 16:04:13 -0700325 return 1;
326 }
Stefan Reinauer63217582012-10-29 16:52:36 -0700327 if (writerom(cbfs_name, rom, romsize)) {
328 free(cbfsfile);
329 free(rom);
Stefan Reinauer20848ee2012-10-22 16:04:13 -0700330 return 1;
Stefan Reinauer63217582012-10-29 16:52:36 -0700331 }
332
333 free(cbfsfile);
334 free(rom);
Stefan Reinauer20848ee2012-10-22 16:04:13 -0700335 return 0;
336}
337
Stefan Reinauer63217582012-10-29 16:52:36 -0700338static int cbfs_remove(void)
Gabe Blacke1bb49e2012-01-27 00:33:47 -0800339{
Stefan Reinauer63217582012-10-29 16:52:36 -0700340 void *rom;
Gabe Blacke1bb49e2012-01-27 00:33:47 -0800341
Stefan Reinauer63217582012-10-29 16:52:36 -0700342 if (!rom_name) {
343 fprintf(stderr, "E: You need to specify -n/--name.\n");
344 return 1;
345 }
346
347 rom = loadrom(cbfs_name);
Gabe Blacke1bb49e2012-01-27 00:33:47 -0800348 if (rom == NULL) {
Stefan Reinauer63217582012-10-29 16:52:36 -0700349 fprintf(stderr, "E: Could not load ROM image '%s'.\n",
350 cbfs_name);
Gabe Blacke1bb49e2012-01-27 00:33:47 -0800351 return 1;
352 }
353
Stefan Reinauer63217582012-10-29 16:52:36 -0700354 if (remove_file_from_cbfs(rom_name)) {
355 fprintf(stderr, "E: Removing file '%s' failed.\n",
356 rom_name);
357 free(rom);
Gabe Blacke1bb49e2012-01-27 00:33:47 -0800358 return 1;
359 }
360
Stefan Reinauer63217582012-10-29 16:52:36 -0700361 if (writerom(cbfs_name, rom, romsize)) {
362 free(rom);
Gabe Blacke1bb49e2012-01-27 00:33:47 -0800363 return 1;
364 }
Stefan Reinauer63217582012-10-29 16:52:36 -0700365
366 free(rom);
Gabe Blacke1bb49e2012-01-27 00:33:47 -0800367 return 0;
368}
369
Stefan Reinauer63217582012-10-29 16:52:36 -0700370static int cbfs_create(void)
Stefan Reinauer3fec29c2009-09-22 15:58:19 +0000371{
Stefan Reinauer63217582012-10-29 16:52:36 -0700372 if (rom_size == 0) {
Stefan Reinauer0a977592012-11-30 11:21:05 -0800373 fprintf(stderr, "E: You need to specify a valid -s/--size.\n");
Stefan Reinauer3fec29c2009-09-22 15:58:19 +0000374 return 1;
375 }
376
Stefan Reinauer63217582012-10-29 16:52:36 -0700377 if (!rom_bootblock) {
Stefan Reinauer0a977592012-11-30 11:21:05 -0800378 fprintf(stderr, "E: You need to specify -b/--bootblock.\n");
Stefan Reinauer63217582012-10-29 16:52:36 -0700379 return 1;
Patrick Georgi467b12a2009-12-21 13:50:37 +0000380 }
Stefan Reinauer3fec29c2009-09-22 15:58:19 +0000381
David Hendricks90ca3b62012-11-16 14:48:22 -0800382 if (arch == CBFS_ARCHITECTURE_UNKNOWN) {
383 fprintf(stderr, "E: You need to specify -m/--machine arch\n");
384 return 1;
385 }
386
Stefan Reinauer63217582012-10-29 16:52:36 -0700387 return create_cbfs_image(cbfs_name, rom_size, rom_bootblock,
388 rom_alignment, rom_offset);
Stefan Reinauer3fec29c2009-09-22 15:58:19 +0000389}
390
Stefan Reinauer63217582012-10-29 16:52:36 -0700391static int cbfs_locate(void)
Patrick Georgi0da38dd2009-11-09 17:18:02 +0000392{
Stefan Reinauer63217582012-10-29 16:52:36 -0700393 uint32_t filesize, location;
394
395 if (!rom_filename) {
396 fprintf(stderr, "E: You need to specify -f/--filename.\n");
Patrick Georgi0da38dd2009-11-09 17:18:02 +0000397 return 1;
398 }
399
Stefan Reinauer63217582012-10-29 16:52:36 -0700400 if (!rom_name) {
401 fprintf(stderr, "E: You need to specify -n/--name.\n");
402 return 1;
403 }
404
405 filesize = getfilesize(rom_filename);
406
407 location = cbfs_find_location(cbfs_name, filesize,
408 rom_name, rom_alignment);
Patrick Georgi0da38dd2009-11-09 17:18:02 +0000409
zbao93dd07f2012-02-17 21:44:09 +0800410 printf("%x\n", location);
411 return location == 0 ? 1 : 0;
Patrick Georgi0da38dd2009-11-09 17:18:02 +0000412}
413
Stefan Reinauer63217582012-10-29 16:52:36 -0700414static int cbfs_print(void)
Stefan Reinauer3fec29c2009-09-22 15:58:19 +0000415{
Stefan Reinauer63217582012-10-29 16:52:36 -0700416 void *rom;
Stefan Reinauer3fec29c2009-09-22 15:58:19 +0000417
Stefan Reinauer63217582012-10-29 16:52:36 -0700418 rom = loadrom(cbfs_name);
Stefan Reinauer3fec29c2009-09-22 15:58:19 +0000419 if (rom == NULL) {
Stefan Reinauer63217582012-10-29 16:52:36 -0700420 fprintf(stderr, "E: Could not load ROM image '%s'.\n",
421 cbfs_name);
Stefan Reinauer3fec29c2009-09-22 15:58:19 +0000422 return 1;
423 }
424
Stefan Reinauer63217582012-10-29 16:52:36 -0700425 print_cbfs_directory(cbfs_name);
426
427 free(rom);
Stefan Reinauer3fec29c2009-09-22 15:58:19 +0000428 return 0;
429}
430
Stefan Reinauer63217582012-10-29 16:52:36 -0700431static int cbfs_extract(void)
Aurelien Guillaumefe7d6b92011-01-13 09:09:21 +0000432{
Stefan Reinauer63217582012-10-29 16:52:36 -0700433 void *rom;
434 int ret;
Aurelien Guillaumefe7d6b92011-01-13 09:09:21 +0000435
Stefan Reinauer63217582012-10-29 16:52:36 -0700436 if (!rom_filename) {
437 fprintf(stderr, "E: You need to specify -f/--filename.\n");
438 return 1;
439 }
440
441 if (!rom_name) {
442 fprintf(stderr, "E: You need to specify -n/--name.\n");
443 return 1;
444 }
445
446 rom = loadrom(cbfs_name);
Aurelien Guillaumefe7d6b92011-01-13 09:09:21 +0000447 if (rom == NULL) {
Stefan Reinauer63217582012-10-29 16:52:36 -0700448 fprintf(stderr, "E: Could not load ROM image '%s'.\n",
449 cbfs_name);
Aurelien Guillaumefe7d6b92011-01-13 09:09:21 +0000450 return 1;
451 }
452
Stefan Reinauer63217582012-10-29 16:52:36 -0700453 ret = extract_file_from_cbfs(cbfs_name, rom_name, rom_filename);
Aurelien Guillaumefe7d6b92011-01-13 09:09:21 +0000454
Stefan Reinauer63217582012-10-29 16:52:36 -0700455 free(rom);
456 return ret;
Aurelien Guillaumefe7d6b92011-01-13 09:09:21 +0000457}
458
Stefan Reinauera1e48242011-10-21 14:24:57 -0700459static const struct command commands[] = {
Stefan Reinauer63217582012-10-29 16:52:36 -0700460 {"add", "f:n:t:b:h?", cbfs_add},
461 {"add-payload", "f:n:t:c:b:h?", cbfs_add_payload},
462 {"add-stage", "f:n:t:c:b:h?", cbfs_add_stage},
463 {"add-flat-binary", "f:n:l:e:c:b:h?", cbfs_add_flat_binary},
464 {"remove", "n:h?", cbfs_remove},
David Hendricks90ca3b62012-11-16 14:48:22 -0800465 {"create", "s:B:a:o:m:h?", cbfs_create},
Stefan Reinauer63217582012-10-29 16:52:36 -0700466 {"locate", "f:n:a:h?", cbfs_locate},
467 {"print", "h?", cbfs_print},
468 {"extract", "n:f:h?", cbfs_extract},
Stefan Reinauer3fec29c2009-09-22 15:58:19 +0000469};
470
Stefan Reinauer63217582012-10-29 16:52:36 -0700471static struct option long_options[] = {
472 {"name", required_argument, 0, 'n' },
473 {"type", required_argument, 0, 't' },
474 {"compression", required_argument, 0, 'c' },
475 {"base-address", required_argument, 0, 'b' },
476 {"load-address", required_argument, 0, 'l' },
477 {"entry-point", required_argument, 0, 'e' },
478 {"size", required_argument, 0, 's' },
479 {"bootblock", required_argument, 0, 'B' },
480 {"alignment", required_argument, 0, 'a' },
481 {"offset", required_argument, 0, 'o' },
482 {"file", required_argument, 0, 'f' },
David Hendricks90ca3b62012-11-16 14:48:22 -0800483 {"arch", required_argument, 0, 'm' },
Stefan Reinauer63217582012-10-29 16:52:36 -0700484 {"verbose", no_argument, 0, 'v' },
485 {"help", no_argument, 0, 'h' },
486 {NULL, 0, 0, 0 }
487};
488
489static void usage(char *name)
Stefan Reinauer3fec29c2009-09-22 15:58:19 +0000490{
491 printf
Stefan Reinauer07040582010-04-24 21:24:06 +0000492 ("cbfstool: Management utility for CBFS formatted ROM images\n\n"
Stefan Reinauer63217582012-10-29 16:52:36 -0700493 "USAGE:\n" " %s [-h]\n"
494 " %s FILE COMMAND [PARAMETERS]...\n\n" "OPTIONs:\n"
Stefan Reinauer07040582010-04-24 21:24:06 +0000495 " -h Display this help message\n\n"
Stefan Reinauer3fec29c2009-09-22 15:58:19 +0000496 "COMMANDs:\n"
David Hendricks90ca3b62012-11-16 14:48:22 -0800497 " add -f FILE -n NAME -t TYPE [-b base-address] "
Stefan Reinauer63217582012-10-29 16:52:36 -0700498 "Add a component\n"
David Hendricks90ca3b62012-11-16 14:48:22 -0800499 " add-payload -f FILE -n NAME [-c compression] [-b base] "
Stefan Reinauer63217582012-10-29 16:52:36 -0700500 "Add a payload to the ROM\n"
David Hendricks90ca3b62012-11-16 14:48:22 -0800501 " add-stage -f FILE -n NAME [-c compression] [-b base] "
Stefan Reinauer63217582012-10-29 16:52:36 -0700502 "Add a stage to the ROM\n"
503 " add-flat-binary -f FILE -n NAME -l load-address \\\n"
David Hendricks90ca3b62012-11-16 14:48:22 -0800504 " -e entry-point [-c compression] [-b base] "
Stefan Reinauer63217582012-10-29 16:52:36 -0700505 "Add a 32bit flat mode binary\n"
David Hendricks90ca3b62012-11-16 14:48:22 -0800506 " remove -n NAME "
Stefan Reinauer63217582012-10-29 16:52:36 -0700507 "Remove a component\n"
David Hendricks90ca3b62012-11-16 14:48:22 -0800508 " create -s size -B bootblock -m ARCH [-a align] [-o offset] "
Stefan Reinauer63217582012-10-29 16:52:36 -0700509 "Create a ROM file\n"
David Hendricks90ca3b62012-11-16 14:48:22 -0800510 " locate -f FILE -n NAME -a align "
Stefan Reinauer63217582012-10-29 16:52:36 -0700511 "Find a place for a file of that size\n"
David Hendricks90ca3b62012-11-16 14:48:22 -0800512 " print "
Stefan Reinauer63217582012-10-29 16:52:36 -0700513 "Show the contents of the ROM\n"
David Hendricks90ca3b62012-11-16 14:48:22 -0800514 " extract -n NAME -f FILE "
Stefan Reinauer63217582012-10-29 16:52:36 -0700515 "Extracts a raw payload from ROM\n"
Peter Stugeb347e0d2011-01-17 05:02:09 +0000516 "\n"
David Hendricks90ca3b62012-11-16 14:48:22 -0800517 "ARCHes:\n"
518 " armv7, x86\n"
Stefan Reinauer63217582012-10-29 16:52:36 -0700519 "TYPEs:\n", name, name
520 );
Stefan Reinauer07040582010-04-24 21:24:06 +0000521 print_supported_filetypes();
Stefan Reinauer3fec29c2009-09-22 15:58:19 +0000522}
523
Stefan Reinauer63217582012-10-29 16:52:36 -0700524/* Small, OS/libc independent runtime check for endianess */
Stefan Reinauera1e48242011-10-21 14:24:57 -0700525int host_bigendian = 0;
526
527static void which_endian(void)
528{
Mathias Kraused2567c82012-07-17 20:52:17 +0200529 static const uint32_t inttest = 0x12345678;
530 uint8_t inttest_lsb = *(uint8_t *)&inttest;
531 if (inttest_lsb == 0x12) {
Stefan Reinauera1e48242011-10-21 14:24:57 -0700532 host_bigendian = 1;
533 }
534}
535
Stefan Reinauer3fec29c2009-09-22 15:58:19 +0000536int main(int argc, char **argv)
537{
Mathias Krause41c229c2012-07-17 21:17:15 +0200538 size_t i;
Stefan Reinauer63217582012-10-29 16:52:36 -0700539 int c;
Stefan Reinauer3fec29c2009-09-22 15:58:19 +0000540
541 if (argc < 3) {
Stefan Reinauer63217582012-10-29 16:52:36 -0700542 usage(argv[0]);
Stefan Reinauer3fec29c2009-09-22 15:58:19 +0000543 return 1;
544 }
545
Stefan Reinauera1e48242011-10-21 14:24:57 -0700546 which_endian();
547
Stefan Reinauer63217582012-10-29 16:52:36 -0700548 cbfs_name = argv[1];
Stefan Reinauer3fec29c2009-09-22 15:58:19 +0000549 char *cmd = argv[2];
Stefan Reinauer63217582012-10-29 16:52:36 -0700550 optind += 2;
Stefan Reinauer3fec29c2009-09-22 15:58:19 +0000551
552 for (i = 0; i < ARRAY_SIZE(commands); i++) {
553 if (strcmp(cmd, commands[i].name) != 0)
554 continue;
Stefan Reinauer63217582012-10-29 16:52:36 -0700555
556 while (1) {
557 char *suffix = NULL;
558 int option_index = 0;
559
560 c = getopt_long(argc, argv, commands[i].optstring,
561 long_options, &option_index);
562 if (c == -1)
563 break;
564
565 /* filter out illegal long options */
566 if (index(commands[i].optstring, c) == NULL) {
567 /* TODO maybe print actual long option instead */
568 printf("%s: invalid option -- '%c'\n",
569 argv[0], c);
570 c = '?';
571 }
572
573 switch(c) {
574 case 'n':
575 rom_name = optarg;
576 break;
577 case 't':
578 if (intfiletype(optarg) != ((uint64_t) - 1))
579 rom_type = intfiletype(optarg);
580 else
581 rom_type = strtoul(optarg, NULL, 0);
582 if (rom_type == 0)
583 printf("W: Unknown type '%s' ignored\n",
584 optarg);
585 break;
586 case 'c':
587 if (!strncasecmp(optarg, "lzma", 5))
588 rom_algo = CBFS_COMPRESS_LZMA;
589 else if (!strncasecmp(optarg, "none", 5))
590 rom_algo = CBFS_COMPRESS_NONE;
591 else
592 printf("W: Unknown compression '%s'"
593 " ignored.\n", optarg);
594 break;
595 case 'b':
596 rom_baseaddress = strtoul(optarg, NULL, 0);
597 break;
598 case 'l':
599 rom_loadaddress = strtoul(optarg, NULL, 0);
600
601 break;
602 case 'e':
603 rom_entrypoint = strtoul(optarg, NULL, 0);
604 break;
605 case 's':
606 rom_size = strtoul(optarg, &suffix, 0);
607 if (tolower(suffix[0])=='k') {
608 rom_size *= 1024;
609 }
610 if (tolower(suffix[0])=='m') {
611 rom_size *= 1024 * 1024;
612 }
613 case 'B':
614 rom_bootblock = optarg;
615 break;
616 case 'a':
617 rom_alignment = strtoul(optarg, NULL, 0);
618 break;
619 case 'o':
620 rom_offset = strtoul(optarg, NULL, 0);
621 break;
622 case 'f':
623 rom_filename = optarg;
624 break;
625 case 'v':
626 verbose++;
627 break;
David Hendricks90ca3b62012-11-16 14:48:22 -0800628 case 'm':
629 arch = string_to_arch(optarg);
630 break;
Stefan Reinauer63217582012-10-29 16:52:36 -0700631 case 'h':
632 case '?':
633 usage(argv[0]);
634 return 1;
635 default:
636 break;
637 }
638 }
639
640 return commands[i].function();
Stefan Reinauer3fec29c2009-09-22 15:58:19 +0000641 }
642
643 printf("Unknown command '%s'.\n", cmd);
Stefan Reinauer63217582012-10-29 16:52:36 -0700644 usage(argv[0]);
Stefan Reinauer3fec29c2009-09-22 15:58:19 +0000645 return 1;
646}