firmware-utils: replace GPL 2.0 boilerplate/reference with SPDX
[openwrt/staging/ldir.git] / tools / firmware-utils / src / mkbuffaloimg.c
1 // SPDX-License-Identifier: GPL-2.0-only
2 /*
3 * Copyright (C) 2009 Gabor Juhos <juhosg@openwrt.org>
4 * Copyright (C) 2016 FUKAUMI Naoki <naobsd@gmail.com>
5 *
6 * Based on mkdniimg.c
7 */
8
9 #include <stdio.h>
10 #include <stdlib.h>
11 #include <stdint.h>
12 #include <string.h>
13 #include <unistd.h> /* for unlink() */
14 #include <libgen.h>
15 #include <getopt.h> /* for getopt() */
16 #include <stdarg.h>
17 #include <errno.h>
18 #include <sys/stat.h>
19
20 #define DNI_HDR_LEN 128
21
22 /*
23 * Globals
24 */
25 static char *ifname;
26 static char *progname;
27 static char *ofname;
28 static char *version = "0.00_0.00";
29 static char *region = "JP";
30 static char *rootfs_size;
31 static char *kernel_size;
32
33 static char *board_id;
34 /*
35 * Message macros
36 */
37 #define ERR(fmt, ...) do { \
38 fflush(0); \
39 fprintf(stderr, "[%s] *** error: " fmt "\n", \
40 progname, ## __VA_ARGS__ ); \
41 } while (0)
42
43 #define ERRS(fmt, ...) do { \
44 int save = errno; \
45 fflush(0); \
46 fprintf(stderr, "[%s] *** error: " fmt ": %s\n", \
47 progname, ## __VA_ARGS__, strerror(save)); \
48 } while (0)
49
50 void usage(int status)
51 {
52 FILE *stream = (status != EXIT_SUCCESS) ? stderr : stdout;
53
54 fprintf(stream, "Usage: %s [OPTIONS...]\n", progname);
55 fprintf(stream,
56 "\n"
57 "Options:\n"
58 " -B <board> create image for the board specified with <board>\n"
59 " -i <file> read input from the file <file>\n"
60 " -o <file> write output to the file <file>\n"
61 " -v <version> set image version to <version>\n"
62 " -r <region> set image region to <region>\n"
63 " -R <rootfs_size> set RootfsSize to <rootfs_size>\n"
64 " -K <kernel_size> set KernelSize to <kernel_size>\n"
65 " -h show this screen\n"
66 );
67
68 exit(status);
69 }
70
71 int main(int argc, char *argv[])
72 {
73 int res = EXIT_FAILURE;
74 int buflen;
75 int err;
76 struct stat st;
77 char *buf;
78 int i;
79 uint8_t csum;
80
81 FILE *outfile, *infile;
82
83 progname = basename(argv[0]);
84
85 while ( 1 ) {
86 int c;
87
88 c = getopt(argc, argv, "B:i:o:v:r:R:K:h");
89 if (c == -1)
90 break;
91
92 switch (c) {
93 case 'B':
94 board_id = optarg;
95 break;
96 case 'i':
97 ifname = optarg;
98 break;
99 case 'o':
100 ofname = optarg;
101 break;
102 case 'v':
103 version = optarg;
104 break;
105 case 'r':
106 region = optarg;
107 break;
108 case 'R':
109 rootfs_size = optarg;
110 break;
111 case 'K':
112 kernel_size = optarg;
113 break;
114 case 'h':
115 usage(EXIT_SUCCESS);
116 break;
117 default:
118 usage(EXIT_FAILURE);
119 break;
120 }
121 }
122
123 if (board_id == NULL) {
124 ERR("no board specified");
125 goto err;
126 }
127
128 if (rootfs_size == NULL) {
129 ERR("no rootfs_size specified");
130 goto err;
131 }
132
133 if (kernel_size == NULL) {
134 ERR("no kernel_size specified");
135 goto err;
136 }
137
138 if (ifname == NULL) {
139 ERR("no input file specified");
140 goto err;
141 }
142
143 if (ofname == NULL) {
144 ERR("no output file specified");
145 goto err;
146 }
147
148 err = stat(ifname, &st);
149 if (err){
150 ERRS("stat failed on %s", ifname);
151 goto err;
152 }
153
154 buflen = st.st_size + DNI_HDR_LEN + 1;
155 buf = malloc(buflen);
156 if (!buf) {
157 ERR("no memory for buffer\n");
158 goto err;
159 }
160
161 memset(buf, 0, DNI_HDR_LEN);
162 snprintf(buf, DNI_HDR_LEN, "device:%s\nversion:%s\nregion:%s\n"
163 "RootfsSize:%s\nKernelSize:%s\nInfoHeadSize:128\n",
164 board_id, version, region, rootfs_size, kernel_size);
165 buf[DNI_HDR_LEN - 2] = 0x12;
166 buf[DNI_HDR_LEN - 1] = 0x32;
167
168 infile = fopen(ifname, "r");
169 if (infile == NULL) {
170 ERRS("could not open \"%s\" for reading", ifname);
171 goto err_free;
172 }
173
174 errno = 0;
175 fread(buf + DNI_HDR_LEN, st.st_size, 1, infile);
176 if (errno != 0) {
177 ERRS("unable to read from file %s", ifname);
178 goto err_close_in;
179 }
180
181 csum = 0;
182 for (i = 0; i < (st.st_size + DNI_HDR_LEN); i++)
183 csum += buf[i];
184
185 csum = 0xff - csum;
186 buf[st.st_size + DNI_HDR_LEN] = csum;
187
188 outfile = fopen(ofname, "w");
189 if (outfile == NULL) {
190 ERRS("could not open \"%s\" for writing", ofname);
191 goto err_close_in;
192 }
193
194 errno = 0;
195 fwrite(buf, buflen, 1, outfile);
196 if (errno) {
197 ERRS("unable to write to file %s", ofname);
198 goto err_close_out;
199 }
200
201 res = EXIT_SUCCESS;
202
203 fflush(outfile);
204
205 err_close_out:
206 fclose(outfile);
207 if (res != EXIT_SUCCESS) {
208 unlink(ofname);
209 }
210
211 err_close_in:
212 fclose(infile);
213
214 err_free:
215 free(buf);
216
217 err:
218 return res;
219 }