Author: smh
Date: Thu Jan 28 16:52:02 2016
New Revision: 294997
URL: https://svnweb.freebsd.org/changeset/base/294997

Log:
  MFC r281060, r294060, r294291, r294493, r294284:
  
  MFC r281060:
  Remove an unnecessary space in a printf call
  
  MFC r294060:
  Modularise EFI boot loader
  
  MFC r294291 (by andrew):
  Reset the filesystem cache
  
  MFC r294493:
  Fix EFI UFS caching
  
  MFC r294284 (by emaste):
  boot1: correct typo in error message
  
  Sponsored by: Multiplay

Added:
  stable/10/sys/boot/efi/boot1/boot_module.h
     - copied unchanged from r294060, head/sys/boot/efi/boot1/boot_module.h
  stable/10/sys/boot/efi/boot1/ufs_module.c
     - copied, changed from r294060, head/sys/boot/efi/boot1/ufs_module.c
Modified:
  stable/10/sys/boot/common/ufsread.c
  stable/10/sys/boot/efi/boot1/Makefile
  stable/10/sys/boot/efi/boot1/boot1.c
  stable/10/sys/boot/efi/include/efilib.h
  stable/10/sys/boot/efi/loader/devicename.c
  stable/10/sys/boot/efi/loader/main.c
Directory Properties:
  stable/10/   (props changed)

Modified: stable/10/sys/boot/common/ufsread.c
==============================================================================
--- stable/10/sys/boot/common/ufsread.c Thu Jan 28 16:51:56 2016        
(r294996)
+++ stable/10/sys/boot/common/ufsread.c Thu Jan 28 16:52:02 2016        
(r294997)
@@ -165,7 +165,7 @@ static int sblock_try[] = SBLOCKSEARCH;
 #endif
 
 static ssize_t
-fsread(ufs_ino_t inode, void *buf, size_t nbyte)
+fsread_size(ufs_ino_t inode, void *buf, size_t nbyte, size_t *fsizep)
 {
 #ifndef UFS2_ONLY
        static struct ufs1_dinode dp1;
@@ -185,6 +185,10 @@ fsread(ufs_ino_t inode, void *buf, size_
        static ufs2_daddr_t blkmap, indmap;
        u_int u;
 
+       /* Basic parameter validation. */
+       if ((buf == NULL && nbyte != 0) || dmadat == NULL)
+               return (-1);
+
        blkbuf = dmadat->blkbuf;
        indbuf = dmadat->indbuf;
 
@@ -231,18 +235,18 @@ fsread(ufs_ino_t inode, void *buf, size_
                        return -1;
                n = INO_TO_VBO(n, inode);
 #if defined(UFS1_ONLY)
-               memcpy(&dp1, (struct ufs1_dinode *)blkbuf + n,
-                   sizeof(struct ufs1_dinode));
+               memcpy(&dp1, (struct ufs1_dinode *)(void *)blkbuf + n,
+                   sizeof(dp1));
 #elif defined(UFS2_ONLY)
-               memcpy(&dp2, (struct ufs2_dinode *)blkbuf + n,
-                   sizeof(struct ufs2_dinode));
+               memcpy(&dp2, (struct ufs2_dinode *)(void *)blkbuf + n,
+                   sizeof(dp2));
 #else
                if (fs.fs_magic == FS_UFS1_MAGIC)
                        memcpy(&dp1, (struct ufs1_dinode *)(void *)blkbuf + n,
-                           sizeof(struct ufs1_dinode));
+                           sizeof(dp1));
                else
                        memcpy(&dp2, (struct ufs2_dinode *)(void *)blkbuf + n,
-                           sizeof(struct ufs2_dinode));
+                           sizeof(dp2));
 #endif
                inomap = inode;
                fs_off = 0;
@@ -306,5 +310,17 @@ fsread(ufs_ino_t inode, void *buf, size_
                fs_off += n;
                nb -= n;
        }
+
+       if (fsizep != NULL)
+               *fsizep = size;
+
        return nbyte;
 }
