diff options
author | Michael Knudsen <mk@cvs.openbsd.org> | 2010-02-12 17:30:42 +0000 |
---|---|---|
committer | Michael Knudsen <mk@cvs.openbsd.org> | 2010-02-12 17:30:42 +0000 |
commit | 53c661edb4c189d6ebbe9a4d15f7a2558ab9772f (patch) | |
tree | 041b273d76aaf2ea8b23f49ae5ab53afc6f923e1 /sys/stand/mkuboot/mkuboot.c | |
parent | ec7fb50579ff98011f937e43fd0c0ff6c022d7f6 (diff) |
Add mkuboot, a utility to build images for Das U-Boot.
This code is basically sys/arch/socppc/stand/mkboot/ but fixed to work
on little endian machines and extended slightly to allow specifying the
image OS and platform.
Input from drahn and kettenis.
ok kettenis
Diffstat (limited to 'sys/stand/mkuboot/mkuboot.c')
-rw-r--r-- | sys/stand/mkuboot/mkuboot.c | 234 |
1 files changed, 234 insertions, 0 deletions
diff --git a/sys/stand/mkuboot/mkuboot.c b/sys/stand/mkuboot/mkuboot.c new file mode 100644 index 00000000000..516288a6ee4 --- /dev/null +++ b/sys/stand/mkuboot/mkuboot.c @@ -0,0 +1,234 @@ +/* $OpenBSD: mkuboot.c,v 1.1 2010/02/12 17:30:41 mk Exp $ */ + +/* + * Copyright (c) 2008 Mark Kettenis + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#include <sys/types.h> +#include <err.h> +#include <fcntl.h> +#include <stdint.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <time.h> +#include <unistd.h> +#include <zlib.h> + +#define IH_OS_OPENBSD 1 /* OpenBSD */ +#define IH_OS_LINUX 5 /* Linux */ + +#define IH_ARCH_ALPHA 1 /* Alpha */ +#define IH_ARCH_ARM 2 /* ARM */ +#define IH_ARCH_I386 3 /* Intel x86 */ +#define IH_ARCH_IA64 4 /* IA64 */ +#define IH_ARCH_MIPS 5 /* MIPS */ +#define IH_ARCH_MIPS64 6 /* MIPS 64 Bit */ +#define IH_ARCH_PPC 7 /* PowerPC */ +#define IH_ARCH_SH 9 /* SuperH */ +#define IH_ARCH_SPARC 10 /* Sparc */ +#define IH_ARCH_SPARC64 11 /* Sparc 64 Bit */ +#define IH_ARCH_M68K 12 /* M68K */ + +#define IH_TYPE_STANDALONE 1 /* Standalone */ +#define IH_TYPE_KERNEL 2 /* OS Kernel Image */ + +#define IH_COMP_NONE 0 /* No compression */ + +#define IH_MAGIC 0x27051956 /* Image Magic Number */ +#define IH_NMLEN 32 /* Image Name Length */ + +struct image_header { + uint32_t ih_magic; + uint32_t ih_hcrc; + uint32_t ih_time; + uint32_t ih_size; + uint32_t ih_load; + uint32_t ih_ep; + uint32_t ih_dcrc; + uint8_t ih_os; + uint8_t ih_arch; + uint8_t ih_type; + uint8_t ih_comp; + uint8_t ih_name[IH_NMLEN]; +}; + +extern char *__progname; + +void usage(void); + +struct arch_map { + int id; + const char *arch; +}; + +static const struct arch_map archmap[] = { + { IH_ARCH_ALPHA, "alpha" }, + { IH_ARCH_IA64, "amd64" }, + { IH_ARCH_ARM, "arm" }, + { IH_ARCH_I386, "i386" }, + { IH_ARCH_M68K, "m68k" }, + { IH_ARCH_MIPS, "mips" }, + { IH_ARCH_MIPS64, "mips64" }, + { IH_ARCH_PPC, "powerpc" }, + { IH_ARCH_SPARC, "sparc" }, + { IH_ARCH_SPARC64, "sparc64" }, + { IH_ARCH_SH, "superh" }, + { 0, NULL } +}; + +struct os_map { + int id; + const char *arch; +}; + +static const struct os_map osmap[] = { + { IH_OS_OPENBSD, "OpenBSD" }, + { IH_OS_LINUX, "Linux" }, + { 0, NULL } +}; + + +int +main(int argc, char *argv[]) +{ + struct image_header ih; + const struct arch_map *mapptr; + const struct os_map *osmapptr; + const char *iname, *oname; + const char *arch = MACHINE_ARCH; + const char *os = "OpenBSD"; + int ifd, ofd; + u_long crc; + ssize_t nbytes; + char buf[BUFSIZ]; + int c, ep, load; + + ep = load = 0; + while ((c = getopt(argc, argv, "a:e:l:o:")) != -1) { + switch (c) { + case 'a': + arch = optarg; + break; + case 'e': + sscanf(optarg, "0x%x", &ep); + break; + case 'l': + sscanf(optarg, "0x%x", &load); + break; + case 'o': + os = optarg; + break; + default: + usage(); + } + } + + for (mapptr = archmap; mapptr->arch; mapptr++) + if (strcasecmp(arch, mapptr->arch) == 0) + break; + + if (mapptr->arch == NULL) { + printf("unknown arch '%s'\n", arch); + usage(); + } + + for (osmapptr = osmap; osmapptr->arch; osmapptr++) + if (strcasecmp(os, osmapptr->arch) == 0) + break; + + if (osmapptr->arch == NULL) { + printf("unknown OS '%s'\n", os); + usage(); + } + + if (argc - optind != 2) + usage(); + + iname = argv[optind++]; + oname = argv[optind++]; + + /* Initialize U-Boot header. */ + bzero(&ih, sizeof ih); + ih.ih_magic = htobe32(IH_MAGIC); + ih.ih_time = htobe32(time(NULL)); + ih.ih_load = htobe32(load); + ih.ih_ep = htobe32(ep); + ih.ih_os = osmapptr->id; + ih.ih_arch = mapptr->id; + ih.ih_type = IH_TYPE_KERNEL; + ih.ih_comp = IH_COMP_NONE; + strlcpy(ih.ih_name, "boot", sizeof ih.ih_name); + + ifd = open(iname, O_RDONLY); + if (ifd < 0) + err(1, "%s", iname); + + ofd = open(oname, O_RDWR | O_TRUNC | O_CREAT, 0644); + if (ofd < 0) + err(1, "%s", oname); + + /* Write initial header. */ + if (write(ofd, &ih, sizeof ih) != sizeof ih) + err(1, "%s", oname); + + /* Copy data, calculating the data CRC as we go. */ + crc = crc32(0L, Z_NULL, 0); + while ((nbytes = read(ifd, buf, sizeof buf)) != 0) { + if (nbytes == -1) + err(1, "%s", iname); + if (write(ofd, buf, nbytes) != nbytes) + err(1, "%s", oname); + crc = crc32(crc, buf, nbytes); + ih.ih_size += nbytes; + } + ih.ih_dcrc = htobe32(crc); + ih.ih_size = htobe32(ih.ih_size); + + /* Calculate header CRC. */ + crc = crc32(0, (void *)&ih, sizeof ih); + ih.ih_hcrc = htobe32(crc); + + /* Write finalized header. */ + if (lseek(ofd, 0, SEEK_SET) != 0) + err(1, "%s", oname); + if (write(ofd, &ih, sizeof ih) != sizeof ih) + err(1, "%s", oname); + + return(0); +} + +void +usage(void) +{ + const struct arch_map *mapptr; + const struct os_map *osmapptr; + + (void)fprintf(stderr, + "usage: %s [-a arch] [-e entry] [-l loadaddr] [-o os] " + "infile outfile\n", __progname); + (void)fprintf(stderr, + "arch is one of:"); + for (mapptr = archmap; mapptr->arch; mapptr++) + (void)fprintf(stderr, " %s", mapptr->arch); + (void)fprintf(stderr, "\n"); + (void)fprintf(stderr, + "os is one of:"); + for (osmapptr = osmap; osmapptr->arch; osmapptr++) + (void)fprintf(stderr, " %s", osmapptr->arch); + (void)fprintf(stderr, "\n"); + + exit(1); +} |