blob: eeb69365108f1189ab2e05885b18ee2b22422e85 [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"
Hung-Te Lin3bb035b2013-01-29 02:15:49 +080030#include "cbfs_image.h"
Ronald G. Minnich5d01ec02009-03-31 11:57:36 +000031
Stefan Reinauer3fec29c2009-09-22 15:58:19 +000032struct command {
Stefan Reinauer3fec29c2009-09-22 15:58:19 +000033 const char *name;
Stefan Reinauer63217582012-10-29 16:52:36 -070034 const char *optstring;
35 int (*function) (void);
Stefan Reinauer3fec29c2009-09-22 15:58:19 +000036};
37
Stefan Reinauer63217582012-10-29 16:52:36 -070038int verbose = 0;
Hung-Te Lind1739622013-01-28 14:23:49 +080039static struct param {
40 char *cbfs_name;
41 char *name;
42 char *filename;
43 char *bootblock;
44 uint32_t type;
45 uint32_t baseaddress;
Hung-Te Linf56c73f2013-01-29 09:45:12 +080046 uint32_t baseaddress_assigned;
Hung-Te Lind1739622013-01-28 14:23:49 +080047 uint32_t loadaddress;
Hung-Te Linf56c73f2013-01-29 09:45:12 +080048 uint32_t headeroffset;
49 uint32_t headeroffset_assigned;
Hung-Te Lind1739622013-01-28 14:23:49 +080050 uint32_t entrypoint;
51 uint32_t size;
52 uint32_t alignment;
Hung-Te Line9198372013-03-19 12:17:12 +080053 uint32_t pagesize;
Hung-Te Lind1739622013-01-28 14:23:49 +080054 uint32_t offset;
Hung-Te Lin215d1d72013-01-29 03:46:02 +080055 uint32_t top_aligned;
Hung-Te Lind1739622013-01-28 14:23:49 +080056 comp_algo algo;
57} param = {
58 /* All variables not listed are initialized as zero. */
59 .algo = CBFS_COMPRESS_NONE,
60};
Stefan Reinauer63217582012-10-29 16:52:36 -070061
Hung-Te Linc13e4bf2013-01-29 15:22:11 +080062typedef int (*convert_buffer_t)(struct buffer *buffer, uint32_t *offset);
Stefan Reinauer63217582012-10-29 16:52:36 -070063
Hung-Te Lin5f3eb262013-01-29 10:24:00 +080064static int cbfs_add_component(const char *cbfs_name,
65 const char *filename,
66 const char *name,
67 uint32_t type,
68 uint32_t offset,
69 convert_buffer_t convert) {
70 struct cbfs_image image;
71 struct buffer buffer;
72
73 if (!filename) {
Hung-Te Lin4d87d4e2013-01-28 14:39:43 +080074 ERROR("You need to specify -f/--filename.\n");
Stefan Reinauer63217582012-10-29 16:52:36 -070075 return 1;
76 }
77
Hung-Te Lin5f3eb262013-01-29 10:24:00 +080078 if (!name) {
Hung-Te Lin4d87d4e2013-01-28 14:39:43 +080079 ERROR("You need to specify -n/--name.\n");
Stefan Reinauer63217582012-10-29 16:52:36 -070080 return 1;
81 }
82
Hung-Te Lin5f3eb262013-01-29 10:24:00 +080083 if (type == 0) {
Hung-Te Lin4d87d4e2013-01-28 14:39:43 +080084 ERROR("You need to specify a valid -t/--type.\n");
Stefan Reinauer63217582012-10-29 16:52:36 -070085 return 1;
86 }
87
Hung-Te Lin5f3eb262013-01-29 10:24:00 +080088 if (buffer_from_file(&buffer, filename) != 0) {
89 ERROR("Could not load file '%s'.\n", filename);
Stefan Reinauer63217582012-10-29 16:52:36 -070090 return 1;
91 }
92
Hung-Te Linc13e4bf2013-01-29 15:22:11 +080093 if (convert && convert(&buffer, &offset) != 0) {
Hung-Te Lin5f3eb262013-01-29 10:24:00 +080094 ERROR("Failed to parse file '%s'.\n", filename);
95 buffer_delete(&buffer);
Patrick Georgi45d8a832009-09-15 08:21:46 +000096 return 1;
97 }
Ronald G. Minnich5d01ec02009-03-31 11:57:36 +000098
Hung-Te Lin5f3eb262013-01-29 10:24:00 +080099 if (cbfs_image_from_file(&image, cbfs_name) != 0) {
100 ERROR("Could not load ROM image '%s'.\n", cbfs_name);
101 buffer_delete(&buffer);
Patrick Georgi56f5fb72009-09-30 11:21:18 +0000102 return 1;
Stefan Reinauerfbadc492011-10-14 12:44:14 -0700103 }
Stefan Reinauer63217582012-10-29 16:52:36 -0700104
Hung-Te Lin5f3eb262013-01-29 10:24:00 +0800105 if (cbfs_get_entry(&image, name)) {
106 ERROR("'%s' already in ROM image.\n", name);
107 buffer_delete(&buffer);
108 cbfs_image_delete(&image);
109 return 1;
110 }
111
112 if (cbfs_add_entry(&image, &buffer, name, type, offset) != 0) {
113 ERROR("Failed to add '%s' into ROM image.\n", filename);
114 buffer_delete(&buffer);
115 cbfs_image_delete(&image);
116 return 1;
117 }
118
119 if (cbfs_image_write_file(&image, cbfs_name) != 0) {
120 buffer_delete(&buffer);
121 cbfs_image_delete(&image);
122 return 1;
123 }
124
125 buffer_delete(&buffer);
126 cbfs_image_delete(&image);
Stefan Reinauer3fec29c2009-09-22 15:58:19 +0000127 return 0;
128}
129
Hung-Te Linc13e4bf2013-01-29 15:22:11 +0800130static int cbfstool_convert_mkstage(struct buffer *buffer, uint32_t *offset) {
131 struct buffer output;
132 if (parse_elf_to_stage(buffer, &output, param.algo, offset) != 0)
133 return -1;
134 buffer_delete(buffer);
135 // direct assign, no dupe.
136 memcpy(buffer, &output, sizeof(*buffer));
137 return 0;
138}
139
140static int cbfstool_convert_mkpayload(struct buffer *buffer, uint32_t *offset) {
141 struct buffer output;
Stefan Reinauer543a6822013-02-04 15:39:13 -0800142 int ret;
143 /* per default, try and see if payload is an ELF binary */
144 ret = parse_elf_to_payload(buffer, &output, param.algo);
145
146 /* If it's not an ELF, see if it's a UEFI FV */
147 if (ret != 0)
148 ret = parse_fv_to_payload(buffer, &output, param.algo);
149
150 /* Not a supported payload type */
151 if (ret != 0) {
152 ERROR("Not a supported payload type (ELF / FV).\n");
Hung-Te Linc13e4bf2013-01-29 15:22:11 +0800153 return -1;
Stefan Reinauer543a6822013-02-04 15:39:13 -0800154 }
155
Hung-Te Linc13e4bf2013-01-29 15:22:11 +0800156 buffer_delete(buffer);
157 // direct assign, no dupe.
158 memcpy(buffer, &output, sizeof(*buffer));
159 return 0;
160}
161
162static int cbfstool_convert_mkflatpayload(struct buffer *buffer,
163 uint32_t *offset) {
164 struct buffer output;
165 if (parse_flat_binary_to_payload(buffer, &output,
166 param.loadaddress,
167 param.entrypoint,
168 param.algo) != 0) {
169 return -1;
170 }
171 buffer_delete(buffer);
172 // direct assign, no dupe.
173 memcpy(buffer, &output, sizeof(*buffer));
174 return 0;
175}
176
177
Hung-Te Lin5f3eb262013-01-29 10:24:00 +0800178static int cbfs_add(void)
179{
180 return cbfs_add_component(param.cbfs_name,
181 param.filename,
182 param.name,
183 param.type,
184 param.baseaddress,
185 NULL);
186}
187
Stefan Reinauer63217582012-10-29 16:52:36 -0700188static int cbfs_add_stage(void)
Stefan Reinauer20848ee2012-10-22 16:04:13 -0700189{
Hung-Te Linc13e4bf2013-01-29 15:22:11 +0800190 return cbfs_add_component(param.cbfs_name,
191 param.filename,
192 param.name,
193 CBFS_COMPONENT_STAGE,
194 param.baseaddress,
195 cbfstool_convert_mkstage);
196}
Stefan Reinauer20848ee2012-10-22 16:04:13 -0700197
Hung-Te Linc13e4bf2013-01-29 15:22:11 +0800198static int cbfs_add_payload(void)
199{
200 return cbfs_add_component(param.cbfs_name,
201 param.filename,
202 param.name,
203 CBFS_COMPONENT_PAYLOAD,
204 param.baseaddress,
205 cbfstool_convert_mkpayload);
Stefan Reinauer63217582012-10-29 16:52:36 -0700206}
207
208static int cbfs_add_flat_binary(void)
209{
Hung-Te Lind1739622013-01-28 14:23:49 +0800210 if (param.loadaddress == 0) {
Hung-Te Lin4d87d4e2013-01-28 14:39:43 +0800211 ERROR("You need to specify a valid "
Stefan Reinauer63217582012-10-29 16:52:36 -0700212 "-l/--load-address.\n");
213 return 1;
214 }
Hung-Te Lind1739622013-01-28 14:23:49 +0800215 if (param.entrypoint == 0) {
Hung-Te Lin4d87d4e2013-01-28 14:39:43 +0800216 ERROR("You need to specify a valid "
Stefan Reinauer63217582012-10-29 16:52:36 -0700217 "-e/--entry-point.\n");
218 return 1;
219 }
Hung-Te Linc13e4bf2013-01-29 15:22:11 +0800220 return cbfs_add_component(param.cbfs_name,
221 param.filename,
222 param.name,
223 CBFS_COMPONENT_PAYLOAD,
224 param.baseaddress,
225 cbfstool_convert_mkflatpayload);
Stefan Reinauer20848ee2012-10-22 16:04:13 -0700226}
227
Stefan Reinauer63217582012-10-29 16:52:36 -0700228static int cbfs_remove(void)
Gabe Blacke1bb49e2012-01-27 00:33:47 -0800229{
Hung-Te Linc03d9b02013-01-29 02:38:40 +0800230 struct cbfs_image image;
Gabe Blacke1bb49e2012-01-27 00:33:47 -0800231
Hung-Te Lind1739622013-01-28 14:23:49 +0800232 if (!param.name) {
Hung-Te Lin4d87d4e2013-01-28 14:39:43 +0800233 ERROR("You need to specify -n/--name.\n");
Stefan Reinauer63217582012-10-29 16:52:36 -0700234 return 1;
235 }
236
Hung-Te Linc03d9b02013-01-29 02:38:40 +0800237 if (cbfs_image_from_file(&image, param.cbfs_name) != 0) {
Hung-Te Lin4d87d4e2013-01-28 14:39:43 +0800238 ERROR("Could not load ROM image '%s'.\n",
Hung-Te Lind1739622013-01-28 14:23:49 +0800239 param.cbfs_name);
Gabe Blacke1bb49e2012-01-27 00:33:47 -0800240 return 1;
241 }
242
Hung-Te Linc03d9b02013-01-29 02:38:40 +0800243 if (cbfs_remove_entry(&image, param.name) != 0) {
Hung-Te Lin4d87d4e2013-01-28 14:39:43 +0800244 ERROR("Removing file '%s' failed.\n",
Hung-Te Linc03d9b02013-01-29 02:38:40 +0800245 param.name);
246 cbfs_image_delete(&image);
247 return 1;
248 }
249 if (cbfs_image_write_file(&image, param.cbfs_name) != 0) {
250 cbfs_image_delete(&image);
Gabe Blacke1bb49e2012-01-27 00:33:47 -0800251 return 1;
252 }
253
Hung-Te Linc03d9b02013-01-29 02:38:40 +0800254 cbfs_image_delete(&image);
Gabe Blacke1bb49e2012-01-27 00:33:47 -0800255 return 0;
256}
257
Stefan Reinauer63217582012-10-29 16:52:36 -0700258static int cbfs_create(void)
Stefan Reinauer3fec29c2009-09-22 15:58:19 +0000259{
Hung-Te Linf56c73f2013-01-29 09:45:12 +0800260 struct cbfs_image image;
261 struct buffer bootblock;
262
Hung-Te Lind1739622013-01-28 14:23:49 +0800263 if (param.size == 0) {
Hung-Te Lin4d87d4e2013-01-28 14:39:43 +0800264 ERROR("You need to specify a valid -s/--size.\n");
Stefan Reinauer3fec29c2009-09-22 15:58:19 +0000265 return 1;
266 }
267
Hung-Te Lind1739622013-01-28 14:23:49 +0800268 if (!param.bootblock) {
Hung-Te Linf56c73f2013-01-29 09:45:12 +0800269 ERROR("You need to specify -B/--bootblock.\n");
Stefan Reinauer63217582012-10-29 16:52:36 -0700270 return 1;
Patrick Georgi467b12a2009-12-21 13:50:37 +0000271 }
Stefan Reinauer3fec29c2009-09-22 15:58:19 +0000272
Hung-Te Linf56c73f2013-01-29 09:45:12 +0800273 // TODO Remove arch or pack into param.
David Hendricks90ca3b62012-11-16 14:48:22 -0800274 if (arch == CBFS_ARCHITECTURE_UNKNOWN) {
Hung-Te Lin4d87d4e2013-01-28 14:39:43 +0800275 ERROR("You need to specify -m/--machine arch\n");
David Hendricks90ca3b62012-11-16 14:48:22 -0800276 return 1;
277 }
278
Hung-Te Linf56c73f2013-01-29 09:45:12 +0800279 if (buffer_from_file(&bootblock, param.bootblock) != 0) {
280 return 1;
281 }
282
283 // Setup default boot offset and header offset.
284 if (!param.baseaddress_assigned) {
285 // put boot block before end of ROM.
286 param.baseaddress = param.size - bootblock.size;
287 DEBUG("bootblock in end of ROM.\n");
288 }
289 if (!param.headeroffset_assigned) {
290 // Put header before bootblock, and make a reference in end of
291 // bootblock.
292 param.headeroffset = (
293 param.baseaddress -
294 sizeof(struct cbfs_header));
295 if (bootblock.size >= sizeof(uint32_t)) {
296 // TODO this only works for 32b top-aligned system now...
297 uint32_t ptr = param.headeroffset - param.size;
298 uint32_t *sig = (uint32_t *)(bootblock.data +
299 bootblock.size -
300 sizeof(ptr));
301 *sig = ptr;
302 DEBUG("CBFS header reference in end of bootblock.\n");
303 }
304 }
305
306 if (cbfs_image_create(&image,
307 arch,
308 param.size,
309 param.alignment,
310 &bootblock,
311 param.baseaddress,
312 param.headeroffset,
313 param.offset) != 0) {
314 ERROR("Failed to create %s.\n", param.cbfs_name);
315 return 1;
316 }
317 buffer_delete(&bootblock);
318
319 if (cbfs_image_write_file(&image, param.cbfs_name) != 0) {
320 ERROR("Failed to write %s.\n", param.cbfs_name);
321 cbfs_image_delete(&image);
322 return 1;
323 }
324 cbfs_image_delete(&image);
325 return 0;
Stefan Reinauer3fec29c2009-09-22 15:58:19 +0000326}
327
Stefan Reinauer63217582012-10-29 16:52:36 -0700328static int cbfs_locate(void)
Patrick Georgi0da38dd2009-11-09 17:18:02 +0000329{
Hung-Te Lin215d1d72013-01-29 03:46:02 +0800330 struct cbfs_image image;
331 struct buffer buffer;
332 int32_t address;
Stefan Reinauer63217582012-10-29 16:52:36 -0700333
Hung-Te Lind1739622013-01-28 14:23:49 +0800334 if (!param.filename) {
Hung-Te Lin4d87d4e2013-01-28 14:39:43 +0800335 ERROR("You need to specify -f/--filename.\n");
Patrick Georgi0da38dd2009-11-09 17:18:02 +0000336 return 1;
337 }
338
Hung-Te Lind1739622013-01-28 14:23:49 +0800339 if (!param.name) {
Hung-Te Lin4d87d4e2013-01-28 14:39:43 +0800340 ERROR("You need to specify -n/--name.\n");
Stefan Reinauer63217582012-10-29 16:52:36 -0700341 return 1;
342 }
343
Hung-Te Lin215d1d72013-01-29 03:46:02 +0800344 if (cbfs_image_from_file(&image, param.cbfs_name) != 0) {
345 ERROR("Failed to load %s.\n", param.cbfs_name);
346 return 1;
347 }
Stefan Reinauer63217582012-10-29 16:52:36 -0700348
Hung-Te Lin215d1d72013-01-29 03:46:02 +0800349 if (cbfs_get_entry(&image, param.name))
350 WARN("'%s' already in CBFS.\n", param.name);
Patrick Georgi0da38dd2009-11-09 17:18:02 +0000351
Hung-Te Lin215d1d72013-01-29 03:46:02 +0800352 if (buffer_from_file(&buffer, param.filename) != 0) {
353 ERROR("Cannot load %s.\n", param.filename);
354 cbfs_image_delete(&image);
355 return 1;
356 }
357
358 address = cbfs_locate_entry(&image, param.name, buffer.size,
Hung-Te Line4ea2ca2013-03-19 12:24:43 +0800359 param.pagesize, param.alignment);
Hung-Te Lin215d1d72013-01-29 03:46:02 +0800360 buffer_delete(&buffer);
361
362 if (address == -1) {
Hung-Te Line4ea2ca2013-03-19 12:24:43 +0800363 ERROR("'%s' can't fit in CBFS for page-size %#x, align %#x.\n",
364 param.name, param.pagesize, param.alignment);
Hung-Te Lin215d1d72013-01-29 03:46:02 +0800365 cbfs_image_delete(&image);
366 return 1;
367 }
368
369 if (param.top_aligned)
370 address = address - ntohl(image.header->romsize);
371
372 cbfs_image_delete(&image);
373 printf("0x%x\n", address);
374 return 0;
Patrick Georgi0da38dd2009-11-09 17:18:02 +0000375}
376
Stefan Reinauer63217582012-10-29 16:52:36 -0700377static int cbfs_print(void)
Stefan Reinauer3fec29c2009-09-22 15:58:19 +0000378{
Hung-Te Lin3bb035b2013-01-29 02:15:49 +0800379 struct cbfs_image image;
380 if (cbfs_image_from_file(&image, param.cbfs_name) != 0) {
Hung-Te Lin4d87d4e2013-01-28 14:39:43 +0800381 ERROR("Could not load ROM image '%s'.\n",
Hung-Te Lind1739622013-01-28 14:23:49 +0800382 param.cbfs_name);
Stefan Reinauer3fec29c2009-09-22 15:58:19 +0000383 return 1;
384 }
Hung-Te Lin3bb035b2013-01-29 02:15:49 +0800385 cbfs_print_directory(&image);
386 cbfs_image_delete(&image);
Stefan Reinauer3fec29c2009-09-22 15:58:19 +0000387 return 0;
388}
389
Stefan Reinauer63217582012-10-29 16:52:36 -0700390static int cbfs_extract(void)
Aurelien Guillaumefe7d6b92011-01-13 09:09:21 +0000391{
Hung-Te Lin0f8af712013-01-29 02:29:49 +0800392 int result = 0;
393 struct cbfs_image image;
Aurelien Guillaumefe7d6b92011-01-13 09:09:21 +0000394
Hung-Te Lind1739622013-01-28 14:23:49 +0800395 if (!param.filename) {
Hung-Te Lin4d87d4e2013-01-28 14:39:43 +0800396 ERROR("You need to specify -f/--filename.\n");
Stefan Reinauer63217582012-10-29 16:52:36 -0700397 return 1;
398 }
399
Hung-Te Lind1739622013-01-28 14:23:49 +0800400 if (!param.name) {
Hung-Te Lin4d87d4e2013-01-28 14:39:43 +0800401 ERROR("You need to specify -n/--name.\n");
Stefan Reinauer63217582012-10-29 16:52:36 -0700402 return 1;
403 }
404
Hung-Te Lin0f8af712013-01-29 02:29:49 +0800405 if (cbfs_image_from_file(&image, param.cbfs_name) != 0) {
Hung-Te Lin4d87d4e2013-01-28 14:39:43 +0800406 ERROR("Could not load ROM image '%s'.\n",
Hung-Te Lind1739622013-01-28 14:23:49 +0800407 param.cbfs_name);
Hung-Te Lin0f8af712013-01-29 02:29:49 +0800408 result = 1;
409 } else if (cbfs_export_entry(&image, param.name,
410 param.filename) != 0) {
411 result = 1;
Aurelien Guillaumefe7d6b92011-01-13 09:09:21 +0000412 }
413
Hung-Te Lin0f8af712013-01-29 02:29:49 +0800414 cbfs_image_delete(&image);
415 return result;
Aurelien Guillaumefe7d6b92011-01-13 09:09:21 +0000416}
417
Stefan Reinauera1e48242011-10-21 14:24:57 -0700418static const struct command commands[] = {
Hung-Te Lin4d87d4e2013-01-28 14:39:43 +0800419 {"add", "f:n:t:b:vh?", cbfs_add},
420 {"add-payload", "f:n:t:c:b:vh?", cbfs_add_payload},
421 {"add-stage", "f:n:t:c:b:vh?", cbfs_add_stage},
422 {"add-flat-binary", "f:n:l:e:c:b:vh?", cbfs_add_flat_binary},
423 {"remove", "n:vh?", cbfs_remove},
Hung-Te Linf56c73f2013-01-29 09:45:12 +0800424 {"create", "s:B:b:H:a:o:m:vh?", cbfs_create},
Hung-Te Line4ea2ca2013-03-19 12:24:43 +0800425 {"locate", "f:n:P:a:Tvh?", cbfs_locate},
Hung-Te Lin4d87d4e2013-01-28 14:39:43 +0800426 {"print", "vh?", cbfs_print},
427 {"extract", "n:f:vh?", cbfs_extract},
Stefan Reinauer3fec29c2009-09-22 15:58:19 +0000428};
429
Stefan Reinauer63217582012-10-29 16:52:36 -0700430static struct option long_options[] = {
431 {"name", required_argument, 0, 'n' },
432 {"type", required_argument, 0, 't' },
433 {"compression", required_argument, 0, 'c' },
434 {"base-address", required_argument, 0, 'b' },
435 {"load-address", required_argument, 0, 'l' },
Hung-Te Lin215d1d72013-01-29 03:46:02 +0800436 {"top-aligned", required_argument, 0, 'T' },
Stefan Reinauer63217582012-10-29 16:52:36 -0700437 {"entry-point", required_argument, 0, 'e' },
438 {"size", required_argument, 0, 's' },
439 {"bootblock", required_argument, 0, 'B' },
440 {"alignment", required_argument, 0, 'a' },
Hung-Te Line9198372013-03-19 12:17:12 +0800441 {"page-size", required_argument, 0, 'P' },
Stefan Reinauer63217582012-10-29 16:52:36 -0700442 {"offset", required_argument, 0, 'o' },
443 {"file", required_argument, 0, 'f' },
David Hendricks90ca3b62012-11-16 14:48:22 -0800444 {"arch", required_argument, 0, 'm' },
Stefan Reinauer63217582012-10-29 16:52:36 -0700445 {"verbose", no_argument, 0, 'v' },
446 {"help", no_argument, 0, 'h' },
447 {NULL, 0, 0, 0 }
448};
449
450static void usage(char *name)
Stefan Reinauer3fec29c2009-09-22 15:58:19 +0000451{
452 printf
Stefan Reinauer07040582010-04-24 21:24:06 +0000453 ("cbfstool: Management utility for CBFS formatted ROM images\n\n"
Stefan Reinauer63217582012-10-29 16:52:36 -0700454 "USAGE:\n" " %s [-h]\n"
Hung-Te Lin4d87d4e2013-01-28 14:39:43 +0800455 " %s FILE COMMAND [-v] [PARAMETERS]...\n\n" "OPTIONs:\n"
Hung-Te Lin215d1d72013-01-29 03:46:02 +0800456 " -T Output top-aligned memory address\n"
Hung-Te Lin4d87d4e2013-01-28 14:39:43 +0800457 " -v Provide verbose output\n"
458 " -h Display this help message\n\n"
Stefan Reinauer3fec29c2009-09-22 15:58:19 +0000459 "COMMANDs:\n"
David Hendricks90ca3b62012-11-16 14:48:22 -0800460 " add -f FILE -n NAME -t TYPE [-b base-address] "
Stefan Reinauer63217582012-10-29 16:52:36 -0700461 "Add a component\n"
David Hendricks90ca3b62012-11-16 14:48:22 -0800462 " add-payload -f FILE -n NAME [-c compression] [-b base] "
Stefan Reinauer63217582012-10-29 16:52:36 -0700463 "Add a payload to the ROM\n"
David Hendricks90ca3b62012-11-16 14:48:22 -0800464 " add-stage -f FILE -n NAME [-c compression] [-b base] "
Stefan Reinauer63217582012-10-29 16:52:36 -0700465 "Add a stage to the ROM\n"
466 " add-flat-binary -f FILE -n NAME -l load-address \\\n"
David Hendricks90ca3b62012-11-16 14:48:22 -0800467 " -e entry-point [-c compression] [-b base] "
Stefan Reinauer63217582012-10-29 16:52:36 -0700468 "Add a 32bit flat mode binary\n"
David Hendricks90ca3b62012-11-16 14:48:22 -0800469 " remove -n NAME "
Stefan Reinauer63217582012-10-29 16:52:36 -0700470 "Remove a component\n"
David Hendricks90ca3b62012-11-16 14:48:22 -0800471 " create -s size -B bootblock -m ARCH [-a align] [-o offset] "
Stefan Reinauer63217582012-10-29 16:52:36 -0700472 "Create a ROM file\n"
Hung-Te Line4ea2ca2013-03-19 12:24:43 +0800473 " locate -f FILE -n NAME [-P page-size] [-a align] [-T] "
Stefan Reinauer63217582012-10-29 16:52:36 -0700474 "Find a place for a file of that size\n"
David Hendricks90ca3b62012-11-16 14:48:22 -0800475 " print "
Stefan Reinauer63217582012-10-29 16:52:36 -0700476 "Show the contents of the ROM\n"
David Hendricks90ca3b62012-11-16 14:48:22 -0800477 " extract -n NAME -f FILE "
Stefan Reinauer63217582012-10-29 16:52:36 -0700478 "Extracts a raw payload from ROM\n"
Peter Stugeb347e0d2011-01-17 05:02:09 +0000479 "\n"
David Hendricks90ca3b62012-11-16 14:48:22 -0800480 "ARCHes:\n"
481 " armv7, x86\n"
Stefan Reinauer63217582012-10-29 16:52:36 -0700482 "TYPEs:\n", name, name
483 );
Stefan Reinauer07040582010-04-24 21:24:06 +0000484 print_supported_filetypes();
Stefan Reinauer3fec29c2009-09-22 15:58:19 +0000485}
486
487int main(int argc, char **argv)
488{
Mathias Krause41c229c2012-07-17 21:17:15 +0200489 size_t i;
Stefan Reinauer63217582012-10-29 16:52:36 -0700490 int c;
Stefan Reinauer3fec29c2009-09-22 15:58:19 +0000491
492 if (argc < 3) {
Stefan Reinauer63217582012-10-29 16:52:36 -0700493 usage(argv[0]);
Stefan Reinauer3fec29c2009-09-22 15:58:19 +0000494 return 1;
495 }
496
Hung-Te Lind1739622013-01-28 14:23:49 +0800497 param.cbfs_name = argv[1];
Stefan Reinauer3fec29c2009-09-22 15:58:19 +0000498 char *cmd = argv[2];
Stefan Reinauer63217582012-10-29 16:52:36 -0700499 optind += 2;
Stefan Reinauer3fec29c2009-09-22 15:58:19 +0000500
501 for (i = 0; i < ARRAY_SIZE(commands); i++) {
502 if (strcmp(cmd, commands[i].name) != 0)
503 continue;
Stefan Reinauer63217582012-10-29 16:52:36 -0700504
505 while (1) {
506 char *suffix = NULL;
507 int option_index = 0;
508
509 c = getopt_long(argc, argv, commands[i].optstring,
510 long_options, &option_index);
511 if (c == -1)
512 break;
513
514 /* filter out illegal long options */
zbao062730d2013-01-08 10:10:16 +0800515 if (strchr(commands[i].optstring, c) == NULL) {
Stefan Reinauer63217582012-10-29 16:52:36 -0700516 /* TODO maybe print actual long option instead */
Hung-Te Lin4d87d4e2013-01-28 14:39:43 +0800517 ERROR("%s: invalid option -- '%c'\n",
518 argv[0], c);
Stefan Reinauer63217582012-10-29 16:52:36 -0700519 c = '?';
520 }
521
522 switch(c) {
523 case 'n':
Hung-Te Lind1739622013-01-28 14:23:49 +0800524 param.name = optarg;
Stefan Reinauer63217582012-10-29 16:52:36 -0700525 break;
526 case 't':
527 if (intfiletype(optarg) != ((uint64_t) - 1))
Hung-Te Lind1739622013-01-28 14:23:49 +0800528 param.type = intfiletype(optarg);
Stefan Reinauer63217582012-10-29 16:52:36 -0700529 else
Hung-Te Lind1739622013-01-28 14:23:49 +0800530 param.type = strtoul(optarg, NULL, 0);
531 if (param.type == 0)
Hung-Te Lin4d87d4e2013-01-28 14:39:43 +0800532 WARN("Unknown type '%s' ignored\n",
Stefan Reinauer63217582012-10-29 16:52:36 -0700533 optarg);
534 break;
535 case 'c':
536 if (!strncasecmp(optarg, "lzma", 5))
Hung-Te Lind1739622013-01-28 14:23:49 +0800537 param.algo = CBFS_COMPRESS_LZMA;
Stefan Reinauer63217582012-10-29 16:52:36 -0700538 else if (!strncasecmp(optarg, "none", 5))
Hung-Te Lind1739622013-01-28 14:23:49 +0800539 param.algo = CBFS_COMPRESS_NONE;
Stefan Reinauer63217582012-10-29 16:52:36 -0700540 else
Hung-Te Lin4d87d4e2013-01-28 14:39:43 +0800541 WARN("Unknown compression '%s'"
542 " ignored.\n", optarg);
Stefan Reinauer63217582012-10-29 16:52:36 -0700543 break;
544 case 'b':
Hung-Te Lind1739622013-01-28 14:23:49 +0800545 param.baseaddress = strtoul(optarg, NULL, 0);
Hung-Te Linf56c73f2013-01-29 09:45:12 +0800546 // baseaddress may be zero on non-x86, so we
547 // need an explicit "baseaddress_assigned".
548 param.baseaddress = strtoul(optarg, NULL, 0);
549 param.baseaddress_assigned = 1;
Stefan Reinauer63217582012-10-29 16:52:36 -0700550 break;
551 case 'l':
Hung-Te Lind1739622013-01-28 14:23:49 +0800552 param.loadaddress = strtoul(optarg, NULL, 0);
Stefan Reinauer63217582012-10-29 16:52:36 -0700553
554 break;
555 case 'e':
Hung-Te Lind1739622013-01-28 14:23:49 +0800556 param.entrypoint = strtoul(optarg, NULL, 0);
Stefan Reinauer63217582012-10-29 16:52:36 -0700557 break;
558 case 's':
Hung-Te Lind1739622013-01-28 14:23:49 +0800559 param.size = strtoul(optarg, &suffix, 0);
Stefan Reinauer63217582012-10-29 16:52:36 -0700560 if (tolower(suffix[0])=='k') {
Hung-Te Lind1739622013-01-28 14:23:49 +0800561 param.size *= 1024;
Stefan Reinauer63217582012-10-29 16:52:36 -0700562 }
563 if (tolower(suffix[0])=='m') {
Hung-Te Lind1739622013-01-28 14:23:49 +0800564 param.size *= 1024 * 1024;
Stefan Reinauer63217582012-10-29 16:52:36 -0700565 }
566 case 'B':
Hung-Te Lind1739622013-01-28 14:23:49 +0800567 param.bootblock = optarg;
Stefan Reinauer63217582012-10-29 16:52:36 -0700568 break;
Hung-Te Linf56c73f2013-01-29 09:45:12 +0800569 case 'H':
570 param.headeroffset = strtoul(
571 optarg, NULL, 0);
572 param.headeroffset_assigned = 1;
573 break;
Stefan Reinauer63217582012-10-29 16:52:36 -0700574 case 'a':
Hung-Te Lind1739622013-01-28 14:23:49 +0800575 param.alignment = strtoul(optarg, NULL, 0);
Stefan Reinauer63217582012-10-29 16:52:36 -0700576 break;
Hung-Te Line9198372013-03-19 12:17:12 +0800577 case 'P':
578 param.pagesize = strtoul(optarg, NULL, 0);
579 break;
Stefan Reinauer63217582012-10-29 16:52:36 -0700580 case 'o':
Hung-Te Lind1739622013-01-28 14:23:49 +0800581 param.offset = strtoul(optarg, NULL, 0);
Stefan Reinauer63217582012-10-29 16:52:36 -0700582 break;
583 case 'f':
Hung-Te Lind1739622013-01-28 14:23:49 +0800584 param.filename = optarg;
Stefan Reinauer63217582012-10-29 16:52:36 -0700585 break;
Hung-Te Lin215d1d72013-01-29 03:46:02 +0800586 case 'T':
587 param.top_aligned = 1;
588 break;
Stefan Reinauer63217582012-10-29 16:52:36 -0700589 case 'v':
590 verbose++;
591 break;
David Hendricks90ca3b62012-11-16 14:48:22 -0800592 case 'm':
593 arch = string_to_arch(optarg);
594 break;
Stefan Reinauer63217582012-10-29 16:52:36 -0700595 case 'h':
596 case '?':
597 usage(argv[0]);
598 return 1;
599 default:
600 break;
601 }
602 }
603
604 return commands[i].function();
Stefan Reinauer3fec29c2009-09-22 15:58:19 +0000605 }
606
Hung-Te Lin4d87d4e2013-01-28 14:39:43 +0800607 ERROR("Unknown command '%s'.\n", cmd);
Stefan Reinauer63217582012-10-29 16:52:36 -0700608 usage(argv[0]);
Stefan Reinauer3fec29c2009-09-22 15:58:19 +0000609 return 1;
610}