+
+static ssize_t
+fsread(ufs_ino_t inode, void *buf, size_t nbyte)
+{
+
+       return fsread_size(inode, buf, nbyte, NULL);
+}
+

Modified: stable/10/sys/boot/efi/boot1/Makefile
==============================================================================
--- stable/10/sys/boot/efi/boot1/Makefile       Thu Jan 28 16:51:56 2016        
(r294996)
+++ stable/10/sys/boot/efi/boot1/Makefile       Thu Jan 28 16:52:02 2016        
(r294997)
@@ -11,7 +11,7 @@ INTERNALPROG=
 WARNS?=                6
 
 # architecture-specific loader code
-SRCS=  boot1.c reloc.c start.S
+SRCS=  boot1.c reloc.c start.S ufs_module.c
 
 CFLAGS+=       -fPIC
 CFLAGS+=       -I.
@@ -19,6 +19,7 @@ CFLAGS+=      -I${.CURDIR}/../include
 CFLAGS+=       -I${.CURDIR}/../include/${MACHINE}
 CFLAGS+=       -I${.CURDIR}/../../../contrib/dev/acpica/include
 CFLAGS+=       -I${.CURDIR}/../../..
+CFLAGS+=       -DEFI_UFS_BOOT
 
 # Always add MI sources and REGULAR efi loader bits
 .PATH:         ${.CURDIR}/../loader/arch/${MACHINE}

Modified: stable/10/sys/boot/efi/boot1/boot1.c
==============================================================================
--- stable/10/sys/boot/efi/boot1/boot1.c        Thu Jan 28 16:51:56 2016        
(r294996)
+++ stable/10/sys/boot/efi/boot1/boot1.c        Thu Jan 28 16:52:02 2016        
(r294997)
@@ -5,6 +5,8 @@
  * All rights reserved.
  * Copyright (c) 2014 Nathan Whitehorn
  * All rights reserved.
+ * Copyright (c) 2015 Eric McCorkle
+ * All rights reserved.
  *
  * Redistribution and use in source and binary forms are freely
  * permitted provided that the above copyright notice and this
@@ -21,7 +23,6 @@
 __FBSDID("$FreeBSD$");
 
 #include <sys/param.h>
-#include <sys/dirent.h>
 #include <machine/elf.h>
 #include <machine/stdarg.h>
 #include <stand.h>
@@ -29,19 +30,29 @@ __FBSDID("$FreeBSD$");
 #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
+static const boot_module_t *boot_modules[] =
+{
+#ifdef EFI_UFS_BOOT
+       &ufs_module
+#endif
+};
+
+#define NUM_BOOT_MODULES (sizeof(boot_modules) / sizeof(boot_module_t*))
+/* The initial number of handles used to query EFI for partitions. */
+#define NUM_HANDLES_INIT       24
 
-void panic(const char *fmt, ...) __dead2;
 void putchar(int c);
 EFI_STATUS efi_main(EFI_HANDLE Ximage, EFI_SYSTEM_TABLE* Xsystab);
 
-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 EFI_GUID BlockIoProtocolGUID = BLOCK_IO_PROTOCOL;
@@ -49,27 +60,92 @@ static EFI_GUID DevicePathGUID = DEVICE_
 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;
+/*
+ * Provide Malloc / Free backed by EFIs AllocatePool / FreePool which ensures
+ * memory is correctly aligned avoiding EFI_INVALID_PARAMETER returns from
+ * EFI methods.
+ */
+void *
+Malloc(size_t len, const char *file __unused, int line __unused)
+{
+       void *out;
+
+       if (bs->AllocatePool(EfiLoaderData, len, &out) == EFI_SUCCESS)
+               return (out);
+
+       return (NULL);
+}
+
+void
+Free(void *buf, const char *file __unused, int line __unused)
+{
+       (void)bs->FreePool(buf);
+}
 
