199767f8919635c4928607450d9e0abb932109ceToomas Soome/*-
199767f8919635c4928607450d9e0abb932109ceToomas Soome * Copyright (c) 1998 Robert Nordier
199767f8919635c4928607450d9e0abb932109ceToomas Soome * All rights reserved.
199767f8919635c4928607450d9e0abb932109ceToomas Soome * Copyright (c) 2001 Robert Drehmel
199767f8919635c4928607450d9e0abb932109ceToomas Soome * All rights reserved.
199767f8919635c4928607450d9e0abb932109ceToomas Soome * Copyright (c) 2014 Nathan Whitehorn
199767f8919635c4928607450d9e0abb932109ceToomas Soome * All rights reserved.
199767f8919635c4928607450d9e0abb932109ceToomas Soome * Copyright (c) 2015 Eric McCorkle
199767f8919635c4928607450d9e0abb932109ceToomas Soome * All rights reserved.
199767f8919635c4928607450d9e0abb932109ceToomas Soome *
199767f8919635c4928607450d9e0abb932109ceToomas Soome * Redistribution and use in source and binary forms are freely
199767f8919635c4928607450d9e0abb932109ceToomas Soome * permitted provided that the above copyright notice and this
199767f8919635c4928607450d9e0abb932109ceToomas Soome * paragraph and the following disclaimer are duplicated in all
199767f8919635c4928607450d9e0abb932109ceToomas Soome * such forms.
199767f8919635c4928607450d9e0abb932109ceToomas Soome *
199767f8919635c4928607450d9e0abb932109ceToomas Soome * This software is provided "AS IS" and without any express or
199767f8919635c4928607450d9e0abb932109ceToomas Soome * implied warranties, including, without limitation, the implied
199767f8919635c4928607450d9e0abb932109ceToomas Soome * warranties of merchantability and fitness for a particular
199767f8919635c4928607450d9e0abb932109ceToomas Soome * purpose.
199767f8919635c4928607450d9e0abb932109ceToomas Soome */
199767f8919635c4928607450d9e0abb932109ceToomas Soome
199767f8919635c4928607450d9e0abb932109ceToomas Soome#include <sys/cdefs.h>
199767f8919635c4928607450d9e0abb932109ceToomas Soome__FBSDID("$FreeBSD$");
199767f8919635c4928607450d9e0abb932109ceToomas Soome
199767f8919635c4928607450d9e0abb932109ceToomas Soome#include <sys/param.h>
199767f8919635c4928607450d9e0abb932109ceToomas Soome#include <machine/elf.h>
199767f8919635c4928607450d9e0abb932109ceToomas Soome#include <machine/stdarg.h>
199767f8919635c4928607450d9e0abb932109ceToomas Soome#include <stand.h>
199767f8919635c4928607450d9e0abb932109ceToomas Soome
199767f8919635c4928607450d9e0abb932109ceToomas Soome#include <efi.h>
199767f8919635c4928607450d9e0abb932109ceToomas Soome#include <eficonsctl.h>
199767f8919635c4928607450d9e0abb932109ceToomas Soome
199767f8919635c4928607450d9e0abb932109ceToomas Soome#include <bootstrap.h>
199767f8919635c4928607450d9e0abb932109ceToomas Soome#include "boot_module.h"
199767f8919635c4928607450d9e0abb932109ceToomas Soome#include "paths.h"
199767f8919635c4928607450d9e0abb932109ceToomas Soome
199767f8919635c4928607450d9e0abb932109ceToomas Soomestruct arch_switch archsw;
199767f8919635c4928607450d9e0abb932109ceToomas Soomestruct fs_ops *file_system[] = {
199767f8919635c4928607450d9e0abb932109ceToomas Soome NULL
199767f8919635c4928607450d9e0abb932109ceToomas Soome};
199767f8919635c4928607450d9e0abb932109ceToomas Soome
199767f8919635c4928607450d9e0abb932109ceToomas Soomestatic const boot_module_t *boot_modules[] =
199767f8919635c4928607450d9e0abb932109ceToomas Soome{
199767f8919635c4928607450d9e0abb932109ceToomas Soome#ifdef EFI_ZFS_BOOT
199767f8919635c4928607450d9e0abb932109ceToomas Soome &zfs_module,
199767f8919635c4928607450d9e0abb932109ceToomas Soome#endif
199767f8919635c4928607450d9e0abb932109ceToomas Soome#ifdef EFI_UFS_BOOT
199767f8919635c4928607450d9e0abb932109ceToomas Soome &ufs_module
199767f8919635c4928607450d9e0abb932109ceToomas Soome#endif
199767f8919635c4928607450d9e0abb932109ceToomas Soome};
199767f8919635c4928607450d9e0abb932109ceToomas Soome
199767f8919635c4928607450d9e0abb932109ceToomas Soome#define NUM_BOOT_MODULES (sizeof(boot_modules) / sizeof(boot_module_t*))
199767f8919635c4928607450d9e0abb932109ceToomas Soome/* The initial number of handles used to query EFI for partitions. */
199767f8919635c4928607450d9e0abb932109ceToomas Soome#define NUM_HANDLES_INIT 24
199767f8919635c4928607450d9e0abb932109ceToomas Soome
199767f8919635c4928607450d9e0abb932109ceToomas SoomeEFI_STATUS efi_main(EFI_HANDLE Ximage, EFI_SYSTEM_TABLE* Xsystab);
199767f8919635c4928607450d9e0abb932109ceToomas Soome
199767f8919635c4928607450d9e0abb932109ceToomas SoomeEFI_SYSTEM_TABLE *systab;
199767f8919635c4928607450d9e0abb932109ceToomas SoomeEFI_BOOT_SERVICES *bs;
199767f8919635c4928607450d9e0abb932109ceToomas Soomestatic EFI_HANDLE *image;
199767f8919635c4928607450d9e0abb932109ceToomas Soome
199767f8919635c4928607450d9e0abb932109ceToomas Soomestatic EFI_GUID BlockIoProtocolGUID = BLOCK_IO_PROTOCOL;
199767f8919635c4928607450d9e0abb932109ceToomas Soomestatic EFI_GUID DevicePathGUID = DEVICE_PATH_PROTOCOL;
199767f8919635c4928607450d9e0abb932109ceToomas Soomestatic EFI_GUID LoadedImageGUID = LOADED_IMAGE_PROTOCOL;
199767f8919635c4928607450d9e0abb932109ceToomas Soomestatic EFI_GUID ConsoleControlGUID = EFI_CONSOLE_CONTROL_PROTOCOL_GUID;
199767f8919635c4928607450d9e0abb932109ceToomas Soome
199767f8919635c4928607450d9e0abb932109ceToomas Soome/*
199767f8919635c4928607450d9e0abb932109ceToomas Soome * Provide Malloc / Free backed by EFIs AllocatePool / FreePool which ensures
199767f8919635c4928607450d9e0abb932109ceToomas Soome * memory is correctly aligned avoiding EFI_INVALID_PARAMETER returns from
199767f8919635c4928607450d9e0abb932109ceToomas Soome * EFI methods.
199767f8919635c4928607450d9e0abb932109ceToomas Soome */
199767f8919635c4928607450d9e0abb932109ceToomas Soomevoid *
199767f8919635c4928607450d9e0abb932109ceToomas SoomeMalloc(size_t len, const char *file __unused, int line __unused)
199767f8919635c4928607450d9e0abb932109ceToomas Soome{
199767f8919635c4928607450d9e0abb932109ceToomas Soome void *out;
199767f8919635c4928607450d9e0abb932109ceToomas Soome
199767f8919635c4928607450d9e0abb932109ceToomas Soome if (bs->AllocatePool(EfiLoaderData, len, &out) == EFI_SUCCESS)
199767f8919635c4928607450d9e0abb932109ceToomas Soome return (out);
199767f8919635c4928607450d9e0abb932109ceToomas Soome
199767f8919635c4928607450d9e0abb932109ceToomas Soome return (NULL);
199767f8919635c4928607450d9e0abb932109ceToomas Soome}
199767f8919635c4928607450d9e0abb932109ceToomas Soome
199767f8919635c4928607450d9e0abb932109ceToomas Soomevoid
199767f8919635c4928607450d9e0abb932109ceToomas SoomeFree(void *buf, const char *file __unused, int line __unused)
199767f8919635c4928607450d9e0abb932109ceToomas Soome{
199767f8919635c4928607450d9e0abb932109ceToomas Soome (void)bs->FreePool(buf);
199767f8919635c4928607450d9e0abb932109ceToomas Soome}
199767f8919635c4928607450d9e0abb932109ceToomas Soome
199767f8919635c4928607450d9e0abb932109ceToomas Soome/*
199767f8919635c4928607450d9e0abb932109ceToomas Soome * nodes_match returns TRUE if the imgpath isn't NULL and the nodes match,
199767f8919635c4928607450d9e0abb932109ceToomas Soome * FALSE otherwise.
199767f8919635c4928607450d9e0abb932109ceToomas Soome */
199767f8919635c4928607450d9e0abb932109ceToomas Soomestatic BOOLEAN
199767f8919635c4928607450d9e0abb932109ceToomas Soomenodes_match(EFI_DEVICE_PATH *imgpath, EFI_DEVICE_PATH *devpath)
199767f8919635c4928607450d9e0abb932109ceToomas Soome{
199767f8919635c4928607450d9e0abb932109ceToomas Soome int len;
199767f8919635c4928607450d9e0abb932109ceToomas Soome
199767f8919635c4928607450d9e0abb932109ceToomas Soome if (imgpath == NULL || imgpath->Type != devpath->Type ||
199767f8919635c4928607450d9e0abb932109ceToomas Soome imgpath->SubType != devpath->SubType)
199767f8919635c4928607450d9e0abb932109ceToomas Soome return (FALSE);
199767f8919635c4928607450d9e0abb932109ceToomas Soome
199767f8919635c4928607450d9e0abb932109ceToomas Soome len = DevicePathNodeLength(imgpath);
199767f8919635c4928607450d9e0abb932109ceToomas Soome if (len != DevicePathNodeLength(devpath))
199767f8919635c4928607450d9e0abb932109ceToomas Soome return (FALSE);
199767f8919635c4928607450d9e0abb932109ceToomas Soome
199767f8919635c4928607450d9e0abb932109ceToomas Soome return (memcmp(imgpath, devpath, (size_t)len) == 0);
199767f8919635c4928607450d9e0abb932109ceToomas Soome}
199767f8919635c4928607450d9e0abb932109ceToomas Soome
199767f8919635c4928607450d9e0abb932109ceToomas Soome/*
199767f8919635c4928607450d9e0abb932109ceToomas Soome * device_paths_match returns TRUE if the imgpath isn't NULL and all nodes
199767f8919635c4928607450d9e0abb932109ceToomas Soome * in imgpath and devpath match up to their respect occurances of a media
199767f8919635c4928607450d9e0abb932109ceToomas Soome * node, FALSE otherwise.
199767f8919635c4928607450d9e0abb932109ceToomas Soome */
199767f8919635c4928607450d9e0abb932109ceToomas Soomestatic BOOLEAN
199767f8919635c4928607450d9e0abb932109ceToomas Soomedevice_paths_match(EFI_DEVICE_PATH *imgpath, EFI_DEVICE_PATH *devpath)
199767f8919635c4928607450d9e0abb932109ceToomas Soome{
199767f8919635c4928607450d9e0abb932109ceToomas Soome
199767f8919635c4928607450d9e0abb932109ceToomas Soome if (imgpath == NULL)
199767f8919635c4928607450d9e0abb932109ceToomas Soome return (FALSE);
199767f8919635c4928607450d9e0abb932109ceToomas Soome
199767f8919635c4928607450d9e0abb932109ceToomas Soome while (!IsDevicePathEnd(imgpath) && !IsDevicePathEnd(devpath)) {
199767f8919635c4928607450d9e0abb932109ceToomas Soome if (IsDevicePathType(imgpath, MEDIA_DEVICE_PATH) &&
199767f8919635c4928607450d9e0abb932109ceToomas Soome IsDevicePathType(devpath, MEDIA_DEVICE_PATH))
199767f8919635c4928607450d9e0abb932109ceToomas Soome return (TRUE);
199767f8919635c4928607450d9e0abb932109ceToomas Soome
199767f8919635c4928607450d9e0abb932109ceToomas Soome if (!nodes_match(imgpath, devpath))
199767f8919635c4928607450d9e0abb932109ceToomas Soome return (FALSE);
199767f8919635c4928607450d9e0abb932109ceToomas Soome
199767f8919635c4928607450d9e0abb932109ceToomas Soome imgpath = NextDevicePathNode(imgpath);
199767f8919635c4928607450d9e0abb932109ceToomas Soome devpath = NextDevicePathNode(devpath);
199767f8919635c4928607450d9e0abb932109ceToomas Soome }
199767f8919635c4928607450d9e0abb932109ceToomas Soome
199767f8919635c4928607450d9e0abb932109ceToomas Soome return (FALSE);
199767f8919635c4928607450d9e0abb932109ceToomas Soome}
199767f8919635c4928607450d9e0abb932109ceToomas Soome
199767f8919635c4928607450d9e0abb932109ceToomas Soome/*
199767f8919635c4928607450d9e0abb932109ceToomas Soome * devpath_last returns the last non-path end node in devpath.
199767f8919635c4928607450d9e0abb932109ceToomas Soome */
199767f8919635c4928607450d9e0abb932109ceToomas Soomestatic EFI_DEVICE_PATH *
199767f8919635c4928607450d9e0abb932109ceToomas Soomedevpath_last(EFI_DEVICE_PATH *devpath)
199767f8919635c4928607450d9e0abb932109ceToomas Soome{
199767f8919635c4928607450d9e0abb932109ceToomas Soome
199767f8919635c4928607450d9e0abb932109ceToomas Soome while (!IsDevicePathEnd(NextDevicePathNode(devpath)))
199767f8919635c4928607450d9e0abb932109ceToomas Soome devpath = NextDevicePathNode(devpath);
199767f8919635c4928607450d9e0abb932109ceToomas Soome
199767f8919635c4928607450d9e0abb932109ceToomas Soome return (devpath);
199767f8919635c4928607450d9e0abb932109ceToomas Soome}
199767f8919635c4928607450d9e0abb932109ceToomas Soome
199767f8919635c4928607450d9e0abb932109ceToomas Soome/*
199767f8919635c4928607450d9e0abb932109ceToomas Soome * devpath_node_str is a basic output method for a devpath node which
199767f8919635c4928607450d9e0abb932109ceToomas Soome * only understands a subset of the available sub types.
199767f8919635c4928607450d9e0abb932109ceToomas Soome *
199767f8919635c4928607450d9e0abb932109ceToomas Soome * If we switch to UEFI 2.x then we should update it to use:
199767f8919635c4928607450d9e0abb932109ceToomas Soome * EFI_DEVICE_PATH_TO_TEXT_PROTOCOL.
199767f8919635c4928607450d9e0abb932109ceToomas Soome */
199767f8919635c4928607450d9e0abb932109ceToomas Soomestatic int
199767f8919635c4928607450d9e0abb932109ceToomas Soomedevpath_node_str(char *buf, size_t size, EFI_DEVICE_PATH *devpath)
199767f8919635c4928607450d9e0abb932109ceToomas Soome{
199767f8919635c4928607450d9e0abb932109ceToomas Soome
199767f8919635c4928607450d9e0abb932109ceToomas Soome switch (devpath->Type) {
199767f8919635c4928607450d9e0abb932109ceToomas Soome case MESSAGING_DEVICE_PATH:
199767f8919635c4928607450d9e0abb932109ceToomas Soome switch (devpath->SubType) {
199767f8919635c4928607450d9e0abb932109ceToomas Soome case MSG_ATAPI_DP: {
199767f8919635c4928607450d9e0abb932109ceToomas Soome ATAPI_DEVICE_PATH *atapi;
199767f8919635c4928607450d9e0abb932109ceToomas Soome
199767f8919635c4928607450d9e0abb932109ceToomas Soome atapi = (ATAPI_DEVICE_PATH *)(void *)devpath;
199767f8919635c4928607450d9e0abb932109ceToomas Soome return snprintf(buf, size, "ata(%s,%s,0x%x)",
199767f8919635c4928607450d9e0abb932109ceToomas Soome (atapi->PrimarySecondary == 1) ? "Sec" : "Pri",
199767f8919635c4928607450d9e0abb932109ceToomas Soome (atapi->SlaveMaster == 1) ? "Slave" : "Master",
199767f8919635c4928607450d9e0abb932109ceToomas Soome atapi->Lun);
199767f8919635c4928607450d9e0abb932109ceToomas Soome }
199767f8919635c4928607450d9e0abb932109ceToomas Soome case MSG_USB_DP: {
199767f8919635c4928607450d9e0abb932109ceToomas Soome USB_DEVICE_PATH *usb;
199767f8919635c4928607450d9e0abb932109ceToomas Soome
199767f8919635c4928607450d9e0abb932109ceToomas Soome usb = (USB_DEVICE_PATH *)devpath;
199767f8919635c4928607450d9e0abb932109ceToomas Soome return snprintf(buf, size, "usb(0x%02x,0x%02x)",
199767f8919635c4928607450d9e0abb932109ceToomas Soome usb->ParentPortNumber, usb->InterfaceNumber);
199767f8919635c4928607450d9e0abb932109ceToomas Soome }
199767f8919635c4928607450d9e0abb932109ceToomas Soome case MSG_SCSI_DP: {
199767f8919635c4928607450d9e0abb932109ceToomas Soome SCSI_DEVICE_PATH *scsi;
199767f8919635c4928607450d9e0abb932109ceToomas Soome
199767f8919635c4928607450d9e0abb932109ceToomas Soome scsi = (SCSI_DEVICE_PATH *)(void *)devpath;
199767f8919635c4928607450d9e0abb932109ceToomas Soome return snprintf(buf, size, "scsi(0x%02x,0x%02x)",
199767f8919635c4928607450d9e0abb932109ceToomas Soome scsi->Pun, scsi->Lun);
199767f8919635c4928607450d9e0abb932109ceToomas Soome }
199767f8919635c4928607450d9e0abb932109ceToomas Soome case MSG_SATA_DP: {
199767f8919635c4928607450d9e0abb932109ceToomas Soome SATA_DEVICE_PATH *sata;
199767f8919635c4928607450d9e0abb932109ceToomas Soome
199767f8919635c4928607450d9e0abb932109ceToomas Soome sata = (SATA_DEVICE_PATH *)(void *)devpath;
199767f8919635c4928607450d9e0abb932109ceToomas Soome return snprintf(buf, size, "sata(0x%x,0x%x,0x%x)",
199767f8919635c4928607450d9e0abb932109ceToomas Soome sata->HBAPortNumber, sata->PortMultiplierPortNumber,
199767f8919635c4928607450d9e0abb932109ceToomas Soome sata->Lun);
199767f8919635c4928607450d9e0abb932109ceToomas Soome }
199767f8919635c4928607450d9e0abb932109ceToomas Soome default:
199767f8919635c4928607450d9e0abb932109ceToomas Soome return snprintf(buf, size, "msg(0x%02x)",
199767f8919635c4928607450d9e0abb932109ceToomas Soome devpath->SubType);
199767f8919635c4928607450d9e0abb932109ceToomas Soome }
199767f8919635c4928607450d9e0abb932109ceToomas Soome break;
199767f8919635c4928607450d9e0abb932109ceToomas Soome case HARDWARE_DEVICE_PATH:
199767f8919635c4928607450d9e0abb932109ceToomas Soome switch (devpath->SubType) {
199767f8919635c4928607450d9e0abb932109ceToomas Soome case HW_PCI_DP: {
199767f8919635c4928607450d9e0abb932109ceToomas Soome PCI_DEVICE_PATH *pci;
199767f8919635c4928607450d9e0abb932109ceToomas Soome
199767f8919635c4928607450d9e0abb932109ceToomas Soome pci = (PCI_DEVICE_PATH *)devpath;
199767f8919635c4928607450d9e0abb932109ceToomas Soome return snprintf(buf, size, "pci(0x%02x,0x%02x)",
199767f8919635c4928607450d9e0abb932109ceToomas Soome pci->Device, pci->Function);
199767f8919635c4928607450d9e0abb932109ceToomas Soome }
199767f8919635c4928607450d9e0abb932109ceToomas Soome default:
199767f8919635c4928607450d9e0abb932109ceToomas Soome return snprintf(buf, size, "hw(0x%02x)",
199767f8919635c4928607450d9e0abb932109ceToomas Soome devpath->SubType);
199767f8919635c4928607450d9e0abb932109ceToomas Soome }
199767f8919635c4928607450d9e0abb932109ceToomas Soome break;
199767f8919635c4928607450d9e0abb932109ceToomas Soome case ACPI_DEVICE_PATH: {
199767f8919635c4928607450d9e0abb932109ceToomas Soome ACPI_HID_DEVICE_PATH *acpi;
199767f8919635c4928607450d9e0abb932109ceToomas Soome
199767f8919635c4928607450d9e0abb932109ceToomas Soome acpi = (ACPI_HID_DEVICE_PATH *)(void *)devpath;
199767f8919635c4928607450d9e0abb932109ceToomas Soome if ((acpi->HID & PNP_EISA_ID_MASK) == PNP_EISA_ID_CONST) {
199767f8919635c4928607450d9e0abb932109ceToomas Soome switch (EISA_ID_TO_NUM(acpi->HID)) {
199767f8919635c4928607450d9e0abb932109ceToomas Soome case 0x0a03:
199767f8919635c4928607450d9e0abb932109ceToomas Soome return snprintf(buf, size, "pciroot(0x%x)",
199767f8919635c4928607450d9e0abb932109ceToomas Soome acpi->UID);
199767f8919635c4928607450d9e0abb932109ceToomas Soome case 0x0a08:
199767f8919635c4928607450d9e0abb932109ceToomas Soome return snprintf(buf, size, "pcieroot(0x%x)",
199767f8919635c4928607450d9e0abb932109ceToomas Soome acpi->UID);
199767f8919635c4928607450d9e0abb932109ceToomas Soome case 0x0604:
199767f8919635c4928607450d9e0abb932109ceToomas Soome return snprintf(buf, size, "floppy(0x%x)",
199767f8919635c4928607450d9e0abb932109ceToomas Soome acpi->UID);
199767f8919635c4928607450d9e0abb932109ceToomas Soome case 0x0301:
199767f8919635c4928607450d9e0abb932109ceToomas Soome return snprintf(buf, size, "keyboard(0x%x)",
199767f8919635c4928607450d9e0abb932109ceToomas Soome acpi->UID);
199767f8919635c4928607450d9e0abb932109ceToomas Soome case 0x0501:
199767f8919635c4928607450d9e0abb932109ceToomas Soome return snprintf(buf, size, "serial(0x%x)",
199767f8919635c4928607450d9e0abb932109ceToomas Soome acpi->UID);
199767f8919635c4928607450d9e0abb932109ceToomas Soome case 0x0401:
199767f8919635c4928607450d9e0abb932109ceToomas Soome return snprintf(buf, size, "parallelport(0x%x)",
199767f8919635c4928607450d9e0abb932109ceToomas Soome acpi->UID);
199767f8919635c4928607450d9e0abb932109ceToomas Soome default:
199767f8919635c4928607450d9e0abb932109ceToomas Soome return snprintf(buf, size, "acpi(pnp%04x,0x%x)",
199767f8919635c4928607450d9e0abb932109ceToomas Soome EISA_ID_TO_NUM(acpi->HID), acpi->UID);
199767f8919635c4928607450d9e0abb932109ceToomas Soome }
199767f8919635c4928607450d9e0abb932109ceToomas Soome }
199767f8919635c4928607450d9e0abb932109ceToomas Soome
199767f8919635c4928607450d9e0abb932109ceToomas Soome return snprintf(buf, size, "acpi(0x%08x,0x%x)", acpi->HID,
199767f8919635c4928607450d9e0abb932109ceToomas Soome acpi->UID);
199767f8919635c4928607450d9e0abb932109ceToomas Soome }
199767f8919635c4928607450d9e0abb932109ceToomas Soome case MEDIA_DEVICE_PATH:
199767f8919635c4928607450d9e0abb932109ceToomas Soome switch (devpath->SubType) {
199767f8919635c4928607450d9e0abb932109ceToomas Soome case MEDIA_CDROM_DP: {
199767f8919635c4928607450d9e0abb932109ceToomas Soome CDROM_DEVICE_PATH *cdrom;
199767f8919635c4928607450d9e0abb932109ceToomas Soome
199767f8919635c4928607450d9e0abb932109ceToomas Soome cdrom = (CDROM_DEVICE_PATH *)(void *)devpath;
199767f8919635c4928607450d9e0abb932109ceToomas Soome return snprintf(buf, size, "cdrom(%x)",
199767f8919635c4928607450d9e0abb932109ceToomas Soome cdrom->BootEntry);
199767f8919635c4928607450d9e0abb932109ceToomas Soome }
199767f8919635c4928607450d9e0abb932109ceToomas Soome case MEDIA_HARDDRIVE_DP: {
199767f8919635c4928607450d9e0abb932109ceToomas Soome HARDDRIVE_DEVICE_PATH *hd;
199767f8919635c4928607450d9e0abb932109ceToomas Soome
199767f8919635c4928607450d9e0abb932109ceToomas Soome hd = (HARDDRIVE_DEVICE_PATH *)(void *)devpath;
199767f8919635c4928607450d9e0abb932109ceToomas Soome return snprintf(buf, size, "hd(%x)",
199767f8919635c4928607450d9e0abb932109ceToomas Soome hd->PartitionNumber);
199767f8919635c4928607450d9e0abb932109ceToomas Soome }
199767f8919635c4928607450d9e0abb932109ceToomas Soome default:
199767f8919635c4928607450d9e0abb932109ceToomas Soome return snprintf(buf, size, "media(0x%02x)",
199767f8919635c4928607450d9e0abb932109ceToomas Soome devpath->SubType);
199767f8919635c4928607450d9e0abb932109ceToomas Soome }
199767f8919635c4928607450d9e0abb932109ceToomas Soome case BBS_DEVICE_PATH:
199767f8919635c4928607450d9e0abb932109ceToomas Soome return snprintf(buf, size, "bbs(0x%02x)", devpath->SubType);
199767f8919635c4928607450d9e0abb932109ceToomas Soome case END_DEVICE_PATH_TYPE:
199767f8919635c4928607450d9e0abb932109ceToomas Soome return (0);
199767f8919635c4928607450d9e0abb932109ceToomas Soome }
199767f8919635c4928607450d9e0abb932109ceToomas Soome
199767f8919635c4928607450d9e0abb932109ceToomas Soome return snprintf(buf, size, "type(0x%02x, 0x%02x)", devpath->Type,
199767f8919635c4928607450d9e0abb932109ceToomas Soome devpath->SubType);
199767f8919635c4928607450d9e0abb932109ceToomas Soome}
199767f8919635c4928607450d9e0abb932109ceToomas Soome
199767f8919635c4928607450d9e0abb932109ceToomas Soome/*
199767f8919635c4928607450d9e0abb932109ceToomas Soome * devpath_strlcat appends a text description of devpath to buf but not more
199767f8919635c4928607450d9e0abb932109ceToomas Soome * than size - 1 characters followed by NUL-terminator.
199767f8919635c4928607450d9e0abb932109ceToomas Soome */
199767f8919635c4928607450d9e0abb932109ceToomas Soomeint
199767f8919635c4928607450d9e0abb932109ceToomas Soomedevpath_strlcat(char *buf, size_t size, EFI_DEVICE_PATH *devpath)
199767f8919635c4928607450d9e0abb932109ceToomas Soome{
199767f8919635c4928607450d9e0abb932109ceToomas Soome size_t len, used;
199767f8919635c4928607450d9e0abb932109ceToomas Soome const char *sep;
199767f8919635c4928607450d9e0abb932109ceToomas Soome
199767f8919635c4928607450d9e0abb932109ceToomas Soome sep = "";
199767f8919635c4928607450d9e0abb932109ceToomas Soome used = 0;
199767f8919635c4928607450d9e0abb932109ceToomas Soome while (!IsDevicePathEnd(devpath)) {
199767f8919635c4928607450d9e0abb932109ceToomas Soome len = snprintf(buf, size - used, "%s", sep);
199767f8919635c4928607450d9e0abb932109ceToomas Soome used += len;
199767f8919635c4928607450d9e0abb932109ceToomas Soome if (used > size)
199767f8919635c4928607450d9e0abb932109ceToomas Soome return (used);
199767f8919635c4928607450d9e0abb932109ceToomas Soome buf += len;
199767f8919635c4928607450d9e0abb932109ceToomas Soome
199767f8919635c4928607450d9e0abb932109ceToomas Soome len = devpath_node_str(buf, size - used, devpath);
199767f8919635c4928607450d9e0abb932109ceToomas Soome used += len;
199767f8919635c4928607450d9e0abb932109ceToomas Soome if (used > size)
199767f8919635c4928607450d9e0abb932109ceToomas Soome return (used);
199767f8919635c4928607450d9e0abb932109ceToomas Soome buf += len;
199767f8919635c4928607450d9e0abb932109ceToomas Soome devpath = NextDevicePathNode(devpath);
199767f8919635c4928607450d9e0abb932109ceToomas Soome sep = ":";
199767f8919635c4928607450d9e0abb932109ceToomas Soome }
199767f8919635c4928607450d9e0abb932109ceToomas Soome
199767f8919635c4928607450d9e0abb932109ceToomas Soome return (used);
199767f8919635c4928607450d9e0abb932109ceToomas Soome}
199767f8919635c4928607450d9e0abb932109ceToomas Soome
199767f8919635c4928607450d9e0abb932109ceToomas Soome/*
199767f8919635c4928607450d9e0abb932109ceToomas Soome * devpath_str is convenience method which returns the text description of
199767f8919635c4928607450d9e0abb932109ceToomas Soome * devpath using a static buffer, so it isn't thread safe!
199767f8919635c4928607450d9e0abb932109ceToomas Soome */
199767f8919635c4928607450d9e0abb932109ceToomas Soomechar *
199767f8919635c4928607450d9e0abb932109ceToomas Soomedevpath_str(EFI_DEVICE_PATH *devpath)
199767f8919635c4928607450d9e0abb932109ceToomas Soome{
199767f8919635c4928607450d9e0abb932109ceToomas Soome static char buf[256];
199767f8919635c4928607450d9e0abb932109ceToomas Soome
199767f8919635c4928607450d9e0abb932109ceToomas Soome devpath_strlcat(buf, sizeof(buf), devpath);
199767f8919635c4928607450d9e0abb932109ceToomas Soome
199767f8919635c4928607450d9e0abb932109ceToomas Soome return buf;
199767f8919635c4928607450d9e0abb932109ceToomas Soome}
199767f8919635c4928607450d9e0abb932109ceToomas Soome
199767f8919635c4928607450d9e0abb932109ceToomas Soome/*
199767f8919635c4928607450d9e0abb932109ceToomas Soome * load_loader attempts to load the loader image data.
199767f8919635c4928607450d9e0abb932109ceToomas Soome *
199767f8919635c4928607450d9e0abb932109ceToomas Soome * It tries each module and its respective devices, identified by mod->probe,
199767f8919635c4928607450d9e0abb932109ceToomas Soome * in order until a successful load occurs at which point it returns EFI_SUCCESS
199767f8919635c4928607450d9e0abb932109ceToomas Soome * and EFI_NOT_FOUND otherwise.
199767f8919635c4928607450d9e0abb932109ceToomas Soome *
199767f8919635c4928607450d9e0abb932109ceToomas Soome * Only devices which have preferred matching the preferred parameter are tried.
199767f8919635c4928607450d9e0abb932109ceToomas Soome */
199767f8919635c4928607450d9e0abb932109ceToomas Soomestatic EFI_STATUS
199767f8919635c4928607450d9e0abb932109ceToomas Soomeload_loader(const boot_module_t **modp, dev_info_t **devinfop, void **bufp,
199767f8919635c4928607450d9e0abb932109ceToomas Soome size_t *bufsize, BOOLEAN preferred)
199767f8919635c4928607450d9e0abb932109ceToomas Soome{
199767f8919635c4928607450d9e0abb932109ceToomas Soome UINTN i;
199767f8919635c4928607450d9e0abb932109ceToomas Soome dev_info_t *dev;
199767f8919635c4928607450d9e0abb932109ceToomas Soome const boot_module_t *mod;
199767f8919635c4928607450d9e0abb932109ceToomas Soome
199767f8919635c4928607450d9e0abb932109ceToomas Soome for (i = 0; i < NUM_BOOT_MODULES; i++) {
199767f8919635c4928607450d9e0abb932109ceToomas Soome if (boot_modules[i] == NULL)
199767f8919635c4928607450d9e0abb932109ceToomas Soome continue;
199767f8919635c4928607450d9e0abb932109ceToomas Soome mod = boot_modules[i];
199767f8919635c4928607450d9e0abb932109ceToomas Soome for (dev = mod->devices(); dev != NULL; dev = dev->next) {
199767f8919635c4928607450d9e0abb932109ceToomas Soome if (dev->preferred != preferred)
199767f8919635c4928607450d9e0abb932109ceToomas Soome continue;
199767f8919635c4928607450d9e0abb932109ceToomas Soome
199767f8919635c4928607450d9e0abb932109ceToomas Soome if (mod->load(PATH_LOADER_EFI, dev, bufp, bufsize) ==
199767f8919635c4928607450d9e0abb932109ceToomas Soome EFI_SUCCESS) {
199767f8919635c4928607450d9e0abb932109ceToomas Soome *devinfop = dev;
199767f8919635c4928607450d9e0abb932109ceToomas Soome *modp = mod;
199767f8919635c4928607450d9e0abb932109ceToomas Soome return (EFI_SUCCESS);
199767f8919635c4928607450d9e0abb932109ceToomas Soome }
199767f8919635c4928607450d9e0abb932109ceToomas Soome }
199767f8919635c4928607450d9e0abb932109ceToomas Soome }
199767f8919635c4928607450d9e0abb932109ceToomas Soome
199767f8919635c4928607450d9e0abb932109ceToomas Soome return (EFI_NOT_FOUND);
199767f8919635c4928607450d9e0abb932109ceToomas Soome}
199767f8919635c4928607450d9e0abb932109ceToomas Soome
199767f8919635c4928607450d9e0abb932109ceToomas Soome/*
199767f8919635c4928607450d9e0abb932109ceToomas Soome * try_boot only returns if it fails to load the loader. If it succeeds
199767f8919635c4928607450d9e0abb932109ceToomas Soome * it simply boots, otherwise it returns the status of last EFI call.
199767f8919635c4928607450d9e0abb932109ceToomas Soome */
199767f8919635c4928607450d9e0abb932109ceToomas Soomestatic EFI_STATUS
199767f8919635c4928607450d9e0abb932109ceToomas Soometry_boot(void)
199767f8919635c4928607450d9e0abb932109ceToomas Soome{
199767f8919635c4928607450d9e0abb932109ceToomas Soome size_t bufsize, loadersize, cmdsize;
199767f8919635c4928607450d9e0abb932109ceToomas Soome void *buf, *loaderbuf;
199767f8919635c4928607450d9e0abb932109ceToomas Soome char *cmd;
199767f8919635c4928607450d9e0abb932109ceToomas Soome dev_info_t *dev;
199767f8919635c4928607450d9e0abb932109ceToomas Soome const boot_module_t *mod;
199767f8919635c4928607450d9e0abb932109ceToomas Soome EFI_HANDLE loaderhandle;
199767f8919635c4928607450d9e0abb932109ceToomas Soome EFI_LOADED_IMAGE *loaded_image;
199767f8919635c4928607450d9e0abb932109ceToomas Soome EFI_STATUS status;
199767f8919635c4928607450d9e0abb932109ceToomas Soome
199767f8919635c4928607450d9e0abb932109ceToomas Soome status = load_loader(&mod, &dev, &loaderbuf, &loadersize, TRUE);
199767f8919635c4928607450d9e0abb932109ceToomas Soome if (status != EFI_SUCCESS) {
199767f8919635c4928607450d9e0abb932109ceToomas Soome status = load_loader(&mod, &dev, &loaderbuf, &loadersize,
199767f8919635c4928607450d9e0abb932109ceToomas Soome FALSE);
199767f8919635c4928607450d9e0abb932109ceToomas Soome if (status != EFI_SUCCESS) {
199767f8919635c4928607450d9e0abb932109ceToomas Soome printf("Failed to load '%s'\n", PATH_LOADER_EFI);
199767f8919635c4928607450d9e0abb932109ceToomas Soome return (status);
199767f8919635c4928607450d9e0abb932109ceToomas Soome }
199767f8919635c4928607450d9e0abb932109ceToomas Soome }
199767f8919635c4928607450d9e0abb932109ceToomas Soome
199767f8919635c4928607450d9e0abb932109ceToomas Soome /*
199767f8919635c4928607450d9e0abb932109ceToomas Soome * Read in and parse the command line from /boot.config or /boot/config,
199767f8919635c4928607450d9e0abb932109ceToomas Soome * if present. We'll pass it the next stage via a simple ASCII
199767f8919635c4928607450d9e0abb932109ceToomas Soome * string. loader.efi has a hack for ASCII strings, so we'll use that to
199767f8919635c4928607450d9e0abb932109ceToomas Soome * keep the size down here. We only try to read the alternate file if
199767f8919635c4928607450d9e0abb932109ceToomas Soome * we get EFI_NOT_FOUND because all other errors mean that the boot_module
199767f8919635c4928607450d9e0abb932109ceToomas Soome * had troubles with the filesystem. We could return early, but we'll let
199767f8919635c4928607450d9e0abb932109ceToomas Soome * loading the actual kernel sort all that out. Since these files are
199767f8919635c4928607450d9e0abb932109ceToomas Soome * optional, we don't report errors in trying to read them.
199767f8919635c4928607450d9e0abb932109ceToomas Soome */
199767f8919635c4928607450d9e0abb932109ceToomas Soome cmd = NULL;
199767f8919635c4928607450d9e0abb932109ceToomas Soome cmdsize = 0;
199767f8919635c4928607450d9e0abb932109ceToomas Soome status = mod->load(PATH_DOTCONFIG, dev, &buf, &bufsize);
199767f8919635c4928607450d9e0abb932109ceToomas Soome if (status == EFI_NOT_FOUND)
199767f8919635c4928607450d9e0abb932109ceToomas Soome status = mod->load(PATH_CONFIG, dev, &buf, &bufsize);
199767f8919635c4928607450d9e0abb932109ceToomas Soome if (status == EFI_SUCCESS) {
199767f8919635c4928607450d9e0abb932109ceToomas Soome cmdsize = bufsize + 1;
199767f8919635c4928607450d9e0abb932109ceToomas Soome cmd = malloc(cmdsize);
199767f8919635c4928607450d9e0abb932109ceToomas Soome if (cmd == NULL)
199767f8919635c4928607450d9e0abb932109ceToomas Soome goto errout;
199767f8919635c4928607450d9e0abb932109ceToomas Soome memcpy(cmd, buf, bufsize);
199767f8919635c4928607450d9e0abb932109ceToomas Soome cmd[bufsize] = '\0';
199767f8919635c4928607450d9e0abb932109ceToomas Soome free(buf);
199767f8919635c4928607450d9e0abb932109ceToomas Soome buf = NULL;
199767f8919635c4928607450d9e0abb932109ceToomas Soome }
199767f8919635c4928607450d9e0abb932109ceToomas Soome
199767f8919635c4928607450d9e0abb932109ceToomas Soome if ((status = bs->LoadImage(TRUE, image, devpath_last(dev->devpath),
199767f8919635c4928607450d9e0abb932109ceToomas Soome loaderbuf, loadersize, &loaderhandle)) != EFI_SUCCESS) {
199767f8919635c4928607450d9e0abb932109ceToomas Soome printf("Failed to load image provided by %s, size: %zu, (%lu)\n",
f4fb84c03b3f4c46dab36872e953dd3c27317c3aToomas Soome mod->name, loadersize, EFI_ERROR_CODE(status));
199767f8919635c4928607450d9e0abb932109ceToomas Soome goto errout;
199767f8919635c4928607450d9e0abb932109ceToomas Soome }
199767f8919635c4928607450d9e0abb932109ceToomas Soome
199767f8919635c4928607450d9e0abb932109ceToomas Soome if ((status = bs->HandleProtocol(loaderhandle, &LoadedImageGUID,
199767f8919635c4928607450d9e0abb932109ceToomas Soome (VOID**)&loaded_image)) != EFI_SUCCESS) {
199767f8919635c4928607450d9e0abb932109ceToomas Soome printf("Failed to query LoadedImage provided by %s (%lu)\n",
199767f8919635c4928607450d9e0abb932109ceToomas Soome mod->name, EFI_ERROR_CODE(status));
199767f8919635c4928607450d9e0abb932109ceToomas Soome goto errout;
199767f8919635c4928607450d9e0abb932109ceToomas Soome }
199767f8919635c4928607450d9e0abb932109ceToomas Soome
199767f8919635c4928607450d9e0abb932109ceToomas Soome if (cmd != NULL)
199767f8919635c4928607450d9e0abb932109ceToomas Soome printf(" command args: %s\n", cmd);
199767f8919635c4928607450d9e0abb932109ceToomas Soome
199767f8919635c4928607450d9e0abb932109ceToomas Soome loaded_image->DeviceHandle = dev->devhandle;
199767f8919635c4928607450d9e0abb932109ceToomas Soome loaded_image->LoadOptionsSize = cmdsize;
199767f8919635c4928607450d9e0abb932109ceToomas Soome loaded_image->LoadOptions = cmd;
199767f8919635c4928607450d9e0abb932109ceToomas Soome
199767f8919635c4928607450d9e0abb932109ceToomas Soome DPRINTF("Starting '%s' in 5 seconds...", PATH_LOADER_EFI);
199767f8919635c4928607450d9e0abb932109ceToomas Soome DSTALL(1000000);
199767f8919635c4928607450d9e0abb932109ceToomas Soome DPRINTF(".");
199767f8919635c4928607450d9e0abb932109ceToomas Soome DSTALL(1000000);
199767f8919635c4928607450d9e0abb932109ceToomas Soome DPRINTF(".");
199767f8919635c4928607450d9e0abb932109ceToomas Soome DSTALL(1000000);
199767f8919635c4928607450d9e0abb932109ceToomas Soome DPRINTF(".");
199767f8919635c4928607450d9e0abb932109ceToomas Soome DSTALL(1000000);
199767f8919635c4928607450d9e0abb932109ceToomas Soome DPRINTF(".");
199767f8919635c4928607450d9e0abb932109ceToomas Soome DSTALL(1000000);
199767f8919635c4928607450d9e0abb932109ceToomas Soome DPRINTF(".\n");
199767f8919635c4928607450d9e0abb932109ceToomas Soome
199767f8919635c4928607450d9e0abb932109ceToomas Soome if ((status = bs->StartImage(loaderhandle, NULL, NULL)) !=
199767f8919635c4928607450d9e0abb932109ceToomas Soome EFI_SUCCESS) {
199767f8919635c4928607450d9e0abb932109ceToomas Soome printf("Failed to start image provided by %s (%lu)\n",
199767f8919635c4928607450d9e0abb932109ceToomas Soome mod->name, EFI_ERROR_CODE(status));
199767f8919635c4928607450d9e0abb932109ceToomas Soome loaded_image->LoadOptionsSize = 0;
199767f8919635c4928607450d9e0abb932109ceToomas Soome loaded_image->LoadOptions = NULL;
199767f8919635c4928607450d9e0abb932109ceToomas Soome }
199767f8919635c4928607450d9e0abb932109ceToomas Soome
199767f8919635c4928607450d9e0abb932109ceToomas Soomeerrout:
199767f8919635c4928607450d9e0abb932109ceToomas Soome if (cmd != NULL)
199767f8919635c4928607450d9e0abb932109ceToomas Soome free(cmd);
199767f8919635c4928607450d9e0abb932109ceToomas Soome if (buf != NULL)
199767f8919635c4928607450d9e0abb932109ceToomas Soome free(buf);
199767f8919635c4928607450d9e0abb932109ceToomas Soome if (loaderbuf != NULL)
199767f8919635c4928607450d9e0abb932109ceToomas Soome free(loaderbuf);
199767f8919635c4928607450d9e0abb932109ceToomas Soome
199767f8919635c4928607450d9e0abb932109ceToomas Soome return (status);
199767f8919635c4928607450d9e0abb932109ceToomas Soome}
199767f8919635c4928607450d9e0abb932109ceToomas Soome
199767f8919635c4928607450d9e0abb932109ceToomas Soome/*
199767f8919635c4928607450d9e0abb932109ceToomas Soome * probe_handle determines if the passed handle represents a logical partition
199767f8919635c4928607450d9e0abb932109ceToomas Soome * if it does it uses each module in order to probe it and if successful it
199767f8919635c4928607450d9e0abb932109ceToomas Soome * returns EFI_SUCCESS.
199767f8919635c4928607450d9e0abb932109ceToomas Soome */
199767f8919635c4928607450d9e0abb932109ceToomas Soomestatic EFI_STATUS
199767f8919635c4928607450d9e0abb932109ceToomas Soomeprobe_handle(EFI_HANDLE h, EFI_DEVICE_PATH *imgpath, BOOLEAN *preferred)
199767f8919635c4928607450d9e0abb932109ceToomas Soome{
199767f8919635c4928607450d9e0abb932109ceToomas Soome dev_info_t *devinfo;
199767f8919635c4928607450d9e0abb932109ceToomas Soome EFI_BLOCK_IO *blkio;
199767f8919635c4928607450d9e0abb932109ceToomas Soome EFI_DEVICE_PATH *devpath;
199767f8919635c4928607450d9e0abb932109ceToomas Soome EFI_STATUS status;
199767f8919635c4928607450d9e0abb932109ceToomas Soome UINTN i;
199767f8919635c4928607450d9e0abb932109ceToomas Soome
199767f8919635c4928607450d9e0abb932109ceToomas Soome /* Figure out if we're dealing with an actual partition. */
199767f8919635c4928607450d9e0abb932109ceToomas Soome status = bs->HandleProtocol(h, &DevicePathGUID, (void **)&devpath);
199767f8919635c4928607450d9e0abb932109ceToomas Soome if (status == EFI_UNSUPPORTED)
199767f8919635c4928607450d9e0abb932109ceToomas Soome return (status);
199767f8919635c4928607450d9e0abb932109ceToomas Soome
199767f8919635c4928607450d9e0abb932109ceToomas Soome if (status != EFI_SUCCESS) {
199767f8919635c4928607450d9e0abb932109ceToomas Soome DPRINTF("\nFailed to query DevicePath (%lu)\n",
199767f8919635c4928607450d9e0abb932109ceToomas Soome EFI_ERROR_CODE(status));
199767f8919635c4928607450d9e0abb932109ceToomas Soome return (status);
199767f8919635c4928607450d9e0abb932109ceToomas Soome }
199767f8919635c4928607450d9e0abb932109ceToomas Soome
199767f8919635c4928607450d9e0abb932109ceToomas Soome DPRINTF("probing: %s\n", devpath_str(devpath));
199767f8919635c4928607450d9e0abb932109ceToomas Soome
199767f8919635c4928607450d9e0abb932109ceToomas Soome status = bs->HandleProtocol(h, &BlockIoProtocolGUID, (void **)&blkio);
199767f8919635c4928607450d9e0abb932109ceToomas Soome if (status == EFI_UNSUPPORTED)
199767f8919635c4928607450d9e0abb932109ceToomas Soome return (status);
199767f8919635c4928607450d9e0abb932109ceToomas Soome
199767f8919635c4928607450d9e0abb932109ceToomas Soome if (status != EFI_SUCCESS) {
199767f8919635c4928607450d9e0abb932109ceToomas Soome DPRINTF("\nFailed to query BlockIoProtocol (%lu)\n",
199767f8919635c4928607450d9e0abb932109ceToomas Soome EFI_ERROR_CODE(status));
199767f8919635c4928607450d9e0abb932109ceToomas Soome return (status);
199767f8919635c4928607450d9e0abb932109ceToomas Soome }
199767f8919635c4928607450d9e0abb932109ceToomas Soome
199767f8919635c4928607450d9e0abb932109ceToomas Soome if (!blkio->Media->LogicalPartition)
199767f8919635c4928607450d9e0abb932109ceToomas Soome return (EFI_UNSUPPORTED);
199767f8919635c4928607450d9e0abb932109ceToomas Soome
199767f8919635c4928607450d9e0abb932109ceToomas Soome *preferred = device_paths_match(imgpath, devpath);
199767f8919635c4928607450d9e0abb932109ceToomas Soome
199767f8919635c4928607450d9e0abb932109ceToomas Soome /* Run through each module, see if it can load this partition */
199767f8919635c4928607450d9e0abb932109ceToomas Soome for (i = 0; i < NUM_BOOT_MODULES; i++) {
199767f8919635c4928607450d9e0abb932109ceToomas Soome if (boot_modules[i] == NULL)
199767f8919635c4928607450d9e0abb932109ceToomas Soome continue;
199767f8919635c4928607450d9e0abb932109ceToomas Soome
199767f8919635c4928607450d9e0abb932109ceToomas Soome if ((status = bs->AllocatePool(EfiLoaderData,
199767f8919635c4928607450d9e0abb932109ceToomas Soome sizeof(*devinfo), (void **)&devinfo)) !=
199767f8919635c4928607450d9e0abb932109ceToomas Soome EFI_SUCCESS) {
199767f8919635c4928607450d9e0abb932109ceToomas Soome DPRINTF("\nFailed to allocate devinfo (%lu)\n",
199767f8919635c4928607450d9e0abb932109ceToomas Soome EFI_ERROR_CODE(status));
199767f8919635c4928607450d9e0abb932109ceToomas Soome continue;
199767f8919635c4928607450d9e0abb932109ceToomas Soome }
199767f8919635c4928607450d9e0abb932109ceToomas Soome devinfo->dev = blkio;
199767f8919635c4928607450d9e0abb932109ceToomas Soome devinfo->devpath = devpath;
199767f8919635c4928607450d9e0abb932109ceToomas Soome devinfo->devhandle = h;
199767f8919635c4928607450d9e0abb932109ceToomas Soome devinfo->devdata = NULL;
199767f8919635c4928607450d9e0abb932109ceToomas Soome devinfo->preferred = *preferred;
199767f8919635c4928607450d9e0abb932109ceToomas Soome devinfo->next = NULL;
199767f8919635c4928607450d9e0abb932109ceToomas Soome
199767f8919635c4928607450d9e0abb932109ceToomas Soome status = boot_modules[i]->probe(devinfo);
199767f8919635c4928607450d9e0abb932109ceToomas Soome if (status == EFI_SUCCESS)
199767f8919635c4928607450d9e0abb932109ceToomas Soome return (EFI_SUCCESS);
199767f8919635c4928607450d9e0abb932109ceToomas Soome (void)bs->FreePool(devinfo);
199767f8919635c4928607450d9e0abb932109ceToomas Soome }
199767f8919635c4928607450d9e0abb932109ceToomas Soome
199767f8919635c4928607450d9e0abb932109ceToomas Soome return (EFI_UNSUPPORTED);
199767f8919635c4928607450d9e0abb932109ceToomas Soome}
199767f8919635c4928607450d9e0abb932109ceToomas Soome
199767f8919635c4928607450d9e0abb932109ceToomas Soome/*
199767f8919635c4928607450d9e0abb932109ceToomas Soome * probe_handle_status calls probe_handle and outputs the returned status
199767f8919635c4928607450d9e0abb932109ceToomas Soome * of the call.
199767f8919635c4928607450d9e0abb932109ceToomas Soome */
199767f8919635c4928607450d9e0abb932109ceToomas Soomestatic void
199767f8919635c4928607450d9e0abb932109ceToomas Soomeprobe_handle_status(EFI_HANDLE h, EFI_DEVICE_PATH *imgpath)
199767f8919635c4928607450d9e0abb932109ceToomas Soome{
199767f8919635c4928607450d9e0abb932109ceToomas Soome EFI_STATUS status;
199767f8919635c4928607450d9e0abb932109ceToomas Soome BOOLEAN preferred = false;
199767f8919635c4928607450d9e0abb932109ceToomas Soome
199767f8919635c4928607450d9e0abb932109ceToomas Soome status = probe_handle(h, imgpath, &preferred);
199767f8919635c4928607450d9e0abb932109ceToomas Soome
199767f8919635c4928607450d9e0abb932109ceToomas Soome DPRINTF("probe: ");
199767f8919635c4928607450d9e0abb932109ceToomas Soome switch (status) {
199767f8919635c4928607450d9e0abb932109ceToomas Soome case EFI_UNSUPPORTED:
199767f8919635c4928607450d9e0abb932109ceToomas Soome printf(".");
199767f8919635c4928607450d9e0abb932109ceToomas Soome DPRINTF(" not supported\n");
199767f8919635c4928607450d9e0abb932109ceToomas Soome break;
199767f8919635c4928607450d9e0abb932109ceToomas Soome case EFI_SUCCESS:
199767f8919635c4928607450d9e0abb932109ceToomas Soome if (preferred) {
199767f8919635c4928607450d9e0abb932109ceToomas Soome printf("%c", '*');
199767f8919635c4928607450d9e0abb932109ceToomas Soome DPRINTF(" supported (preferred)\n");
199767f8919635c4928607450d9e0abb932109ceToomas Soome } else {
199767f8919635c4928607450d9e0abb932109ceToomas Soome printf("%c", '+');
199767f8919635c4928607450d9e0abb932109ceToomas Soome DPRINTF(" supported\n");
199767f8919635c4928607450d9e0abb932109ceToomas Soome }
199767f8919635c4928607450d9e0abb932109ceToomas Soome break;
199767f8919635c4928607450d9e0abb932109ceToomas Soome default:
199767f8919635c4928607450d9e0abb932109ceToomas Soome printf("x");
199767f8919635c4928607450d9e0abb932109ceToomas Soome DPRINTF(" error (%lu)\n", EFI_ERROR_CODE(status));
199767f8919635c4928607450d9e0abb932109ceToomas Soome break;
199767f8919635c4928607450d9e0abb932109ceToomas Soome }
199767f8919635c4928607450d9e0abb932109ceToomas Soome DSTALL(500000);
199767f8919635c4928607450d9e0abb932109ceToomas Soome}
199767f8919635c4928607450d9e0abb932109ceToomas Soome
199767f8919635c4928607450d9e0abb932109ceToomas SoomeEFI_STATUS
199767f8919635c4928607450d9e0abb932109ceToomas Soomeefi_main(EFI_HANDLE Ximage, EFI_SYSTEM_TABLE *Xsystab)
199767f8919635c4928607450d9e0abb932109ceToomas Soome{
199767f8919635c4928607450d9e0abb932109ceToomas Soome EFI_HANDLE *handles;
199767f8919635c4928607450d9e0abb932109ceToomas Soome EFI_LOADED_IMAGE *img;
199767f8919635c4928607450d9e0abb932109ceToomas Soome EFI_DEVICE_PATH *imgpath;
199767f8919635c4928607450d9e0abb932109ceToomas Soome EFI_STATUS status;
199767f8919635c4928607450d9e0abb932109ceToomas Soome EFI_CONSOLE_CONTROL_PROTOCOL *ConsoleControl = NULL;
199767f8919635c4928607450d9e0abb932109ceToomas Soome SIMPLE_TEXT_OUTPUT_INTERFACE *conout = NULL;
199767f8919635c4928607450d9e0abb932109ceToomas Soome UINTN i, max_dim, best_mode, cols, rows, hsize, nhandles;
199767f8919635c4928607450d9e0abb932109ceToomas Soome
199767f8919635c4928607450d9e0abb932109ceToomas Soome /* Basic initialization*/
199767f8919635c4928607450d9e0abb932109ceToomas Soome systab = Xsystab;
199767f8919635c4928607450d9e0abb932109ceToomas Soome image = Ximage;
199767f8919635c4928607450d9e0abb932109ceToomas Soome bs = Xsystab->BootServices;
199767f8919635c4928607450d9e0abb932109ceToomas Soome
199767f8919635c4928607450d9e0abb932109ceToomas Soome /* Set up the console, so printf works. */
199767f8919635c4928607450d9e0abb932109ceToomas Soome status = bs->LocateProtocol(&ConsoleControlGUID, NULL,
199767f8919635c4928607450d9e0abb932109ceToomas Soome (VOID **)&ConsoleControl);
199767f8919635c4928607450d9e0abb932109ceToomas Soome if (status == EFI_SUCCESS)
199767f8919635c4928607450d9e0abb932109ceToomas Soome (void)ConsoleControl->SetMode(ConsoleControl,
199767f8919635c4928607450d9e0abb932109ceToomas Soome EfiConsoleControlScreenText);
199767f8919635c4928607450d9e0abb932109ceToomas Soome /*
199767f8919635c4928607450d9e0abb932109ceToomas Soome * Reset the console and find the best text mode.
199767f8919635c4928607450d9e0abb932109ceToomas Soome */
199767f8919635c4928607450d9e0abb932109ceToomas Soome conout = systab->ConOut;
199767f8919635c4928607450d9e0abb932109ceToomas Soome conout->Reset(conout, TRUE);
199767f8919635c4928607450d9e0abb932109ceToomas Soome max_dim = best_mode = 0;
199767f8919635c4928607450d9e0abb932109ceToomas Soome for (i = 0; ; i++) {
199767f8919635c4928607450d9e0abb932109ceToomas Soome status = conout->QueryMode(conout, i, &cols, &rows);
199767f8919635c4928607450d9e0abb932109ceToomas Soome if (EFI_ERROR(status))
199767f8919635c4928607450d9e0abb932109ceToomas Soome break;
199767f8919635c4928607450d9e0abb932109ceToomas Soome if (cols * rows > max_dim) {
199767f8919635c4928607450d9e0abb932109ceToomas Soome max_dim = cols * rows;
199767f8919635c4928607450d9e0abb932109ceToomas Soome best_mode = i;
199767f8919635c4928607450d9e0abb932109ceToomas Soome }
199767f8919635c4928607450d9e0abb932109ceToomas Soome }
199767f8919635c4928607450d9e0abb932109ceToomas Soome if (max_dim > 0)
199767f8919635c4928607450d9e0abb932109ceToomas Soome conout->SetMode(conout, best_mode);
199767f8919635c4928607450d9e0abb932109ceToomas Soome conout->EnableCursor(conout, TRUE);
199767f8919635c4928607450d9e0abb932109ceToomas Soome conout->ClearScreen(conout);
199767f8919635c4928607450d9e0abb932109ceToomas Soome
199767f8919635c4928607450d9e0abb932109ceToomas Soome printf("\n>> illumos EFI boot block\n");
199767f8919635c4928607450d9e0abb932109ceToomas Soome printf(" Loader path: %s\n\n", PATH_LOADER_EFI);
199767f8919635c4928607450d9e0abb932109ceToomas Soome printf(" Initializing modules:");
199767f8919635c4928607450d9e0abb932109ceToomas Soome for (i = 0; i < NUM_BOOT_MODULES; i++) {
199767f8919635c4928607450d9e0abb932109ceToomas Soome if (boot_modules[i] == NULL)
199767f8919635c4928607450d9e0abb932109ceToomas Soome continue;
199767f8919635c4928607450d9e0abb932109ceToomas Soome
199767f8919635c4928607450d9e0abb932109ceToomas Soome printf(" %s", boot_modules[i]->name);
199767f8919635c4928607450d9e0abb932109ceToomas Soome if (boot_modules[i]->init != NULL)
199767f8919635c4928607450d9e0abb932109ceToomas Soome boot_modules[i]->init();
199767f8919635c4928607450d9e0abb932109ceToomas Soome }
199767f8919635c4928607450d9e0abb932109ceToomas Soome putchar('\n');
199767f8919635c4928607450d9e0abb932109ceToomas Soome
199767f8919635c4928607450d9e0abb932109ceToomas Soome /* Get all the device handles */
199767f8919635c4928607450d9e0abb932109ceToomas Soome hsize = (UINTN)NUM_HANDLES_INIT * sizeof(EFI_HANDLE);
199767f8919635c4928607450d9e0abb932109ceToomas Soome if ((status = bs->AllocatePool(EfiLoaderData, hsize, (void **)&handles))
199767f8919635c4928607450d9e0abb932109ceToomas Soome != EFI_SUCCESS)
199767f8919635c4928607450d9e0abb932109ceToomas Soome panic("Failed to allocate %d handles (%lu)", NUM_HANDLES_INIT,
199767f8919635c4928607450d9e0abb932109ceToomas Soome EFI_ERROR_CODE(status));
199767f8919635c4928607450d9e0abb932109ceToomas Soome
199767f8919635c4928607450d9e0abb932109ceToomas Soome status = bs->LocateHandle(ByProtocol, &BlockIoProtocolGUID, NULL,
199767f8919635c4928607450d9e0abb932109ceToomas Soome &hsize, handles);
199767f8919635c4928607450d9e0abb932109ceToomas Soome switch (status) {
199767f8919635c4928607450d9e0abb932109ceToomas Soome case EFI_SUCCESS:
199767f8919635c4928607450d9e0abb932109ceToomas Soome break;
199767f8919635c4928607450d9e0abb932109ceToomas Soome case EFI_BUFFER_TOO_SMALL:
199767f8919635c4928607450d9e0abb932109ceToomas Soome (void)bs->FreePool(handles);
199767f8919635c4928607450d9e0abb932109ceToomas Soome if ((status = bs->AllocatePool(EfiLoaderData, hsize,
199767f8919635c4928607450d9e0abb932109ceToomas Soome (void **)&handles) != EFI_SUCCESS)) {
199767f8919635c4928607450d9e0abb932109ceToomas Soome panic("Failed to allocate %zu handles (%lu)", hsize /
199767f8919635c4928607450d9e0abb932109ceToomas Soome sizeof(*handles), EFI_ERROR_CODE(status));
199767f8919635c4928607450d9e0abb932109ceToomas Soome }
199767f8919635c4928607450d9e0abb932109ceToomas Soome status = bs->LocateHandle(ByProtocol, &BlockIoProtocolGUID,
199767f8919635c4928607450d9e0abb932109ceToomas Soome NULL, &hsize, handles);
199767f8919635c4928607450d9e0abb932109ceToomas Soome if (status != EFI_SUCCESS)
199767f8919635c4928607450d9e0abb932109ceToomas Soome panic("Failed to get device handles (%lu)\n",
199767f8919635c4928607450d9e0abb932109ceToomas Soome EFI_ERROR_CODE(status));
199767f8919635c4928607450d9e0abb932109ceToomas Soome break;
199767f8919635c4928607450d9e0abb932109ceToomas Soome default:
199767f8919635c4928607450d9e0abb932109ceToomas Soome panic("Failed to get device handles (%lu)",
199767f8919635c4928607450d9e0abb932109ceToomas Soome EFI_ERROR_CODE(status));
199767f8919635c4928607450d9e0abb932109ceToomas Soome }
199767f8919635c4928607450d9e0abb932109ceToomas Soome
199767f8919635c4928607450d9e0abb932109ceToomas Soome /* Scan all partitions, probing with all modules. */
199767f8919635c4928607450d9e0abb932109ceToomas Soome nhandles = hsize / sizeof(*handles);
199767f8919635c4928607450d9e0abb932109ceToomas Soome printf(" Probing %zu block devices...", nhandles);
199767f8919635c4928607450d9e0abb932109ceToomas Soome DPRINTF("\n");
199767f8919635c4928607450d9e0abb932109ceToomas Soome
199767f8919635c4928607450d9e0abb932109ceToomas Soome /* Determine the devpath of our image so we can prefer it. */
199767f8919635c4928607450d9e0abb932109ceToomas Soome status = bs->HandleProtocol(image, &LoadedImageGUID, (VOID**)&img);
199767f8919635c4928607450d9e0abb932109ceToomas Soome imgpath = NULL;
199767f8919635c4928607450d9e0abb932109ceToomas Soome if (status == EFI_SUCCESS) {
199767f8919635c4928607450d9e0abb932109ceToomas Soome status = bs->HandleProtocol(img->DeviceHandle, &DevicePathGUID,
199767f8919635c4928607450d9e0abb932109ceToomas Soome (void **)&imgpath);
199767f8919635c4928607450d9e0abb932109ceToomas Soome if (status != EFI_SUCCESS)
199767f8919635c4928607450d9e0abb932109ceToomas Soome DPRINTF("Failed to get image DevicePath (%lu)\n",
199767f8919635c4928607450d9e0abb932109ceToomas Soome EFI_ERROR_CODE(status));
199767f8919635c4928607450d9e0abb932109ceToomas Soome DPRINTF("boot1 imagepath: %s\n", devpath_str(imgpath));
199767f8919635c4928607450d9e0abb932109ceToomas Soome }
199767f8919635c4928607450d9e0abb932109ceToomas Soome
199767f8919635c4928607450d9e0abb932109ceToomas Soome for (i = 0; i < nhandles; i++)
199767f8919635c4928607450d9e0abb932109ceToomas Soome probe_handle_status(handles[i], imgpath);
199767f8919635c4928607450d9e0abb932109ceToomas Soome printf(" done\n");
199767f8919635c4928607450d9e0abb932109ceToomas Soome
199767f8919635c4928607450d9e0abb932109ceToomas Soome /* Status summary. */
199767f8919635c4928607450d9e0abb932109ceToomas Soome for (i = 0; i < NUM_BOOT_MODULES; i++) {
199767f8919635c4928607450d9e0abb932109ceToomas Soome if (boot_modules[i] != NULL) {
199767f8919635c4928607450d9e0abb932109ceToomas Soome printf(" ");
199767f8919635c4928607450d9e0abb932109ceToomas Soome boot_modules[i]->status();
199767f8919635c4928607450d9e0abb932109ceToomas Soome }
199767f8919635c4928607450d9e0abb932109ceToomas Soome }
199767f8919635c4928607450d9e0abb932109ceToomas Soome
199767f8919635c4928607450d9e0abb932109ceToomas Soome try_boot();
199767f8919635c4928607450d9e0abb932109ceToomas Soome
199767f8919635c4928607450d9e0abb932109ceToomas Soome /* If we get here, we're out of luck... */
199767f8919635c4928607450d9e0abb932109ceToomas Soome panic("No bootable partitions found!");
199767f8919635c4928607450d9e0abb932109ceToomas Soome}
199767f8919635c4928607450d9e0abb932109ceToomas Soome
199767f8919635c4928607450d9e0abb932109ceToomas Soome/*
199767f8919635c4928607450d9e0abb932109ceToomas Soome * add_device adds a device to the passed devinfo list.
199767f8919635c4928607450d9e0abb932109ceToomas Soome */
199767f8919635c4928607450d9e0abb932109ceToomas Soomevoid
199767f8919635c4928607450d9e0abb932109ceToomas Soomeadd_device(dev_info_t **devinfop, dev_info_t *devinfo)
199767f8919635c4928607450d9e0abb932109ceToomas Soome{
199767f8919635c4928607450d9e0abb932109ceToomas Soome dev_info_t *dev;
199767f8919635c4928607450d9e0abb932109ceToomas Soome
199767f8919635c4928607450d9e0abb932109ceToomas Soome if (*devinfop == NULL) {
199767f8919635c4928607450d9e0abb932109ceToomas Soome *devinfop = devinfo;
199767f8919635c4928607450d9e0abb932109ceToomas Soome return;
199767f8919635c4928607450d9e0abb932109ceToomas Soome }
199767f8919635c4928607450d9e0abb932109ceToomas Soome
199767f8919635c4928607450d9e0abb932109ceToomas Soome for (dev = *devinfop; dev->next != NULL; dev = dev->next)
199767f8919635c4928607450d9e0abb932109ceToomas Soome ;
199767f8919635c4928607450d9e0abb932109ceToomas Soome
199767f8919635c4928607450d9e0abb932109ceToomas Soome dev->next = devinfo;
199767f8919635c4928607450d9e0abb932109ceToomas Soome}
199767f8919635c4928607450d9e0abb932109ceToomas Soome
199767f8919635c4928607450d9e0abb932109ceToomas Soomevoid
199767f8919635c4928607450d9e0abb932109ceToomas Soomepanic(const char *fmt, ...)
199767f8919635c4928607450d9e0abb932109ceToomas Soome{
199767f8919635c4928607450d9e0abb932109ceToomas Soome va_list ap;
199767f8919635c4928607450d9e0abb932109ceToomas Soome
199767f8919635c4928607450d9e0abb932109ceToomas Soome printf("panic: ");
199767f8919635c4928607450d9e0abb932109ceToomas Soome va_start(ap, fmt);
199767f8919635c4928607450d9e0abb932109ceToomas Soome vprintf(fmt, ap);
199767f8919635c4928607450d9e0abb932109ceToomas Soome va_end(ap);
199767f8919635c4928607450d9e0abb932109ceToomas Soome printf("\n");
199767f8919635c4928607450d9e0abb932109ceToomas Soome
199767f8919635c4928607450d9e0abb932109ceToomas Soome while (1) {}
199767f8919635c4928607450d9e0abb932109ceToomas Soome}
199767f8919635c4928607450d9e0abb932109ceToomas Soome
199767f8919635c4928607450d9e0abb932109ceToomas Soomevoid
199767f8919635c4928607450d9e0abb932109ceToomas Soomeputchar(int c)
199767f8919635c4928607450d9e0abb932109ceToomas Soome{
199767f8919635c4928607450d9e0abb932109ceToomas Soome CHAR16 buf[2];
199767f8919635c4928607450d9e0abb932109ceToomas Soome
199767f8919635c4928607450d9e0abb932109ceToomas Soome if (c == '\n') {
199767f8919635c4928607450d9e0abb932109ceToomas Soome buf[0] = '\r';
199767f8919635c4928607450d9e0abb932109ceToomas Soome buf[1] = 0;
199767f8919635c4928607450d9e0abb932109ceToomas Soome systab->ConOut->OutputString(systab->ConOut, buf);
199767f8919635c4928607450d9e0abb932109ceToomas Soome }
199767f8919635c4928607450d9e0abb932109ceToomas Soome buf[0] = c;
199767f8919635c4928607450d9e0abb932109ceToomas Soome buf[1] = 0;
199767f8919635c4928607450d9e0abb932109ceToomas Soome systab->ConOut->OutputString(systab->ConOut, buf);
199767f8919635c4928607450d9e0abb932109ceToomas Soome}
199767f8919635c4928607450d9e0abb932109ceToomas Soome
199767f8919635c4928607450d9e0abb932109ceToomas Soomeint
199767f8919635c4928607450d9e0abb932109ceToomas Soomegetchar(void)
199767f8919635c4928607450d9e0abb932109ceToomas Soome{
199767f8919635c4928607450d9e0abb932109ceToomas Soome EFI_INPUT_KEY key;
199767f8919635c4928607450d9e0abb932109ceToomas Soome EFI_STATUS status;
199767f8919635c4928607450d9e0abb932109ceToomas Soome UINTN junk;
199767f8919635c4928607450d9e0abb932109ceToomas Soome
199767f8919635c4928607450d9e0abb932109ceToomas Soome status = systab->ConIn->ReadKeyStroke(systab->ConIn, &key);
199767f8919635c4928607450d9e0abb932109ceToomas Soome if (status == EFI_NOT_READY) {
199767f8919635c4928607450d9e0abb932109ceToomas Soome bs->WaitForEvent(1, &systab->ConIn->WaitForKey, &junk);
199767f8919635c4928607450d9e0abb932109ceToomas Soome status = systab->ConIn->ReadKeyStroke(systab->ConIn, &key);
199767f8919635c4928607450d9e0abb932109ceToomas Soome }
199767f8919635c4928607450d9e0abb932109ceToomas Soome return (key.UnicodeChar);
199767f8919635c4928607450d9e0abb932109ceToomas Soome}