blob: 798ce0487aa7160b250fd6eda83556e255135b45 [file] [log] [blame]
Peer Chen8d782ee2011-01-18 21:34:18 -05001/**
2 * Copyright (c) 2011 NVIDIA Corporation. All rights reserved.
3 *
4 * See file CREDITS for list of people who contributed to this
5 * project.
6 *
7 * This program is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU General Public License as
9 * published by the Free Software Foundation; either version 2 of
10 * the License, or (at your option) any later version.
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., 59 Temple Place, Suite 330, Boston,
20 * MA 02111-1307 USA
21 */
22
23/*
24 * cbootimage.c - Implementation of the cbootimage tool.
25 */
26
27#include "cbootimage.h"
28#include "nvbctlib.h"
29#include "crypto.h"
30#include "data_layout.h"
31#include "parse.h"
32#include "set.h"
33
34/*
35 * Global data
36 */
37int enable_debug = 0;
38
39static int help_only = 0; // Only print help & exit
40
41/*
42 * Function prototypes
43 */
44int main(int argc, char *argv[]);
45
46static int
47query_alloc(build_image_context *context,
48 nvbct_lib_id size_id,
49 u_int8_t **dst)
50{
51 u_int32_t size;
52
53 /* Note: 3rd argument not used in this particular query. */
54 if (context->bctlib.get_value(size_id,
55 &size, context->bct) != 0)
56 return -ENODATA;
57 *dst = malloc(size);
58
59 if (*dst == NULL)
60 return -ENOMEM;
61
62 memset(*dst, 0, size);
63
64 return 0;
65}
66
67static void
68cleanup_context(build_image_context *context)
69{
70 destroy_block_list(context->memory);
71 destroy_addon_list(context->addon_tbl.addon_item_list);
72 free(context->bct);
73}
74
75static int
76init_context(build_image_context *context)
77{
78 int e = 0;
79
80 /* Set defaults */
81 context->memory = new_block_list();
82 context->journal_blk = 1; /* Default to 1st block */
83
84 /* Allocate space for the bct.
85 * Note that this is different from the old code which pointed directly
86 * into a memory image.
87 */
88 e = query_alloc(context, nvbct_lib_id_bct_size, &(context->bct));
89 if (e != 0)
90 goto fail;
91
92 context_set_value(context, token_page_size, 2048);
93 context_set_value(context, token_redundancy, 1);
94 context_set_value(context, token_version, 1);
95
96 return 0;
97
98 fail:
99 cleanup_context(context);
100
101 return e;
102}
103
104int
105write_image_file(build_image_context *context)
106{
107 assert(context != NULL);
108
109 return write_block_raw(context);
110}
111
112static void
113usage(void)
114{
115 printf("Usage: cbootimage [options] configfile imagename\n");
116 printf(" options:\n");
117 printf(" -h, --help, -? Display this message.\n");
118 printf(" -d, --debug Output debugging information.\n");
119 printf(" configfile File with configuration information\n");
120 printf(" imagename Output image name\n");
121}
122
123static int
124process_command_line(int argc, char *argv[], build_image_context *context)
125{
126 int arg = 1;
127
128 while (arg < argc) {
129 /* Process the next argument. */
130 if (!strcmp(argv[arg], "-h") ||
131 !strcmp(argv[arg], "--help") ||
132 !strcmp(argv[arg], "-?")) {
133 help_only = 1;
134 usage();
135 return 0;
136 } else if (!strcmp(argv[arg], "-d") ||
137 !strcmp(argv[arg], "--debug")) {
138 enable_debug = 1;
139 arg++;
140 } else if (argv[arg][0] == '-') {
141 printf("Illegal option %s\n", argv[arg]);
142 usage();
143 return -EINVAL;
144 }
145 else
146 break; /* Finished with options */
147 }
148
149 /* Handle file specification errors. */
150 switch (argc - arg) {
151 case 0:
152 printf("Missing configuration and image file names.\n");
153 usage();
154 return -EINVAL;
155
156 case 1:
157 printf("Missing configuration or image file name.\n");
158 usage();
159 return -EINVAL;
160
161 case 2:
162 /* Correct args, so break from the switch statement. */
163 break;
164
165 default:
166 printf("Too many arguments.\n");
167 usage();
168 return -EINVAL;
169 }
170
171 /* Open the configuration file. */
172 context->config_file = fopen(argv[arg], "r");
173 if (context->config_file == NULL) {
174 printf("Error opening config file.\n");
175 return -ENODATA;
176 }
177
178 /* Record the output filename */
179 context->image_filename = argv[arg + 1];
180
181 /* Set up the Nvbctlib function pointers. */
182 nvbct_lib_get_fns(&(context->bctlib));
183
184 return 0;
185}
186
187int
188main(int argc, char *argv[])
189{
190 int e = 0;
191 build_image_context context;
192 u_int32_t data = 0;
193
194 memset(&context, 0, sizeof(build_image_context));
195
196 /* Process command line arguments. */
197 if (process_command_line(argc, argv, &context) != 0)
198 return -EINVAL;
199
200 if (help_only)
201 return 1;
202
203 e = init_context(&context);
204 if (e != 0) {
205 printf("context initialization failed. Aborting.\n");
206 return e;
207 }
208
209 if (enable_debug) {
210 /* Debugging information... */
211 e = context.bctlib.get_value(nvbct_lib_id_bct_size,
212 &data, context.bct);
213 printf("bct size: %d\n", e == 0 ? data : -1);
214 }
215
216 /* Open the raw output file. */
217 context.raw_file = fopen(context.image_filename,
218 "w+");
219 if (context.raw_file == NULL) {
220 printf("Error opening raw file %s.\n",
221 context.image_filename);
222 goto fail;
223 }
224
225 /* Parse & process the contents of the config file. */
226 process_config_file(&context);
227
228 /* Update the bct file */
229 /* Update the add on file */
230 e = update_addon_item(&context);
231 if ( e!= 0) {
232 printf("Write addon item failed, error: %d.\n", e);
233 goto fail;
234 }
235 /* Peform final signing & encryption of bct. */
236 e = sign_bct(&context, context.bct);
237 if (e != 0) {
238 printf("Signing BCT failed, error: %d.\n", e);
239 goto fail;
240 }
241 /* Write the image file. */
242 /* The image hasn't been written yet. */
243 if (write_image_file(&context) != 0)
244 printf("Error writing image file.\n");
245 else
246 printf("Image file %s has been successfully generated!\n",
247 context.image_filename);
248
249 fail:
250 /* Close the file(s). */
251 if (context.raw_file)
252 fclose(context.raw_file);
253
254 /* Clean up memory. */
255 cleanup_context(&context);
256
257 return e;
258}