-EFI_STATUS efi_main(EFI_HANDLE Ximage, EFI_SYSTEM_TABLE* Xsystab)
+/*
+ * 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)
 {
-       EFI_HANDLE handles[128];
-       EFI_BLOCK_IO *blkio;
-       UINTN i, nparts = sizeof(handles), cols, rows, max_dim, best_mode;
+       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;
+
+       if (status != EFI_SUCCESS) {
+               printf("%s failed to load %s (%lu)\n", mod->name, _PATH_LOADER,
+                   EFI_ERROR_CODE(status));
+               return;
+       }
+
+       if ((status = bs->LoadImage(TRUE, image, dev->devpath, buf, bufsize,
+           &loaderhandle)) != EFI_SUCCESS) {
+               printf("Failed to load image provided by %s, size: %zu, 
(%lu)\n",
+                    mod->name, bufsize, EFI_ERROR_CODE(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, EFI_ERROR_CODE(status));
+               return;
+       }
+
+       loaded_image->DeviceHandle = dev->devhandle;
+
+       if ((status = bs->StartImage(loaderhandle, NULL, NULL)) !=
+           EFI_SUCCESS) {
+               printf("Failed to start image provided by %s (%lu)\n",
+                   mod->name, EFI_ERROR_CODE(status));
+               return;
+       }
+}
+
+EFI_STATUS
+efi_main(EFI_HANDLE Ximage, EFI_SYSTEM_TABLE *Xsystab)
+{
+       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;
-       const 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,
@@ -94,199 +170,162 @@ EFI_STATUS efi_main(EFI_HANDLE Ximage, E
        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);
+               printf(" %s", boot_modules[i]->name);
+               if (boot_modules[i]->init != NULL)
+                       boot_modules[i]->init();
+       }
+       putchar('\n');
 
-               status = systab->BootServices->HandleProtocol(handles[i],
-                   &BlockIoProtocolGUID, (void **)&blkio);
-               if (EFI_ERROR(status))
-                       continue;
+       /* Get all the device handles */
+       hsize = (UINTN)NUM_HANDLES_INIT * sizeof(EFI_HANDLE);
+       if ((status = bs->AllocatePool(EfiLoaderData, hsize, (void **)&handles))
+           != EFI_SUCCESS)
+               panic("Failed to allocate %d handles (%lu)", NUM_HANDLES_INIT,
+                   EFI_ERROR_CODE(status));
 
-               if (!blkio->Media->LogicalPartition)
-                       continue;
+       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 %zu handles (%lu)", hsize /
+                           sizeof(*handles), EFI_ERROR_CODE(status));
+               }
+               status = bs->LocateHandle(ByProtocol, &BlockIoProtocolGUID,
+                   NULL, &hsize, handles);
+               if (status != EFI_SUCCESS)
+                       panic("Failed to get device handles (%lu)\n",
+                           EFI_ERROR_CODE(status));
+               break;
+       default:
+               panic("Failed to get device handles (%lu)",
+                   EFI_ERROR_CODE(status));
+       }
 
-               if (domount(devpath, blkio, 1) >= 0)
+       /* Scan all partitions, probing with all modules. */
+       nhandles = hsize / sizeof(*handles);
+       printf("   Probing %zu 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);
+       /* Status summary. */
+       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);
+       /* Figure out if we're dealing with an actual partition. */
+       status = bs->HandleProtocol(h, &DevicePathGUID, (void **)&devpath);
+       if (status == EFI_UNSUPPORTED)
+               return (status);
 
-       if (EFI_ERROR(status))
-               return (-1);
+       if (status != EFI_SUCCESS) {
+               DPRINTF("\nFailed to query DevicePath (%lu)\n",
+                   EFI_ERROR_CODE(status));
+               return (status);
+       }
 
-       return (0);
-}
+       while (!IsDevicePathEnd(NextDevicePathNode(devpath)))
+               devpath = NextDevicePathNode(devpath);
 
-#include "ufsread.c"
+       status = bs->HandleProtocol(h, &BlockIoProtocolGUID, (void **)&blkio);
+       if (status == EFI_UNSUPPORTED)
+               return (status);
 
