Page Menu
Home
FreeBSD
Search
Configure Global Search
Log In
Files
F144960081
D4515.id11158.diff
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Flag For Later
Award Token
Size
35 KB
Referenced Files
None
Subscribers
None
D4515.id11158.diff
View Options
Index: sys/boot/common/self_reloc.c
===================================================================
--- sys/boot/common/self_reloc.c
+++ sys/boot/common/self_reloc.c
@@ -61,6 +61,8 @@
#define RELOC_TYPE_RELATIVE R_386_RELATIVE
#endif
+void self_reloc(Elf_Addr baseaddr, ElfW_Dyn *dynamic);
+
/*
* A simple elf relocator.
*/
Index: sys/boot/efi/Makefile
===================================================================
--- sys/boot/efi/Makefile
+++ sys/boot/efi/Makefile
@@ -16,4 +16,6 @@
SUBDIR+= loader boot1
.endif
+CFLAGSWARN+= -Wall
+
.include <bsd.subdir.mk>
Index: sys/boot/efi/boot1/Makefile
===================================================================
--- sys/boot/efi/boot1/Makefile
+++ sys/boot/efi/boot1/Makefile
@@ -2,7 +2,18 @@
MAN=
+CWARNFLAGS?= -Wall -Wredundant-decls -Wnested-externs -Wstrict-prototypes \
+ -Wmissing-prototypes -Wpointer-arith -Winline -Wcast-qual \
+ -Wundef -Wno-pointer-sign -Wmissing-include-dirs \
+ -fdiagnostics-show-option -Wno-unknown-pragmas
+
+# EFI_GUID assignments
+CWARNFLAGS+= -Wno-missing-braces
+# zfsimpl.c
+CWARNFLAGS+= -Wno-unused-function -Wno-array-bounds
+
.include <bsd.own.mk>
+.include <src.opts.mk>
# In-tree GCC does not support __attribute__((ms_abi)).
.if ${COMPILER_TYPE} != "gcc"
@@ -13,13 +24,21 @@
INTERNALPROG=
# architecture-specific loader code
-SRCS= boot1.c self_reloc.c start.S
+SRCS= boot1.c self_reloc.c start.S ufs_module.c
+.if ${MK_ZFS} != "no"
+SRCS+= zfs_module.c
+.endif
CFLAGS+= -I.
CFLAGS+= -I${.CURDIR}/../include
CFLAGS+= -I${.CURDIR}/../include/${MACHINE}
CFLAGS+= -I${.CURDIR}/../../../contrib/dev/acpica/include
CFLAGS+= -I${.CURDIR}/../../..
+.if ${MK_ZFS} != "no"
+CFLAGS+= -I${.CURDIR}/../../zfs/
+CFLAGS+= -I${.CURDIR}/../../../cddl/boot/zfs/
+CFLAGS+= -DZFS_EFI_BOOT
+.endif
# Always add MI sources and REGULAR efi loader bits
.PATH: ${.CURDIR}/../loader/arch/${MACHINE}
Index: sys/boot/efi/boot1/boot1.c
===================================================================
--- sys/boot/efi/boot1/boot1.c
+++ sys/boot/efi/boot1/boot1.c
@@ -5,6 +5,8 @@
* All rights reserved.
* Copyright (c) 2014 Nathan Whitehorn
* All rights reserved.
+ * Copyright (c) 2015 Eric McCorkle
+ * All rights reverved.
*
* Redistribution and use in source and binary forms are freely
* permitted provided that the above copyright notice and this
@@ -21,17 +23,24 @@
__FBSDID("$FreeBSD$");
#include <sys/param.h>
-#include <sys/dirent.h>
#include <machine/elf.h>
#include <machine/stdarg.h>
#include <efi.h>
#include <eficonsctl.h>
+#include "boot_module.h"
+
#define _PATH_LOADER "/boot/loader.efi"
-#define _PATH_KERNEL "/boot/kernel/kernel"
-#define BSIZEMAX 16384
+#ifdef EFI_DEBUG
+#define DPRINTF(fmt, args...) \
+ do { \
+ printf(fmt, ##args) \
+ } while (0)
+#else
+#define DPRINTF(fmt, args...) {}
+#endif
typedef int putc_func_t(char c, void *arg);
@@ -41,28 +50,133 @@
u_int sp_size;
};
-static const char digits[] = "0123456789abcdef";
+static const boot_module_t *boot_modules[] =
+{
+#ifdef ZFS_EFI_BOOT
+ &zfs_module,
+#endif
+#ifdef UFS_EFI_BOOT
+ &ufs_module
+#endif
+};
-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);
+#define NUM_BOOT_MODULES (sizeof(boot_modules) / sizeof(boot_module_t*))
+
+static const char digits[] = "0123456789abcdef";
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 putchr(char c, void *arg);
-static int domount(EFI_DEVICE_PATH *device, EFI_BLOCK_IO *blkio, int quiet);
-static void load(const char *fname);
+static void try_load(const boot_module_t* mod);
+static EFI_STATUS probe_handle(EFI_HANDLE h);
-static EFI_SYSTEM_TABLE *systab;
+EFI_SYSTEM_TABLE *systab;
+EFI_BOOT_SERVICES *bs;
static EFI_HANDLE *image;
-static void
+void *
+Malloc(size_t len, const char *file, int line)
+{
+ void *out;
+
+ if (bs->AllocatePool(EfiLoaderData, len, &out) == EFI_SUCCESS)
+ return (out);
+
+ return (NULL);
+}
+
+char *
+strcpy(char *dst, const char *src)
+{
+ int i;
+
+ for (i = 0; src[i]; i++)
+ dst[i] = src[i];
+ dst[i] = '\0';
+
+ return (dst);
+}
+
+char *
+strchr(const char *s, int c)
+{
+ int i;
+
+ for (i = 0; s[i]; i++)
+ if (s[i] == c)
+ return ((char*)(s + i));
+
+ return (NULL);
+}
+
+int
+strncmp(const char *a, const char *b, size_t len)
+{
+ int i;
+
+ for (i = 0; i < len; i++) {
+ if (a[i] == '\0' && b[i] == '\0')
+ return (0);
+ else if (a[i] < b[i])
+ return (-1);
+ else if (a[i] > b[i])
+ return (1);
+ }
+
+ return (0);
+}
+
+size_t
+strlen(const char *s)
+{
+ size_t len = 0;
+
+ for (; *s != '\0'; s++, len++)
+ ;
+
+ return (len);
+}
+
+char *
+strdup(const char *s)
+{
+ char *out;
+
+ out = malloc(strlen(s) + 1);
+ if (out == NULL)
+ return (NULL);
+
+ strcpy(out, s);
+
+ return (out);
+}
+
+int
+bcmp(const void *a, const void *b, size_t len)
+{
+ const char *sa = a;
+ const char *sb = b;
+ int i;
+
+ for (i = 0; i < len; i++)
+ if (sa[i] != sb[i])
+ return (1);
+
+ return (0);
+}
+
+int
+memcmp(const void *a, const void *b, size_t len)
+{
+
+ return bcmp(a, b, len);
+}
+
+void
bcopy(const void *src, void *dst, size_t len)
{
const char *s = src;
@@ -72,55 +186,121 @@
*d++ = *s++;
}
-static void
+void *
memcpy(void *dst, const void *src, size_t len)
{
+
bcopy(src, dst, len);
+
+ return (dst);
}
-static void
-bzero(void *b, size_t len)
+void *
+memset(void *b, int val, size_t len)
{
char *p = b;
while (len-- != 0)
- *p++ = 0;
+ *p++ = val;
+
+ return (b);
}
-static int
+int
strcmp(const char *s1, const char *s2)
{
+
for (; *s1 == *s2 && *s1; s1++, s2++)
;
return ((u_char)*s1 - (u_char)*s2);
}
+static int
+putchr(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 EFI_GUID BlockIoProtocolGUID = BLOCK_IO_PROTOCOL;
static EFI_GUID DevicePathGUID = DEVICE_PATH_PROTOCOL;
static EFI_GUID LoadedImageGUID = LOADED_IMAGE_PROTOCOL;
static EFI_GUID ConsoleControlGUID = EFI_CONSOLE_CONTROL_PROTOCOL_GUID;
-static EFI_BLOCK_IO *bootdev;
-static EFI_DEVICE_PATH *bootdevpath;
-static EFI_HANDLE *bootdevhandle;
+/*
+ * This function only returns if it fails to load the kernel. If it
+ * succeeds, it simply boots the kernel.
+ */
+void
+try_load(const boot_module_t *mod)
+{
+ size_t bufsize;
+ void *buf;
+ dev_info_t *dev;
+ EFI_HANDLE loaderhandle;
+ EFI_LOADED_IMAGE *loaded_image;
+ EFI_STATUS status;
+
+ status = mod->load(_PATH_LOADER, &dev, &buf, &bufsize);
+ if (status == EFI_NOT_FOUND)
+ return;
-EFI_STATUS efi_main(EFI_HANDLE Ximage, EFI_SYSTEM_TABLE* Xsystab)
+ if (status != EFI_SUCCESS) {
+ printf("%s failed to load %s (%lu)\n", mod->name, _PATH_LOADER,
+ status);
+ return;
+ }
+
+ if ((status = bs->LoadImage(TRUE, image, dev->devpath, buf, bufsize,
+ &loaderhandle)) != EFI_SUCCESS) {
+ printf("Failed to load image provided by %s (%lu)\n", mod->name,
+ status);
+ return;
+ }
+
+ if ((status = bs->HandleProtocol(loaderhandle, &LoadedImageGUID,
+ (VOID**)&loaded_image)) != EFI_SUCCESS) {
+ printf("Failed to query LoadedImage provided by %s (%lu)\n",
+ mod->name, status);
+ return;
+ }
+
+ loaded_image->DeviceHandle = dev->devhandle;
+
+ if ((status = bs->StartImage(loaderhandle, NULL, NULL)) !=
+ EFI_SUCCESS) {
+ printf("Failed start image provided by %s (%lu)\n", mod->name,
+ status);
+ return;
+ }
+}
+
+void
+efi_main(EFI_HANDLE Ximage, EFI_SYSTEM_TABLE *Xsystab)
{
- EFI_HANDLE handles[128];
- EFI_BLOCK_IO *blkio;
- UINTN i, nparts = sizeof(handles), cols, rows, max_dim, best_mode;
+ EFI_HANDLE *handles;
EFI_STATUS status;
- EFI_DEVICE_PATH *devpath;
- EFI_BOOT_SERVICES *BS;
EFI_CONSOLE_CONTROL_PROTOCOL *ConsoleControl = NULL;
SIMPLE_TEXT_OUTPUT_INTERFACE *conout = NULL;
- char *path = _PATH_LOADER;
+ UINTN i, max_dim, best_mode, cols, rows, hsize, nhandles;
+ /* Basic initialization*/
systab = Xsystab;
image = Ximage;
+ bs = Xsystab->BootServices;
- BS = systab->BootServices;
- status = BS->LocateProtocol(&ConsoleControlGUID, NULL,
+ /* Set up the console, so printf works. */
+ status = bs->LocateProtocol(&ConsoleControlGUID, NULL,
(VOID **)&ConsoleControl);
if (status == EFI_SUCCESS)
(void)ConsoleControl->SetMode(ConsoleControl,
@@ -132,8 +312,7 @@
conout->Reset(conout, TRUE);
max_dim = best_mode = 0;
for (i = 0; ; i++) {
- status = conout->QueryMode(conout, i,
- &cols, &rows);
+ status = conout->QueryMode(conout, i, &cols, &rows);
if (EFI_ERROR(status))
break;
if (cols * rows > max_dim) {
@@ -146,205 +325,159 @@
conout->EnableCursor(conout, TRUE);
conout->ClearScreen(conout);
- 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))
+ printf("\n>> FreeBSD EFI boot block\n");
+ printf(" Loader path: %s\n\n", _PATH_LOADER);
+ printf(" Initializing modules:");
+ for (i = 0; i < NUM_BOOT_MODULES; i++) {
+ if (boot_modules[i] == NULL)
continue;
- while (!IsDevicePathEnd(NextDevicePathNode(devpath)))
- devpath = NextDevicePathNode(devpath);
-
- status = systab->BootServices->HandleProtocol(handles[i],
- &BlockIoProtocolGUID, (void **)&blkio);
- if (EFI_ERROR(status))
- continue;
+ printf(" %s", boot_modules[i]->name);
+ if (boot_modules[i]->init != NULL)
+ boot_modules[i]->init();
+ }
+ putchr('\n', NULL);
- if (!blkio->Media->LogicalPartition)
- continue;
+ /* Get all the device handles */
+ hsize = sizeof(EFI_HANDLE) * 24;
+ if (bs->AllocatePool(EfiLoaderData, hsize, (void **)&handles) != EFI_SUCCESS)
+ panic("Failed to allocate handles");
+
+ status = bs->LocateHandle(ByProtocol, &BlockIoProtocolGUID, NULL,
+ &hsize, handles);
+ switch (status) {
+ case EFI_SUCCESS:
+ break;
+ case EFI_BUFFER_TOO_SMALL:
+ (void)bs->FreePool(handles);
+ if ((status = bs->AllocatePool(EfiLoaderData, hsize,
+ (void **)&handles) != EFI_SUCCESS)) {
+ panic("Failed to allocate %lu handles (%lu)", hsize /
+ sizeof(*handles), status);
+ }
+ status = bs->LocateHandle(ByProtocol, &BlockIoProtocolGUID,
+ NULL, &hsize, handles);
+ if (status != EFI_SUCCESS)
+ panic("Failed to get device handles (%lu)\n", status);
+ break;
+ default:
+ panic("Failed to get device handles (%lu)", status);
+ }
- if (domount(devpath, blkio, 1) >= 0)
+ /* Scan all partitions, probing with all modules. */
+ nhandles = hsize / sizeof(*handles);
+ printf(" Probing %lu block devices...", nhandles);
+ for (i = 0; i < nhandles; i++) {
+ status = probe_handle(handles[i]);
+ switch (status) {
+ case EFI_UNSUPPORTED:
+ printf(".");
+ break;
+ case EFI_SUCCESS:
+ printf("+");
+ break;
+ default:
+ printf("x");
break;
+ }
}
+ printf(" done\n");
- if (i == nparts)
- panic("No bootable partition found");
-
- bootdevhandle = handles[i];
- load(path);
+ /* Summary status. */
+ for (i = 0; i < NUM_BOOT_MODULES; i++) {
+ if (boot_modules[i] != NULL) {
+ printf(" ");
+ boot_modules[i]->status();
+ }
+ }
- panic("Load failed");
+ /* Select a partition to boot by trying each module in order. */
+ for (i = 0; i < NUM_BOOT_MODULES; i++)
+ if (boot_modules[i] != NULL)
+ try_load(boot_modules[i]);
- return EFI_SUCCESS;
+ /* If we get here, we're out of luck... */
+ panic("No bootable partitions found!");
}
-static int
-dskread(void *buf, u_int64_t lba, int nblk)
+static EFI_STATUS
+probe_handle(EFI_HANDLE h)
{
+ dev_info_t *devinfo;
+ EFI_BLOCK_IO *blkio;
+ EFI_DEVICE_PATH *devpath;
EFI_STATUS status;
- int size;
+ UINTN i;
- lba = lba / (bootdev->Media->BlockSize / DEV_BSIZE);
- size = nblk * DEV_BSIZE;
- status = bootdev->ReadBlocks(bootdev, bootdev->Media->MediaId, lba,
- size, buf);
-
- if (EFI_ERROR(status))
- return (-1);
-
- return (0);
-}
+ /* Figure out if we're dealing with an actual partition. */
+ status = bs->HandleProtocol(h, &DevicePathGUID, (void **)&devpath);
+ if (status == EFI_UNSUPPORTED)
+ return (status);
+
+ if (status != EFI_SUCCESS) {
+ DPRINTF("\nFailed to query DevicePath (%lu)\n", status);
+ return (status);
+ }
-#include "ufsread.c"
+ while (!IsDevicePathEnd(NextDevicePathNode(devpath)))
+ devpath = NextDevicePathNode(devpath);
-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;
+ status = bs->HandleProtocol(h, &BlockIoProtocolGUID, (void **)&blkio);
+ if (status == EFI_UNSUPPORTED)
+ return (status);
+
+ if (status != EFI_SUCCESS) {
+ DPRINTF("\nFailed to query BlockIoProtocol (%lu)\n", status);
+ return (status);
}
- size = DIP(di_size);
- n = size - fs_off;
- return (n);
-}
-static struct dmadat __dmadat;
+ if (!blkio->Media->LogicalPartition)
+ return (EFI_UNSUPPORTED);
-static int
-domount(EFI_DEVICE_PATH *device, EFI_BLOCK_IO *blkio, int quiet)
-{
+ /* Run through each module, see if it can load this partition */
+ for (i = 0; i < NUM_BOOT_MODULES; i++ ) {
+ if (boot_modules[i] == NULL)
+ continue;
- dmadat = &__dmadat;
- bootdev = blkio;
- bootdevpath = device;
- if (fsread(0, NULL, 0)) {
- if (!quiet)
- printf("domount: can't read superblock\n");
- return (-1);
+ if ((status = bs->AllocatePool(EfiLoaderData,
+ sizeof(*devinfo), (void **)&devinfo)) !=
+ EFI_SUCCESS) {
+ DPRINTF("\nFailed to allocate devinfo (%lu)\n",
+ status);
+ continue;
+ }
+ devinfo->dev = blkio;
+ devinfo->devpath = devpath;
+ devinfo->devhandle = h;
+ devinfo->devdata = NULL;
+ devinfo->next = NULL;
+
+ status = boot_modules[i]->probe(devinfo);
+ if (status == EFI_SUCCESS)
+ return (EFI_SUCCESS);
+ (void)bs->FreePool(devinfo);
}
- if (!quiet)
- printf("Succesfully mounted UFS filesystem\n");
- return (0);
+
+ return (EFI_UNSUPPORTED);
}
-static void
-load(const char *fname)
+void
+add_device(dev_info_t **devinfop, dev_info_t *devinfo)
{
- 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);
+ dev_info_t *dev;
+
+ if (*devinfop == NULL) {
+ *devinfop = devinfo;
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);
- if (EFI_ERROR(status))
- printf("LoadImage failed with error %lx\n", status);
-
- status = systab->BootServices->HandleProtocol(loaderhandle,
- &LoadedImageGUID, (VOID**)&loaded_image);
- if (EFI_ERROR(status))
- printf("HandleProtocol failed with error %lx\n", status);
-
- loaded_image->DeviceHandle = bootdevhandle;
-
- status = systab->BootServices->StartImage(loaderhandle, NULL, NULL);
- if (EFI_ERROR(status))
- printf("StartImage failed with error %lx\n", status);
+ for (dev = *devinfop; dev->next != NULL; dev = dev->next)
+ ;
+
+ dev->next = devinfo;
}
-static void
+void
panic(const char *fmt, ...)
{
char buf[128];
@@ -358,7 +491,7 @@
while (1) {}
}
-static int
+int
printf(const char *fmt, ...)
{
va_list ap;
@@ -369,38 +502,17 @@
return 0;
va_start(ap, fmt);
- ret = vprintf(fmt, ap);
+ ret = __printf(fmt, putchr, 0, ap);
va_end(ap);
return (ret);
}
-static int
-putchar(char c, void *arg)
+void vprintf(const char *fmt, va_list ap)
{
- 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);
+ __printf(fmt, putchr, 0, ap);
}
-static int
-vsnprintf(char *str, size_t sz, const char *fmt, va_list ap)
+int vsnprintf(char *str, size_t sz, const char *fmt, va_list ap)
{
struct sp_data sp;
int ret;
@@ -416,15 +528,10 @@
__printf(const char *fmt, putc_func_t *putc, void *arg, va_list ap)
{
char buf[(sizeof(long) * 8) + 1];
- char *nbuf;
+ char *nbuf, *s;
u_long ul;
u_int ui;
- int lflag;
- int sflag;
- char *s;
- int pad;
- int ret;
- int c;
+ int lflag, sflag, pad, ret, c;
nbuf = &buf[sizeof buf - 1];
ret = 0;
Index: sys/boot/efi/include/amd64/efibind.h
===================================================================
--- sys/boot/efi/include/amd64/efibind.h
+++ sys/boot/efi/include/amd64/efibind.h
@@ -39,7 +39,7 @@
// No ANSI C 1999/2000 stdint.h integer width declarations
- #if _MSC_EXTENSIONS
+ #ifdef _MSC_EXTENSIONS
// Use Microsoft C compiler integer width declarations
@@ -164,7 +164,7 @@
#endif
#ifndef EFIAPI // Forces EFI calling conventions reguardless of compiler options
- #if _MSC_EXTENSIONS
+ #ifdef _MSC_EXTENSIONS
#define EFIAPI __cdecl // Force C calling convention for Microsoft C compiler
#else
#define EFIAPI // Substitute expresion to force C calling convention
@@ -265,7 +265,7 @@
#endif
#endif /* __FreeBSD__ */
-#if _MSC_EXTENSIONS
+#ifdef _MSC_EXTENSIONS
#pragma warning ( disable : 4731 ) // Suppress warnings about modification of EBP
#endif
Index: sys/boot/efi/include/arm64/efibind.h
===================================================================
--- sys/boot/efi/include/arm64/efibind.h
+++ sys/boot/efi/include/arm64/efibind.h
@@ -39,7 +39,7 @@
// No ANSI C 1999/2000 stdint.h integer width declarations
- #if _MSC_EXTENSIONS
+ #ifdef _MSC_EXTENSIONS
// Use Microsoft C compiler integer width declarations
@@ -159,7 +159,7 @@
//
#ifndef EFIAPI // Forces EFI calling conventions reguardless of compiler options
- #if _MSC_EXTENSIONS
+ #ifdef _MSC_EXTENSIONS
#define EFIAPI __cdecl // Force C calling convention for Microsoft C compiler
#else
#define EFIAPI // Substitute expresion to force C calling convention
Index: sys/boot/efi/include/efilib.h
===================================================================
--- sys/boot/efi/include/efilib.h
+++ sys/boot/efi/include/efilib.h
@@ -43,7 +43,8 @@
int efi_register_handles(struct devsw *, EFI_HANDLE *, EFI_HANDLE *, int);
EFI_HANDLE efi_find_handle(struct devsw *, int);
-int efi_handle_lookup(EFI_HANDLE, struct devsw **, int *);
+int efi_handle_lookup(EFI_HANDLE, struct devsw **, int *, uint64_t *);
+int efi_handle_update_dev(EFI_HANDLE, struct devsw *, int, uint64_t);
int efi_status_to_errno(EFI_STATUS);
time_t efi_time(EFI_TIME *);
Index: sys/boot/efi/include/i386/efibind.h
===================================================================
--- sys/boot/efi/include/i386/efibind.h
+++ sys/boot/efi/include/i386/efibind.h
@@ -39,7 +39,7 @@
// No ANSI C 1999/2000 stdint.h integer width declarations
- #if _MSC_EXTENSIONS
+ #ifdef _MSC_EXTENSIONS
// Use Microsoft C compiler integer width declarations
@@ -160,7 +160,7 @@
//
#ifndef EFIAPI // Forces EFI calling conventions reguardless of compiler options
- #if _MSC_EXTENSIONS
+ #ifdef _MSC_EXTENSIONS
#define EFIAPI __cdecl // Force C calling convention for Microsoft C compiler
#else
#define EFIAPI // Substitute expresion to force C calling convention
@@ -261,7 +261,7 @@
#endif
#endif /* __FreeBSD__ */
-#if _MSC_EXTENSIONS
+#ifdef _MSC_EXTENSIONS
#pragma warning ( disable : 4731 ) // Suppress warnings about modification of EBP
#endif
Index: sys/boot/efi/libefi/handles.c
===================================================================
--- sys/boot/efi/libefi/handles.c
+++ sys/boot/efi/libefi/handles.c
@@ -35,6 +35,7 @@
EFI_HANDLE alias;
struct devsw *dev;
int unit;
+ uint64_t extra;
};
struct entry *entry;
@@ -79,7 +80,7 @@
}
int
-efi_handle_lookup(EFI_HANDLE h, struct devsw **dev, int *unit)
+efi_handle_lookup(EFI_HANDLE h, struct devsw **dev, int *unit, uint64_t *extra)
{
int idx;
@@ -90,7 +91,28 @@
*dev = entry[idx].dev;
if (unit != NULL)
*unit = entry[idx].unit;
+ if (extra != NULL)
+ *extra = entry[idx].extra;
return (0);
}
return (ENOENT);
}
+
+int
+efi_handle_update_dev(EFI_HANDLE h, struct devsw *dev, int unit,
+ uint64_t guid)
+{
+ int idx;
+
+ for (idx = 0; idx < nentries; idx++) {
+ if (entry[idx].handle != h)
+ continue;
+ entry[idx].dev = dev;
+ entry[idx].unit = unit;
+ entry[idx].alias = NULL;
+ entry[idx].extra = guid;
+ return (0);
+ }
+
+ return (ENOENT);
+}
Index: sys/boot/efi/loader/Makefile
===================================================================
--- sys/boot/efi/loader/Makefile
+++ sys/boot/efi/loader/Makefile
@@ -23,6 +23,10 @@
smbios.c \
vers.c
+.if ${MK_ZFS} != "no"
+SRCS+= zfs.c
+.endif
+
.PATH: ${.CURDIR}/arch/${MACHINE}
# For smbios.c
.PATH: ${.CURDIR}/../../i386/libi386
@@ -35,6 +39,13 @@
CFLAGS+= -I${.CURDIR}/../../../contrib/dev/acpica/include
CFLAGS+= -I${.CURDIR}/../../..
CFLAGS+= -I${.CURDIR}/../../i386/libi386
+.if ${MK_ZFS} != "no"
+CFLAGS+= -I${.CURDIR}/../../zfs
+CFLAGS+= -I${.CURDIR}/../../../cddl/boot/zfs
+CFLAGS+= -DZFS_EFI_BOOT
+# For zfsimpl.c
+CWARNFLAGS+= -Wno-array-bounds
+.endif
CFLAGS+= -DNO_PCI -DEFI
# make buildenv doesn't set DESTDIR, this means LIBSTAND
@@ -67,7 +78,7 @@
CFLAGS+= -DEFI_STAGING_SIZE=${EFI_STAGING_SIZE}
.endif
-# Always add MI sources
+# Always add MI sources
.PATH: ${.CURDIR}/../../common
.include "${.CURDIR}/../../common/Makefile.inc"
CFLAGS+= -I${.CURDIR}/../../common
Index: sys/boot/efi/loader/conf.c
===================================================================
--- sys/boot/efi/loader/conf.c
+++ sys/boot/efi/loader/conf.c
@@ -31,14 +31,23 @@
#include <bootstrap.h>
#include <efi.h>
#include <efilib.h>
+#ifdef ZFS_EFI_BOOT
+#include "../zfs/libzfs.h"
+#endif
struct devsw *devsw[] = {
&efipart_dev,
&efinet_dev,
+#ifdef ZFS_EFI_BOOT
+ &zfs_dev,
+#endif
NULL
};
struct fs_ops *file_system[] = {
+#ifdef ZFS_EFI_BOOT
+ &zfs_fsops,
+#endif
&dosfs_fsops,
&ufs_fsops,
&cd9660_fsops,
Index: sys/boot/efi/loader/devicename.c
===================================================================
--- sys/boot/efi/loader/devicename.c
+++ sys/boot/efi/loader/devicename.c
@@ -31,14 +31,18 @@
#include <stand.h>
#include <string.h>
#include <sys/disklabel.h>
+#include <sys/param.h>
#include "bootstrap.h"
+#ifdef ZFS_EFI_BOOT
+#include "libzfs.h"
+#endif
#include <efi.h>
#include <efilib.h>
static int efi_parsedev(struct devdesc **, const char *, const char **);
-/*
+/*
* Point (dev) at an allocated device specifier for the device matching the
* path in (devspec). If it contains an explicit device specification,
* use that. If not, use the default device.
@@ -84,7 +88,7 @@
struct devsw *dv;
char *cp;
const char *np;
- int i, err;
+ int i;
/* minimum length check */
if (strlen(devspec) < 2)
@@ -99,24 +103,44 @@
if (devsw[i] == NULL)
return (ENOENT);
- idev = malloc(sizeof(struct devdesc));
- if (idev == NULL)
- return (ENOMEM);
-
- idev->d_dev = dv;
- idev->d_type = dv->dv_type;
- idev->d_unit = -1;
-
- err = 0;
np = devspec + strlen(dv->dv_name);
- if (*np != '\0' && *np != ':') {
- idev->d_unit = strtol(np, &cp, 0);
- if (cp == np) {
- idev->d_unit = -1;
+
+#ifdef ZFS_EFI_BOOT
+ if (dv->dv_type == DEVT_ZFS) {
+ int err;
+
+ idev = malloc(sizeof(struct zfs_devdesc));
+ if (idev == NULL)
+ return (ENOMEM);
+
+ err = zfs_parsedev((struct zfs_devdesc*)idev, np, path);
+ if (err != 0) {
free(idev);
- return (EUNIT);
+ return (err);
}
+ *dev = idev;
+ cp = strchr(np + 1, ':');
+ } else {
+#endif
+ idev = malloc(sizeof(struct devdesc));
+ if (idev == NULL)
+ return (ENOMEM);
+
+ idev->d_dev = dv;
+ idev->d_type = dv->dv_type;
+ idev->d_unit = -1;
+ if (*np != '\0' && *np != ':') {
+ idev->d_unit = strtol(np, &cp, 0);
+ if (cp == np) {
+ idev->d_unit = -1;
+ free(idev);
+ return (EUNIT);
+ }
+ }
+#ifdef ZFS_EFI_BOOT
}
+#endif
+
if (*cp != '\0' && *cp != ':') {
free(idev);
return (EINVAL);
@@ -135,9 +159,13 @@
efi_fmtdev(void *vdev)
{
struct devdesc *dev = (struct devdesc *)vdev;
- static char buf[32]; /* XXX device length constant? */
+ static char buf[SPECNAMELEN + 1];
switch(dev->d_type) {
+#ifdef ZFS_EFI_BOOT
+ case DEVT_ZFS:
+ return (zfs_fmtdev(dev));
+#endif
case DEVT_NONE:
strcpy(buf, "(no device)");
break;
@@ -147,7 +175,7 @@
break;
}
- return(buf);
+ return (buf);
}
/*
@@ -161,7 +189,7 @@
rv = efi_parsedev(&ncurr, value, NULL);
if (rv != 0)
- return(rv);
+ return (rv);
free(ncurr);
env_setenv(ev->ev_name, flags | EV_NOHOOK, value, NULL, NULL);
Index: sys/boot/efi/loader/main.c
===================================================================
--- sys/boot/efi/loader/main.c
+++ sys/boot/efi/loader/main.c
@@ -28,6 +28,7 @@
#include <sys/cdefs.h>
__FBSDID("$FreeBSD$");
+#include <sys/param.h>
#include <stand.h>
#include <string.h>
#include <setjmp.h>
@@ -39,13 +40,13 @@
#include <smbios.h>
#include "loader_efi.h"
+#include "libzfs.h"
extern char bootprog_name[];
extern char bootprog_rev[];
extern char bootprog_date[];
extern char bootprog_maker[];
-struct devdesc currdev; /* our current device */
struct arch_switch archsw; /* MI/MD interface boundary */
EFI_GUID acpi = ACPI_TABLE_GUID;
@@ -61,13 +62,41 @@
EFI_GUID debugimg = DEBUG_IMAGE_INFO_TABLE_GUID;
EFI_GUID fdtdtb = FDT_TABLE_GUID;
+static void efi_zfs_probe(void);
+
+/*
+ * Need this because EFI uses UTF-16 unicode string constants, but we
+ * use UTF-8. We can't use printf due to the possiblity of \0 and we
+ * don't support support wide characters either.
+ */
+static void
+print_str16(const CHAR16 *str)
+{
+ int i;
+
+ for (i = 0; str[i]; i++)
+ printf("%c", (char)str[i]);
+}
+
EFI_STATUS
main(int argc, CHAR16 *argv[])
{
char vendor[128];
EFI_LOADED_IMAGE *img;
EFI_GUID *guid;
- int i;
+ int i, unit;
+ struct devsw *dev;
+ uint64_t pool_guid;
+
+ archsw.arch_autoload = efi_autoload;
+ archsw.arch_getdev = efi_getdev;
+ archsw.arch_copyin = efi_copyin;
+ archsw.arch_copyout = efi_copyout;
+ archsw.arch_readin = efi_readin;
+#ifdef ZFS_EFI_BOOT
+ /* Note this needs to be set before ZFS init. */
+ archsw.arch_zfs_probe = efi_zfs_probe;
+#endif
/*
* XXX Chicken-and-egg problem; we want to have console output
@@ -92,6 +121,13 @@
/* Get our loaded image protocol interface structure. */
BS->HandleProtocol(IH, &imgid, (VOID**)&img);
+ printf("Command line arguments:");
+ for (i = 0; i < argc; i++) {
+ printf(" ");
+ print_str16(argv[i]);
+ }
+ printf("\n");
+
printf("Image base: 0x%lx\n", (u_long)img->ImageBase);
printf("EFI version: %d.%02d\n", ST->Hdr.Revision >> 16,
ST->Hdr.Revision & 0xffff);
@@ -105,9 +141,6 @@
printf("%s, Revision %s\n", bootprog_name, bootprog_rev);
printf("(%s, %s)\n", bootprog_maker, bootprog_date);
- efi_handle_lookup(img->DeviceHandle, &currdev.d_dev, &currdev.d_unit);
- currdev.d_type = currdev.d_dev->dv_type;
-
/*
* Disable the watchdog timer. By default the boot manager sets
* the timer to 5 minutes before invoking a boot option. If we
@@ -119,18 +152,43 @@
*/
BS->SetWatchdogTimer(0, 0, 0, NULL);
- env_setenv("currdev", EV_VOLATILE, efi_fmtdev(&currdev),
- efi_setcurrdev, env_nounset);
- env_setenv("loaddev", EV_VOLATILE, efi_fmtdev(&currdev), env_noset,
- env_nounset);
+ if (efi_handle_lookup(img->DeviceHandle, &dev, &unit, &pool_guid) != 0)
+ return (EFI_NOT_FOUND);
- setenv("LINES", "24", 1); /* optional */
+ switch (dev->dv_type) {
+#ifdef ZFS_EFI_BOOT
+ case DEVT_ZFS: {
+ struct zfs_devdesc currdev;
+
+ currdev.d_dev = dev;
+ currdev.d_unit = unit;
+ currdev.d_type = currdev.d_dev->dv_type;
+ currdev.d_opendata = NULL;
+ currdev.pool_guid = pool_guid;
+ currdev.root_guid = 0;
+ env_setenv("currdev", EV_VOLATILE, efi_fmtdev(&currdev),
+ efi_setcurrdev, env_nounset);
+ env_setenv("loaddev", EV_VOLATILE, efi_fmtdev(&currdev), env_noset,
+ env_nounset);
+ break;
+ }
+#endif
+ default: {
+ struct devdesc currdev;
- archsw.arch_autoload = efi_autoload;
- archsw.arch_getdev = efi_getdev;
- archsw.arch_copyin = efi_copyin;
- archsw.arch_copyout = efi_copyout;
- archsw.arch_readin = efi_readin;
+ currdev.d_dev = dev;
+ currdev.d_unit = unit;
+ currdev.d_opendata = NULL;
+ currdev.d_type = currdev.d_dev->dv_type;
+ env_setenv("currdev", EV_VOLATILE, efi_fmtdev(&currdev),
+ efi_setcurrdev, env_nounset);
+ env_setenv("loaddev", EV_VOLATILE, efi_fmtdev(&currdev), env_noset,
+ env_nounset);
+ break;
+ }
+ }
+
+ setenv("LINES", "24", 1); /* optional */
for (i = 0; i < ST->NumberOfTableEntries; i++) {
guid = &ST->ConfigurationTable[i].VendorGuid;
@@ -204,50 +262,47 @@
status = BS->GetMemoryMap(&sz, 0, &key, &dsz, &dver);
if (status != EFI_BUFFER_TOO_SMALL) {
printf("Can't determine memory map size\n");
- return CMD_ERROR;
+ return (CMD_ERROR);
}
map = malloc(sz);
status = BS->GetMemoryMap(&sz, map, &key, &dsz, &dver);
if (EFI_ERROR(status)) {
printf("Can't read memory map\n");
- return CMD_ERROR;
+ return (CMD_ERROR);
}
ndesc = sz / dsz;
printf("%23s %12s %12s %8s %4s\n",
- "Type", "Physical", "Virtual", "#Pages", "Attr");
+ "Type", "Physical", "Virtual", "#Pages", "Attr");
for (i = 0, p = map; i < ndesc;
- i++, p = NextMemoryDescriptor(p, dsz)) {
- printf("%23s %012lx %012lx %08lx ",
- types[p->Type],
- p->PhysicalStart,
- p->VirtualStart,
- p->NumberOfPages);
- if (p->Attribute & EFI_MEMORY_UC)
- printf("UC ");
- if (p->Attribute & EFI_MEMORY_WC)
- printf("WC ");
- if (p->Attribute & EFI_MEMORY_WT)
- printf("WT ");
- if (p->Attribute & EFI_MEMORY_WB)
- printf("WB ");
- if (p->Attribute & EFI_MEMORY_UCE)
- printf("UCE ");
- if (p->Attribute & EFI_MEMORY_WP)
- printf("WP ");
- if (p->Attribute & EFI_MEMORY_RP)
- printf("RP ");
- if (p->Attribute & EFI_MEMORY_XP)
- printf("XP ");
- printf("\n");
+ i++, p = NextMemoryDescriptor(p, dsz)) {
+ printf("%23s %012lx %012lx %08lx ", types[p->Type],
+ p->PhysicalStart, p->VirtualStart, p->NumberOfPages);
+ if (p->Attribute & EFI_MEMORY_UC)
+ printf("UC ");
+ if (p->Attribute & EFI_MEMORY_WC)
+ printf("WC ");
+ if (p->Attribute & EFI_MEMORY_WT)
+ printf("WT ");
+ if (p->Attribute & EFI_MEMORY_WB)
+ printf("WB ");
+ if (p->Attribute & EFI_MEMORY_UCE)
+ printf("UCE ");
+ if (p->Attribute & EFI_MEMORY_WP)
+ printf("WP ");
+ if (p->Attribute & EFI_MEMORY_RP)
+ printf("RP ");
+ if (p->Attribute & EFI_MEMORY_XP)
+ printf("XP ");
+ printf("\n");
}
- return CMD_OK;
+ return (CMD_OK);
}
-COMMAND_SET(configuration, "configuration",
- "print configuration tables", command_configuration);
+COMMAND_SET(configuration, "configuration", "print configuration tables",
+ command_configuration);
static const char *
guid_to_string(EFI_GUID *guid)
@@ -295,7 +350,7 @@
printf(" at %p\n", ST->ConfigurationTable[i].VendorTable);
}
- return CMD_OK;
+ return (CMD_OK);
}
@@ -370,20 +425,17 @@
status = RS->GetNextVariableName(&varsz, NULL, NULL);
for (; status != EFI_NOT_FOUND; ) {
- status = RS->GetNextVariableName(&varsz, var,
- &varguid);
+ status = RS->GetNextVariableName(&varsz, var, &varguid);
//if (EFI_ERROR(status))
//break;
conout->OutputString(conout, var);
printf("=");
datasz = 0;
- status = RS->GetVariable(var, &varguid, NULL, &datasz,
- NULL);
+ status = RS->GetVariable(var, &varguid, NULL, &datasz, NULL);
/* XXX: check status */
data = malloc(datasz);
- status = RS->GetVariable(var, &varguid, NULL, &datasz,
- data);
+ status = RS->GetVariable(var, &varguid, NULL, &datasz, data);
if (EFI_ERROR(status))
printf("<error retrieving variable>");
else {
@@ -402,6 +454,27 @@
return (CMD_OK);
}
+COMMAND_SET(lszfs, "lszfs", "list child datasets of a zfs dataset",
+ command_lszfs);
+
+static int
+command_lszfs(int argc, char *argv[])
+{
+ int err;
+
+ if (argc != 2) {
+ command_errmsg = "wrong number of arguments";
+ return (CMD_ERROR);
+ }
+
+ err = zfs_list(argv[1]);
+ if (err != 0) {
+ command_errmsg = strerror(err);
+ return (CMD_ERROR);
+ }
+ return (CMD_OK);
+}
+
#ifdef LOADER_FDT_SUPPORT
extern int command_fdt_internal(int argc, char *argv[]);
@@ -420,3 +493,21 @@
COMMAND_SET(fdt, "fdt", "flattened device tree handling", command_fdt);
#endif
+
+static void
+efi_zfs_probe(void)
+{
+ EFI_HANDLE h;
+ u_int unit;
+ int i;
+ char dname[SPECNAMELEN + 1];
+ uint64_t guid;
+
+ unit = 0;
+ h = efi_find_handle(&efipart_dev, 0);
+ for (i = 0; h != NULL; h = efi_find_handle(&efipart_dev, ++i)) {
+ snprintf(dname, sizeof(dname), "%s%d:", efipart_dev.dv_name, i);
+ if (zfs_probe_dev(dname, &guid) == 0)
+ (void)efi_handle_update_dev(h, &zfs_dev, unit++, guid);
+ }
+}
Index: sys/boot/zfs/zfs.c
===================================================================
--- sys/boot/zfs/zfs.c
+++ sys/boot/zfs/zfs.c
@@ -140,7 +140,7 @@
n = size;
if (fp->f_seekp + n > sb.st_size)
n = sb.st_size - fp->f_seekp;
-
+
rc = dnode_read(spa, &fp->f_dnode, fp->f_seekp, start, n);
if (rc)
return (rc);
@@ -493,7 +493,7 @@
}
}
close(pa.fd);
- return (0);
+ return (ret);
}
/*
Index: sys/cddl/boot/zfs/lz4.c
===================================================================
--- sys/cddl/boot/zfs/lz4.c
+++ sys/cddl/boot/zfs/lz4.c
@@ -52,7 +52,7 @@
* Returns 0 on success (decompression function returned non-negative)
* and non-zero on failure (decompression function returned negative).
*/
- return (LZ4_uncompress_unknownOutputSize(s_start + 4, d_start, bufsiz,
+ return (LZ4_uncompress_unknownOutputSize((const char *)s_start + 4, d_start, bufsiz,
d_len) < 0);
}
File Metadata
Details
Attached
Mime Type
text/plain
Expires
Sun, Feb 15, 12:38 PM (18 h, 37 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
28741317
Default Alt Text
D4515.id11158.diff (35 KB)
Attached To
Mode
D4515: ZFS EFI Boot Support #2
Attached
Detach File
Event Timeline
Log In to Comment