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
15 static const char rcsid[] =
16 "$FreeBSD: src/usr.bin/kzip/kzip.c,v 1.13.2.2 2000/07/20 10:35:20 kris Exp $";
24 #include <sys/types.h>
26 #include <sys/param.h>
31 #define MAXIMAGE (2*1024*1024)
32 /* This is the limit because a kzip'ed kernel loads at 3Mb and
38 fprintf(stderr, "usage: kzip [-v] [ -l loadaddr] kernel\n");
43 main(int argc, char **argv)
45 pid_t Pext, Pgzip, Ppiggy, Pld;
46 int pipe1[2], pipe2[2];
47 int status, fdi, fdo, fdn, c, verbose;
52 u_long forceaddr = 0, entry;
54 char obj[MAXPATHLEN + 1];
55 char out[MAXPATHLEN + 1];
58 while ((c = getopt(argc, argv, "l:v")) != -1) {
61 forceaddr = strtoul(optarg, NULL, 0);
63 errx(1, "invalid load address");
73 if ((argc - optind) != 1)
81 if (strlen(kernname) > MAXPATHLEN - 3)
82 errx(1, "%s: File name too long", kernname);
83 strcpy(obj, kernname); strcat(obj,".o");
84 strcpy(out, kernname); strcat(out,".kz");
86 fdi = open(kernname ,O_RDONLY);
92 /* figure out how big the uncompressed image will be */
93 if (read (fdi, (char *)&hdr, sizeof(hdr)) != sizeof(hdr))
94 err(2, "%s", argv[1]);
96 size = hdr.a_text + hdr.a_data + hdr.a_bss;
97 entry = hdr.a_entry & 0x00FFFFFF;
99 lseek (fdi, 0, SEEK_SET);
102 printf("real kernel start address will be: 0x%x\n", entry);
103 printf("real kernel end address will be: 0x%x\n", entry+size);
107 fdo = open(obj,O_WRONLY|O_TRUNC|O_CREAT,0666);
113 if (pipe(pipe1) < 0) { perror("pipe()"); return 1; }
115 if (pipe(pipe2) < 0) { perror("pipe()"); return 1; }
118 if (Pext < 0) { perror("fork()"); return 1; }
122 close(pipe1[0]); close(pipe1[1]);
123 close(pipe2[0]); close(pipe2[1]);
124 close(fdi); close(fdo);
130 if (Pgzip < 0) { perror("fork()"); return 1; }
134 close(pipe1[0]); close(pipe1[1]);
135 close(pipe2[0]); close(pipe2[1]);
136 close(fdi); close(fdo);
137 execlp("gzip", "gzip", "-9", "-n", 0);
142 if (Ppiggy < 0) { warn("fork()"); return 1; }
146 close(pipe1[0]); close(pipe1[1]);
147 close(pipe2[0]); close(pipe2[1]);
148 close(fdi); close(fdo);
153 close(pipe1[0]); close(pipe1[1]);
154 close(pipe2[0]); close(pipe2[1]);
155 close(fdi); close(fdo);
157 if (waitpid(Pext, &status,0) < 0)
158 { warn("waitpid(Pextract)"); return 1; }
161 warnx("extract returned %x",status);
165 if (waitpid(Pgzip, &status,0) < 0)
166 { perror("waitpid(Pgzip)"); return 1; }
169 warnx("gzip returned %x",status);
173 if (waitpid(Ppiggy, &status,0) < 0)
174 { warn("waitpid(Ppiggy)"); return 1; }
177 warnx("piggyback returned %x",status);
184 /* a kludge to dynamically figure out where to start it */
185 if (stat (obj, &st) < 0) {
186 warn("cannot get size of compressed data");
189 zip_size = (int)st.st_size;
190 offset = entry + size - zip_size + 0x8000; /* fudge factor */
192 sprintf(base, "0x%x", roundup(offset, 4096));
195 if (Pld < 0) { warn("fork()"); return 1; }
206 "/usr/lib/aout/kzhead.o",
208 "/usr/lib/aout/kztail.o",
213 if (waitpid(Pld, &status,0) < 0)
214 { warn("waitpid(Pld)"); return 1; }
217 warnx("ld returned %x",status);
223 fdn = open(obj ,O_RDONLY);
229 /* figure out how big the compressed image is */
230 if (read (fdn, (char *)&hdr, sizeof(hdr)) != sizeof(hdr)) {
236 size = hdr.a_text + hdr.a_data + hdr.a_bss;
238 printf("kzip data start address will be: 0x%x\n",offset);
239 printf("kzip data end address will be: 0x%x\n",offset+size);
253 if (read (0, (char *)&hdr, sizeof(hdr)) != sizeof(hdr))
255 if (hdr.a_magic != ZMAGIC)
256 errx(2, "bad magic in file %s, probably not a kernel", file);
257 if (lseek (0, N_TXTOFF(hdr), 0) < 0)
260 sz = N_SYMOFF (hdr) - N_TXTOFF (hdr);
269 n = read (0, buf, l);
274 errx(1, "unexpected EOF");
284 char string_names[] = {"_input_data\0_input_len\0"};
286 struct nlist var_names[2] = { /* Symbol table */
287 { { (char*) 4 }, N_EXT|N_TEXT, 0, 0, 0 }, /* _input_data */
288 { { (char*) 16 }, N_EXT|N_TEXT, 0, 0, 0 }, /* _input_len */
292 piggyback(char *file)
295 struct exec hdr; /* object header */
296 char image[MAXIMAGE]; /* kernel image buffer */
299 while ((n = read (0, &image[len], sizeof(image)-len+1)) > 0)
305 if (len >= sizeof(image))
306 errx(1, "input too large");
309 * Output object header
311 memset(&hdr,0,sizeof hdr);
312 hdr.a_magic = OMAGIC;
313 hdr.a_text = len + sizeof(long);
314 hdr.a_syms = sizeof(var_names);
315 write (1, (char *)&hdr, sizeof(hdr));
318 * Output text segment (compressed system & len)
320 write (1, image, len);
321 write (1, (char *)&len, sizeof(len));
324 * Output symbol table
326 var_names[1].n_value = len;
327 write (1, (char *)&var_names, sizeof(var_names));
330 * Output string table
332 len = sizeof(string_names) + sizeof(len);
333 write (1, (char *)&len, sizeof(len));
334 write (1, string_names, sizeof(string_names));