-static ssize_t
-fsstat(ufs_ino_t inode)
-{
-#ifndef UFS2_ONLY
-       static struct ufs1_dinode dp1;
-#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, size;
-       static ufs2_daddr_t blkmap, indmap;
-
-       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 >= (int32_t)sizeof(struct fs))
-                               break;
-               }
-               if (sblock_try[n] == -1) {
-                       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 *)(void *)blkbuf + n,
-                           sizeof(struct ufs1_dinode));
-               else
-                       memcpy(&dp2, (struct ufs2_dinode *)(void *)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);
-}
+       if (status != EFI_SUCCESS) {
+               DPRINTF("\nFailed to query BlockIoProtocol (%lu)\n",
+                   EFI_ERROR_CODE(status));
+               return (status);
+       }
 
-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;
+
+               if ((status = bs->AllocatePool(EfiLoaderData,
+                   sizeof(*devinfo), (void **)&devinfo)) !=
+                   EFI_SUCCESS) {
+                       DPRINTF("\nFailed to allocate devinfo (%lu)\n",
+                           EFI_ERROR_CODE(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);
+       }
 
-       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);
+       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;
+       dev_info_t *dev;
 
-       if ((ino = lookup(fname)) == 0) {
-               printf("File %s not found\n", fname);
+       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 %lu\n",
-                   EFI_ERROR_CODE(status));
-
-       status = systab->BootServices->HandleProtocol(loaderhandle,
-           &LoadedImageGUID, (VOID**)&loaded_image);
-       if (EFI_ERROR(status))
-               printf("HandleProtocol failed with error %lu\n",
-                   EFI_ERROR_CODE(status));
+       for (dev = *devinfop; dev->next != NULL; dev = dev->next)
+               ;
 
-       loaded_image->DeviceHandle = bootdevhandle;
-
-       status = systab->BootServices->StartImage(loaderhandle, NULL, NULL);
-       if (EFI_ERROR(status))
-               printf("StartImage failed with error %lu\n",
-                   EFI_ERROR_CODE(status));
+       dev->next = devinfo;
 }
 
 void

