1 /*
2  * Copyright (c) 2014 Brian Swetland
3  *
4  * Use of this source code is governed by a MIT-style
5  * license that can be found in the LICENSE file or at
6  * https://opensource.org/licenses/MIT
7  */
8 
9 #include <stdio.h>
10 #include <stdlib.h>
11 #include <string.h>
12 #include <unistd.h>
13 #include <fcntl.h>
14 
15 #include "bootimage.h"
16 
17 static const char *outname = "boot.img";
18 
19 static struct {
20     const char *cmd;
21     unsigned kind;
22     unsigned type;
23 } types[] = {
24     { "lk", KIND_FILE, TYPE_LK },
25     { "fpga", KIND_FILE, TYPE_FPGA_IMAGE },
26     { "linux", KIND_FILE, TYPE_LINUX_KERNEL },
27     { "initrd", KIND_FILE, TYPE_LINUX_INITRD },
28     { "devicetree", KIND_FILE, TYPE_DEVICE_TREE },
29     { "sysparams", KIND_FILE, TYPE_SYSPARAMS },
30     { "board", KIND_BOARD, 0 },
31     { "build", KIND_BUILD, 0 },
32     { NULL, 0 },
33 };
34 
usage(const char * binary)35 void usage(const char *binary) {
36     unsigned n;
37     fprintf(stderr, "usage:\n");
38     fprintf(stderr, "%s [-h] [-o <output file] section:file ...\n\n", binary);
39 
40     fprintf(stderr, "Supported section types:\n");
41     for (n = 0; types[n].cmd != NULL; n++) {
42         if (types[n].kind == KIND_FILE) {
43             fprintf(stderr, "\t%s\n", types[n].cmd);
44         }
45     }
46 
47     fprintf(stderr, "\nSupported string types:\n");
48     for (n = 0; types[n].cmd != NULL; n++) {
49         if (types[n].kind != KIND_FILE) {
50             fprintf(stderr, "\t%s\n", types[n].cmd);
51         }
52     }
53 }
54 
process(bootimage * img,char * cmd,char * arg)55 int process(bootimage *img, char *cmd, char *arg) {
56     unsigned n;
57 
58     for (n = 0; types[n].cmd != NULL; n++) {
59         if (strcmp(cmd, types[n].cmd)) {
60             continue;
61         }
62         if (types[n].kind == KIND_FILE) {
63             if (bootimage_add_file(img, types[n].type, arg) == NULL) {
64                 return -1;
65             }
66         } else {
67             if (bootimage_add_string(img, types[n].kind, arg) == NULL) {
68                 return -1;
69             }
70         }
71         return 0;
72     }
73 
74     fprintf(stderr, "unknown command '%s'\n", cmd);
75     return -1;
76 }
77 
main(int argc,char ** argv)78 int main(int argc, char **argv) {
79     const char *binary = argv[0];
80     bootimage *img;
81     int fd;
82     int count = 0;
83 
84     img = bootimage_init();
85 
86     while (argc > 1) {
87         char *cmd = argv[1];
88         char *arg = strchr(cmd, ':');
89         argc--;
90         argv++;
91 
92         if (!strcmp(cmd, "-h") || !strcmp(cmd, "--help")) {
93             usage(binary);
94             return 1;
95         } else if (!strcmp(cmd, "-o")) {
96             outname = argv[1];
97             argc--;
98             argv++;
99         } else {
100             if (arg == NULL) {
101                 fprintf(stderr, "error: invalid argument '%s'\n", cmd);
102                 return 1;
103             }
104 
105             *arg++ = 0;
106 
107             if (process(img, cmd, arg)) {
108                 return 1;
109             }
110             count++;
111         }
112     }
113 
114     if (count == 0) {
115         fprintf(stderr, "no sections to process\n");
116         return 1;
117     }
118 
119     bootimage_done(img);
120 
121     if ((fd = open(outname, O_CREAT|O_TRUNC|O_WRONLY, 0644)) < 0) {
122         fprintf(stderr, "error: cannot open '%s' for writing\n", outname);
123         return 1;
124     }
125     if (bootimage_write(img, fd)) {
126         fprintf(stderr, "error: failed to write '%s'\n", outname);
127         unlink(outname);
128         return 1;
129     }
130     close(fd);
131     return 0;
132 }
133