148905Srnordier/*
248905Srnordier * Copyright (c) 1999 Global Technology Associates, Inc.
348905Srnordier * All rights reserved.
448905Srnordier *
548905Srnordier * Redistribution and use in source and binary forms, with or without
648905Srnordier * modification, are permitted provided that the following conditions
748905Srnordier * are met:
848905Srnordier * 1. Redistributions of source code must retain the above copyright
948905Srnordier *    notice, this list of conditions and the following disclaimer.
1048905Srnordier * 2. Redistributions in binary form must reproduce the above copyright
1148905Srnordier *    notice, this list of conditions and the following disclaimer in the
1248905Srnordier *    documentation and/or other materials provided with the distribution.
1348905Srnordier *
1448905Srnordier * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS``AS IS'' AND
1548905Srnordier * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
1648905Srnordier * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
1748905Srnordier * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS
1848905Srnordier * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
1948905Srnordier * OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
2048905Srnordier * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
2148905Srnordier * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
2248905Srnordier * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
2348905Srnordier * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
2448905Srnordier * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
2548905Srnordier *
2650479Speter * $FreeBSD$
2748905Srnordier */
2848905Srnordier
2948905Srnordier#include <sys/types.h>
30130927Sobrien#include <sys/endian.h>
3148905Srnordier#include <sys/wait.h>
3248905Srnordier
3348905Srnordier#include <err.h>
3448905Srnordier#include <fcntl.h>
3548905Srnordier#include <stdio.h>
3648905Srnordier#include <stdlib.h>
3748905Srnordier#include <string.h>
3848905Srnordier#include <unistd.h>
3948905Srnordier
4068313Srnordier#include "aouthdr.h"
4148905Srnordier#include "elfhdr.h"
4248905Srnordier#include "kgzip.h"
4348905Srnordier
4448905Srnordier#define align(x, y) (((x) + (y) - 1) & ~((y) - 1))
4548905Srnordier
4648905Srnordier/*
4748905Srnordier * Link KGZ file and loader.
4848905Srnordier */
4948905Srnordiervoid
5048905Srnordierkgzld(struct kgz_hdr * kh, const char *f1, const char *f2)
5148905Srnordier{
5248905Srnordier    char addr[16];
5348905Srnordier    struct iodesc idi;
5448905Srnordier    pid_t pid;
5548905Srnordier    size_t n;
5648905Srnordier    int status;
5748905Srnordier
5848905Srnordier    if (strcmp(kh->ident, "KGZ")) {
5948905Srnordier	if ((idi.fd = open(idi.fname = f1, O_RDONLY)) == -1)
6048905Srnordier	    err(1, "%s", idi.fname);
6168313Srnordier	if (!format) {
6268313Srnordier	    union {
6368313Srnordier		struct exec ex;
6468313Srnordier		Elf32_Ehdr ee;
6568313Srnordier	    } hdr;
6668313Srnordier	    n = xread(&idi, &hdr, sizeof(hdr), 0);
6768313Srnordier	    if (n >= sizeof(hdr.ee) && IS_ELF(hdr.ee))
6868313Srnordier		format = F_ELF;
6968313Srnordier	    else if (n >= sizeof(hdr.ex) &&
7068313Srnordier		     N_GETMAGIC(hdr.ex) == OMAGIC)
7168313Srnordier		format = F_AOUT;
7268313Srnordier	    if (!format)
7368313Srnordier		errx(1, "%s: Format not supported", idi.fname);
7468313Srnordier	}
7568313Srnordier	n = xread(&idi, kh, sizeof(*kh),
7668313Srnordier		  format == F_AOUT ? sizeof(struct kgz_aouthdr0)
7768313Srnordier				   : sizeof(struct kgz_elfhdr));
7848905Srnordier	xclose(&idi);
7948905Srnordier	if (n != sizeof(*kh) || strcmp(kh->ident, "KGZ"))
8048905Srnordier	    errx(1, "%s: Invalid format", idi.fname);
8148905Srnordier    }
8248905Srnordier    sprintf(addr, "%#x", align(kh->dload + kh->dsize, 0x1000));
8348905Srnordier    switch (pid = fork()) {
8448905Srnordier    case -1:
8548905Srnordier	err(1, NULL);
8648905Srnordier    case 0:
8768313Srnordier	if (format == F_AOUT)
8868313Srnordier	    execlp("ld", "ld", "-aout", "-Z", "-T", addr, "-o", f2,
8979452Sbrian		   loader, f1, (char *)NULL);
9068313Srnordier	else
9168313Srnordier	    execlp("ld", "ld", "-Ttext", addr, "-o", f2, loader, f1,
9279452Sbrian		   (char *)NULL);
9348905Srnordier	warn(NULL);
9448905Srnordier	_exit(1);
9548905Srnordier    default:
9648905Srnordier	if ((pid = waitpid(pid, &status, 0)) == -1)
9748905Srnordier	    err(1, NULL);
9848905Srnordier	if (WIFSIGNALED(status) || WEXITSTATUS(status))
9948905Srnordier	    exit(1);
10048905Srnordier    }
10148905Srnordier}
102