1 /*
2  * Copyright (c) 2014 Brian Swetland
3  *
4  * Permission is hereby granted, free of charge, to any person obtaining
5  * a copy of this software and associated documentation files
6  * (the "Software"), to deal in the Software without restriction,
7  * including without limitation the rights to use, copy, modify, merge,
8  * publish, distribute, sublicense, and/or sell copies of the Software,
9  * and to permit persons to whom the Software is furnished to do so,
10  * subject to the following conditions:
11  *
12  * The above copyright notice and this permission notice shall be
13  * included in all copies or substantial portions of the Software.
14  *
15  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
16  * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
17  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
18  * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
19  * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
20  * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
21  * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
22  */
23 
24 #include <stdio.h>
25 #include <stdlib.h>
26 #include <string.h>
27 #include <unistd.h>
28 #include <fcntl.h>
29 
30 #include "bootimage.h"
31 
32 static const char *outname = "boot.img";
33 
34 static struct {
35     const char *cmd;
36     unsigned kind;
37     unsigned type;
38 } types[] = {
39     { "lk", KIND_FILE, TYPE_LK },
40     { "fpga", KIND_FILE, TYPE_FPGA_IMAGE },
41     { "linux", KIND_FILE, TYPE_LINUX_KERNEL },
42     { "initrd", KIND_FILE, TYPE_LINUX_INITRD },
43     { "devicetree", KIND_FILE, TYPE_DEVICE_TREE },
44     { "sysparams", KIND_FILE, TYPE_SYSPARAMS },
45     { "board", KIND_BOARD, 0 },
46     { "build", KIND_BUILD, 0 },
47     { NULL, 0 },
48 };
49 
usage(const char * binary)50 void usage(const char *binary)
51 {
52     unsigned n;
53     fprintf(stderr, "usage:\n");
54     fprintf(stderr, "%s [-h] [-o <output file] section:file ...\n\n", binary);
55 
56     fprintf(stderr, "Supported section types:\n");
57     for (n = 0; types[n].cmd != NULL; n++) {
58         if (types[n].kind == KIND_FILE) {
59             fprintf(stderr, "\t%s\n", types[n].cmd);
60         }
61     }
62 
63     fprintf(stderr, "\nSupported string types:\n");
64     for (n = 0; types[n].cmd != NULL; n++) {
65         if (types[n].kind != KIND_FILE) {
66             fprintf(stderr, "\t%s\n", types[n].cmd);
67         }
68     }
69 }
70 
process(bootimage * img,char * cmd,char * arg)71 int process(bootimage *img, char *cmd, char *arg)
72 {
73     unsigned n;
74 
75     for (n = 0; types[n].cmd != NULL; n++) {
76         if (strcmp(cmd, types[n].cmd)) {
77             continue;
78         }
79         if (types[n].kind == KIND_FILE) {
80             if (bootimage_add_file(img, types[n].type, arg) == NULL) {
81                 return -1;
82             }
83         } else {
84             if (bootimage_add_string(img, types[n].kind, arg) == NULL) {
85                 return -1;
86             }
87         }
88         return 0;
89     }
90 
91     fprintf(stderr, "unknown command '%s'\n", cmd);
92     return -1;
93 }
94 
main(int argc,char ** argv)95 int main(int argc, char **argv)
96 {
97     const char *binary = argv[0];
98     bootimage *img;
99     int fd;
100     int count = 0;
101 
102     img = bootimage_init();
103 
104     while (argc > 1) {
105         char *cmd = argv[1];
106         char *arg = strchr(cmd, ':');
107         argc--;
108         argv++;
109 
110         if (!strcmp(cmd, "-h") || !strcmp(cmd, "--help")) {
111             usage(binary);
112             return 1;
113         } else if (!strcmp(cmd, "-o")) {
114             outname = argv[1];
115             argc--;
116             argv++;
117         } else {
118             if (arg == NULL) {
119                 fprintf(stderr, "error: invalid argument '%s'\n", cmd);
120                 return 1;
121             }
122 
123             *arg++ = 0;
124 
125             if (process(img, cmd, arg)) {
126                 return 1;
127             }
128             count++;
129         }
130     }
131 
132     if (count == 0) {
133         fprintf(stderr, "no sections to process\n");
134         return 1;
135     }
136 
137     bootimage_done(img);
138 
139     if ((fd = open(outname, O_CREAT|O_TRUNC|O_WRONLY, 0644)) < 0) {
140         fprintf(stderr, "error: cannot open '%s' for writing\n", outname);
141         return 1;
142     }
143     if (bootimage_write(img, fd)) {
144         fprintf(stderr, "error: failed to write '%s'\n", outname);
145         unlink(outname);
146         return 1;
147     }
148     close(fd);
149     return 0;
150 }
151