blob: 2de9b7439883910b78779d9c022cb65e396cf5bd [file] [log] [blame]
Kinson Chik6a7be432010-11-08 17:13:02 -08001/*
2 * Copyright (c) 2007, Google Inc.
3 * All rights reserved.
4 *
Duy Truongf3ac7b32013-02-13 01:07:28 -08005 * Copyright (c) 2009-2010, The Linux Foundation. All rights reserved.
Kinson Chik6a7be432010-11-08 17:13:02 -08006 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * * Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * * Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in
14 * the documentation and/or other materials provided with the
15 * distribution.
16 * * Neither the name of Google, Inc. nor the names of its contributors
17 * may be used to endorse or promote products derived from this
18 * software without specific prior written permission.
19 *
20 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
21 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
22 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
23 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
24 * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
25 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
26 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
27 * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
28 * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
29 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
30 * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
31 * SUCH DAMAGE.
32 */
Chandan Uddarajua9b07bb2009-11-21 12:22:02 -080033
34#include <stdio.h>
35#include <stdlib.h>
36#include <unistd.h>
37#include <fcntl.h>
Kinson Chik6a7be432010-11-08 17:13:02 -080038#include <string.h>
Chandan Uddarajua9b07bb2009-11-21 12:22:02 -080039
40#include <sys/stat.h>
41
Ajay Dudanib01e5062011-12-03 23:23:42 -080042int print_usage()
43{
44 fprintf(stderr, "usage: mkheader <bin> <hdr> <none|unified-boot>\n");
45 fprintf(stderr,
46 " mkheader <bin> <hdr> <unsecure-boot> <outbin>\n");
47 fprintf(stderr,
48 " mkheader <bin> <hdr> <secure-boot> <outbin> <maxsize>\n");
49 fprintf(stderr,
50 " mkheader <bin> <hdr> <secure-boot> <outbin> <maxsize> <certchain> <files...>\n\n");
51 fprintf(stderr, "bin: Input raw appsbl binary\n");
52 fprintf(stderr,
53 "hdr: Output of appsbl header location\n");
54 fprintf(stderr,
55 "outbin: Output of the signed or unsigned apps boot location\n");
56 fprintf(stderr,
57 "maxsize: Maximum size for certificate chain\n");
58 fprintf(stderr,
59 "certchain: Output of the certchain location\n");
60 fprintf(stderr,
61 "files: Input format <bin signature> <certifcate file(s) for certificate chain>...\n");
62 fprintf(stderr,
63 "certificate chain: Files will be concatenated in order to create the certificate chain\n\n");
Kinson Chik6a7be432010-11-08 17:13:02 -080064 return -1;
65}
66
Ajay Dudanib01e5062011-12-03 23:23:42 -080067int cat(FILE * in, FILE * out, unsigned size, unsigned buff_size)
68{
Kinson Chik6a7be432010-11-08 17:13:02 -080069 unsigned bytes_left = size;
70 char buf[buff_size];
71 int ret = 0;
72
Ajay Dudanib01e5062011-12-03 23:23:42 -080073 while (bytes_left) {
Kinson Chik6a7be432010-11-08 17:13:02 -080074 fread(buf, sizeof(char), buff_size, in);
Ajay Dudanib01e5062011-12-03 23:23:42 -080075 if (!feof(in)) {
Kinson Chik6a7be432010-11-08 17:13:02 -080076 bytes_left -= fwrite(buf, sizeof(char), buff_size, out);
Ajay Dudanib01e5062011-12-03 23:23:42 -080077 } else
Kinson Chik6a7be432010-11-08 17:13:02 -080078 bytes_left = 0;
79 }
80 ret = ferror(in) | ferror(out);
Ajay Dudanib01e5062011-12-03 23:23:42 -080081 if (ret)
Kinson Chik6a7be432010-11-08 17:13:02 -080082 fprintf(stderr, "ERROR: Occured during file concatenation\n");
83 return ret;
84}
85
Chandan Uddarajua9b07bb2009-11-21 12:22:02 -080086int main(int argc, char *argv[])
87{
88 struct stat s;
89 unsigned size, base;
90 int unified_boot = 0;
91 unsigned unified_boot_magic[20];
92 unsigned non_unified_boot_magic[10];
93 unsigned magic_len = 0;
94 unsigned *magic;
Kinson Chik6a7be432010-11-08 17:13:02 -080095 unsigned cert_chain_size = 0;
96 unsigned signature_size = 0;
97 int secure_boot = 0;
Chandan Uddarajua9b07bb2009-11-21 12:22:02 -080098 int fd;
99
Ajay Dudanib01e5062011-12-03 23:23:42 -0800100 if (argc < 3) {
Kinson Chik6a7be432010-11-08 17:13:02 -0800101 return print_usage();
Chandan Uddarajua9b07bb2009-11-21 12:22:02 -0800102 }
103
104 if (argc == 4) {
Ajay Dudanib01e5062011-12-03 23:23:42 -0800105 if (!strcmp("unified-boot", argv[3])) {
Chandan Uddarajua9b07bb2009-11-21 12:22:02 -0800106 unified_boot = 1;
Ajay Dudanib01e5062011-12-03 23:23:42 -0800107 } else if (!strcmp("secure-boot", argv[3])) {
Kinson Chik6a7be432010-11-08 17:13:02 -0800108 fprintf(stderr,
109 "ERROR: Missing arguments: [outbin maxsize] | [outbin, maxsize, certchain, signature + certifcate(s)]\n");
110 return print_usage();
Ajay Dudanib01e5062011-12-03 23:23:42 -0800111 } else if (!strcmp("unsecure-boot", argv[3])) {
112 fprintf(stderr,
113 "ERROR: Missing arguments: outbin directory\n");
Kinson Chik6a7be432010-11-08 17:13:02 -0800114 return print_usage();
115 }
116 }
117
118 if (argc > 4) {
Ajay Dudanib01e5062011-12-03 23:23:42 -0800119 if (!strcmp("secure-boot", argv[3])) {
120 if (argc < 9 && argc != 6) {
Kinson Chik6a7be432010-11-08 17:13:02 -0800121 fprintf(stderr,
122 "ERROR: Missing argument(s): [outbin maxsize] | [outbin, maxsize, certchain, signature + certifcate(s)]\n");
123 return print_usage();
Ajay Dudanib01e5062011-12-03 23:23:42 -0800124 }
125 secure_boot = 1;
126 signature_size = 256; //Support SHA 256
Kinson Chik6a7be432010-11-08 17:13:02 -0800127 cert_chain_size = atoi(argv[5]);
Ajay Dudanib01e5062011-12-03 23:23:42 -0800128 }
Chandan Uddarajua9b07bb2009-11-21 12:22:02 -0800129 }
130
Ajay Dudanib01e5062011-12-03 23:23:42 -0800131 if (stat(argv[1], &s)) {
Chandan Uddarajua9b07bb2009-11-21 12:22:02 -0800132 perror("cannot stat binary");
133 return -1;
134 }
135
Ajay Dudanib01e5062011-12-03 23:23:42 -0800136 if (unified_boot) {
Chandan Uddarajua9b07bb2009-11-21 12:22:02 -0800137 magic = unified_boot_magic;
138 magic_len = sizeof(unified_boot_magic);
139 } else {
140 magic = non_unified_boot_magic;
141 magic_len = sizeof(non_unified_boot_magic);
142 }
143
144 size = s.st_size;
David Ng6e1711f2010-01-19 15:27:00 -0800145#if MEMBASE
146 base = MEMBASE;
147#else
Chandan Uddarajua9b07bb2009-11-21 12:22:02 -0800148 base = 0;
David Ng6e1711f2010-01-19 15:27:00 -0800149#endif
Chandan Uddarajua9b07bb2009-11-21 12:22:02 -0800150
Kinson Chikc874a2b2010-11-16 18:24:05 -0800151 printf("Image Destination Pointer: 0x%x\n", base);
152
Ajay Dudanib01e5062011-12-03 23:23:42 -0800153 magic[0] = 0x00000005; /* appsbl */
154 magic[1] = 0x00000003; //Flash_partition_version /* nand */
155 magic[2] = 0x00000000; //image source pointer
156 magic[3] = base; //image destination pointer
157 magic[4] = size + cert_chain_size + signature_size; //image size
158 magic[5] = size; //code size
Kinson Chik6a7be432010-11-08 17:13:02 -0800159 magic[6] = base + size;
160 magic[7] = signature_size;
161 magic[8] = size + base + signature_size;
162 magic[9] = cert_chain_size;
Chandan Uddarajua9b07bb2009-11-21 12:22:02 -0800163
Ajay Dudanib01e5062011-12-03 23:23:42 -0800164 if (unified_boot == 1) {
165 magic[10] = 0x33836685; /* cookie magic number */
166 magic[11] = 0x00000001; /* cookie version */
167 magic[12] = 0x00000002; /* file formats */
Chandan Uddarajua9b07bb2009-11-21 12:22:02 -0800168 magic[13] = 0x00000000;
Ajay Dudanib01e5062011-12-03 23:23:42 -0800169 magic[14] = 0x00000000; /* not setting size for boot.img */
Chandan Uddarajua9b07bb2009-11-21 12:22:02 -0800170 magic[15] = 0x00000000;
171 magic[16] = 0x00000000;
172 magic[17] = 0x00000000;
173 magic[18] = 0x00000000;
174 magic[19] = 0x00000000;
175 }
176
177 fd = open(argv[2], O_WRONLY | O_CREAT | O_TRUNC, 0644);
Ajay Dudanib01e5062011-12-03 23:23:42 -0800178 if (fd < 0) {
Chandan Uddarajua9b07bb2009-11-21 12:22:02 -0800179 perror("cannot open header for writing");
180 return -1;
181 }
Ajay Dudanib01e5062011-12-03 23:23:42 -0800182 if (write(fd, magic, magic_len) != magic_len) {
Chandan Uddarajua9b07bb2009-11-21 12:22:02 -0800183 perror("cannot write header");
184 close(fd);
185 unlink(argv[2]);
186 return -1;
187 }
188 close(fd);
189
Ajay Dudanib01e5062011-12-03 23:23:42 -0800190 if (secure_boot && argc > 6) {
191 FILE *input_file;
192 FILE *output_file;
Kinson Chik6a7be432010-11-08 17:13:02 -0800193 unsigned buff_size = 1;
194 char buf[buff_size];
195 unsigned bytes_left;
196 unsigned current_cert_chain_size = 0;
197 int padding_size = 0;
198 int i;
199
Ajay Dudanib01e5062011-12-03 23:23:42 -0800200 if ((output_file = fopen(argv[6], "wb")) == NULL) {
Kinson Chik6a7be432010-11-08 17:13:02 -0800201 perror("ERROR: Occured during fopen");
202 return -1;
203 }
Kinson Chikc874a2b2010-11-16 18:24:05 -0800204 printf("Certificate Chain Output File: %s\n", argv[6]);
Kinson Chik6a7be432010-11-08 17:13:02 -0800205
Ajay Dudanib01e5062011-12-03 23:23:42 -0800206 for (i = 8; i < argc; i++) {
207 if ((input_file = fopen(argv[i], "rb")) == NULL) {
Kinson Chik6a7be432010-11-08 17:13:02 -0800208 perror("ERROR: Occured during fopen");
209 return -1;
210 }
211 stat(argv[i], &s);
212 bytes_left = s.st_size;
213 current_cert_chain_size += bytes_left;
214 if (cat(input_file, output_file, bytes_left, buff_size))
215 return -1;
216 fclose(input_file);
217 }
218
219 //Pad certifcate chain to the max expected size from input
220 memset(buf, 0xFF, sizeof(buf));
221 padding_size = cert_chain_size - current_cert_chain_size;
Kinson Chik kchik@codeaurora.org1cb7b4d2010-12-15 15:00:59 -0800222
Ajay Dudanib01e5062011-12-03 23:23:42 -0800223 if (padding_size < 0) {
224 fprintf(stderr,
225 "ERROR: Input certificate chain (Size=%d) is larger than the maximum specified (Size=%d)\n",
Kinson Chik kchik@codeaurora.org1cb7b4d2010-12-15 15:00:59 -0800226 current_cert_chain_size, cert_chain_size);
227 return -1;
228 }
229
Kinson Chik6a7be432010-11-08 17:13:02 -0800230 bytes_left = (padding_size > 0) ? padding_size : 0;
Ajay Dudanib01e5062011-12-03 23:23:42 -0800231 while (bytes_left) {
232 if (!ferror(output_file))
233 bytes_left -=
234 fwrite(buf, sizeof(buf), buff_size,
235 output_file);
236 else {
237 fprintf(stderr,
238 "ERROR: Occured during certifcate chain padding\n");
Kinson Chik6a7be432010-11-08 17:13:02 -0800239 return -1;
240 }
241 }
242 fclose(output_file);
243
244 //Concat and combine to signed image. Format [HDR][RAW APPSBOOT][PADDED CERT CHAIN]
Ajay Dudanib01e5062011-12-03 23:23:42 -0800245 if ((output_file = fopen(argv[4], "wb")) == NULL) {
Kinson Chik6a7be432010-11-08 17:13:02 -0800246 perror("ERROR: Occured during fopen");
247 return -1;
248 }
Kinson Chikc874a2b2010-11-16 18:24:05 -0800249 printf("Image Output File: %s\n", argv[4]);
Kinson Chik6a7be432010-11-08 17:13:02 -0800250
251 //Header
Ajay Dudanib01e5062011-12-03 23:23:42 -0800252 if ((input_file = fopen(argv[2], "rb")) == NULL) {
Kinson Chik6a7be432010-11-08 17:13:02 -0800253 perror("ERROR: Occured during fopen");
254 return -1;
255 }
256 stat(argv[2], &s);
257 if (cat(input_file, output_file, s.st_size, buff_size))
258 return -1;
259 fclose(input_file);
260
261 //Raw Appsbl
Ajay Dudanib01e5062011-12-03 23:23:42 -0800262 if ((input_file = fopen(argv[1], "rb")) == NULL) {
Kinson Chik6a7be432010-11-08 17:13:02 -0800263 perror("ERROR: Occured during fopen");
264 return -1;
265 }
266 stat(argv[1], &s);
Ajay Dudanib01e5062011-12-03 23:23:42 -0800267 if (cat(input_file, output_file, s.st_size, buff_size))
Kinson Chik6a7be432010-11-08 17:13:02 -0800268 return -1;
269 fclose(input_file);
270
271 //Signature
Ajay Dudanib01e5062011-12-03 23:23:42 -0800272 if ((input_file = fopen(argv[7], "rb")) == NULL) {
Kinson Chik6a7be432010-11-08 17:13:02 -0800273 perror("ERROR: Occured during fopen");
274 return -1;
275 }
276 stat(argv[7], &s);
Ajay Dudanib01e5062011-12-03 23:23:42 -0800277 if (cat(input_file, output_file, s.st_size, buff_size))
Kinson Chik6a7be432010-11-08 17:13:02 -0800278 return -1;
279 fclose(input_file);
280
281 //Certifcate Chain
Ajay Dudanib01e5062011-12-03 23:23:42 -0800282 if ((input_file = fopen(argv[6], "rb")) == NULL) {
Kinson Chik6a7be432010-11-08 17:13:02 -0800283 perror("ERROR: Occured during fopen");
284 return -1;
285 }
Ajay Dudanib01e5062011-12-03 23:23:42 -0800286 if (cat
287 (input_file, output_file,
288 (current_cert_chain_size + padding_size), buff_size))
Kinson Chik6a7be432010-11-08 17:13:02 -0800289 return -1;
290 fclose(input_file);
291
292 fclose(output_file);
293
Ajay Dudanib01e5062011-12-03 23:23:42 -0800294 } else if (argc == 5 || argc == 6) {
295 FILE *input_file;
296 FILE *output_file;
Kinson Chik6a7be432010-11-08 17:13:02 -0800297 unsigned buff_size = 1;
298 char buf[buff_size];
299
300 //Concat and combine to unsigned image. Format [HDR][RAW APPSBOOT]
Ajay Dudanib01e5062011-12-03 23:23:42 -0800301 if ((output_file = fopen(argv[4], "wb")) == NULL) {
Kinson Chik6a7be432010-11-08 17:13:02 -0800302 perror("ERROR: Occured during fopen");
303 return -1;
304 }
Kinson Chikc874a2b2010-11-16 18:24:05 -0800305 printf("Image Output File: %s\n", argv[4]);
Kinson Chik6a7be432010-11-08 17:13:02 -0800306
307 //Header
Ajay Dudanib01e5062011-12-03 23:23:42 -0800308 if ((input_file = fopen(argv[2], "rb")) == NULL) {
Kinson Chik6a7be432010-11-08 17:13:02 -0800309 perror("ERROR: Occured during fopen");
310 return -1;
311 }
312 stat(argv[2], &s);
313 if (cat(input_file, output_file, s.st_size, buff_size))
314 return -1;
315 fclose(input_file);
316
317 //Raw Appsbl
Ajay Dudanib01e5062011-12-03 23:23:42 -0800318 if ((input_file = fopen(argv[1], "rb")) == NULL) {
Kinson Chik6a7be432010-11-08 17:13:02 -0800319 perror("ERROR: Occured during fopen");
320 return -1;
321 }
322 stat(argv[1], &s);
Ajay Dudanib01e5062011-12-03 23:23:42 -0800323 if (cat(input_file, output_file, s.st_size, buff_size))
Kinson Chik6a7be432010-11-08 17:13:02 -0800324 return -1;
325 fclose(input_file);
326 fclose(output_file);
327 }
328
Kinson Chikc874a2b2010-11-16 18:24:05 -0800329 printf("Done execution\n");
330
Chandan Uddarajua9b07bb2009-11-21 12:22:02 -0800331 return 0;
332}