1*0976a62eSguenther /* $OpenBSD: build.c,v 1.4 2014/07/20 02:03:21 guenther Exp $ */
2d1455811Smglocker
3d1455811Smglocker /*
4d1455811Smglocker * Copyright (c) 2006 Marcus Glocker <mglocker@openbsd.org>
5d1455811Smglocker *
6d1455811Smglocker * Permission to use, copy, modify, and distribute this software for any
7d1455811Smglocker * purpose with or without fee is hereby granted, provided that the above
8d1455811Smglocker * copyright notice and this permission notice appear in all copies.
9d1455811Smglocker *
10d1455811Smglocker * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
11d1455811Smglocker * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
12d1455811Smglocker * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
13d1455811Smglocker * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
14d1455811Smglocker * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
15d1455811Smglocker * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
16d1455811Smglocker * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
17d1455811Smglocker */
18d1455811Smglocker
19d1455811Smglocker #include <sys/types.h>
20d1455811Smglocker #include <sys/stat.h>
21d1455811Smglocker
22d1455811Smglocker #include <err.h>
23*0976a62eSguenther #include <errno.h>
24d1455811Smglocker #include <fcntl.h>
25d1455811Smglocker #include <stdio.h>
26d1455811Smglocker #include <stdlib.h>
27d1455811Smglocker #include <string.h>
28d1455811Smglocker #include <unistd.h>
29d1455811Smglocker
30d1455811Smglocker //#define VERBOSE 1
31d1455811Smglocker #define FILENAME "bwi-airforce"
32d1455811Smglocker
33d1455811Smglocker struct header {
34d1455811Smglocker char filename[64];
35d1455811Smglocker int filesize;
36d1455811Smglocker int fileoffset;
37d1455811Smglocker };
38d1455811Smglocker
39d1455811Smglocker int
main(int argc,char * argv[])40d1455811Smglocker main(int argc, char *argv[])
41d1455811Smglocker {
42d1455811Smglocker void *p;
43d1455811Smglocker int i, j, offset;
44d1455811Smglocker int fdout, fdin;
45d1455811Smglocker int nfiles, headersize;
46d1455811Smglocker int fwsize, totalsize;
47d1455811Smglocker struct header h[argc - 1];
48d1455811Smglocker struct stat s;
49d1455811Smglocker
50d1455811Smglocker if (argc < 2) {
51d1455811Smglocker printf("%s <firmware files>\n", argv[0]);
52d1455811Smglocker exit(1);
53d1455811Smglocker }
54d1455811Smglocker
55d1455811Smglocker nfiles = argc - 1; /* number of firmware files */
56d1455811Smglocker headersize = sizeof(h) + sizeof(nfiles); /* size of file header */
57d1455811Smglocker
58d1455811Smglocker /* initialize header struct */
59d1455811Smglocker for (i = 1, j = 0, fwsize = 0; i < argc; i++, j++) {
60d1455811Smglocker bzero(h[j].filename, sizeof(h[j].filename));
61d1455811Smglocker strlcpy(h[j].filename, argv[i], sizeof(h[j].filename));
62d1455811Smglocker
63d1455811Smglocker if (stat(h[j].filename, &s) == -1)
64d1455811Smglocker err(1, "header initialization failed");
65d1455811Smglocker
66d1455811Smglocker h[j].filesize = s.st_size;
67d1455811Smglocker h[j].fileoffset = 0;
68d1455811Smglocker
69d1455811Smglocker fwsize += h[j].filesize;
70d1455811Smglocker #ifdef VERBOSE
71d1455811Smglocker printf("create header entry for %s (%d bytes)\n",
72d1455811Smglocker h[j].filename, h[j].filesize);
73d1455811Smglocker #endif
74d1455811Smglocker }
75d1455811Smglocker
76d1455811Smglocker /* calculate total file size */
77d1455811Smglocker totalsize = headersize + fwsize;
78d1455811Smglocker #if VERBOSE
79d1455811Smglocker printf("\n");
80d1455811Smglocker printf("header size = %d bytes, ", headersize);
81d1455811Smglocker printf("fw size = %d bytes, ", fwsize);
82d1455811Smglocker printf("total file size = %d bytes\n", totalsize);
83d1455811Smglocker printf("\n");
84d1455811Smglocker #endif
85d1455811Smglocker
86d1455811Smglocker /* calculating firmware offsets */
87d1455811Smglocker for (i = 0, offset = headersize; i < nfiles; i++) {
88d1455811Smglocker h[i].fileoffset = offset;
89d1455811Smglocker offset += h[i].filesize;
90d1455811Smglocker #ifdef VERBOSE
91d1455811Smglocker printf("offset of %s = %d\n", h[i].filename, h[i].fileoffset);
92d1455811Smglocker #endif
93d1455811Smglocker }
94d1455811Smglocker
95d1455811Smglocker /* open output file */
96d1455811Smglocker if ((fdout = open(FILENAME, O_CREAT|O_TRUNC|O_RDWR, 0644)) == -1)
97d1455811Smglocker err(1, "open output file failed");
98d1455811Smglocker
99d1455811Smglocker /* host to network byte order */
100d1455811Smglocker for (i = 0; i < nfiles; i++) {
101d1455811Smglocker h[i].filesize = htonl(h[i].filesize);
102d1455811Smglocker h[i].fileoffset = htonl(h[i].fileoffset);
103d1455811Smglocker }
104d1455811Smglocker nfiles = htonl(nfiles);
105d1455811Smglocker
106d1455811Smglocker /* write header */
107d1455811Smglocker if (write(fdout, &nfiles, sizeof(nfiles)) < 1) {
108*0976a62eSguenther int saved_errno = errno;
109d1455811Smglocker close(fdout);
110*0976a62eSguenther errc(1, saved_errno, "write header 1 to output file failed");
111d1455811Smglocker }
112d1455811Smglocker if (write(fdout, h, headersize - sizeof(nfiles)) < 1) {
113*0976a62eSguenther int saved_errno = errno;
114d1455811Smglocker close(fdout);
115*0976a62eSguenther errc(1, saved_errno, "write header 2 to output file failed");
116d1455811Smglocker }
117d1455811Smglocker
118d1455811Smglocker /* network to host byte order */
119d1455811Smglocker nfiles = ntohl(nfiles);
120d1455811Smglocker for (i = 0; i < nfiles; i++) {
121d1455811Smglocker h[i].filesize = ntohl(h[i].filesize);
122d1455811Smglocker h[i].fileoffset = ntohl(h[i].fileoffset);
123d1455811Smglocker }
124d1455811Smglocker
125d1455811Smglocker /* write each file */
126d1455811Smglocker for (i = 0; i < nfiles; i++) {
127d1455811Smglocker if ((fdin = open(h[i].filename, O_RDONLY)) == -1) {
128*0976a62eSguenther int saved_errno = errno;
129d1455811Smglocker close(fdout);
130*0976a62eSguenther errc(1, saved_errno, "open input file failed");
131d1455811Smglocker }
132d1455811Smglocker if ((p = malloc(h[i].filesize)) == NULL) {
133*0976a62eSguenther int saved_errno = errno;
134d1455811Smglocker close(fdout);
135d1455811Smglocker close(fdin);
136*0976a62eSguenther errc(1, saved_errno, "malloc");
137d1455811Smglocker }
138d1455811Smglocker if (read(fdin, p, h[i].filesize) < 1) {
139*0976a62eSguenther int saved_errno = errno;
1404c67e3eeStedu free(p);
141d1455811Smglocker close(fdout);
142d1455811Smglocker close(fdin);
143*0976a62eSguenther errc(1, saved_errno, "read input file failed");
144d1455811Smglocker }
145d1455811Smglocker if (write(fdout, p, h[i].filesize) < 1) {
146*0976a62eSguenther int saved_errno = errno;
1474c67e3eeStedu free(p);
148d1455811Smglocker close(fdout);
149d1455811Smglocker close(fdin);
150*0976a62eSguenther errc(1, saved_errno, "write to output file failed");
151d1455811Smglocker }
1524c67e3eeStedu free(p);
153d1455811Smglocker close(fdin);
154d1455811Smglocker }
155d1455811Smglocker
156d1455811Smglocker close(fdout);
157d1455811Smglocker
158d1455811Smglocker #ifdef VERBOSE
159d1455811Smglocker printf("\n");
160d1455811Smglocker #endif
161d1455811Smglocker
162d1455811Smglocker /* game over */
163d1455811Smglocker printf("wrote %d files to %s (%d bytes).\n",
164d1455811Smglocker nfiles, FILENAME, totalsize);
165d1455811Smglocker
166d1455811Smglocker return (0);
167d1455811Smglocker }
168