kernel: Fix building of snd_gusc.
[dragonfly.git] / usr.bin / kzip / kzip.c
blob2c213de1cb826c4b6ecf1ac40e06785d5445b14b
1 /*
2 * ----------------------------------------------------------------------------
3 * "THE BEER-WARE LICENSE" (Revision 42):
4 * <phk@login.dknet.dk> wrote this file. As long as you retain this notice you
5 * can do whatever you want with this stuff. If we meet some day, and you think
6 * this stuff is worth it, you can buy me a beer in return. Poul-Henning Kamp
7 * ----------------------------------------------------------------------------
9 * Copyright (C) 1993 Hannu Savolainen
10 * Ported to 386bsd by Serge Vakulenko
11 * based on tools/build.c by Linus Torvalds
13 * $FreeBSD: src/usr.bin/kzip/kzip.c,v 1.13.2.2 2000/07/20 10:35:20 kris Exp $
16 #include <err.h>
17 #include <stdio.h>
18 #include <stdlib.h>
19 #include <unistd.h>
20 #include <sys/file.h>
21 #include <sys/types.h>
22 #include <sys/stat.h>
23 #include <sys/param.h>
24 #include <sys/wait.h>
25 #include <a.out.h>
26 #include <string.h>
29 * This is the limit because a kzip'ed kernel loads at 3Mb and
30 * ends up at 1Mb
32 #define MAXIMAGE (2*1024*1024)
34 static char string_names[] = {"_input_data\0_input_len\0"};
36 static struct nlist var_names[2] = { /* Symbol table */
37 { { (char*) 4 }, N_EXT|N_TEXT, 0, 0, 0 }, /* _input_data */
38 { { (char*) 16 }, N_EXT|N_TEXT, 0, 0, 0 }, /* _input_len */
41 static int
42 extract(char *file)
44 int sz;
45 char buf[BUFSIZ];
46 struct exec hdr;
48 if (read(0, (char *)&hdr, sizeof(hdr)) != sizeof(hdr))
49 err(2, "%s", file);
50 if (hdr.a_magic != ZMAGIC)
51 errx(2, "bad magic in file %s, probably not a kernel", file);
52 if (lseek(0, N_TXTOFF(hdr), 0) < 0)
53 err(2, "%s", file);
55 sz = N_SYMOFF(hdr) - N_TXTOFF(hdr);
57 while (sz) {
58 size_t l;
59 ssize_t n;
61 l = sz;
62 if (l > sizeof(buf))
63 l = sizeof(buf);
65 n = read(0, buf, l);
66 if (n != l) {
67 if (n == -1)
68 err(1, "%s", file);
69 else
70 errx(1, "unexpected EOF");
73 write(1, buf, l);
74 sz -= l;
76 exit(0);
79 static int
80 piggyback(char *file)
82 int n, len;
83 struct exec hdr; /* object header */
84 char image[MAXIMAGE]; /* kernel image buffer */
86 len = 0;
87 while ((n = read(0, &image[len], sizeof(image)-len+1)) > 0)
88 len += n;
90 if (n < 0)
91 err(1, "stdin");
93 if (len >= sizeof(image))
94 errx(1, "input too large");
97 * Output object header
99 memset(&hdr,0,sizeof hdr);
100 hdr.a_magic = OMAGIC;
101 hdr.a_text = len + sizeof(long);
102 hdr.a_syms = sizeof(var_names);
103 write(1, (char *)&hdr, sizeof(hdr));
106 * Output text segment (compressed system & len)
108 write(1, image, len);
109 write(1, (char *)&len, sizeof(len));
112 * Output symbol table
114 var_names[1].n_value = len;
115 write(1, (char *)&var_names, sizeof(var_names));
118 * Output string table
120 len = sizeof(string_names) + sizeof(len);
121 write(1, (char *)&len, sizeof(len));
122 write(1, string_names, sizeof(string_names));
124 return (0);
127 static void
128 usage(void)
130 fprintf(stderr, "usage: kzip [-v] [ -l loadaddr] kernel\n");
131 exit(1);
135 main(int argc, char **argv)
137 pid_t Pext, Pgzip, Ppiggy, Pld;
138 int pipe1[2], pipe2[2];
139 int status, fdi, fdo, fdn, c, verbose;
140 int size;
141 struct exec hdr;
142 int zip_size, offset;
143 struct stat st;
144 u_long forceaddr = 0, entry;
145 char *kernname;
146 char obj[MAXPATHLEN + 1];
147 char out[MAXPATHLEN + 1];
148 char base[32];
150 while ((c = getopt(argc, argv, "l:v")) != -1) {
151 switch (c) {
152 case 'l':
153 forceaddr = strtoul(optarg, NULL, 0);
154 if (forceaddr == 0)
155 errx(1, "invalid load address");
156 break;
157 case 'v':
158 verbose++;
159 break;
160 default:
161 usage();
165 if ((argc - optind) != 1)
166 usage();
168 argc -= optind;
169 argv += optind;
171 kernname = argv[0];
173 if (strlen(kernname) > MAXPATHLEN - 3)
174 errx(1, "%s: File name too long", kernname);
175 strcpy(obj, kernname); strcat(obj,".o");
176 strcpy(out, kernname); strcat(out,".kz");
178 fdi = open(kernname ,O_RDONLY);
179 if(fdi<0) {
180 warn("%s", kernname);
181 return 2;
184 /* figure out how big the uncompressed image will be */
185 if (read(fdi, (char *)&hdr, sizeof(hdr)) != sizeof(hdr))
186 err(2, "%s", argv[1]);
188 size = hdr.a_text + hdr.a_data + hdr.a_bss;
189 entry = hdr.a_entry & 0x00FFFFFF;
191 lseek(fdi, 0, SEEK_SET);
193 if (verbose) {
194 printf("real kernel start address will be: 0x%lx\n", entry);
195 printf("real kernel end address will be: 0x%lx\n", entry+size);
199 fdo = open(obj,O_WRONLY|O_TRUNC|O_CREAT,0666);
200 if(fdo<0) {
201 warn("%s", obj);
202 return 2;
205 if (pipe(pipe1) < 0) { perror("pipe()"); return 1; }
207 if (pipe(pipe2) < 0) { perror("pipe()"); return 1; }
209 Pext = fork();
210 if (Pext < 0) { perror("fork()"); return 1; }
211 if (!Pext) {
212 dup2(fdi,0);
213 dup2(pipe1[1],1);
214 close(pipe1[0]); close(pipe1[1]);
215 close(pipe2[0]); close(pipe2[1]);
216 close(fdi); close(fdo);
217 extract(kernname);
218 exit(0);
221 Pgzip = fork();
222 if (Pgzip < 0) { perror("fork()"); return 1; }
223 if (!Pgzip) {
224 dup2(pipe1[0],0);
225 dup2(pipe2[1],1);
226 close(pipe1[0]); close(pipe1[1]);
227 close(pipe2[0]); close(pipe2[1]);
228 close(fdi); close(fdo);
229 execlp("gzip", "gzip", "-9", "-n", NULL);
230 exit(0);
233 Ppiggy = fork();
234 if (Ppiggy < 0) { warn("fork()"); return 1; }
235 if (!Ppiggy) {
236 dup2(pipe2[0],0);
237 dup2(fdo,1);
238 close(pipe1[0]); close(pipe1[1]);
239 close(pipe2[0]); close(pipe2[1]);
240 close(fdi); close(fdo);
241 piggyback(obj);
242 exit(0);
245 close(pipe1[0]); close(pipe1[1]);
246 close(pipe2[0]); close(pipe2[1]);
247 close(fdi); close(fdo);
249 if (waitpid(Pext, &status,0) < 0)
250 { warn("waitpid(Pextract)"); return 1; }
252 if(status) {
253 warnx("extract returned %x",status);
254 return 3;
257 if (waitpid(Pgzip, &status,0) < 0)
258 { perror("waitpid(Pgzip)"); return 1; }
260 if(status) {
261 warnx("gzip returned %x",status);
262 return 3;
265 if (waitpid(Ppiggy, &status,0) < 0)
266 { warn("waitpid(Ppiggy)"); return 1; }
268 if(status) {
269 warnx("piggyback returned %x",status);
270 return 3;
273 if (forceaddr)
274 offset = forceaddr;
275 else {
276 /* a kludge to dynamically figure out where to start it */
277 if (stat(obj, &st) < 0) {
278 warn("cannot get size of compressed data");
279 return 3;
281 zip_size = (int)st.st_size;
282 offset = entry + size - zip_size + 0x8000; /* fudge factor */
284 sprintf(base, "0x%x", roundup(offset, 4096));
286 Pld = fork();
287 if (Pld < 0) { warn("fork()"); return 1; }
288 if (!Pld) {
289 execlp("ld",
290 "ld",
291 "-aout",
292 "-Bstatic",
293 "-Z",
294 "-T",
295 base,
296 "-o",
297 out,
298 "/usr/lib/aout/kzhead.o",
299 obj,
300 "/usr/lib/aout/kztail.o",
301 NULL);
302 exit(2);
305 if (waitpid(Pld, &status,0) < 0)
306 { warn("waitpid(Pld)"); return 1; }
308 if(status) {
309 warnx("ld returned %x",status);
310 return 3;
313 if (verbose) {
315 fdn = open(obj ,O_RDONLY);
316 if(fdn<0) {
317 warn("%s", obj);
318 return 3;
321 /* figure out how big the compressed image is */
322 if (read(fdn, (char *)&hdr, sizeof(hdr)) != sizeof(hdr)) {
323 warn("%s", obj);
324 return 3;
326 close(fdn);
328 size = hdr.a_text + hdr.a_data + hdr.a_bss;
330 printf("kzip data start address will be: 0x%x\n",offset);
331 printf("kzip data end address will be: 0x%x\n",offset+size);
334 unlink(obj);
335 exit(0);