Copied: stable/10/sys/boot/efi/boot1/boot_module.h (from r294060, 
head/sys/boot/efi/boot1/boot_module.h)
==============================================================================
--- /dev/null   00:00:00 1970   (empty, because file is newly added)
+++ stable/10/sys/boot/efi/boot1/boot_module.h  Thu Jan 28 16:52:02 2016        
(r294997, copy of r294060, head/sys/boot/efi/boot1/boot_module.h)
@@ -0,0 +1,110 @@
+/*-
+ * Copyright (c) 2015 Eric McCorkle
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * $FreeBSD$
+ */
+
+#ifndef _BOOT_MODULE_H_
+#define _BOOT_MODULE_H_
+
+#include <stdbool.h>
+
+#include <efi.h>
+#include <efilib.h>
+#include <eficonsctl.h>
+
+#ifdef EFI_DEBUG
+#define DPRINTF(fmt, args...) \
+        do { \
+                printf(fmt, ##args) \
+        } while (0)
+#else
+#define DPRINTF(fmt, args...) {}
+#endif
+
+/* EFI device info */
+typedef struct dev_info
+{
+       EFI_BLOCK_IO *dev;
+       EFI_DEVICE_PATH *devpath;
+       EFI_HANDLE *devhandle;
+       void *devdata;
+       struct dev_info *next;
+} dev_info_t;
+
+/*
+ * A boot loader module.
+ *
+ * This is a standard interface for filesystem modules in the EFI system.
+ */
+typedef struct boot_module_t
+{
+       const char *name;
+
+       /* init is the optional initialiser for the module. */
+       void (*init)();
+
+       /*
+        * probe checks to see if the module can handle dev.
+        *
+        * Return codes:
+        * EFI_SUCCESS = The module can handle the device.
+        * EFI_NOT_FOUND = The module can not handle the device.
+        * Other = The module encountered an error.
+        */
+       EFI_STATUS (*probe)(dev_info_t* dev);
+
+       /*
+        * load should select the best out of a set of devices that probe
+        * indicated were loadable and load it.
+        *
+        * Return codes:
+        * EFI_SUCCESS = The module can handle the device.
+        * EFI_NOT_FOUND = The module can not handle the device.
+        * Other = The module encountered an error.
+        */
+       EFI_STATUS (*load)(const char *loader_path, dev_info_t **devinfo,
+           void **buf, size_t *bufsize);
+
+       /* status outputs information about the probed devices. */
+       void (*status)();
+
+} boot_module_t;
+
+/* Standard boot modules. */
+#ifdef EFI_UFS_BOOT
+extern const boot_module_t ufs_module;
+#endif
+
+/* Functions available to modules. */
+extern void add_device(dev_info_t **devinfop, dev_info_t *devinfo);
+extern void panic(const char *fmt, ...) __dead2;
+extern int printf(const char *fmt, ...);
+extern int vsnprintf(char *str, size_t sz, const char *fmt, va_list ap);
+
+extern EFI_SYSTEM_TABLE *systab;
+extern EFI_BOOT_SERVICES *bs;
+
+#endif

Copied and modified: stable/10/sys/boot/efi/boot1/ufs_module.c (from r294060, 
head/sys/boot/efi/boot1/ufs_module.c)
==============================================================================
--- head/sys/boot/efi/boot1/ufs_module.c        Fri Jan 15 01:22:36 2016        
(r294060, copy source)
+++ stable/10/sys/boot/efi/boot1/ufs_module.c   Thu Jan 28 16:52:02 2016        
(r294997)
@@ -68,93 +68,23 @@ dskread(void *buf, u_int64_t lba, int nb
 
 #include "ufsread.c"
 
-static ssize_t
-fsstat(ufs_ino_t inode)
+static struct dmadat __dmadat;
+
+static int
+init_dev(dev_info_t* dev)
 {
-#ifndef UFS2_ONLY
-       static struct ufs1_dinode dp1;
-#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, size;
-       static ufs2_daddr_t blkmap, indmap;
-
-       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 >= (int32_t)sizeof(struct fs))
-                               break;
-               }
-               if (sblock_try[n] == -1) {
-                       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 *)(void *)blkbuf + n,
-                           sizeof(struct ufs1_dinode));
-               else
-                       memcpy(&dp2, (struct ufs2_dinode *)(void *)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);
-}
+       devinfo = dev;
+       dmadat = &__dmadat;
 
