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 $
14 * $DragonFly: src/usr.bin/kzip/kzip.c,v 1.3 2003/10/04 20:36:47 hmp Exp $
22 #include <sys/types.h>
24 #include <sys/param.h>
29 #define MAXIMAGE (2*1024*1024)
30 /* This is the limit because a kzip'ed kernel loads at 3Mb and
36 fprintf(stderr
, "usage: kzip [-v] [ -l loadaddr] kernel\n");
41 main(int argc
, char **argv
)
43 pid_t Pext
, Pgzip
, Ppiggy
, Pld
;
44 int pipe1
[2], pipe2
[2];
45 int status
, fdi
, fdo
, fdn
, c
, verbose
;
50 u_long forceaddr
= 0, entry
;
52 char obj
[MAXPATHLEN
+ 1];
53 char out
[MAXPATHLEN
+ 1];
56 while ((c
= getopt(argc
, argv
, "l:v")) != -1) {
59 forceaddr
= strtoul(optarg
, NULL
, 0);
61 errx(1, "invalid load address");
71 if ((argc
- optind
) != 1)
79 if (strlen(kernname
) > MAXPATHLEN
- 3)
80 errx(1, "%s: File name too long", kernname
);
81 strcpy(obj
, kernname
); strcat(obj
,".o");
82 strcpy(out
, kernname
); strcat(out
,".kz");
84 fdi
= open(kernname
,O_RDONLY
);
90 /* figure out how big the uncompressed image will be */
91 if (read (fdi
, (char *)&hdr
, sizeof(hdr
)) != sizeof(hdr
))
92 err(2, "%s", argv
[1]);
94 size
= hdr
.a_text
+ hdr
.a_data
+ hdr
.a_bss
;
95 entry
= hdr
.a_entry
& 0x00FFFFFF;
97 lseek (fdi
, 0, SEEK_SET
);
100 printf("real kernel start address will be: 0x%x\n", entry
);
101 printf("real kernel end address will be: 0x%x\n", entry
+size
);
105 fdo
= open(obj
,O_WRONLY
|O_TRUNC
|O_CREAT
,0666);
111 if (pipe(pipe1
) < 0) { perror("pipe()"); return 1; }
113 if (pipe(pipe2
) < 0) { perror("pipe()"); return 1; }
116 if (Pext
< 0) { perror("fork()"); return 1; }
120 close(pipe1
[0]); close(pipe1
[1]);
121 close(pipe2
[0]); close(pipe2
[1]);
122 close(fdi
); close(fdo
);
128 if (Pgzip
< 0) { perror("fork()"); return 1; }
132 close(pipe1
[0]); close(pipe1
[1]);
133 close(pipe2
[0]); close(pipe2
[1]);
134 close(fdi
); close(fdo
);
135 execlp("gzip", "gzip", "-9", "-n", 0);
140 if (Ppiggy
< 0) { warn("fork()"); return 1; }
144 close(pipe1
[0]); close(pipe1
[1]);
145 close(pipe2
[0]); close(pipe2
[1]);
146 close(fdi
); close(fdo
);
151 close(pipe1
[0]); close(pipe1
[1]);
152 close(pipe2
[0]); close(pipe2
[1]);
153 close(fdi
); close(fdo
);
155 if (waitpid(Pext
, &status
,0) < 0)
156 { warn("waitpid(Pextract)"); return 1; }
159 warnx("extract returned %x",status
);
163 if (waitpid(Pgzip
, &status
,0) < 0)
164 { perror("waitpid(Pgzip)"); return 1; }
167 warnx("gzip returned %x",status
);
171 if (waitpid(Ppiggy
, &status
,0) < 0)
172 { warn("waitpid(Ppiggy)"); return 1; }
175 warnx("piggyback returned %x",status
);
182 /* a kludge to dynamically figure out where to start it */
183 if (stat (obj
, &st
) < 0) {
184 warn("cannot get size of compressed data");
187 zip_size
= (int)st
.st_size
;
188 offset
= entry
+ size
- zip_size
+ 0x8000; /* fudge factor */
190 sprintf(base
, "0x%x", roundup(offset
, 4096));
193 if (Pld
< 0) { warn("fork()"); return 1; }
204 "/usr/lib/aout/kzhead.o",
206 "/usr/lib/aout/kztail.o",
211 if (waitpid(Pld
, &status
,0) < 0)
212 { warn("waitpid(Pld)"); return 1; }
215 warnx("ld returned %x",status
);
221 fdn
= open(obj
,O_RDONLY
);
227 /* figure out how big the compressed image is */
228 if (read (fdn
, (char *)&hdr
, sizeof(hdr
)) != sizeof(hdr
)) {
234 size
= hdr
.a_text
+ hdr
.a_data
+ hdr
.a_bss
;
236 printf("kzip data start address will be: 0x%x\n",offset
);
237 printf("kzip data end address will be: 0x%x\n",offset
+size
);
251 if (read (0, (char *)&hdr
, sizeof(hdr
)) != sizeof(hdr
))
253 if (hdr
.a_magic
!= ZMAGIC
)
254 errx(2, "bad magic in file %s, probably not a kernel", file
);
255 if (lseek (0, N_TXTOFF(hdr
), 0) < 0)
258 sz
= N_SYMOFF (hdr
) - N_TXTOFF (hdr
);
267 n
= read (0, buf
, l
);
272 errx(1, "unexpected EOF");
282 char string_names
[] = {"_input_data\0_input_len\0"};
284 struct nlist var_names
[2] = { /* Symbol table */
285 { { (char*) 4 }, N_EXT
|N_TEXT
, 0, 0, 0 }, /* _input_data */
286 { { (char*) 16 }, N_EXT
|N_TEXT
, 0, 0, 0 }, /* _input_len */
290 piggyback(char *file
)
293 struct exec hdr
; /* object header */
294 char image
[MAXIMAGE
]; /* kernel image buffer */
297 while ((n
= read (0, &image
[len
], sizeof(image
)-len
+1)) > 0)
303 if (len
>= sizeof(image
))
304 errx(1, "input too large");
307 * Output object header
309 memset(&hdr
,0,sizeof hdr
);
310 hdr
.a_magic
= OMAGIC
;
311 hdr
.a_text
= len
+ sizeof(long);
312 hdr
.a_syms
= sizeof(var_names
);
313 write (1, (char *)&hdr
, sizeof(hdr
));
316 * Output text segment (compressed system & len)
318 write (1, image
, len
);
319 write (1, (char *)&len
, sizeof(len
));
322 * Output symbol table
324 var_names
[1].n_value
= len
;
325 write (1, (char *)&var_names
, sizeof(var_names
));
328 * Output string table
330 len
= sizeof(string_names
) + sizeof(len
);
331 write (1, (char *)&len
, sizeof(len
));
332 write (1, string_names
, sizeof(string_names
));