Page MenuHomeFreeBSD

D5108.id12850.diff
No OneTemporary

D5108.id12850.diff

Index: sys/boot/efi/boot1/boot1.c
===================================================================
--- sys/boot/efi/boot1/boot1.c
+++ sys/boot/efi/boot1/boot1.c
@@ -51,7 +51,10 @@
EFI_STATUS efi_main(EFI_HANDLE Ximage, EFI_SYSTEM_TABLE* Xsystab);
static void try_load(const boot_module_t* mod);
-static EFI_STATUS probe_handle(EFI_HANDLE h);
+static void probe_handle_status(EFI_HANDLE h, EFI_DEVICE_PATH *imgpath,
+ BOOLEAN match);
+static EFI_STATUS probe_handle(EFI_HANDLE h, EFI_DEVICE_PATH *imgpath,
+ BOOLEAN match);
EFI_SYSTEM_TABLE *systab;
EFI_BOOT_SERVICES *bs;
@@ -84,11 +87,204 @@
(void)bs->FreePool(buf);
}
+static BOOLEAN
+paths_match(EFI_DEVICE_PATH *imgpath, EFI_DEVICE_PATH *devpath)
+{
+ int len;
+
+ if (imgpath == NULL || imgpath->Type != devpath->Type ||
+ imgpath->SubType != devpath->SubType)
+ return (FALSE);
+
+ len = DevicePathNodeLength(imgpath);
+
+ if (len != DevicePathNodeLength(devpath))
+ return (FALSE);
+
+ return (memcmp(imgpath, devpath, (size_t)len) == 0);
+}
+
+static EFI_DEVICE_PATH *
+devpath_last(EFI_DEVICE_PATH *devpath)
+{
+ while (!IsDevicePathEnd(NextDevicePathNode(devpath)))
+ devpath = NextDevicePathNode(devpath);
+
+ return (devpath);
+}
+
+static EFI_DEVICE_PATH *
+devpath_by_type(EFI_DEVICE_PATH *devpath, UINT8 type)
+{
+ while (!IsDevicePathType(devpath, type) &&
+ !IsDevicePathEnd(NextDevicePathNode(devpath)))
+ devpath = NextDevicePathNode(devpath);
+
+ if (!IsDevicePathType(devpath, type))
+ return (NULL);
+
+ return (devpath);
+}
+
+/*
+ * devpath_print_node is a basic output method for a devpath.
+ * If we switch to UEFI 2.x then we should update it to use:
+ * EFI_DEVICE_PATH_TO_TEXT_PROTOCOL.
+ */
+static int
+devpath_str_node(char *buf, size_t size, EFI_DEVICE_PATH *devpath)
+{
+
+ switch (devpath->Type) {
+ case MESSAGING_DEVICE_PATH:
+ switch (devpath->SubType) {
+ case MSG_ATAPI_DP: {
+ ATAPI_DEVICE_PATH *atapi;
+
+ atapi = (ATAPI_DEVICE_PATH *)(void *)devpath;
+ return snprintf(buf, size, "ata(%s,%s,0x%x)",
+ (atapi->PrimarySecondary == 1) ? "Sec" : "Pri",
+ (atapi->SlaveMaster == 1) ? "Slave" : "Master",
+ atapi->Lun);
+ }
+ case MSG_USB_DP: {
+ USB_DEVICE_PATH *usb;
+
+ usb = (USB_DEVICE_PATH *)devpath;
+ return snprintf(buf, size, "usb(0x%02x,0x%02x)",
+ usb->ParentPortNumber, usb->InterfaceNumber);
+ }
+ case MSG_SCSI_DP: {
+ SCSI_DEVICE_PATH *scsi;
+
+ scsi = (SCSI_DEVICE_PATH *)(void *)devpath;
+ return snprintf(buf, size, "scsi(0x%02x,0x%02x)",
+ scsi->Pun, scsi->Lun);
+ }
+ default:
+ return snprintf(buf, size, "msg(0x%02x)",
+ devpath->SubType);
+ }
+ break;
+ case HARDWARE_DEVICE_PATH:
+ switch (devpath->SubType) {
+ case HW_PCI_DP: {
+ PCI_DEVICE_PATH *pci;
+
+ pci = (PCI_DEVICE_PATH *)devpath;
+ return snprintf(buf, size, "pci(0x%02x,0x%02x)",
+ pci->Device, pci->Function);
+ }
+ default:
+ return snprintf(buf, size, "hw(0x%02x)",
+ devpath->SubType);
+ }
+ break;
+ case ACPI_DEVICE_PATH: {
+ ACPI_HID_DEVICE_PATH *acpi;
+
+ acpi = (ACPI_HID_DEVICE_PATH *)(void *)devpath;
+ if ((acpi->HID & PNP_EISA_ID_MASK) == PNP_EISA_ID_CONST) {
+ switch (EISA_ID_TO_NUM(acpi->HID)) {
+ case 0x0a03:
+ return snprintf(buf, size, "pciroot(0x%x)",
+ acpi->UID);
+ case 0x0a08:
+ return snprintf(buf, size, "pcieroot(0x%x)",
+ acpi->UID);
+ case 0x0604:
+ return snprintf(buf, size, "floppy(0x%x)",
+ acpi->UID);
+ case 0x0301:
+ return snprintf(buf, size, "keyboard(0x%x)",
+ acpi->UID);
+ case 0x0501:
+ return snprintf(buf, size, "serial(0x%x)",
+ acpi->UID);
+ case 0x0401:
+ return snprintf(buf, size, "parallelport(0x%x)",
+ acpi->UID);
+ default:
+ return snprintf(buf, size, "acpi(pnp%04x,0x%x)",
+ EISA_ID_TO_NUM(acpi->HID), acpi->UID);
+ }
+ }
+
+ return snprintf(buf, size, "acpi(0x%08x,0x%x)", acpi->HID,
+ acpi->UID);
+ }
+ case MEDIA_DEVICE_PATH:
+ switch (devpath->SubType) {
+ case MEDIA_CDROM_DP: {
+ CDROM_DEVICE_PATH *cdrom;
+
+ cdrom = (CDROM_DEVICE_PATH *)(void *)devpath;
+ return snprintf(buf, size, "cdrom(%x)",
+ cdrom->BootEntry);
+ }
+ case MEDIA_HARDDRIVE_DP: {
+ HARDDRIVE_DEVICE_PATH *hd;
+
+ hd = (HARDDRIVE_DEVICE_PATH *)(void *)devpath;
+ return snprintf(buf, size, "hd(%x)",
+ hd->PartitionNumber);
+ }
+ default:
+ return snprintf(buf, size, "media(0x%02x)",
+ devpath->SubType);
+ }
+ case BBS_DEVICE_PATH:
+ return snprintf(buf, size, "bbs(0x%02x)", devpath->SubType);
+ case END_DEVICE_PATH_TYPE:
+ return (0);
+ }
+
+ return snprintf(buf, size, "type(0x%02x, 0x%02x)", devpath->Type,
+ devpath->SubType);
+}
+
+int
+devpath_strncat(char *buf, size_t size, EFI_DEVICE_PATH *devpath)
+{
+ size_t len, used;
+ const char *sep;
+
+ sep = "";
+ used = 0;
+ while (!IsDevicePathEnd(devpath)) {
+ len = snprintf(buf, size - used, "%s", sep);
+ used += len;
+ if (used > size)
+ return (used);
+ buf += len;
+
+ len = devpath_str_node(buf, size - used, devpath);
+ used += len;
+ if (used > size)
+ return (used);
+ buf += len;
+ devpath = NextDevicePathNode(devpath);
+ sep = ":";
+ }
+
+ return (used);
+}
+
+char *
+devpath_str(EFI_DEVICE_PATH *devpath)
+{
+ static char buf[128];
+
+ devpath_strncat(buf, sizeof(buf), devpath);
+
+ return buf;
+}
+
/*
* This function only returns if it fails to load the kernel. If it
* succeeds, it simply boots the kernel.
*/
-void
+static void
try_load(const boot_module_t *mod)
{
size_t bufsize, cmdsize;
@@ -136,8 +332,8 @@
return;
}
- if ((status = bs->LoadImage(TRUE, image, dev->devpath, buf, bufsize,
- &loaderhandle)) != EFI_SUCCESS) {
+ if ((status = bs->LoadImage(TRUE, image, devpath_last(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;
@@ -172,6 +368,8 @@
efi_main(EFI_HANDLE Ximage, EFI_SYSTEM_TABLE *Xsystab)
{
EFI_HANDLE *handles;
+ EFI_LOADED_IMAGE *img;
+ EFI_DEVICE_PATH *imgpath;
EFI_STATUS status;
EFI_CONSOLE_CONTROL_PROTOCOL *ConsoleControl = NULL;
SIMPLE_TEXT_OUTPUT_INTERFACE *conout = NULL;
@@ -254,20 +452,31 @@
/* 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;
+ DPRINTF("\n");
+
+ /*
+ * We start by probing handles which match our images media path, so if
+ * possible we boot from a partition on our device.
+ */
+ status = bs->HandleProtocol(image, &LoadedImageGUID, (VOID**)&img);
+ imgpath = NULL;
+ if (status == EFI_SUCCESS) {
+ status = bs->HandleProtocol(img->DeviceHandle, &DevicePathGUID,
+ (void **)&imgpath);
+ if (status == EFI_SUCCESS) {
+ imgpath = devpath_by_type(imgpath,
+ MESSAGING_DEVICE_PATH);
+ if (imgpath != NULL) {
+ for (i = 0; i < nhandles; i++)
+ probe_handle_status(handles[i], imgpath,
+ TRUE);
+ }
}
}
+
+ /* Now check for other bootable partitions. */
+ for (i = 0; i < nhandles; i++)
+ probe_handle_status(handles[i], imgpath, FALSE);
printf(" done\n");
/* Status summary. */
@@ -287,12 +496,47 @@
panic("No bootable partitions found!");
}
+static void
+probe_handle_status(EFI_HANDLE h, EFI_DEVICE_PATH *imgpath, BOOLEAN match)
+{
+ EFI_STATUS status;
+
+ status = probe_handle(h, imgpath, match);
+
+ DPRINTF("probe: match: %d => ", match);
+ switch (status) {
+ case EFI_UNSUPPORTED:
+ printf(".");
+ DPRINTF(" not supported\n");
+ break;
+ case EFI_SUCCESS:
+ if (match) {
+ printf("%c", '*');
+ DPRINTF(" supported (preferred)\n");
+ } else {
+ printf("%c", '+');
+ DPRINTF(" supported\n");
+ }
+ break;
+ case EFI_NOT_FOUND:
+ if (match)
+ DPRINTF("- not matched\n");
+ else
+ DPRINTF("- already tested\n");
+ break;
+ default:
+ printf("x");
+ DPRINTF(" error (%lu)\n", EFI_ERROR_CODE(status));
+ break;
+ }
+}
+
static EFI_STATUS
-probe_handle(EFI_HANDLE h)
+probe_handle(EFI_HANDLE h, EFI_DEVICE_PATH *imgpath, BOOLEAN match)
{
dev_info_t *devinfo;
EFI_BLOCK_IO *blkio;
- EFI_DEVICE_PATH *devpath;
+ EFI_DEVICE_PATH *devpath, *msgpath;
EFI_STATUS status;
UINTN i;
@@ -307,8 +551,20 @@
return (status);
}
- while (!IsDevicePathEnd(NextDevicePathNode(devpath)))
- devpath = NextDevicePathNode(devpath);
+ DPRINTF("probing: %s\n", devpath_str(devpath));
+
+ /* Check this pass needs to process this partition. */
+ msgpath = devpath_by_type(devpath, MESSAGING_DEVICE_PATH);
+ if (msgpath != NULL) {
+ if (match) {
+ if (!paths_match(imgpath, msgpath))
+ return (EFI_NOT_FOUND);
+ } else if (paths_match(imgpath, msgpath)) {
+ /* Already tested. */
+ return (EFI_NOT_FOUND);
+ }
+ } else if (match)
+ return (EFI_NOT_FOUND);
status = bs->HandleProtocol(h, &BlockIoProtocolGUID, (void **)&blkio);
if (status == EFI_UNSUPPORTED)
Index: sys/boot/efi/boot1/boot_module.h
===================================================================
--- sys/boot/efi/boot1/boot_module.h
+++ sys/boot/efi/boot1/boot_module.h
@@ -36,7 +36,7 @@
#include <eficonsctl.h>
#ifdef EFI_DEBUG
-#define DPRINTF(fmt, ...) printf(fmt, __VA_ARGS__)
+#define DPRINTF(fmt, args...) printf(fmt, ##args)
#else
#define DPRINTF(fmt, ...) {}
#endif
@@ -75,14 +75,14 @@
/*
* load should select the best out of a set of devices that probe
- * indicated were loadable and load it.
+ * indicated were loadable and load the specified file.
*
* 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,
+ EFI_STATUS (*load)(const char *filepath, dev_info_t **devinfo,
void **buf, size_t *bufsize);
/* status outputs information about the probed devices. */
@@ -107,4 +107,6 @@
extern EFI_SYSTEM_TABLE *systab;
extern EFI_BOOT_SERVICES *bs;
+extern int devpath_strncat(char *buf, size_t size, EFI_DEVICE_PATH *devpath);
+extern char *devpath_str(EFI_DEVICE_PATH *devpath);
#endif
Index: sys/boot/efi/boot1/ufs_module.c
===================================================================
--- sys/boot/efi/boot1/ufs_module.c
+++ sys/boot/efi/boot1/ufs_module.c
@@ -93,7 +93,7 @@
}
static EFI_STATUS
-try_load(dev_info_t *dev, const char *loader_path, void **bufp, size_t *bufsize)
+try_load(dev_info_t *dev, const char *filepath, void **bufp, size_t *bufsize)
{
ufs_ino_t ino;
EFI_STATUS status;
@@ -101,28 +101,35 @@
ssize_t read;
void *buf;
- if (init_dev(dev) < 0)
+ DPRINTF("try_load: '%s' devpath: %s\n", filepath,
+ devpath_str(dev->devpath));
+
+ if (init_dev(dev) < 0) {
+ DPRINTF("Failed to device %p\n", dev);
return (EFI_UNSUPPORTED);
+ }
- if ((ino = lookup(loader_path)) == 0)
+ if ((ino = lookup(filepath)) == 0) {
+ DPRINTF("Failed to lookup '%s' on %p\n", filepath, dev);
return (EFI_NOT_FOUND);
+ }
if (fsread_size(ino, NULL, 0, &size) < 0 || size <= 0) {
- printf("Failed to read size of '%s' ino: %d\n", loader_path,
+ printf("Failed to read size of '%s' ino: %d\n", filepath,
ino);
return (EFI_INVALID_PARAMETER);
}
if ((status = bs->AllocatePool(EfiLoaderData, size, &buf)) !=
EFI_SUCCESS) {
- printf("Failed to allocate read buffer (%lu)\n",
- EFI_ERROR_CODE(status));
+ printf("Failed to allocate read buffer %zu for '%s' (%lu)\n",
+ size, filepath, EFI_ERROR_CODE(status));
return (status);
}
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", filepath, read,
size);
(void)bs->FreePool(buf);
return (EFI_INVALID_PARAMETER);
@@ -135,19 +142,14 @@
}
static EFI_STATUS
-load(const char *loader_path, dev_info_t **devinfop, void **buf,
- size_t *bufsize)
+load(const char *filepath, dev_info_t **devinfop, void **buf, size_t *bufsize)
{
dev_info_t *dev;
- EFI_STATUS status;
for (dev = devices; dev != NULL; dev = dev->next) {
- status = try_load(dev, loader_path, buf, bufsize);
- if (status == EFI_SUCCESS) {
+ if (try_load(dev, filepath, buf, bufsize) == EFI_SUCCESS) {
*devinfop = dev;
return (EFI_SUCCESS);
- } else if (status != EFI_NOT_FOUND) {
- return (status);
}
}
Index: sys/boot/efi/boot1/zfs_module.c
===================================================================
--- sys/boot/efi/boot1/zfs_module.c
+++ sys/boot/efi/boot1/zfs_module.c
@@ -91,7 +91,8 @@
}
static EFI_STATUS
-try_load(dev_info_t *devinfo, const char *loader_path, void **bufp, size_t *bufsize)
+try_load(dev_info_t *devinfo, const char *filepath, void **bufp,
+ size_t *bufsize)
{
spa_t *spa;
struct zfsmount zfsmount;
@@ -102,32 +103,41 @@
EFI_STATUS status;
spa = devinfo->devdata;
- if (zfs_spa_init(spa) != 0) {
- /* Init failed, don't report this loudly. */
+
+ DPRINTF("try_load: '%s' spa: '%s', devpath: %s\n",
+ filepath, spa->spa_name, devpath_str(devinfo->devpath));
+
+ if ((err = zfs_spa_init(spa)) != 0) {
+ DPRINTF("Failed to load pool '%s' (%d)\n", spa->spa_name, err);
return (EFI_NOT_FOUND);
}
- if (zfs_mount(spa, 0, &zfsmount) != 0) {
- /* Mount failed, don't report this loudly. */
+ if ((err = zfs_mount(spa, 0, &zfsmount)) != 0) {
+ DPRINTF("Failed to mount pool '%s' (%d)\n", spa->spa_name, err);
return (EFI_NOT_FOUND);
}
- if ((err = zfs_lookup(&zfsmount, loader_path, &dn)) != 0) {
- printf("Failed to lookup %s on pool %s (%d)\n", loader_path,
+ if ((err = zfs_lookup(&zfsmount, filepath, &dn)) != 0) {
+ if (err == ENOENT) {
+ DPRINTF("Failed to find '%s' on pool '%s' (%d)\n",
+ filepath, spa->spa_name, err);
+ return (EFI_NOT_FOUND);
+ }
+ printf("Failed to lookup '%s' on pool '%s' (%d)\n", filepath,
spa->spa_name, err);
return (EFI_INVALID_PARAMETER);
}
if ((err = zfs_dnode_stat(spa, &dn, &st)) != 0) {
- printf("Failed to lookup %s on pool %s (%d)\n", loader_path,
+ printf("Failed to stat '%s' on pool '%s' (%d)\n", filepath,
spa->spa_name, err);
return (EFI_INVALID_PARAMETER);
}
if ((status = bs->AllocatePool(EfiLoaderData, (UINTN)st.st_size, &buf))
!= EFI_SUCCESS) {
- printf("Failed to allocate load buffer for pool %s (%lu)\n",
- spa->spa_name, EFI_ERROR_CODE(status));
+ printf("Failed to allocate load buffer %zu for pool '%s' for '%s' "
+ "(%lu)\n", st.st_size, spa->spa_name, filepath, EFI_ERROR_CODE(status));
return (EFI_INVALID_PARAMETER);
}
@@ -145,19 +155,14 @@
}
static EFI_STATUS
-load(const char *loader_path, dev_info_t **devinfop, void **bufp,
- size_t *bufsize)
+load(const char *filepath, dev_info_t **devinfop, void **bufp, size_t *bufsize)
{
- dev_info_t *devinfo;
- EFI_STATUS status;
+ dev_info_t *dev;
- for (devinfo = devices; devinfo != NULL; devinfo = devinfo->next) {
- status = try_load(devinfo, loader_path, bufp, bufsize);
- if (status == EFI_SUCCESS) {
- *devinfop = devinfo;
+ for (dev = devices; dev != NULL; dev = dev->next) {
+ if (try_load(dev, filepath, bufp, bufsize) == EFI_SUCCESS) {
+ *devinfop = dev;
return (EFI_SUCCESS);
- } else if (status != EFI_NOT_FOUND) {
- return (status);
}
}
@@ -195,5 +200,5 @@
.init = init,
.probe = probe,
.load = load,
- .status = status
+ .status = status,
};
Index: sys/boot/efi/include/efidevp.h
===================================================================
--- sys/boot/efi/include/efidevp.h
+++ sys/boot/efi/include/efidevp.h
@@ -40,9 +40,7 @@
#define EFI_DP_TYPE_MASK 0x7F
#define EFI_DP_TYPE_UNPACKED 0x80
-//#define END_DEVICE_PATH_TYPE 0xff
#define END_DEVICE_PATH_TYPE 0x7f
-//#define END_DEVICE_PATH_TYPE_UNPACKED 0x7f
#define END_ENTIRE_DEVICE_PATH_SUBTYPE 0xff
#define END_INSTANCE_DEVICE_PATH_SUBTYPE 0x01
@@ -56,8 +54,9 @@
#define DevicePathSubType(a) ( (a)->SubType )
#define DevicePathNodeLength(a) ( ((a)->Length[0]) | ((a)->Length[1] << 8) )
#define NextDevicePathNode(a) ( (EFI_DEVICE_PATH *) ( ((UINT8 *) (a)) + DevicePathNodeLength(a)))
-//#define IsDevicePathEndType(a) ( DevicePathType(a) == END_DEVICE_PATH_TYPE_UNPACKED )
-#define IsDevicePathEndType(a) ( DevicePathType(a) == END_DEVICE_PATH_TYPE )
+#define IsDevicePathType(a, t) ( DevicePathType(a) == t )
+#define IsDevicePathEndType(a) IsDevicePathType(a, END_DEVICE_PATH_TYPE)
+#define IsDevicePathMessaging(a) IsDevicePathType(a, MESSAGING_DEVICE_PATH)
#define IsDevicePathEndSubType(a) ( (a)->SubType == END_ENTIRE_DEVICE_PATH_SUBTYPE )
#define IsDevicePathEnd(a) ( IsDevicePathEndType(a) && IsDevicePathEndSubType(a) )
#define IsDevicePathUnpacked(a) ( (a)->Type & EFI_DP_TYPE_UNPACKED )

File Metadata

Mime Type
text/plain
Expires
Thu, Sep 10, 2:15 PM (22 h, 6 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
38650024
Default Alt Text
D5108.id12850.diff (16 KB)

Event Timeline