-static struct dmadat __dmadat;
+       return fsread(0, NULL, 0);
+}
 
 static EFI_STATUS
 probe(dev_info_t* dev)
 {
 
-       devinfo = dev;
-       dmadat = &__dmadat;
-       if (fsread(0, NULL, 0) < 0)
+       if (init_dev(dev) < 0)
                return (EFI_UNSUPPORTED);
 
        add_device(&devices, dev);
@@ -171,13 +101,15 @@ try_load(dev_info_t *dev, const char *lo
        ssize_t read;
        void *buf;
 
-       devinfo = dev;
+       if (init_dev(dev) < 0)
+               return (EFI_UNSUPPORTED);
+
        if ((ino = lookup(loader_path)) == 0)
                return (EFI_NOT_FOUND);
 
-       size = fsstat(ino);
-       if (size <= 0) {
-               printf("Failed to fsstat %s ino: %d\n", loader_path, ino);
+       if (fsread_size(ino, NULL, 0, &size) < 0 || size <= 0) {
+               printf("Failed to read size of '%s' ino: %d\n", loader_path,
+                   ino);
                return (EFI_INVALID_PARAMETER);
        }
 
@@ -190,7 +122,7 @@ try_load(dev_info_t *dev, const char *lo
 
        read = fsread(ino, buf, size);
        if ((size_t)read != size) {
-               printf("Failed to read %s (%zd != %zu)\n", loader_path, read,
+               printf("Failed to read '%s' (%zd != %zu)\n", loader_path, read,
                    size);
                (void)bs->FreePool(buf);
                return (EFI_INVALID_PARAMETER);

Modified: stable/10/sys/boot/efi/include/efilib.h
==============================================================================
--- stable/10/sys/boot/efi/include/efilib.h     Thu Jan 28 16:51:56 2016        
(r294996)
+++ stable/10/sys/boot/efi/include/efilib.h     Thu Jan 28 16:52:02 2016        
(r294997)
@@ -39,7 +39,6 @@ extern struct devsw efinet_dev;
 extern struct netif_driver efinetif;
 
 void *efi_get_table(EFI_GUID *tbl);
-void efi_main(EFI_HANDLE image_handle, EFI_SYSTEM_TABLE *system_table);
 
 int efi_register_handles(struct devsw *, EFI_HANDLE *, EFI_HANDLE *, int);
 EFI_HANDLE efi_find_handle(struct devsw *, int);

Modified: stable/10/sys/boot/efi/loader/devicename.c
==============================================================================
--- stable/10/sys/boot/efi/loader/devicename.c  Thu Jan 28 16:51:56 2016        
(r294996)
+++ stable/10/sys/boot/efi/loader/devicename.c  Thu Jan 28 16:52:02 2016        
(r294997)
@@ -31,6 +31,7 @@ __FBSDID("$FreeBSD$");
 #include <stand.h>
 #include <string.h>
 #include <sys/disklabel.h>
+#include <sys/param.h>
 #include <bootstrap.h>
 
 #include <efi.h>
@@ -86,7 +87,7 @@ efi_parsedev(struct devdesc **dev, const
        struct devsw *dv;
        char *cp;
        const char *np;
-       int i, err;
+       int i;
 
        /* minimum length check */
        if (strlen(devspec) < 2)
@@ -101,24 +102,26 @@ efi_parsedev(struct devdesc **dev, const
        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;
-                       free(idev);
-                       return (EUNIT);
+
+       {
+               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);
+                       }
                }
        }
+
        if (*cp != '\0' && *cp != ':') {
                free(idev);
                return (EINVAL);
@@ -137,7 +140,7 @@ char *
 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) {
        case DEVT_NONE:

Modified: stable/10/sys/boot/efi/loader/main.c
==============================================================================
--- stable/10/sys/boot/efi/loader/main.c        Thu Jan 28 16:51:56 2016        
(r294996)
+++ stable/10/sys/boot/efi/loader/main.c        Thu Jan 28 16:52:02 2016        
(r294997)
@@ -28,6 +28,7 @@
 #include <sys/cdefs.h>
 __FBSDID("$FreeBSD$");
 
+#include <sys/param.h>
 #include <stand.h>
 #include <string.h>
 #include <setjmp.h>
@@ -45,7 +46,6 @@ 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;
@@ -60,15 +60,36 @@ EFI_GUID hoblist = HOB_LIST_TABLE_GUID;
 EFI_GUID memtype = MEMORY_TYPE_INFORMATION_TABLE_GUID;
 EFI_GUID debugimg = DEBUG_IMAGE_INFO_TABLE_GUID;
 
+/*
+ * 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 var[128];
        EFI_LOADED_IMAGE *img;
        EFI_GUID *guid;
-       int i, j, vargood;
+       int i, j, vargood, unit;
+       struct devsw *dev;
        UINTN k;
 
+       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;
+
        /*
         * XXX Chicken-and-egg problem; we want to have console output
         * early, but some console attributes may depend on reading from
@@ -115,6 +136,13 @@ main(int argc, CHAR16 *argv[])
        /* 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);
@@ -128,9 +156,6 @@ main(int argc, CHAR16 *argv[])
        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
@@ -142,18 +167,26 @@ main(int argc, CHAR16 *argv[])
         */
        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) != 0)
+               return (EFI_NOT_FOUND);
 
-       setenv("LINES", "24", 1);       /* optional */
+       switch (dev->dv_type) {
+       default: {
+               struct devdesc currdev;
+
+               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,

*** DIFF OUTPUT TRUNCATED AT 1000 LINES ***
_______________________________________________
svn-src-all@freebsd.org mailing list
https://lists.freebsd.org/mailman/listinfo/svn-src-all
To unsubscribe, send any mail to "svn-src-all-unsubscr...@freebsd.org"

Reply via email to