summaryrefslogtreecommitdiffstats
path: root/usr.sbin/kgzip
diff options
context:
space:
mode:
authorrnordier <rnordier@FreeBSD.org>2000-11-04 13:02:00 +0000
committerrnordier <rnordier@FreeBSD.org>2000-11-04 13:02:00 +0000
commit18e0fe6967f684c8adb8dd9db3a8cb24f70e7705 (patch)
tree796a6ec2a8cda6145d54708de7195fc62b04838a /usr.sbin/kgzip
parent2cfec00a84116cb5277eecec357964eb0c113954 (diff)
downloadFreeBSD-src-18e0fe6967f684c8adb8dd9db3a8cb24f70e7705.zip
FreeBSD-src-18e0fe6967f684c8adb8dd9db3a8cb24f70e7705.tar.gz
Add support for creating a.out output files in addition to ELF.
This allows booting from compressed binaries using older bootstraps. Thanks to: dwmalone
Diffstat (limited to 'usr.sbin/kgzip')
-rw-r--r--usr.sbin/kgzip/Makefile2
-rw-r--r--usr.sbin/kgzip/aouthdr.c79
-rw-r--r--usr.sbin/kgzip/aouthdr.h59
-rw-r--r--usr.sbin/kgzip/kgzcmp.c44
-rw-r--r--usr.sbin/kgzip/kgzip.816
-rw-r--r--usr.sbin/kgzip/kgzip.c20
-rw-r--r--usr.sbin/kgzip/kgzip.h4
-rw-r--r--usr.sbin/kgzip/kgzld.c28
8 files changed, 224 insertions, 28 deletions
diff --git a/usr.sbin/kgzip/Makefile b/usr.sbin/kgzip/Makefile
index 1bfad2d..85c3486 100644
--- a/usr.sbin/kgzip/Makefile
+++ b/usr.sbin/kgzip/Makefile
@@ -3,7 +3,7 @@
MAINTAINER= rnordier
PROG= kgzip
-SRCS= kgzip.c elfhdr.c kgzcmp.c kgzld.c xio.c
+SRCS= kgzip.c aouthdr.c elfhdr.c kgzcmp.c kgzld.c xio.c
MAN8= kgzip.8
CFLAGS+=-pedantic \
-W -Wall -Waggregate-return -Wbad-function-cast -Wcast-align \
diff --git a/usr.sbin/kgzip/aouthdr.c b/usr.sbin/kgzip/aouthdr.c
new file mode 100644
index 0000000..27541e6
--- /dev/null
+++ b/usr.sbin/kgzip/aouthdr.c
@@ -0,0 +1,79 @@
+/*
+ * Copyright (c) 2000 Robert Nordier
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS
+ * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
+ * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * $FreeBSD$
+ */
+
+#include <stddef.h>
+#include "aouthdr.h"
+
+#define KGZ_FIX_NSIZE 0 /* Run-time fixup */
+
+const struct kgz_aouthdr0 aouthdr0 = {
+ /* a.out header */
+ {
+ MID_I386 << 020 | OMAGIC, /* a_midmag */
+ 0, /* a_text */
+ sizeof(struct kgz_hdr) + KGZ_FIX_NSIZE, /* a_data */
+ 0, /* a_bss */
+ sizeof(struct nlist) * KGZ__STNUM, /* a_syms */
+ 0, /* a_entry */
+ 0, /* a_trsize */
+ 0 /* a_drsize */
+ }
+};
+
+const struct kgz_aouthdr1 aouthdr1 = {
+ /* Symbol table */
+ {
+ {
+ {
+ (char *)offsetof(struct kgz__strtab,
+ kgz) /* n_un */
+ },
+ N_DATA | N_EXT, /* n_type */
+ AUX_OBJECT, /* n_other */
+ 0, /* n_desc */
+ 0 /* n_value */
+ },
+ {
+ {
+ (char *)offsetof(struct kgz__strtab,
+ kgz_ndata) /* n_un */
+ },
+ N_DATA | N_EXT, /* n_type */
+ AUX_OBJECT, /* n_other */
+ 0, /* n_desc */
+ sizeof(struct kgz_hdr) /* n_value */
+ }
+ },
+ /* String table */
+ {
+ sizeof(struct kgz__strtab), /* length */
+ KGZ__STR_KGZ, /* kgz */
+ KGZ__STR_KGZ_NDATA /* kgz_ndata */
+ }
+};
diff --git a/usr.sbin/kgzip/aouthdr.h b/usr.sbin/kgzip/aouthdr.h
new file mode 100644
index 0000000..63c2dff
--- /dev/null
+++ b/usr.sbin/kgzip/aouthdr.h
@@ -0,0 +1,59 @@
+/*
+ * Copyright (c) 2000 Robert Nordier
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS
+ * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
+ * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * $FreeBSD$
+ */
+
+#include <a.out.h>
+#include "kgz.h"
+
+/* Relocatable header: part 0 */
+struct kgz_aouthdr0 {
+ struct exec a;
+};
+
+/* Symbol table entries */
+#define KGZ__STNUM 2
+
+/* Symbol table strings */
+#define KGZ__STR_KGZ "_kgz"
+#define KGZ__STR_KGZ_NDATA "_kgz_ndata"
+
+/* String table */
+struct kgz__strtab {
+ unsigned long length;
+ char kgz[sizeof(KGZ__STR_KGZ)];
+ char kgz_ndata[sizeof(KGZ__STR_KGZ_NDATA)];
+};
+
+/* Relocatable header: part 1 */
+struct kgz_aouthdr1 {
+ struct nlist st[KGZ__STNUM];
+ struct kgz__strtab strtab;
+};
+
+extern const struct kgz_aouthdr0 aouthdr0;
+extern const struct kgz_aouthdr1 aouthdr1;
diff --git a/usr.sbin/kgzip/kgzcmp.c b/usr.sbin/kgzip/kgzcmp.c
index a10c167..09086ad 100644
--- a/usr.sbin/kgzip/kgzcmp.c
+++ b/usr.sbin/kgzip/kgzcmp.c
@@ -39,16 +39,12 @@
#include <a.out.h>
#include <elf.h>
+#include "aouthdr.h"
#include "elfhdr.h"
#include "kgzip.h"
-#define KGZOFF (sizeof(struct kgz_elfhdr) + sizeof(struct kgz_hdr))
-
-#define F_AOUT 1 /* Input format: a.out */
-#define F_ELF 2 /* Input format: ELF32 */
-
static void mk_data(const struct iodesc *i, const struct iodesc *,
- struct kgz_hdr *);
+ struct kgz_hdr *, size_t);
static int ld_elf(const struct iodesc *, const struct iodesc *,
struct kgz_hdr *, const Elf32_Ehdr *);
static int ld_aout(const struct iodesc *, const struct iodesc *,
@@ -61,7 +57,6 @@ void
kgzcmp(struct kgz_hdr *kh, const char *f1, const char *f2)
{
struct iodesc idi, ido;
- struct kgz_elfhdr ehdr;
if ((idi.fd = open(idi.fname = f1, O_RDONLY)) == -1)
err(1, "%s", idi.fname);
@@ -72,15 +67,31 @@ kgzcmp(struct kgz_hdr *kh, const char *f1, const char *f2)
kh->ident[1] = KGZ_ID1;
kh->ident[2] = KGZ_ID2;
kh->ident[3] = KGZ_ID3;
- xseek(&ido, KGZOFF);
- mk_data(&idi, &ido, kh);
+ mk_data(&idi, &ido, kh,
+ (format == F_AOUT ? sizeof(struct kgz_aouthdr0) :
+ sizeof(struct kgz_elfhdr)) +
+ sizeof(struct kgz_hdr));
kh->dload &= 0xffffff;
kh->entry &= 0xffffff;
- xseek(&ido, 0);
- ehdr = elfhdr;
- ehdr.st[KGZ_ST_KGZ_NDATA].st_size = kh->nsize;
- ehdr.sh[KGZ_SH_DATA].sh_size += kh->nsize;
- xwrite(&ido, &ehdr, sizeof(ehdr));
+ if (format == F_AOUT) {
+ struct kgz_aouthdr0 ahdr0 = aouthdr0;
+ struct kgz_aouthdr1 ahdr1 = aouthdr1;
+ unsigned x = (sizeof(struct kgz_hdr) + kh->nsize) & (16 - 1);
+ if (x) {
+ x = 16 - x;
+ xzero(&ido, x);
+ }
+ xwrite(&ido, &ahdr1, sizeof(ahdr1));
+ ahdr0.a.a_data += kh->nsize + x;
+ xseek(&ido, 0);
+ xwrite(&ido, &ahdr0, sizeof(ahdr0));
+ } else {
+ struct kgz_elfhdr ehdr = elfhdr;
+ ehdr.st[KGZ_ST_KGZ_NDATA].st_size = kh->nsize;
+ ehdr.sh[KGZ_SH_DATA].sh_size += kh->nsize;
+ xseek(&ido, 0);
+ xwrite(&ido, &ehdr, sizeof(ehdr));
+ }
xwrite(&ido, kh, sizeof(*kh));
xclose(&ido);
xclose(&idi);
@@ -91,7 +102,7 @@ kgzcmp(struct kgz_hdr *kh, const char *f1, const char *f2)
*/
static void
mk_data(const struct iodesc * idi, const struct iodesc * ido,
- struct kgz_hdr * kh)
+ struct kgz_hdr * kh, size_t off)
{
union {
struct exec ex;
@@ -112,6 +123,7 @@ mk_data(const struct iodesc * idi, const struct iodesc * ido,
fmt = F_AOUT;
if (!fmt)
errx(1, "%s: Format not supported", idi->fname);
+ xseek(ido, off);
if (pipe(fd))
err(1, NULL);
switch (pid = fork()) {
@@ -143,7 +155,7 @@ mk_data(const struct iodesc * idi, const struct iodesc * ido,
errx(1, "%s: Invalid format", idi->fname);
if (fstat(ido->fd, &sb))
err(1, "%s", ido->fname);
- kh->nsize = sb.st_size - KGZOFF;
+ kh->nsize = sb.st_size - off;
}
/*
diff --git a/usr.sbin/kgzip/kgzip.8 b/usr.sbin/kgzip/kgzip.8
index 97f4ece..462a723 100644
--- a/usr.sbin/kgzip/kgzip.8
+++ b/usr.sbin/kgzip/kgzip.8
@@ -33,6 +33,7 @@
.Sh SYNOPSIS
.Nm kgzip
.Op Fl cv
+.Op Fl f Ar format
.Op Fl l Ar loader
.Op Fl o Ar output
.Ar file
@@ -57,8 +58,7 @@ an executable suitable for booting with either the second- or
third-level bootstraps.
.El
.Pp
-Supported input formats are ELF and a.out ZMAGIC; the output format
-is always ELF. Only 32-bit objects are supported.
+Supported object formats are 32-bit ELF and a.out ZMAGIC.
.Pp
If the
.Ar file
@@ -73,6 +73,16 @@ The options are:
Omit the link phase.
.It Fl v
Display object file information.
+.It Fl f Ar format
+Use
+.Ar format
+as the output format, where
+.Ar format
+is
+.Sq aout
+or
+.Sq elf .
+The default format is ELF.
.It Fl l Ar loader
Link
.Ar loader
@@ -113,8 +123,8 @@ The default loader
.Sh SEE ALSO
.Xr gzip 1 ,
.Xr ld 1 ,
-.Xr elf 5 ,
.Xr a.out 5 ,
+.Xr elf 5 ,
.Xr boot 8 ,
.Xr loader 8
.Sh DIAGNOSTICS
diff --git a/usr.sbin/kgzip/kgzip.c b/usr.sbin/kgzip/kgzip.c
index 3c3df36..5e96432 100644
--- a/usr.sbin/kgzip/kgzip.c
+++ b/usr.sbin/kgzip/kgzip.c
@@ -49,6 +49,7 @@ static const char rcsid[] =
#define SFX_MAX 5 /* Size of larger filename suffix */
const char *loader = "/usr/lib/kgzldr.o"; /* Default loader */
+int format; /* Output format */
char *tname; /* Name of temporary file */
@@ -70,11 +71,11 @@ main(int argc, char *argv[])
tmpdir = getenv("TMPDIR");
if (asprintf(&tname, "%s/kgzXXXXXXXXXX", tmpdir == NULL ? _PATH_TMP : tmpdir) == -1)
- errx(1, "Out of memory");
+ errx(1, "Out of memory");
output = NULL;
cflag = vflag = 0;
- while ((c = getopt(argc, argv, "cvl:o:")) != -1)
+ while ((c = getopt(argc, argv, "cvf:l:o:")) != -1)
switch (c) {
case 'c':
cflag = 1;
@@ -82,6 +83,14 @@ main(int argc, char *argv[])
case 'v':
vflag = 1;
break;
+ case 'f':
+ if (!strcmp(optarg, "aout"))
+ format = F_AOUT;
+ else if (!strcmp(optarg, "elf"))
+ format = F_ELF;
+ else
+ errx(1, "%s: Unknown format", optarg);
+ break;
case 'l':
loader = optarg;
break;
@@ -98,8 +107,11 @@ main(int argc, char *argv[])
atexit(cleanup);
mk_fn(cflag, *argv, output, fn);
memset(&kh, 0, sizeof(kh));
- if (fn[FN_SRC])
+ if (fn[FN_SRC]) {
+ if (!format)
+ format = F_ELF;
kgzcmp(&kh, fn[FN_SRC], fn[FN_OBJ]);
+ }
if (!cflag)
kgzld(&kh, fn[FN_OBJ], fn[FN_KGZ]);
if (vflag)
@@ -159,6 +171,6 @@ static void
usage(void)
{
fprintf(stderr,
- "usage: kgzip [-cv] [-l file] [-o filename] file\n");
+ "usage: kgzip [-cv] [-f format] [-l file] [-o filename] file\n");
exit(1);
}
diff --git a/usr.sbin/kgzip/kgzip.h b/usr.sbin/kgzip/kgzip.h
index 4231c0f..f04f2a4 100644
--- a/usr.sbin/kgzip/kgzip.h
+++ b/usr.sbin/kgzip/kgzip.h
@@ -28,6 +28,9 @@
#include "kgz.h"
+#define F_AOUT 1 /* Format: a.out */
+#define F_ELF 2 /* Format: ELF32 */
+
/* Used by I/O routines */
struct iodesc {
const char *fname; /* File name */
@@ -35,6 +38,7 @@ struct iodesc {
};
extern const char *loader; /* Default loader */
+extern int format; /* Output format */
void kgzcmp(struct kgz_hdr *, const char *, const char *);
void kgzld(struct kgz_hdr *, const char *, const char *);
diff --git a/usr.sbin/kgzip/kgzld.c b/usr.sbin/kgzip/kgzld.c
index a2b0086..3e1d2d1 100644
--- a/usr.sbin/kgzip/kgzld.c
+++ b/usr.sbin/kgzip/kgzld.c
@@ -36,11 +36,10 @@
#include <string.h>
#include <unistd.h>
+#include "aouthdr.h"
#include "elfhdr.h"
#include "kgzip.h"
-#define KGZOFF sizeof(struct kgz_elfhdr)
-
#define align(x, y) (((x) + (y) - 1) & ~((y) - 1))
/*
@@ -58,7 +57,23 @@ kgzld(struct kgz_hdr * kh, const char *f1, const char *f2)
if (strcmp(kh->ident, "KGZ")) {
if ((idi.fd = open(idi.fname = f1, O_RDONLY)) == -1)
err(1, "%s", idi.fname);
- n = xread(&idi, kh, sizeof(*kh), KGZOFF);
+ if (!format) {
+ union {
+ struct exec ex;
+ Elf32_Ehdr ee;
+ } hdr;
+ n = xread(&idi, &hdr, sizeof(hdr), 0);
+ if (n >= sizeof(hdr.ee) && IS_ELF(hdr.ee))
+ format = F_ELF;
+ else if (n >= sizeof(hdr.ex) &&
+ N_GETMAGIC(hdr.ex) == OMAGIC)
+ format = F_AOUT;
+ if (!format)
+ errx(1, "%s: Format not supported", idi.fname);
+ }
+ n = xread(&idi, kh, sizeof(*kh),
+ format == F_AOUT ? sizeof(struct kgz_aouthdr0)
+ : sizeof(struct kgz_elfhdr));
xclose(&idi);
if (n != sizeof(*kh) || strcmp(kh->ident, "KGZ"))
errx(1, "%s: Invalid format", idi.fname);
@@ -68,7 +83,12 @@ kgzld(struct kgz_hdr * kh, const char *f1, const char *f2)
case -1:
err(1, NULL);
case 0:
- execlp("ld", "ld", "-Ttext", addr, "-o", f2, loader, f1, NULL);
+ if (format == F_AOUT)
+ execlp("ld", "ld", "-aout", "-Z", "-T", addr, "-o", f2,
+ loader, f1, NULL);
+ else
+ execlp("ld", "ld", "-Ttext", addr, "-o", f2, loader, f1,
+ NULL);
warn(NULL);
_exit(1);
default:
OpenPOWER on IntegriCloud