Index: stable/12/stand/efi/boot1/proto.c =================================================================== --- stable/12/stand/efi/boot1/proto.c (revision 355283) +++ stable/12/stand/efi/boot1/proto.c (revision 355284) @@ -1,223 +1,223 @@ /*- * Copyright (c) 1998 Robert Nordier * All rights reserved. * Copyright (c) 2001 Robert Drehmel * 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 * 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 __FBSDID("$FreeBSD$"); #include #include #include #include #include #include #include #include "boot_module.h" #include "paths.h" #include "proto.h" static EFI_GUID BlockIoProtocolGUID = BLOCK_IO_PROTOCOL; static EFI_GUID DevicePathGUID = DEVICE_PATH_PROTOCOL; static const char *prio_str[] = { "error", "not supported", "good", "better" }; /* * probe_handle determines if the passed handle represents a logical partition * if it does it uses each module in order to probe it and if successful it * returns EFI_SUCCESS. */ static int probe_handle(EFI_HANDLE h, EFI_DEVICE_PATH *imgpath) { dev_info_t *devinfo; EFI_BLOCK_IO *blkio; EFI_DEVICE_PATH *devpath; EFI_STATUS status; UINTN i; int preferred; /* Figure out if we're dealing with an actual partition. */ - status = BS->HandleProtocol(h, &DevicePathGUID, (void **)&devpath); + status = OpenProtocolByHandle(h, &DevicePathGUID, (void **)&devpath); if (status == EFI_UNSUPPORTED) return (0); if (status != EFI_SUCCESS) { DPRINTF("\nFailed to query DevicePath (%lu)\n", EFI_ERROR_CODE(status)); return (-1); } #ifdef EFI_DEBUG { CHAR16 *text = efi_devpath_name(devpath); DPRINTF("probing: %S ", text); efi_free_devpath_name(text); } #endif - status = BS->HandleProtocol(h, &BlockIoProtocolGUID, (void **)&blkio); + status = OpenProtocolByHandle(h, &BlockIoProtocolGUID, (void **)&blkio); if (status == EFI_UNSUPPORTED) return (0); if (status != EFI_SUCCESS) { DPRINTF("\nFailed to query BlockIoProtocol (%lu)\n", EFI_ERROR_CODE(status)); return (-1); } if (!blkio->Media->LogicalPartition) return (0); preferred = efi_devpath_same_disk(imgpath, devpath); /* Run through each module, see if it can load this partition */ devinfo = malloc(sizeof(*devinfo)); if (devinfo == NULL) { DPRINTF("\nFailed to allocate devinfo\n"); return (-1); } devinfo->dev = blkio; devinfo->devpath = devpath; devinfo->devhandle = h; devinfo->preferred = preferred; devinfo->next = NULL; for (i = 0; i < num_boot_modules; i++) { devinfo->devdata = NULL; status = boot_modules[i]->probe(devinfo); if (status == EFI_SUCCESS) return (preferred + 1); } free(devinfo); return (0); } /* * load_loader attempts to load the loader image data. * * It tries each module and its respective devices, identified by mod->probe, * in order until a successful load occurs at which point it returns EFI_SUCCESS * and EFI_NOT_FOUND otherwise. * * Only devices which have preferred matching the preferred parameter are tried. */ static EFI_STATUS load_loader(const boot_module_t **modp, dev_info_t **devinfop, void **bufp, size_t *bufsize, int preferred) { UINTN i; dev_info_t *dev; const boot_module_t *mod; for (i = 0; i < num_boot_modules; i++) { mod = boot_modules[i]; for (dev = mod->devices(); dev != NULL; dev = dev->next) { if (dev->preferred != preferred) continue; if (mod->load(PATH_LOADER_EFI, dev, bufp, bufsize) == EFI_SUCCESS) { *devinfop = dev; *modp = mod; return (EFI_SUCCESS); } } } return (EFI_NOT_FOUND); } void choice_protocol(EFI_HANDLE *handles, UINTN nhandles, EFI_DEVICE_PATH *imgpath) { UINT16 boot_current; size_t sz; UINT16 boot_order[100]; unsigned i; int rv; EFI_STATUS status; const boot_module_t *mod; dev_info_t *dev; void *loaderbuf; size_t loadersize; /* Report UEFI Boot Manager Protocol details */ boot_current = 0; sz = sizeof(boot_current); if (efi_global_getenv("BootCurrent", &boot_current, &sz) == EFI_SUCCESS) { printf(" BootCurrent: %04x\n", boot_current); sz = sizeof(boot_order); if (efi_global_getenv("BootOrder", &boot_order, &sz) == EFI_SUCCESS) { printf(" BootOrder:"); for (i = 0; i < sz / sizeof(boot_order[0]); i++) printf(" %04x%s", boot_order[i], boot_order[i] == boot_current ? "[*]" : ""); printf("\n"); } } #ifdef TEST_FAILURE /* * For testing failover scenarios, it's nice to be able to fail fast. * Define TEST_FAILURE to create a boot1.efi that always fails after * reporting the boot manager protocol details. */ BS->Exit(IH, EFI_OUT_OF_RESOURCES, 0, NULL); #endif /* Scan all partitions, probing with all modules. */ printf(" Probing %zu block devices...", nhandles); DPRINTF("\n"); for (i = 0; i < nhandles; i++) { rv = probe_handle(handles[i], imgpath); #ifdef EFI_DEBUG printf("%c", "x.+*"[rv + 1]); #else printf("%s\n", prio_str[rv + 1]); #endif } printf(" done\n"); /* Status summary. */ for (i = 0; i < num_boot_modules; i++) { printf(" "); boot_modules[i]->status(); } status = load_loader(&mod, &dev, &loaderbuf, &loadersize, 1); if (status != EFI_SUCCESS) { status = load_loader(&mod, &dev, &loaderbuf, &loadersize, 0); if (status != EFI_SUCCESS) { printf("Failed to load '%s'\n", PATH_LOADER_EFI); return; } } try_boot(mod, dev, loaderbuf, loadersize); } Index: stable/12/stand/efi/gptboot/proto.c =================================================================== --- stable/12/stand/efi/gptboot/proto.c (revision 355283) +++ stable/12/stand/efi/gptboot/proto.c (revision 355284) @@ -1,279 +1,279 @@ /*- * Copyright (c) 2019 Netflix, Inc * * 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. */ #include __FBSDID("$FreeBSD$"); #include #include #include #include #include #include #include #include "boot_module.h" #include "paths.h" #include "proto.h" #include "gpt.h" #include static const uuid_t freebsd_ufs_uuid = GPT_ENT_TYPE_FREEBSD_UFS; static char secbuf[4096]; static struct dsk dsk; static dev_info_t *devices = NULL; static dev_info_t *raw_device = NULL; static EFI_GUID BlockIoProtocolGUID = BLOCK_IO_PROTOCOL; static EFI_GUID DevicePathGUID = DEVICE_PATH_PROTOCOL; /* * Shim routine for the gpt code to read in the gpt table. The * devinfo is always going to be for the raw device. */ int drvread(struct dsk *dskp, void *buf, daddr_t lba, unsigned nblk) { int size; EFI_STATUS status; dev_info_t *devinfo = (dev_info_t *)dskp->devinfo; EFI_BLOCK_IO *dev = devinfo->dev; lba = lba / (dev->Media->BlockSize / DEV_BSIZE); size = nblk * DEV_BSIZE; status = dev->ReadBlocks(dev, dev->Media->MediaId, lba, size, buf); if (status != EFI_SUCCESS) { DPRINTF("dskread: failed dev: %p, id: %u, lba: %ju, size: %d, " "status: %lu\n", devinfo->dev, dev->Media->MediaId, (uintmax_t)lba, size, EFI_ERROR_CODE(status)); return (-1); } return (0); } /* * Shim routine for the gpt code to write in the gpt table. The * devinfo is always going to be for the raw device. */ int drvwrite(struct dsk *dskp, void *buf, daddr_t lba, unsigned nblk) { int size; EFI_STATUS status; dev_info_t *devinfo = (dev_info_t *)dskp->devinfo; EFI_BLOCK_IO *dev = devinfo->dev; if (dev->Media->ReadOnly) return -1; lba = lba / (dev->Media->BlockSize / DEV_BSIZE); size = nblk * DEV_BSIZE; status = dev->WriteBlocks(dev, dev->Media->MediaId, lba, size, buf); if (status != EFI_SUCCESS) { DPRINTF("dskread: failed dev: %p, id: %u, lba: %ju, size: %d, " "status: %lu\n", devinfo->dev, dev->Media->MediaId, (uintmax_t)lba, size, EFI_ERROR_CODE(status)); return (-1); } return (0); } /* * Return the number of LBAs the drive has. */ uint64_t drvsize(struct dsk *dskp) { dev_info_t *devinfo = (dev_info_t *)dskp->devinfo; EFI_BLOCK_IO *dev = devinfo->dev; return (dev->Media->LastBlock + 1); } static int partition_number(EFI_DEVICE_PATH *devpath) { EFI_DEVICE_PATH *md; HARDDRIVE_DEVICE_PATH *hd; md = efi_devpath_last_node(devpath); if (md == NULL) return (-1); if (DevicePathSubType(md) != MEDIA_HARDDRIVE_DP) return (-1); hd = (HARDDRIVE_DEVICE_PATH *)md; return (hd->PartitionNumber); } /* * Find the raw partition for the imgpath and save it */ static void probe_handle(EFI_HANDLE h, EFI_DEVICE_PATH *imgpath) { dev_info_t *devinfo; EFI_BLOCK_IO *blkio; EFI_DEVICE_PATH *devpath, *trimmed = NULL; EFI_STATUS status; /* Figure out if we're dealing with an actual partition. */ - status = BS->HandleProtocol(h, &DevicePathGUID, (void **)&devpath); + status = OpenProtocolByHandle(h, &DevicePathGUID, (void **)&devpath); if (status != EFI_SUCCESS) return; #ifdef EFI_DEBUG { CHAR16 *text = efi_devpath_name(devpath); DPRINTF("probing: %S ", text); efi_free_devpath_name(text); } #endif /* * The RAW device is the same as the imgpath with the last * MEDIA_DEVICE bit trimmed off. imgpath will end with the * MEDIA_DEVICE for the ESP we booted off of. */ if (!efi_devpath_same_disk(imgpath, devpath)) { trimmed = efi_devpath_trim(imgpath); if (!efi_devpath_match(trimmed, devpath)) { free(trimmed); DPRINTF("Not the same disk\n"); return; } } - status = BS->HandleProtocol(h, &BlockIoProtocolGUID, (void **)&blkio); + status = OpenProtocolByHandle(h, &BlockIoProtocolGUID, (void **)&blkio); if (status != EFI_SUCCESS) { DPRINTF("Can't get the block I/O protocol block\n"); return; } devinfo = malloc(sizeof(*devinfo)); if (devinfo == NULL) { DPRINTF("Failed to allocate devinfo\n"); return; } devinfo->dev = blkio; devinfo->devpath = devpath; devinfo->devhandle = h; devinfo->preferred = 1; devinfo->next = NULL; devinfo->devdata = NULL; if (trimmed == NULL) { DPRINTF("Found partition %d\n", partition_number(devpath)); add_device(&devices, devinfo); } else { free(trimmed); DPRINTF("Found raw device\n"); if (raw_device) { printf(BOOTPROG": Found two raw devices, inconceivable?\n"); return; } raw_device = devinfo; } } static void probe_handles(EFI_HANDLE *handles, UINTN nhandles, EFI_DEVICE_PATH *imgpath) { UINTN i; for (i = 0; i < nhandles; i++) probe_handle(handles[i], imgpath); } static dev_info_t * find_partition(int part) { dev_info_t *dev; if (part == 0) return (NULL); for (dev = devices; dev != NULL; dev = dev->next) if (partition_number(dev->devpath) == part) break; return (dev); } void choice_protocol(EFI_HANDLE *handles, UINTN nhandles, EFI_DEVICE_PATH *imgpath) { const boot_module_t *mod = &ufs_module; dev_info_t *bootdev; void *loaderbuf; size_t loadersize; int parts; const char *fn = PATH_LOADER_EFI; /* * Probe the provided handles to find the partitions that * are on the same drive. */ probe_handles(handles, nhandles, imgpath); dsk.devinfo = raw_device; if (dsk.devinfo == NULL) { printf(BOOTPROG": unable to find raw disk to read gpt\n"); return; } /* * Read in the GPT table, and then find the right partition. * gptread, gptfind and gptfaileboot are shared with the * BIOS version of the gptboot program. */ if (gptread(&dsk, secbuf) == -1) { printf(BOOTPROG ": unable to load GPT\n"); return; } // XXX: // real gptboot can parse a command line before trying this loop. // But since we don't parse anything at all, hard wire the partition // to be -1 (meaning look for the next one). parts = 0; while (gptfind(&freebsd_ufs_uuid, &dsk, -1) != -1) { parts++; bootdev = find_partition(dsk.part); if (bootdev == NULL) { printf(BOOTPROG": Can't find partition %d\n", dsk.part); goto next; } if (mod->load(fn, bootdev, &loaderbuf, &loadersize) != EFI_SUCCESS) { printf(BOOTPROG": Can't load %s from partition %d\n", fn, dsk.part); goto next; } try_boot(mod, bootdev, loaderbuf, loadersize); next: gptbootfailed(&dsk); } if (parts == 0) printf("%s: no UFS partition was found\n", BOOTPROG); }