This separates the code for each command in cbfstool. For the good and for the
[coreboot.git] / util / cbfstool / cbfstool.c
1 /*
2  * cbfstool, CLI utility for CBFS file manipulation
3  *
4  * Copyright (C) 2009 coresystems GmbH
5  *                 written by Patrick Georgi <patrick.georgi@coresystems.de>
6  *
7  * This program is free software; you can redistribute it and/or modify
8  * it under the terms of the GNU General Public License as published by
9  * the Free Software Foundation; version 2 of the License.
10  *
11  * This program is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14  * GNU General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License
17  * along with this program; if not, write to the Free Software
18  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA, 02110-1301 USA
19  */
20
21 #include <stdio.h>
22 #include <stdint.h>
23 #include "common.h"
24 #include "cbfs.h"
25
26 typedef enum {
27         CMD_ADD,
28         CMD_ADD_PAYLOAD,
29         CMD_ADD_STAGE,
30         CMD_CREATE,
31         CMD_PRINT
32 } cmd_t;
33
34 struct command {
35         cmd_t id;
36         const char *name;
37         int (*function) (int argc, char **argv);
38 };
39
40 static int cbfs_add(int argc, char **argv)
41 {
42         char *romname = argv[1];
43         char *cmd = argv[2];
44         void *rom = loadrom(romname);
45
46         if (rom == NULL) {
47                 printf("Could not load ROM image '%s'.\n", romname);
48                 return 1;
49         }
50
51         if (argc < 5) {
52                 printf("not enough arguments to '%s'.\n", cmd);
53                 return 1;
54         }
55
56         char *filename = argv[3];
57         char *cbfsname = argv[4];
58
59         uint32_t filesize = 0;
60         void *filedata = loadfile(filename, &filesize, 0, SEEK_SET);
61         if (filedata == NULL) {
62                 printf("Could not load file '%s'.\n", filename);
63                 return 1;
64         }
65
66         uint32_t base = 0;
67         void *cbfsfile = NULL;
68
69         if (argc < 6) {
70                 printf("not enough arguments to 'add'.\n");
71                 return 1;
72         }
73         uint32_t type;
74         if (intfiletype(argv[5]) != ((uint64_t) - 1))
75                 type = intfiletype(argv[5]);
76         else
77                 type = strtoul(argv[5], NULL, 0);
78         if (argc > 6) {
79                 base = strtoul(argv[6], NULL, 0);
80         }
81         cbfsfile =
82             create_cbfs_file(cbfsname, filedata, &filesize, type, &base);
83         add_file_to_cbfs(cbfsfile, filesize, base);
84         writerom(romname, rom, romsize);
85         return 0;
86 }
87
88 static int cbfs_add_payload(int argc, char **argv)
89 {
90         char *romname = argv[1];
91         char *cmd = argv[2];
92         void *rom = loadrom(romname);
93
94         if (rom == NULL) {
95                 printf("Could not load ROM image '%s'.\n", romname);
96                 return 1;
97         }
98
99         if (argc < 5) {
100                 printf("not enough arguments to '%s'.\n", cmd);
101                 return 1;
102         }
103
104         char *filename = argv[3];
105         char *cbfsname = argv[4];
106
107         uint32_t filesize = 0;
108         void *filedata = loadfile(filename, &filesize, 0, SEEK_SET);
109         if (filedata == NULL) {
110                 printf("Could not load file '%s'.\n", filename);
111                 return 1;
112         }
113
114         uint32_t base = 0;
115         void *cbfsfile = NULL;
116
117         comp_algo algo = CBFS_COMPRESS_NONE;
118         if (argc > 5) {
119                 if (argv[5][0] == 'l')
120                         algo = CBFS_COMPRESS_LZMA;
121         }
122         if (argc > 6) {
123                 base = strtoul(argv[6], NULL, 0);
124         }
125         unsigned char *payload;
126         filesize = parse_elf_to_payload(filedata, &payload, algo);
127         cbfsfile =
128             create_cbfs_file(cbfsname, payload, &filesize,
129                              CBFS_COMPONENT_PAYLOAD, &base);
130         add_file_to_cbfs(cbfsfile, filesize, base);
131         writerom(romname, rom, romsize);
132         return 0;
133 }
134
135 static int cbfs_add_stage(int argc, char **argv)
136 {
137         char *romname = argv[1];
138         char *cmd = argv[2];
139         void *rom = loadrom(romname);
140
141         if (rom == NULL) {
142                 printf("Could not load ROM image '%s'.\n", romname);
143                 return 1;
144         }
145
146         if (argc < 5) {
147                 printf("not enough arguments to '%s'.\n", cmd);
148                 return 1;
149         }
150
151         char *filename = argv[3];
152         char *cbfsname = argv[4];
153
154         uint32_t filesize = 0;
155         void *filedata = loadfile(filename, &filesize, 0, SEEK_SET);
156         if (filedata == NULL) {
157                 printf("Could not load file '%s'.\n", filename);
158                 return 1;
159         }
160
161         uint32_t base = 0;
162         void *cbfsfile = NULL;
163
164         comp_algo algo = CBFS_COMPRESS_NONE;
165         if (argc > 5) {
166                 if (argv[5][0] == 'l')
167                         algo = CBFS_COMPRESS_LZMA;
168         }
169         if (argc > 6) {
170                 base = strtoul(argv[6], NULL, 0);
171         }
172         unsigned char *stage;
173         filesize = parse_elf_to_stage(filedata, &stage, algo, &base);
174         cbfsfile =
175             create_cbfs_file(cbfsname, stage, &filesize,
176                              CBFS_COMPONENT_STAGE, &base);
177
178         add_file_to_cbfs(cbfsfile, filesize, base);
179         writerom(romname, rom, romsize);
180         return 0;
181 }
182
183 static int cbfs_create(int argc, char **argv)
184 {
185         char *romname = argv[1];
186         char *cmd = argv[2];
187         if (argc < 6) {
188                 printf("not enough arguments to 'create'.\n");
189                 return 1;
190         }
191
192         uint32_t size = strtoul(argv[3], NULL, 0);
193         /* ignore bootblock size. we use whatever we get and won't allocate any larger */
194         char *bootblock = argv[5];
195         uint32_t align = 0;
196
197         if (argc > 6)
198                 align = strtoul(argv[6], NULL, 0);
199
200         return create_cbfs_image(romname, size, bootblock, align);
201 }
202
203 static int cbfs_print(int argc, char **argv)
204 {
205         char *romname = argv[1];
206         char *cmd = argv[2];
207         void *rom = loadrom(romname);
208
209         if (rom == NULL) {
210                 printf("Could not load ROM image '%s'.\n", romname);
211                 return 1;
212         }
213
214         print_cbfs_directory(romname);
215         return 0;
216 }
217
218 struct command commands[] = {
219         {CMD_ADD, "add", cbfs_add},
220         {CMD_ADD_PAYLOAD, "add-payload", cbfs_add_payload},
221         {CMD_ADD_STAGE, "add-stage", cbfs_add_stage},
222         {CMD_CREATE, "create", cbfs_create},
223         {CMD_PRINT, "print", cbfs_print}
224 };
225
226 void usage(void)
227 {
228         printf
229             ("cbfstool: Management utility for CBFS formatted ROM images\n"
230              "USAGE:\n" "cbfstool [-h]\n"
231              "cbfstool FILE COMMAND [PARAMETERS]...\n\n" "OPTIONs:\n"
232              " -h               Display this help message\n\n"
233              "COMMANDs:\n"
234              "add FILE NAME TYPE [base address]    Add a component\n"
235              "add-payload FILE NAME [COMP] [base]  Add a payload to the ROM\n"
236              "add-stage FILE NAME [COMP] [base]    Add a stage to the ROM\n"
237              "create SIZE BSIZE BOOTBLOCK [ALIGN]  Create a ROM file\n"
238              "print                                Show the contents of the ROM\n");
239 }
240
241 int main(int argc, char **argv)
242 {
243         int i;
244
245         if (argc < 3) {
246                 usage();
247                 return 1;
248         }
249
250         char *cmd = argv[2];
251
252         for (i = 0; i < ARRAY_SIZE(commands); i++) {
253                 if (strcmp(cmd, commands[i].name) != 0)
254                         continue;
255                 return commands[i].function(argc, argv);
256         }
257
258         printf("Unknown command '%s'.\n", cmd);
259         usage();
260         return 1;
261 }