summaryrefslogtreecommitdiffstats
path: root/sys/boot
diff options
context:
space:
mode:
authornwhitehorn <nwhitehorn@FreeBSD.org>2008-10-14 03:32:41 +0000
committernwhitehorn <nwhitehorn@FreeBSD.org>2008-10-14 03:32:41 +0000
commit17c43f6b3532e649770b05ff154eaa81d7eebe40 (patch)
tree9562791759f47f0039444f095efe6aea0e82b821 /sys/boot
parentb18a67ad042354952c5d3c5639f664e53b80a4dd (diff)
downloadFreeBSD-src-17c43f6b3532e649770b05ff154eaa81d7eebe40.zip
FreeBSD-src-17c43f6b3532e649770b05ff154eaa81d7eebe40.tar.gz
Add a simple HFS boot block implementation for booting PowerPC macs. It creates
a small HFS filesystem with a CHRP boot script and an early-stage bootloader derived from the sparc64 boot block. Obtained from: sparc64
Diffstat (limited to 'sys/boot')
-rw-r--r--sys/boot/powerpc/Makefile2
-rw-r--r--sys/boot/powerpc/boot1.chrp/Makefile42
-rw-r--r--sys/boot/powerpc/boot1.chrp/Makefile.hfs4
-rw-r--r--sys/boot/powerpc/boot1.chrp/boot1.c764
-rw-r--r--sys/boot/powerpc/boot1.chrp/bootinfo.txt13
-rwxr-xr-xsys/boot/powerpc/boot1.chrp/generate-hfs.sh64
-rw-r--r--sys/boot/powerpc/boot1.chrp/hfs.tmpl.bz2.uu18
7 files changed, 906 insertions, 1 deletions
diff --git a/sys/boot/powerpc/Makefile b/sys/boot/powerpc/Makefile
index e1dab91..80a68a6 100644
--- a/sys/boot/powerpc/Makefile
+++ b/sys/boot/powerpc/Makefile
@@ -1,5 +1,5 @@
# $FreeBSD$
-SUBDIR= ofw uboot
+SUBDIR= boot1.chrp ofw uboot
.include <bsd.subdir.mk>
diff --git a/sys/boot/powerpc/boot1.chrp/Makefile b/sys/boot/powerpc/boot1.chrp/Makefile
new file mode 100644
index 0000000..621b973
--- /dev/null
+++ b/sys/boot/powerpc/boot1.chrp/Makefile
@@ -0,0 +1,42 @@
+# $FreeBSD$
+
+WITHOUT_SSP=
+
+PROG= boot1.elf
+NEWVERSWHAT= "Open Firmware boot block" ${MACHINE_ARCH}
+BINDIR?= /boot
+INSTALLFLAGS= -b
+
+FILES= boot1.hfs
+SRCS= boot1.c ashldi3.c
+
+INTERNALPROG=
+NO_MAN=
+
+CFLAGS= -ffreestanding -msoft-float -Os -D_KERNEL \
+ -I${.CURDIR}/../../common -I${.CURDIR}/../../../
+LDFLAGS=-nostdlib -static -N
+
+.include "${.CURDIR}/../Makefile.inc"
+.PATH: ${.CURDIR}/../../../libkern ${.CURDIR}
+
+# The following inserts out objects into a template HFS
+# created by generate-hfs.sh
+
+.include "${.CURDIR}/Makefile.hfs"
+
+boot1.hfs: boot1.elf bootinfo.txt
+ echo ${.OBJDIR}
+ uudecode ${.CURDIR}/hfs.tmpl.bz2.uu
+ mv hfs.tmpl.bz2 ${.TARGET}.bz2
+ bzip2 -f -d ${.TARGET}.bz2
+ dd if=boot1.elf of=${.TARGET} seek=${BOOT1_OFFSET} conv=notrunc
+ dd if=${.CURDIR}/bootinfo.txt of=${.TARGET} seek=${BOOTINFO_OFFSET} \
+ conv=notrunc
+
+CLEANFILES= boot1.hfs
+
+boot1.o: ${.CURDIR}/../../common/ufsread.c
+
+.include <bsd.prog.mk>
+
diff --git a/sys/boot/powerpc/boot1.chrp/Makefile.hfs b/sys/boot/powerpc/boot1.chrp/Makefile.hfs
new file mode 100644
index 0000000..7f35cc3
--- /dev/null
+++ b/sys/boot/powerpc/boot1.chrp/Makefile.hfs
@@ -0,0 +1,4 @@
+# This file autogenerated by generate-hfs.sh - DO NOT EDIT
+# $FreeBSD$
+BOOTINFO_OFFSET=0x58
+BOOT1_OFFSET=0x1c
diff --git a/sys/boot/powerpc/boot1.chrp/boot1.c b/sys/boot/powerpc/boot1.chrp/boot1.c
new file mode 100644
index 0000000..651db76
--- /dev/null
+++ b/sys/boot/powerpc/boot1.chrp/boot1.c
@@ -0,0 +1,764 @@
+/*-
+ * Copyright (c) 1998 Robert Nordier
+ * All rights reserved.
+ * Copyright (c) 2001 Robert Drehmel
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms are freely
+ * permitted provided that the above copyright notice and this
+ * paragraph and the following disclaimer are duplicated in all
+ * such forms.
+ *
+ * This software is provided "AS IS" and without any express or
+ * implied warranties, including, without limitation, the implied
+ * warranties of merchantability and fitness for a particular
+ * purpose.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <sys/param.h>
+#include <sys/dirent.h>
+#include <machine/elf.h>
+#include <machine/stdarg.h>
+
+#define _PATH_LOADER "/boot/loader"
+#define _PATH_KERNEL "/boot/kernel/kernel"
+
+#define BSIZEMAX 16384
+
+typedef int putc_func_t(char c, void *arg);
+typedef int32_t ofwh_t;
+
+struct sp_data {
+ char *sp_buf;
+ u_int sp_len;
+ u_int sp_size;
+};
+
+static const char digits[] = "0123456789abcdef";
+
+static char bootpath[128];
+static char bootargs[128];
+
+static ofwh_t bootdev;
+
+static struct fs fs;
+static ino_t inomap;
+static char blkbuf[BSIZEMAX];
+static unsigned int fsblks;
+
+static uint32_t fs_off;
+
+int main(int ac, char **av);
+
+static void exit(int) __dead2;
+static void load(const char *);
+static int dskread(void *, u_int64_t, int);
+
+static void usage(void);
+
+static void bcopy(const void *src, void *dst, size_t len);
+static void bzero(void *b, size_t len);
+
+static int mount(const char *device, int quiet);
+
+static void panic(const char *fmt, ...) __dead2;
+static int printf(const char *fmt, ...);
+static int putchar(char c, void *arg);
+static int vprintf(const char *fmt, va_list ap);
+static int vsnprintf(char *str, size_t sz, const char *fmt, va_list ap);
+
+static int __printf(const char *fmt, putc_func_t *putc, void *arg, va_list ap);
+static int __putc(char c, void *arg);
+static int __puts(const char *s, putc_func_t *putc, void *arg);
+static int __sputc(char c, void *arg);
+static char *__uitoa(char *buf, u_int val, int base);
+static char *__ultoa(char *buf, u_long val, int base);
+
+/*
+ * Open Firmware interface functions
+ */
+typedef u_int32_t ofwcell_t;
+typedef u_int32_t u_ofwh_t;
+typedef int (*ofwfp_t)(void *);
+ofwfp_t ofw; /* the prom Open Firmware entry */
+ofwh_t chosenh;
+
+void ofw_init(void *, int, int (*)(void *), char *, int);
+static ofwh_t ofw_finddevice(const char *);
+static ofwh_t ofw_open(const char *);
+static int ofw_close(ofwh_t);
+static int ofw_getprop(ofwh_t, const char *, void *, size_t);
+static int ofw_setprop(ofwh_t, const char *, void *, size_t);
+static int ofw_read(ofwh_t, void *, size_t);
+static int ofw_write(ofwh_t, const void *, size_t);
+static int ofw_claim(void *virt, size_t len, u_int align);
+static int ofw_seek(ofwh_t, u_int64_t);
+static void ofw_exit(void) __dead2;
+
+ofwh_t bootdevh;
+ofwh_t stdinh, stdouth;
+
+__asm(" \n\
+ .data \n\
+stack: \n\
+ .space 16384 \n\
+ \n\
+ .text \n\
+ .globl _start \n\
+_start: \n\
+ lis %r1,stack@ha \n\
+ addi %r1,%r1,stack@l \n\
+ addi %r1,%r1,8192 \n\
+ \n\
+ b ofw_init \n\
+");
+
+void
+ofw_init(void *vpd, int res, int (*openfirm)(void *), char *arg, int argl)
+{
+ char *av[16];
+ char *p;
+ int ac;
+
+ ofw = openfirm;
+
+ chosenh = ofw_finddevice("/chosen");
+ ofw_getprop(chosenh, "stdin", &stdinh, sizeof(stdinh));
+ ofw_getprop(chosenh, "stdout", &stdouth, sizeof(stdouth));
+ ofw_getprop(chosenh, "bootargs", bootargs, sizeof(bootargs));
+ ofw_getprop(chosenh, "bootpath", bootpath, sizeof(bootpath));
+
+ bootargs[sizeof(bootargs) - 1] = '\0';
+ bootpath[sizeof(bootpath) - 1] = '\0';
+
+ p = bootpath;
+ while (*p != '\0') {
+ if (*p == ':') {
+ *(++p) = '\0';
+ break;
+ }
+ p++;
+ }
+
+ ac = 0;
+ p = bootargs;
+ for (;;) {
+ while (*p == ' ' && *p != '\0')
+ p++;
+ if (*p == '\0' || ac >= 16)
+ break;
+ av[ac++] = p;
+ while (*p != ' ' && *p != '\0')
+ p++;
+ if (*p != '\0')
+ *p++ = '\0';
+ }
+
+ exit(main(ac, av));
+}
+
+static ofwh_t
+ofw_finddevice(const char *name)
+{
+ ofwcell_t args[] = {
+ (ofwcell_t)"finddevice",
+ 1,
+ 1,
+ (ofwcell_t)name,
+ 0
+ };
+
+ if ((*ofw)(args)) {
+ printf("ofw_finddevice: name=\"%s\"\n", name);
+ return (1);
+ }
+ return (args[4]);
+}
+
+static int
+ofw_getprop(ofwh_t ofwh, const char *name, void *buf, size_t len)
+{
+ ofwcell_t args[] = {
+ (ofwcell_t)"getprop",
+ 4,
+ 1,
+ (u_ofwh_t)ofwh,
+ (ofwcell_t)name,
+ (ofwcell_t)buf,
+ len,
+ 0
+ };
+
+ if ((*ofw)(args)) {
+ printf("ofw_getprop: ofwh=0x%x buf=%p len=%u\n",
+ ofwh, buf, len);
+ return (1);
+ }
+ return (0);
+}
+
+static int
+ofw_setprop(ofwh_t ofwh, const char *name, void *buf, size_t len)
+{
+ ofwcell_t args[] = {
+ (ofwcell_t)"setprop",
+ 4,
+ 1,
+ (u_ofwh_t)ofwh,
+ (ofwcell_t)name,
+ (ofwcell_t)buf,
+ len,
+ 0
+ };
+
+ if ((*ofw)(args)) {
+ printf("ofw_setprop: ofwh=0x%x buf=%p len=%u\n",
+ ofwh, buf, len);
+ return (1);
+ }
+ return (0);
+}
+
+static ofwh_t
+ofw_open(const char *path)
+{
+ ofwcell_t args[] = {
+ (ofwcell_t)"open",
+ 1,
+ 1,
+ (ofwcell_t)path,
+ 0
+ };
+
+ if ((*ofw)(args)) {
+ printf("ofw_open: path=\"%s\"\n", path);
+ return (-1);
+ }
+ return (args[4]);
+}
+
+static int
+ofw_close(ofwh_t devh)
+{
+ ofwcell_t args[] = {
+ (ofwcell_t)"close",
+ 1,
+ 0,
+ (u_ofwh_t)devh
+ };
+
+ if ((*ofw)(args)) {
+ printf("ofw_close: devh=0x%x\n", devh);
+ return (1);
+ }
+ return (0);
+}
+
+static int
+ofw_claim(void *virt, size_t len, u_int align)
+{
+ ofwcell_t args[] = {
+ (ofwcell_t)"claim",
+ 3,
+ 1,
+ (ofwcell_t)virt,
+ len,
+ align,
+ 0,
+ 0
+ };
+
+ if ((*ofw)(args)) {
+ printf("ofw_claim: virt=%p len=%u\n", virt, len);
+ return (1);
+ }
+
+ return (0);
+}
+
+static int
+ofw_read(ofwh_t devh, void *buf, size_t len)
+{
+ ofwcell_t args[] = {
+ (ofwcell_t)"read",
+ 3,
+ 1,
+ (u_ofwh_t)devh,
+ (ofwcell_t)buf,
+ len,
+ 0
+ };
+
+ if ((*ofw)(args)) {
+ printf("ofw_read: devh=0x%x buf=%p len=%u\n", devh, buf, len);
+ return (1);
+ }
+ return (0);
+}
+
+static int
+ofw_write(ofwh_t devh, const void *buf, size_t len)
+{
+ ofwcell_t args[] = {
+ (ofwcell_t)"write",
+ 3,
+ 1,
+ (u_ofwh_t)devh,
+ (ofwcell_t)buf,
+ len,
+ 0
+ };
+
+ if ((*ofw)(args)) {
+ printf("ofw_write: devh=0x%x buf=%p len=%u\n", devh, buf, len);
+ return (1);
+ }
+ return (0);
+}
+
+static int
+ofw_seek(ofwh_t devh, u_int64_t off)
+{
+ ofwcell_t args[] = {
+ (ofwcell_t)"seek",
+ 3,
+ 1,
+ (u_ofwh_t)devh,
+ off >> 32,
+ off,
+ 0
+ };
+
+ if ((*ofw)(args)) {
+ printf("ofw_seek: devh=0x%x off=0x%lx\n", devh, off);
+ return (1);
+ }
+ return (0);
+}
+
+static void
+ofw_exit(void)
+{
+ ofwcell_t args[3];
+
+ args[0] = (ofwcell_t)"exit";
+ args[1] = 0;
+ args[2] = 0;
+
+ for (;;)
+ (*ofw)(args);
+}
+
+static void
+bcopy(const void *src, void *dst, size_t len)
+{
+ const char *s = src;
+ char *d = dst;
+
+ while (len-- != 0)
+ *d++ = *s++;
+}
+
+static void
+memcpy(void *dst, const void *src, size_t len)
+{
+ bcopy(src, dst, len);
+}
+
+static void
+bzero(void *b, size_t len)
+{
+ char *p = b;
+
+ while (len-- != 0)
+ *p++ = 0;
+}
+
+static int
+strcmp(const char *s1, const char *s2)
+{
+ for (; *s1 == *s2 && *s1; s1++, s2++)
+ ;
+ return ((u_char)*s1 - (u_char)*s2);
+}
+
+#include "ufsread.c"
+
+int
+main(int ac, char **av)
+{
+ const char *path;
+ char bootpath_full[255];
+ int i, len;
+
+ path = _PATH_LOADER;
+ for (i = 0; i < ac; i++) {
+ switch (av[i][0]) {
+ case '-':
+ switch (av[i][1]) {
+ default:
+ usage();
+ }
+ break;
+ default:
+ path = av[i];
+ break;
+ }
+ }
+
+ printf(" \n>> FreeBSD/powerpc Open Firmware boot block\n"
+ " Boot path: %s\n"
+ " Boot loader: %s\n", bootpath, path);
+
+ len = 0;
+ while (bootpath[len] != '\0') len++;
+
+ memcpy(bootpath_full,bootpath,len+1);
+
+ if (bootpath_full[len-1] == ':') {
+ for (i = 0; i < 16; i++) {
+ if (i < 10) {
+ bootpath_full[len] = i + '0';
+ bootpath_full[len+1] = '\0';
+ } else {
+ bootpath_full[len] = '1';
+ bootpath_full[len+1] = i - 10 + '0';
+ bootpath_full[len+2] = '\0';
+ }
+
+ if (mount(bootpath_full,1) >= 0)
+ break;
+
+ if (bootdev > 0)
+ ofw_close(bootdev);
+ }
+
+ if (i >= 16)
+ panic("mount");
+ } else {
+ if (mount(bootpath_full,0) == -1)
+ panic("mount");
+ }
+
+ printf(" Boot volume: %s\n",bootpath_full);
+ ofw_setprop(chosenh, "bootargs", bootpath_full, len+2);
+ load(path);
+ return (1);
+}
+
+static void
+usage(void)
+{
+
+ printf("usage: boot device [/path/to/loader]\n");
+ exit(1);
+}
+
+static void
+exit(int code)
+{
+
+ ofw_exit();
+}
+
+static struct dmadat __dmadat;
+
+static int
+mount(const char *device, int quiet)
+{
+
+ dmadat = &__dmadat;
+ if ((bootdev = ofw_open(device)) == -1) {
+ printf("mount: can't open device\n");
+ return (-1);
+ }
+ if (fsread(0, NULL, 0)) {
+ if (!quiet)
+ printf("mount: can't read superblock\n");
+ return (-1);
+ }
+ return (0);
+}
+
+static void
+load(const char *fname)
+{
+ Elf32_Ehdr eh;
+ Elf32_Phdr ph;
+ caddr_t p;
+ ino_t ino;
+ int i;
+
+ if ((ino = lookup(fname)) == 0) {
+ printf("File %s not found\n", fname);
+ return;
+ }
+ if (fsread(ino, &eh, sizeof(eh)) != sizeof(eh)) {
+ printf("Can't read elf header\n");
+ return;
+ }
+ if (!IS_ELF(eh)) {
+ printf("Not an ELF file\n");
+ return;
+ }
+ for (i = 0; i < eh.e_phnum; i++) {
+ fs_off = eh.e_phoff + i * eh.e_phentsize;
+ if (fsread(ino, &ph, sizeof(ph)) != sizeof(ph)) {
+ printf("Can't read program header %d\n", i);
+ return;
+ }
+ if (ph.p_type != PT_LOAD)
+ continue;
+ fs_off = ph.p_offset;
+ p = (caddr_t)ph.p_vaddr;
+ ofw_claim(p,(ph.p_filesz > ph.p_memsz) ?
+ ph.p_filesz : ph.p_memsz,0);
+ if (fsread(ino, p, ph.p_filesz) != ph.p_filesz) {
+ printf("Can't read content of section %d\n", i);
+ return;
+ }
+ if (ph.p_filesz != ph.p_memsz)
+ bzero(p + ph.p_filesz, ph.p_memsz - ph.p_filesz);
+ }
+ ofw_close(bootdev);
+ (*(void (*)(void *, int, ofwfp_t, char *, int))eh.e_entry)(NULL, 0,
+ ofw,NULL,0);
+}
+
+static int
+dskread(void *buf, u_int64_t lba, int nblk)
+{
+ /*
+ * The Open Firmware should open the correct partition for us.
+ * That means, if we read from offset zero on an open instance handle,
+ * we should read from offset zero of that partition.
+ */
+ ofw_seek(bootdev, lba * DEV_BSIZE);
+ ofw_read(bootdev, buf, nblk * DEV_BSIZE);
+ return (0);
+}
+
+static void
+panic(const char *fmt, ...)
+{
+ char buf[128];
+ va_list ap;
+
+ va_start(ap, fmt);
+ vsnprintf(buf, sizeof buf, fmt, ap);
+ printf("panic: %s\n", buf);
+ va_end(ap);
+
+ exit(1);
+}
+
+static int
+printf(const char *fmt, ...)
+{
+ va_list ap;
+ int ret;
+
+ va_start(ap, fmt);
+ ret = vprintf(fmt, ap);
+ va_end(ap);
+ return (ret);
+}
+
+static int
+putchar(char c, void *arg)
+{
+ char buf;
+
+ if (c == '\n') {
+ buf = '\r';
+ ofw_write(stdouth, &buf, 1);
+ }
+ buf = c;
+ ofw_write(stdouth, &buf, 1);
+ return (1);
+}
+
+static int
+vprintf(const char *fmt, va_list ap)
+{
+ int ret;
+
+ ret = __printf(fmt, putchar, 0, ap);
+ return (ret);
+}
+
+static int
+vsnprintf(char *str, size_t sz, const char *fmt, va_list ap)
+{
+ struct sp_data sp;
+ int ret;
+
+ sp.sp_buf = str;
+ sp.sp_len = 0;
+ sp.sp_size = sz;
+ ret = __printf(fmt, __sputc, &sp, ap);
+ return (ret);
+}
+
+static int
+__printf(const char *fmt, putc_func_t *putc, void *arg, va_list ap)
+{
+ char buf[(sizeof(long) * 8) + 1];
+ char *nbuf;
+ u_long ul;
+ u_int ui;
+ int lflag;
+ int sflag;
+ char *s;
+ int pad;
+ int ret;
+ int c;
+
+ nbuf = &buf[sizeof buf - 1];
+ ret = 0;
+ while ((c = *fmt++) != 0) {
+ if (c != '%') {
+ ret += putc(c, arg);
+ continue;
+ }
+ lflag = 0;
+ sflag = 0;
+ pad = 0;
+reswitch: c = *fmt++;
+ switch (c) {
+ case '#':
+ sflag = 1;
+ goto reswitch;
+ case '%':
+ ret += putc('%', arg);
+ break;
+ case 'c':
+ c = va_arg(ap, int);
+ ret += putc(c, arg);
+ break;
+ case 'd':
+ if (lflag == 0) {
+ ui = (u_int)va_arg(ap, int);
+ if (ui < (int)ui) {
+ ui = -ui;
+ ret += putc('-', arg);
+ }
+ s = __uitoa(nbuf, ui, 10);
+ } else {
+ ul = (u_long)va_arg(ap, long);
+ if (ul < (long)ul) {
+ ul = -ul;
+ ret += putc('-', arg);
+ }
+ s = __ultoa(nbuf, ul, 10);
+ }
+ ret += __puts(s, putc, arg);
+ break;
+ case 'l':
+ lflag = 1;
+ goto reswitch;
+ case 'o':
+ if (lflag == 0) {
+ ui = (u_int)va_arg(ap, u_int);
+ s = __uitoa(nbuf, ui, 8);
+ } else {
+ ul = (u_long)va_arg(ap, u_long);
+ s = __ultoa(nbuf, ul, 8);
+ }
+ ret += __puts(s, putc, arg);
+ break;
+ case 'p':
+ ul = (u_long)va_arg(ap, void *);
+ s = __ultoa(nbuf, ul, 16);
+ ret += __puts("0x", putc, arg);
+ ret += __puts(s, putc, arg);
+ break;
+ case 's':
+ s = va_arg(ap, char *);
+ ret += __puts(s, putc, arg);
+ break;
+ case 'u':
+ if (lflag == 0) {
+ ui = va_arg(ap, u_int);
+ s = __uitoa(nbuf, ui, 10);
+ } else {
+ ul = va_arg(ap, u_long);
+ s = __ultoa(nbuf, ul, 10);
+ }
+ ret += __puts(s, putc, arg);
+ break;
+ case 'x':
+ if (lflag == 0) {
+ ui = va_arg(ap, u_int);
+ s = __uitoa(nbuf, ui, 16);
+ } else {
+ ul = va_arg(ap, u_long);
+ s = __ultoa(nbuf, ul, 16);
+ }
+ if (sflag)
+ ret += __puts("0x", putc, arg);
+ ret += __puts(s, putc, arg);
+ break;
+ case '0': case '1': case '2': case '3': case '4':
+ case '5': case '6': case '7': case '8': case '9':
+ pad = pad * 10 + c - '0';
+ goto reswitch;
+ default:
+ break;
+ }
+ }
+ return (ret);
+}
+
+static int
+__sputc(char c, void *arg)
+{
+ struct sp_data *sp;
+
+ sp = arg;
+ if (sp->sp_len < sp->sp_size)
+ sp->sp_buf[sp->sp_len++] = c;
+ sp->sp_buf[sp->sp_len] = '\0';
+ return (1);
+}
+
+static int
+__puts(const char *s, putc_func_t *putc, void *arg)
+{
+ const char *p;
+ int ret;
+
+ ret = 0;
+ for (p = s; *p != '\0'; p++)
+ ret += putc(*p, arg);
+ return (ret);
+}
+
+static char *
+__uitoa(char *buf, u_int ui, int base)
+{
+ char *p;
+
+ p = buf;
+ *p = '\0';
+ do
+ *--p = digits[ui % base];
+ while ((ui /= base) != 0);
+ return (p);
+}
+
+static char *
+__ultoa(char *buf, u_long ul, int base)
+{
+ char *p;
+
+ p = buf;
+ *p = '\0';
+ do
+ *--p = digits[ul % base];
+ while ((ul /= base) != 0);
+ return (p);
+}
diff --git a/sys/boot/powerpc/boot1.chrp/bootinfo.txt b/sys/boot/powerpc/boot1.chrp/bootinfo.txt
new file mode 100644
index 0000000..bd4b113
--- /dev/null
+++ b/sys/boot/powerpc/boot1.chrp/bootinfo.txt
@@ -0,0 +1,13 @@
+<CHRP-BOOT>
+<DESCRIPTION>FreeBSD/powerpc bootloader</DESCRIPTION>
+<OS-NAME>FreeBSD</OS-NAME>
+<VERSION> $FreeBSD$ </VERSION>
+
+<COMPATIBLE>
+MacRISC MacRISC3 MacRISC4
+</COMPATIBLE>
+<BOOT-SCRIPT>
+boot &device;:&partition;,\ppc\boot1.elf
+</BOOT-SCRIPT>
+</CHRP-BOOT>
+
diff --git a/sys/boot/powerpc/boot1.chrp/generate-hfs.sh b/sys/boot/powerpc/boot1.chrp/generate-hfs.sh
new file mode 100755
index 0000000..ab5694d
--- /dev/null
+++ b/sys/boot/powerpc/boot1.chrp/generate-hfs.sh
@@ -0,0 +1,64 @@
+#!/bin/sh
+
+# This script generates the dummy HFS filesystem used for the PowerPC boot
+# blocks. It uses hfsutils (emulators/hfsutils) to generate a template
+# filesystem with the relevant interesting files. These are then found by
+# grep, and the offsets written to a Makefile snippet.
+#
+# Because of licensing concerns, and because it is overkill, we do not
+# distribute hfsutils as a build tool. If you need to regenerate the HFS
+# template (e.g. because the boot block or the CHRP script have grown),
+# you must install it from ports.
+
+# $FreeBSD$
+
+HFS_SIZE=1600 #Size in 512-byte blocks of the produced image
+
+CHRPBOOT_SIZE=2k
+BOOT1_SIZE=30k
+
+# Generate 800K HFS image
+OUTPUT_FILE=hfs.tmpl
+
+dd if=/dev/zero of=$OUTPUT_FILE bs=512 count=$HFS_SIZE
+hformat -l "FreeBSD Bootstrap" $OUTPUT_FILE
+hmount $OUTPUT_FILE
+
+# Create and bless a directory for the boot loader
+hmkdir ppc
+hattrib -b ppc
+hcd ppc
+
+# Make two dummy files for the the CHRP boot script and boot1
+echo 'Bootinfo START' | dd of=bootinfo.txt.tmp cbs=$CHRPBOOT_SIZE count=1 conv=block
+echo 'Boot1 START' | dd of=boot1.elf.tmp cbs=$BOOT1_SIZE count=1 conv=block
+
+hcopy boot1.elf.tmp :boot1.elf
+hcopy bootinfo.txt.tmp :bootinfo.txt
+hattrib -c chrp -t tbxi bootinfo.txt
+humount
+
+rm bootinfo.txt.tmp
+rm boot1.elf.tmp
+
+# Locate the offsets of the two fake files
+BOOTINFO_OFFSET=$(hd $OUTPUT_FILE | grep 'Bootinfo START' | cut -f 1 -d ' ')
+BOOT1_OFFSET=$(hd $OUTPUT_FILE | grep 'Boot1 START' | cut -f 1 -d ' ')
+
+# Convert to numbers of blocks
+BOOTINFO_OFFSET=$(echo 0x$BOOTINFO_OFFSET | awk '{printf("%x\n",$1/512);}')
+BOOT1_OFFSET=$(echo 0x$BOOT1_OFFSET | awk '{printf("%x\n",$1/512);}')
+
+echo '# This file autogenerated by generate-hfs.sh - DO NOT EDIT' > Makefile.hfs
+echo '# $FreeBSD$' >> Makefile.hfs
+echo "BOOTINFO_OFFSET=0x$BOOTINFO_OFFSET" >> Makefile.hfs
+echo "BOOT1_OFFSET=0x$BOOT1_OFFSET" >> Makefile.hfs
+
+bzip2 $OUTPUT_FILE
+echo 'HFS template boot filesystem created by generate-hfs.sh' > $OUTPUT_FILE.bz2.uu
+echo 'DO NOT EDIT' >> $OUTPUT_FILE.bz2.uu
+echo '$FreeBSD$' >> $OUTPUT_FILE.bz2.uu
+
+uuencode $OUTPUT_FILE.bz2 $OUTPUT_FILE.bz2 >> $OUTPUT_FILE.bz2.uu
+rm $OUTPUT_FILE.bz2
+
diff --git a/sys/boot/powerpc/boot1.chrp/hfs.tmpl.bz2.uu b/sys/boot/powerpc/boot1.chrp/hfs.tmpl.bz2.uu
new file mode 100644
index 0000000..4ef435e
--- /dev/null
+++ b/sys/boot/powerpc/boot1.chrp/hfs.tmpl.bz2.uu
@@ -0,0 +1,18 @@
+HFS template boot filesystem created by generate-hfs.sh
+DO NOT EDIT
+$FreeBSD$
+begin 644 hfs.tmpl.bz2
+M0EIH.3%!62936?(HJX\``"]_]?___O)20>!4M2$>0#MUW$1$``$!$``"2!`(
+M4EG``>G*VV3"22334_2(/*>ID,@``:#U&"-#(!IZ0`)$HIY0>B-#(/4T```&
+M@R:`&@``<:,F1A&(!A-!@$T&@9,FC)D,(#!4E-*--31ZAB!DT!ID:#$81HT&
+M@9-!Z::C:E=SZCC1((92M^1Q@3&>="[<2FD((A[AT#`[('#?MSV(S,><P)B_
+M'31",-UG78$CN,$&,P3:!)"2/J]\T9KP63TV)"&Y8"1B*E$I(H935A3LKL9M
+M74FBH6E17;ETD`2U#;5%_9P+&>HOI'#2,"EJ0PU5)<J26E2$`KSGEA(F9(P%
+M4&+M\K54E21K+%@1UU%`;'(KZQS5)SNB[)4WUZY`"6K8U]=8Z-W*[M[UXWZ.
+M`DAMLBTF-IC8Z77:KA%),$[3LHK,^`EA`+E,(2&TIFEA-;:US^NQ)+<8%WIC
+M59:&JR9^`#&G)-N@DK.0#ZQ_>.T`PX,54O,RTW8-",N1`R>?SL"+?Q51[H]#
+MJ1C5"]BDBF1UJ!Y`J$WTC]QAFZ%Q21$J,I&0,0?9?DPU!Z>$9.380JJCO$Q8
+MXZTX)GQCCGNC%G1BIDBHTK#J9N0,M[85QC:.'>]#,GPRAALU*=)2`$ND22<.
+-VK/^+N2*<*$AY%%7'@``
+`
+end
OpenPOWER on IntegriCloud