summaryrefslogtreecommitdiffstats
path: root/sys/boot
diff options
context:
space:
mode:
authoremaste <emaste@FreeBSD.org>2014-09-04 21:05:04 +0000
committeremaste <emaste@FreeBSD.org>2014-09-04 21:05:04 +0000
commitd483443db2522b367753afdc67760b7aa80290cb (patch)
treee719e3f42dcb1eaa55a7ad6e2bf8fdea9b4a13ef /sys/boot
parent261ad5a21cf8549e5837942a5890d7a3747adcb6 (diff)
downloadFreeBSD-src-d483443db2522b367753afdc67760b7aa80290cb.zip
FreeBSD-src-d483443db2522b367753afdc67760b7aa80290cb.tar.gz
MFC boot1.efi stub loader
r264391 (nwhitehorn): Add a simple EFI stub loader. This is a quick and dirty of boot1.chrp from the PowerPC port with all the Open Firmware bits removed and replaced by their EFI counterparts. On the whole, I think I prefer Open Firmware. This code is supposed to be an immutable shim that sits on the EFI system partition, loads /boot/loader.efi from UFS and tells the real loader what disk/partition to look at. It finds the UFS root partition by the somewhat braindead approach of picking the first UFS partition it can find. Better approaches are called for, but this works for now. This shim loader will also be useful for secure boot in the future, which will require some rearchitecture. r264403 (nwhitehorn): Fix buildworld. I had some local bits in my build tree that caused this to work by accident. r264404 (nwhitehorn): Add my copyright here. Most of this is unmodified from the original sparc64 version, but at least some indication of changes that postdate the actual invention of EFI is probably a good idea. r264414 (nwhitehorn): Apparently some of the i386 boot blocks are so close to full that adding single lines to ufsread.c spills them over. Duplicate a whole bunch of code to get file sizes into boot1.efi/boot1.c rather than modifying ufsread.c. r264975 (nwhitehorn): Add generation of an EFI filesystem to hold boot1.efi. This is a near- exact copy of the code from boot1.chrp again. The resulting image is installed to /boot/boot1.efifat. If dd'ed to an 800K "efi" partition, it should result in a bootable system. r268975 (sbruno): Remove boot1.efi during clean target. Relnotes: Yes Sponsored by: The FreeBSD Foundation
Diffstat (limited to 'sys/boot')
-rw-r--r--sys/boot/amd64/Makefile2
-rw-r--r--sys/boot/amd64/boot1.efi/Makefile86
-rw-r--r--sys/boot/amd64/boot1.efi/Makefile.fat3
-rw-r--r--sys/boot/amd64/boot1.efi/boot1.c531
-rw-r--r--sys/boot/amd64/boot1.efi/fat.tmpl.bz2.uu22
-rwxr-xr-xsys/boot/amd64/boot1.efi/generate-fat.sh54
6 files changed, 697 insertions, 1 deletions
diff --git a/sys/boot/amd64/Makefile b/sys/boot/amd64/Makefile
index d0013fa..59940e9 100644
--- a/sys/boot/amd64/Makefile
+++ b/sys/boot/amd64/Makefile
@@ -2,6 +2,6 @@
.include <bsd.own.mk>
-SUBDIR= efi
+SUBDIR= efi boot1.efi
.include <bsd.subdir.mk>
diff --git a/sys/boot/amd64/boot1.efi/Makefile b/sys/boot/amd64/boot1.efi/Makefile
new file mode 100644
index 0000000..0307ca7
--- /dev/null
+++ b/sys/boot/amd64/boot1.efi/Makefile
@@ -0,0 +1,86 @@
+# $FreeBSD$
+
+NO_MAN=
+
+.include <bsd.own.mk>
+
+# In-tree GCC does not support __attribute__((ms_abi)).
+.if ${COMPILER_TYPE} != "gcc"
+
+MK_SSP= no
+
+PROG= loader.sym
+INTERNALPROG=
+
+# architecture-specific loader code
+SRCS= boot1.c reloc.c start.S
+
+CFLAGS+= -fPIC
+CFLAGS+= -I.
+CFLAGS+= -I${.CURDIR}/../../efi/include
+CFLAGS+= -I${.CURDIR}/../../efi/include/${MACHINE_CPUARCH}
+CFLAGS+= -I${.CURDIR}/../../../contrib/dev/acpica/include
+CFLAGS+= -I${.CURDIR}/../../..
+
+# Always add MI sources and REGULAR efi loader bits
+.PATH: ${.CURDIR}/../efi ${.CURDIR}/../../common
+CFLAGS+= -I${.CURDIR}/../../common
+
+FILES= boot1.efi boot1.efifat
+FILESMODE_boot1.efi= ${BINMODE}
+
+LDSCRIPT= ${.CURDIR}/../efi/ldscript.${MACHINE_CPUARCH}
+LDFLAGS= -Wl,-T${LDSCRIPT} -Wl,-Bsymbolic -shared -Wl,-znocombreloc
+
+${PROG}: ${LDSCRIPT}
+
+OBJCOPY?= objcopy
+OBJDUMP?= objdump
+
+.if ${MACHINE_CPUARCH} == "amd64"
+EFI_TARGET= efi-app-x86_64
+.else
+EFI_TARGET= efi-app-ia32
+.endif
+
+boot1.efi: loader.sym
+ if [ `${OBJDUMP} -t ${.ALLSRC} | fgrep '*UND*' | wc -l` != 0 ]; then \
+ ${OBJDUMP} -t ${.ALLSRC} | fgrep '*UND*'; \
+ exit 1; \
+ fi
+ ${OBJCOPY} -j .text -j .sdata -j .data \
+ -j .dynamic -j .dynsym -j .rel.dyn \
+ -j .rela.dyn -j .reloc -j .eh_frame -j set_Xcommand_set \
+ --target=${EFI_TARGET} ${.ALLSRC} ${.TARGET}
+
+CFLAGS+= -I${.CURDIR}/../../common
+
+boot1.o: ${.CURDIR}/../../common/ufsread.c
+
+# The following inserts out objects into a template FAT file system
+# created by generate-fat.sh
+
+.include "${.CURDIR}/Makefile.fat"
+
+boot1.efifat: boot1.efi
+ echo ${.OBJDIR}
+ uudecode ${.CURDIR}/fat.tmpl.bz2.uu
+ mv fat.tmpl.bz2 ${.TARGET}.bz2
+ bzip2 -f -d ${.TARGET}.bz2
+ dd if=boot1.efi of=${.TARGET} seek=${BOOT1_OFFSET} conv=notrunc
+
+CLEANFILES= boot1.efifat
+
+.endif # ${COMPILER_TYPE} != "gcc"
+
+.include <bsd.prog.mk>
+
+beforedepend ${OBJS}: machine x86
+
+CLEANFILES+= machine x86 boot1.efi
+
+machine:
+ ln -sf ${.CURDIR}/../../../amd64/include machine
+
+x86:
+ ln -sf ${.CURDIR}/../../../x86/include x86
diff --git a/sys/boot/amd64/boot1.efi/Makefile.fat b/sys/boot/amd64/boot1.efi/Makefile.fat
new file mode 100644
index 0000000..324481e
--- /dev/null
+++ b/sys/boot/amd64/boot1.efi/Makefile.fat
@@ -0,0 +1,3 @@
+# This file autogenerated by generate-fat.sh - DO NOT EDIT
+# $FreeBSD$
+BOOT1_OFFSET=0x2d
diff --git a/sys/boot/amd64/boot1.efi/boot1.c b/sys/boot/amd64/boot1.efi/boot1.c
new file mode 100644
index 0000000..8661f05
--- /dev/null
+++ b/sys/boot/amd64/boot1.efi/boot1.c
@@ -0,0 +1,531 @@
+/*-
+ * Copyright (c) 1998 Robert Nordier
+ * All rights reserved.
+ * Copyright (c) 2001 Robert Drehmel
+ * All rights reserved.
+ * Copyright (c) 2014 Nathan Whitehorn
+ * 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>
+
+#include <efi.h>
+
+#define _PATH_LOADER "/boot/loader.efi"
+#define _PATH_KERNEL "/boot/kernel/kernel"
+
+#define BSIZEMAX 16384
+
+typedef int putc_func_t(char c, void *arg);
+
+struct sp_data {
+ char *sp_buf;
+ u_int sp_len;
+ u_int sp_size;
+};
+
+static const char digits[] = "0123456789abcdef";
+
+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);
+
+static int domount(EFI_DEVICE_PATH *device, EFI_BLOCK_IO *blkio, int quiet);
+static void load(const char *fname);
+
+EFI_SYSTEM_TABLE *systab;
+EFI_HANDLE *image;
+
+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);
+}
+
+static EFI_GUID BlockIoProtocolGUID = BLOCK_IO_PROTOCOL;
+static EFI_GUID DevicePathGUID = DEVICE_PATH_PROTOCOL;
+static EFI_GUID LoadedImageGUID = LOADED_IMAGE_PROTOCOL;
+
+static EFI_BLOCK_IO *bootdev;
+static EFI_DEVICE_PATH *bootdevpath;
+static EFI_HANDLE *bootdevhandle;
+
+EFI_STATUS efi_main(EFI_HANDLE Ximage, EFI_SYSTEM_TABLE* Xsystab)
+{
+ EFI_HANDLE handles[128];
+ EFI_BLOCK_IO *blkio;
+ UINTN i, nparts = sizeof(handles);
+ EFI_STATUS status;
+ EFI_DEVICE_PATH *devpath;
+ char *path = _PATH_LOADER;
+
+ systab = Xsystab;
+ image = Ximage;
+
+ printf(" \n>> FreeBSD EFI boot block\n");
+ printf(" Loader path: %s\n", path);
+
+ status = systab->BootServices->LocateHandle(ByProtocol,
+ &BlockIoProtocolGUID, NULL, &nparts, handles);
+ nparts /= sizeof(handles[0]);
+
+ for (i = 0; i < nparts; i++) {
+ status = systab->BootServices->HandleProtocol(handles[i],
+ &DevicePathGUID, (void **)&devpath);
+ if (EFI_ERROR(status))
+ continue;
+
+ while (!IsDevicePathEnd(NextDevicePathNode(devpath)))
+ devpath = NextDevicePathNode(devpath);
+
+ status = systab->BootServices->HandleProtocol(handles[i],
+ &BlockIoProtocolGUID, (void **)&blkio);
+ if (EFI_ERROR(status))
+ continue;
+
+ if (!blkio->Media->LogicalPartition)
+ continue;
+
+ if (domount(devpath, blkio, 1) >= 0)
+ break;
+ }
+
+ if (i == nparts)
+ panic("No bootable partition found");
+
+ bootdevhandle = handles[i];
+ load(path);
+
+ panic("Load failed");
+
+ return EFI_SUCCESS;
+}
+
+static int
+dskread(void *buf, u_int64_t lba, int nblk)
+{
+ EFI_STATUS status;
+
+ status = bootdev->ReadBlocks(bootdev, bootdev->Media->MediaId, lba,
+ nblk * bootdev->Media->BlockSize, buf);
+
+ if (EFI_ERROR(status))
+ return (-1);
+
+ return (0);
+}
+
+#include "ufsread.c"
+
+static ssize_t
+fsstat(ufs_ino_t inode)
+{
+#ifndef UFS2_ONLY
+ static struct ufs1_dinode dp1;
+ ufs1_daddr_t addr1;
+#endif
+#ifndef UFS1_ONLY
+ static struct ufs2_dinode dp2;
+#endif
+ static struct fs fs;
+ static ufs_ino_t inomap;
+ char *blkbuf;
+ void *indbuf;
+ size_t n, nb, size, off, vboff;
+ ufs_lbn_t lbn;
+ ufs2_daddr_t addr2, vbaddr;
+ static ufs2_daddr_t blkmap, indmap;
+ u_int u;
+
+ blkbuf = dmadat->blkbuf;
+ indbuf = dmadat->indbuf;
+ if (!dsk_meta) {
+ inomap = 0;
+ for (n = 0; sblock_try[n] != -1; n++) {
+ if (dskread(dmadat->sbbuf, sblock_try[n] / DEV_BSIZE,
+ SBLOCKSIZE / DEV_BSIZE))
+ return -1;
+ memcpy(&fs, dmadat->sbbuf, sizeof(struct fs));
+ if ((
+#if defined(UFS1_ONLY)
+ fs.fs_magic == FS_UFS1_MAGIC
+#elif defined(UFS2_ONLY)
+ (fs.fs_magic == FS_UFS2_MAGIC &&
+ fs.fs_sblockloc == sblock_try[n])
+#else
+ fs.fs_magic == FS_UFS1_MAGIC ||
+ (fs.fs_magic == FS_UFS2_MAGIC &&
+ fs.fs_sblockloc == sblock_try[n])
+#endif
+ ) &&
+ fs.fs_bsize <= MAXBSIZE &&
+ fs.fs_bsize >= sizeof(struct fs))
+ break;
+ }
+ if (sblock_try[n] == -1) {
+ printf("Not ufs\n");
+ return -1;
+ }
+ dsk_meta++;
+ } else
+ memcpy(&fs, dmadat->sbbuf, sizeof(struct fs));
+ if (!inode)
+ return 0;
+ if (inomap != inode) {
+ n = IPERVBLK(&fs);
+ if (dskread(blkbuf, INO_TO_VBA(&fs, n, inode), DBPERVBLK))
+ return -1;
+ n = INO_TO_VBO(n, inode);
+#if defined(UFS1_ONLY)
+ memcpy(&dp1, (struct ufs1_dinode *)blkbuf + n,
+ sizeof(struct ufs1_dinode));
+#elif defined(UFS2_ONLY)
+ memcpy(&dp2, (struct ufs2_dinode *)blkbuf + n,
+ sizeof(struct ufs2_dinode));
+#else
+ if (fs.fs_magic == FS_UFS1_MAGIC)
+ memcpy(&dp1, (struct ufs1_dinode *)blkbuf + n,
+ sizeof(struct ufs1_dinode));
+ else
+ memcpy(&dp2, (struct ufs2_dinode *)blkbuf + n,
+ sizeof(struct ufs2_dinode));
+#endif
+ inomap = inode;
+ fs_off = 0;
+ blkmap = indmap = 0;
+ }
+ size = DIP(di_size);
+ n = size - fs_off;
+ return (n);
+}
+
+static struct dmadat __dmadat;
+
+static int
+domount(EFI_DEVICE_PATH *device, EFI_BLOCK_IO *blkio, int quiet)
+{
+
+ dmadat = &__dmadat;
+ bootdev = blkio;
+ bootdevpath = device;
+ if (fsread(0, NULL, 0)) {
+ if (!quiet)
+ printf("domount: can't read superblock\n");
+ return (-1);
+ }
+ if (!quiet)
+ printf("Succesfully mounted UFS filesystem\n");
+ return (0);
+}
+
+static void
+load(const char *fname)
+{
+ ufs_ino_t ino;
+ EFI_STATUS status;
+ EFI_HANDLE loaderhandle;
+ EFI_LOADED_IMAGE *loaded_image;
+ void *buffer;
+ size_t bufsize;
+
+ if ((ino = lookup(fname)) == 0) {
+ printf("File %s not found\n", fname);
+ return;
+ }
+
+ bufsize = fsstat(ino);
+ status = systab->BootServices->AllocatePool(EfiLoaderData,
+ bufsize, &buffer);
+ fsread(ino, buffer, bufsize);
+
+ /* XXX: For secure boot, we need our own loader here */
+ status = systab->BootServices->LoadImage(TRUE, image, bootdevpath,
+ buffer, bufsize, &loaderhandle);
+
+ status = systab->BootServices->HandleProtocol(loaderhandle,
+ &LoadedImageGUID, (VOID**)&loaded_image);
+ loaded_image->DeviceHandle = bootdevhandle;
+
+ status = systab->BootServices->StartImage(loaderhandle, NULL, NULL);
+}
+
+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);
+
+ while (1) {}
+}
+
+static int
+printf(const char *fmt, ...)
+{
+ va_list ap;
+ int ret;
+
+ /* Don't annoy the user as we probe for partitions */
+ if (strcmp(fmt,"Not ufs\n") == 0)
+ return 0;
+
+ va_start(ap, fmt);
+ ret = vprintf(fmt, ap);
+ va_end(ap);
+ return (ret);
+}
+
+static int
+putchar(char c, void *arg)
+{
+ CHAR16 buf[2];
+
+ if (c == '\n') {
+ buf[0] = '\r';
+ buf[1] = 0;
+ systab->ConOut->OutputString(systab->ConOut, buf);
+ }
+ buf[0] = c;
+ buf[1] = 0;
+ systab->ConOut->OutputString(systab->ConOut, buf);
+ 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/amd64/boot1.efi/fat.tmpl.bz2.uu b/sys/boot/amd64/boot1.efi/fat.tmpl.bz2.uu
new file mode 100644
index 0000000..2af4244
--- /dev/null
+++ b/sys/boot/amd64/boot1.efi/fat.tmpl.bz2.uu
@@ -0,0 +1,22 @@
+FAT template boot filesystem created by generate-fat.sh
+DO NOT EDIT
+$FreeBSD$
+begin 644 fat.tmpl.bz2
+M0EIH.3%!62936?1V`!$`&J7____[ZZKJJ_^N_ZO^Z_^[ON_\`4`00!0$#$$"
+M0D)$6&(<P`(Y=SNY1(2DHTC":::-`!H`&@-````#)IH#3(&@:`!IIDT--,@E
+M53TFCWZJGJ`-!D`-`#(::```:```&@:!D`!D``&*B3:C]4T]0#0`:``-`T``
+M``````````&@)131/4T-*>IZC3RGZH\B&$,U&AH#)B:,$8TAF@@]0T>IZF&A
+M&GZID,1IZFAMO%FPGL0"(QIZV"3_!`$@N(@`DD$?C&$["`)`!)$6@#\HOB42
+M0`"2(X0FGX1#L"`'7E,'#-'HM!'QUD0\R,?9U,6ZE8F,Y6*L<9S<6PH)"%_"
+MX'_PL4A),QB"(`B(=14*-"8,(QCG.(2$A(1J'010CB&R$(0B00FPP(0A"$)E
+M#`A"$(1]LB&!"$(0B4&1#`A"$(14W<9J.:&A@8&!@8'`Z$(D(02@^L=UL>:+
+MBG:Q5+4&'[/P4@D2?M<,E!0&YBF8+],4^%$`4<YVD4=K")O.IZ\#)``!CU-1
+M``!L%C7V^RL80`#K(AUU+"D])9/B4@>*%$N9MF:Z29-_VG2G7<$LJ-44RST&
+MB53YE@H%(G5G$.FU;=L[DQVA]"(V4B1+%BP%.A<-10-%#R#NKR='@\'#"_'U
+M'I36ZT:8QIN*3E$:HZIZRJ?$Y1L&<1'C)G(=8,E.L(KU<9X=%/NX.6\=@^IW
+M\-PC$B&I"T\!(VI3"K!X:\%.01Y#X/83[SH.J*H5BH:ILFV1'X/D/V1$W6'\
+MFY>YE:*(I!.X@'D>H_(PY'(W1+B;:,Y?H8Y%(Q')!>DDE;\J1-DRXJJ/O(1@
+M'X/24=!+/V8S1)B(R:UE"0&&1:PUS(1`!$04``++GZ/8(CE5P1P8?^7QB[DB
+(G"A(>CL`"(``
+`
+end
diff --git a/sys/boot/amd64/boot1.efi/generate-fat.sh b/sys/boot/amd64/boot1.efi/generate-fat.sh
new file mode 100755
index 0000000..eafd3e0
--- /dev/null
+++ b/sys/boot/amd64/boot1.efi/generate-fat.sh
@@ -0,0 +1,54 @@
+#!/bin/sh
+
+# This script generates the dummy FAT filesystem used for the EFI boot
+# blocks. It uses newfs_msdos 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 it requires root, and because it is overkill, we do not
+# do this as part of the normal build. If makefs(8) grows workable FAT
+# support, this should be revisited.
+
+# $FreeBSD$
+
+FAT_SIZE=1600 #Size in 512-byte blocks of the produced image
+
+BOOT1_SIZE=64k
+
+# Generate 800K FAT image
+OUTPUT_FILE=fat.tmpl
+
+dd if=/dev/zero of=$OUTPUT_FILE bs=512 count=$FAT_SIZE
+DEVICE=`mdconfig -a -f $OUTPUT_FILE`
+newfs_msdos -F 12 $DEVICE
+mkdir stub
+mount -t msdosfs /dev/$DEVICE stub
+
+# Create and bless a directory for the boot loader
+mkdir -p stub/efi/boot
+
+# Make a dummy file for boot1
+echo 'Boot1 START' | dd of=stub/efi/boot/BOOTx64.efi cbs=$BOOT1_SIZE count=1 conv=block
+
+umount stub
+mdconfig -d -u $DEVICE
+rmdir stub
+
+# Locate the offsets of the two fake files
+BOOT1_OFFSET=$(hd $OUTPUT_FILE | grep 'Boot1 START' | cut -f 1 -d ' ')
+
+# Convert to numbers of blocks
+BOOT1_OFFSET=$(echo 0x$BOOT1_OFFSET | awk '{printf("%x\n",$1/512);}')
+
+echo '# This file autogenerated by generate-fat.sh - DO NOT EDIT' > Makefile.fat
+echo '# $FreeBSD$' >> Makefile.fat
+echo "BOOT1_OFFSET=0x$BOOT1_OFFSET" >> Makefile.fat
+
+bzip2 $OUTPUT_FILE
+echo 'FAT template boot filesystem created by generate-fat.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
+
OpenPOWER on IntegriCloud