From: srs5694 Date: Thu, 19 Apr 2012 00:49:10 +0000 (-0400) Subject: New files with functions to support loading of drivers X-Git-Url: https://code.delx.au/refind/commitdiff_plain/8de66ef58ff93744648fb458845cbe593db69640 New files with functions to support loading of drivers --- diff --git a/refind/bootsvcs.c b/refind/bootsvcs.c new file mode 100644 index 0000000..47d40e7 --- /dev/null +++ b/refind/bootsvcs.c @@ -0,0 +1,251 @@ +/* + * File to implement an full version of EFI_BOOT_SERVICES, to go beyond + * what GNU-EFI provides. These functions were taken, with modification, + * from various EDK2 and earlier files (see comments preceding the + * functions and other blocks of code). The original source files + * bore the following copyright notice: + * + * Copyright (c) 2006 - 2011, Intel Corporation. All rights reserved.
+ * This program and the accompanying materials are licensed and made available under + * the terms and conditions of the BSD License that accompanies this distribution. + * The full text of the license may be found at + * http://opensource.org/licenses/bsd-license.php. + * + * THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + * WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + * + */ + +#include "bootsvcs.h" +#include "refit_call_wrapper.h" + +// Following "global" constants are from AutoGen.c.... +EFI_GUID gEfiLoadedImageProtocolGuid = { 0x5B1B31A1, 0x9562, 0x11D2, { 0x8E, 0x3F, 0x00, 0xA0, 0xC9, 0x69, 0x72, 0x3B }}; +EFI_GUID gEfiDriverBindingProtocolGuid = { 0x18A031AB, 0xB443, 0x4D1A, { 0xA5, 0xC0, 0x0C, 0x09, 0x26, 0x1E, 0x9F, 0x71 }}; +EFI_GUID gEfiDriverConfiguration2ProtocolGuid = { 0xBFD7DC1D, 0x24F1, 0x40D9, { 0x82, 0xE7, 0x2E, 0x09, 0xBB, 0x6B, 0x4E, 0xBE }}; +EFI_GUID gEfiDriverConfigurationProtocolGuid = { 0x107A772B, 0xD5E1, 0x11D4, { 0x9A, 0x46, 0x00, 0x90, 0x27, 0x3F, 0xC1, 0x4D }}; +EFI_GUID gEfiDriverDiagnosticsProtocolGuid = { 0x0784924F, 0xE296, 0x11D4, { 0x9A, 0x49, 0x00, 0x90, 0x27, 0x3F, 0xC1, 0x4D }}; +EFI_GUID gEfiDriverDiagnostics2ProtocolGuid = { 0x4D330321, 0x025F, 0x4AAC, { 0x90, 0xD8, 0x5E, 0xD9, 0x00, 0x17, 0x3B, 0x63 }}; +EFI_GUID gEfiComponentNameProtocolGuid = { 0x107A772C, 0xD5E1, 0x11D4, { 0x9A, 0x46, 0x00, 0x90, 0x27, 0x3F, 0xC1, 0x4D }}; +EFI_GUID gEfiComponentName2ProtocolGuid = { 0x6A7A5CFF, 0xE8D9, 0x4F70, { 0xBA, 0xDA, 0x75, 0xAB, 0x30, 0x25, 0xCE, 0x14 }}; +EFI_GUID gEfiDevicePathProtocolGuid = { 0x09576E91, 0x6D3F, 0x11D2, { 0x8E, 0x39, 0x00, 0xA0, 0xC9, 0x69, 0x72, 0x3B }}; + +// Below is from http://git.etherboot.org/?p=mirror/efi/shell/.git;a=commitdiff;h=b1b0c63423cac54dc964c2930e04aebb46a946ec; +// Seems to have been replaced by ParseHandleDatabaseByRelationshipWithType(), but the latter isn't working for me.... +EFI_STATUS +LibScanHandleDatabase ( + EFI_HANDLE DriverBindingHandle, OPTIONAL + UINT32 *DriverBindingHandleIndex, OPTIONAL + EFI_HANDLE ControllerHandle, OPTIONAL + UINT32 *ControllerHandleIndex, OPTIONAL + UINTN *HandleCount, + EFI_HANDLE **HandleBuffer, + UINT32 **HandleType + ) + +{ + EFI_STATUS Status; + UINTN HandleIndex; + EFI_GUID **ProtocolGuidArray; + UINTN ArrayCount; + UINTN ProtocolIndex; + EFI_OPEN_PROTOCOL_INFORMATION_ENTRY *OpenInfo; + UINTN OpenInfoCount; + UINTN OpenInfoIndex; + UINTN ChildIndex; + BOOLEAN DriverBindingHandleIndexValid; + BOOLEAN ControllerHandleIndexValid; + + DriverBindingHandleIndexValid = FALSE; + if (DriverBindingHandleIndex != NULL) { + *DriverBindingHandleIndex = 0xffffffff; + } + + ControllerHandleIndexValid = FALSE; + if (ControllerHandleIndex != NULL) { + *ControllerHandleIndex = 0xffffffff; + } + + *HandleCount = 0; + *HandleBuffer = NULL; + *HandleType = NULL; + + // + // Retrieve the list of all handles from the handle database + // + + Status = refit_call5_wrapper(gBS->LocateHandleBuffer, + AllHandles, + NULL, + NULL, + HandleCount, + HandleBuffer + ); + if (EFI_ERROR (Status)) { + goto Error; + } + + *HandleType = AllocatePool (*HandleCount * sizeof (UINT32)); + if (*HandleType == NULL) { + goto Error; + } + + for (HandleIndex = 0; HandleIndex < *HandleCount; HandleIndex++) { + // + // Assume that the handle type is unknown + // + (*HandleType)[HandleIndex] = EFI_HANDLE_TYPE_UNKNOWN; + + if (DriverBindingHandle != NULL && + DriverBindingHandleIndex != NULL && + (*HandleBuffer)[HandleIndex] == DriverBindingHandle + ) { + *DriverBindingHandleIndex = (UINT32) HandleIndex; + DriverBindingHandleIndexValid = TRUE; + } + + if (ControllerHandle != NULL && ControllerHandleIndex != NULL && (*HandleBuffer)[HandleIndex] == ControllerHandle) { + *ControllerHandleIndex = (UINT32) HandleIndex; + ControllerHandleIndexValid = TRUE; + } + + } + + for (HandleIndex = 0; HandleIndex < *HandleCount; HandleIndex++) { + // + // Retrieve the list of all the protocols on each handle + // + + Status = refit_call3_wrapper(gBS->ProtocolsPerHandle, + (*HandleBuffer)[HandleIndex], + &ProtocolGuidArray, + &ArrayCount + ); + if (!EFI_ERROR (Status)) { + + for (ProtocolIndex = 0; ProtocolIndex < ArrayCount; ProtocolIndex++) { + + if (CompareGuid (ProtocolGuidArray[ProtocolIndex], &gEfiLoadedImageProtocolGuid) == 0) { + (*HandleType)[HandleIndex] |= EFI_HANDLE_TYPE_IMAGE_HANDLE; + } + + if (CompareGuid (ProtocolGuidArray[ProtocolIndex], &gEfiDriverBindingProtocolGuid) == 0) { + (*HandleType)[HandleIndex] |= EFI_HANDLE_TYPE_DRIVER_BINDING_HANDLE; + } + + if (CompareGuid (ProtocolGuidArray[ProtocolIndex], &gEfiDriverConfigurationProtocolGuid) == 0) { + (*HandleType)[HandleIndex] |= EFI_HANDLE_TYPE_DRIVER_CONFIGURATION_HANDLE; + } + + if (CompareGuid (ProtocolGuidArray[ProtocolIndex], &gEfiDriverDiagnosticsProtocolGuid) == 0) { + (*HandleType)[HandleIndex] |= EFI_HANDLE_TYPE_DRIVER_DIAGNOSTICS_HANDLE; + } + + if (CompareGuid (ProtocolGuidArray[ProtocolIndex], &gEfiComponentNameProtocolGuid) == 0) { + (*HandleType)[HandleIndex] |= EFI_HANDLE_TYPE_COMPONENT_NAME_HANDLE; + } + + if (CompareGuid (ProtocolGuidArray[ProtocolIndex], &gEfiDevicePathProtocolGuid) == 0) { + (*HandleType)[HandleIndex] |= EFI_HANDLE_TYPE_DEVICE_HANDLE; + } + // + // Retrieve the list of agents that have opened each protocol + // + + Status = refit_call4_wrapper(gBS->OpenProtocolInformation, + (*HandleBuffer)[HandleIndex], + ProtocolGuidArray[ProtocolIndex], + &OpenInfo, + &OpenInfoCount + ); + if (!EFI_ERROR (Status)) { + + for (OpenInfoIndex = 0; OpenInfoIndex < OpenInfoCount; OpenInfoIndex++) { + if (DriverBindingHandle != NULL && OpenInfo[OpenInfoIndex].AgentHandle == DriverBindingHandle) { + if ((OpenInfo[OpenInfoIndex].Attributes & EFI_OPEN_PROTOCOL_BY_DRIVER) == EFI_OPEN_PROTOCOL_BY_DRIVER) { + // + // Mark the device handle as being managed by the driver specified by DriverBindingHandle + // + (*HandleType)[HandleIndex] |= (EFI_HANDLE_TYPE_DEVICE_HANDLE | EFI_HANDLE_TYPE_CONTROLLER_HANDLE); + // + // Mark the DriverBindingHandle as being a driver that is managing at least one controller + // + if (DriverBindingHandleIndexValid) { + (*HandleType)[*DriverBindingHandleIndex] |= EFI_HANDLE_TYPE_DEVICE_DRIVER; + } + } + + if (( + OpenInfo[OpenInfoIndex].Attributes & EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER + ) == EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER + ) { + // + // Mark the DriverBindingHandle as being a driver that is managing at least one child controller + // + if (DriverBindingHandleIndexValid) { + (*HandleType)[*DriverBindingHandleIndex] |= EFI_HANDLE_TYPE_BUS_DRIVER; + } + } + + if (ControllerHandle != NULL && (*HandleBuffer)[HandleIndex] == ControllerHandle) { + if (( + OpenInfo[OpenInfoIndex].Attributes & EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER + ) == EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER + ) { + for (ChildIndex = 0; ChildIndex < *HandleCount; ChildIndex++) { + if ((*HandleBuffer)[ChildIndex] == OpenInfo[OpenInfoIndex].ControllerHandle) { + (*HandleType)[ChildIndex] |= (EFI_HANDLE_TYPE_DEVICE_HANDLE | EFI_HANDLE_TYPE_CHILD_HANDLE); + } + } + } + } + } + + if (DriverBindingHandle == NULL && OpenInfo[OpenInfoIndex].ControllerHandle == ControllerHandle) { + if ((OpenInfo[OpenInfoIndex].Attributes & EFI_OPEN_PROTOCOL_BY_DRIVER) == EFI_OPEN_PROTOCOL_BY_DRIVER) { + for (ChildIndex = 0; ChildIndex < *HandleCount; ChildIndex++) { + if ((*HandleBuffer)[ChildIndex] == OpenInfo[OpenInfoIndex].AgentHandle) { + (*HandleType)[ChildIndex] |= EFI_HANDLE_TYPE_DEVICE_DRIVER; + } + } + } + + if (( + OpenInfo[OpenInfoIndex].Attributes & EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER + ) == EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER + ) { + (*HandleType)[HandleIndex] |= EFI_HANDLE_TYPE_PARENT_HANDLE; + for (ChildIndex = 0; ChildIndex < *HandleCount; ChildIndex++) { + if ((*HandleBuffer)[ChildIndex] == OpenInfo[OpenInfoIndex].AgentHandle) { + (*HandleType)[ChildIndex] |= EFI_HANDLE_TYPE_BUS_DRIVER; + } + } + } + } + } + + FreePool (OpenInfo); + } + } + + FreePool (ProtocolGuidArray); + } + } + + return EFI_SUCCESS; + +Error: + if (*HandleType != NULL) { + FreePool (*HandleType); + } + + if (*HandleBuffer != NULL) { + FreePool (*HandleBuffer); + } + + *HandleCount = 0; + *HandleBuffer = NULL; + *HandleType = NULL; + + return Status; +} /* EFI_STATUS LibScanHandleDatabase() */ diff --git a/refind/bootsvcs.h b/refind/bootsvcs.h new file mode 100644 index 0000000..d9500e1 --- /dev/null +++ b/refind/bootsvcs.h @@ -0,0 +1,248 @@ +/* + * File to implement an full version of EFI_BOOT_SERVICES, to go beyond + * what GNU-EFI provides. Most of the data structures in this file are taken + * from the Tianocore UDK's UefiSpec.h file or HandleParsingLib.h files. + * The EFI_DEVICE_PATH_PROTOCOL definition is from + * http://wiki.phoenix.com/wiki/index.php/EFI_DEVICE_PATH_PROTOCOL. + * The UefiSpec.h and HandleParsingLib files include the following copyright + * notice: + * + * Copyright (c) 2006 - 2011, Intel Corporation. All rights reserved.
+ * This program and the accompanying materials are licensed and made available under + * the terms and conditions of the BSD License that accompanies this distribution. + * The full text of the license may be found at + * http://opensource.org/licenses/bsd-license.php. + * + * THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + * WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + * + */ + +#include +#include + +#ifndef _MY_BOOT_SERVICES_FILE +#define _MY_BOOT_SERVICES_FILE + +typedef struct _EFI_DEVICE_PATH_PROTOCOL { + UINT8 Type; + UINT8 SubType; + UINT8 Length[2]; +} EFI_DEVICE_PATH_PROTOCOL; + +typedef +EFI_STATUS +(EFIAPI *EFI_CONNECT_CONTROLLER)( + IN EFI_HANDLE ControllerHandle, + IN EFI_HANDLE *DriverImageHandle, OPTIONAL + IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath, OPTIONAL + IN BOOLEAN Recursive + ); + +typedef +EFI_STATUS +(EFIAPI *EFI_DISCONNECT_CONTROLLER)( + IN EFI_HANDLE ControllerHandle, + IN EFI_HANDLE DriverImageHandle, OPTIONAL + IN EFI_HANDLE ChildHandle OPTIONAL + ); + +typedef +EFI_STATUS +(EFIAPI *EFI_OPEN_PROTOCOL) ( + IN EFI_HANDLE Handle, + IN EFI_GUID * Protocol, + OUT VOID **Interface, + IN EFI_HANDLE ImageHandle, + IN EFI_HANDLE ControllerHandle, OPTIONAL + IN UINT32 Attributes +); + +typedef +EFI_STATUS +(EFIAPI *EFI_CLOSE_PROTOCOL) ( + IN EFI_HANDLE Handle, + IN EFI_GUID * Protocol, + IN EFI_HANDLE ImageHandle, + IN EFI_HANDLE DeviceHandle +); + +typedef struct { + EFI_HANDLE AgentHandle; + EFI_HANDLE ControllerHandle; + UINT32 Attributes; + UINT32 OpenCount; +} EFI_OPEN_PROTOCOL_INFORMATION_ENTRY; + +typedef +EFI_STATUS +(EFIAPI *EFI_OPEN_PROTOCOL_INFORMATION) ( + IN EFI_HANDLE UserHandle, + IN EFI_GUID * Protocol, + IN EFI_OPEN_PROTOCOL_INFORMATION_ENTRY **EntryBuffer, + OUT UINTN *EntryCount +); + +typedef +EFI_STATUS +(EFIAPI *EFI_PROTOCOLS_PER_HANDLE) ( + IN EFI_HANDLE UserHandle, + OUT EFI_GUID ***ProtocolBuffer, + OUT UINTN *ProtocolBufferCount +); + +typedef +EFI_STATUS +(EFIAPI *EFI_LOCATE_HANDLE_BUFFER) ( + IN EFI_LOCATE_SEARCH_TYPE SearchType, + IN EFI_GUID * Protocol OPTIONAL, + IN VOID *SearchKey OPTIONAL, + IN OUT UINTN *NumberHandles, + OUT EFI_HANDLE **Buffer +); + +typedef +EFI_STATUS +(EFIAPI *EFI_LOCATE_PROTOCOL) ( + EFI_GUID * Protocol, + VOID *Registration, OPTIONAL + VOID **Interface +); + +/// +/// EFI Boot Services Table. +/// +typedef struct _MY_BOOT_SERVICES { + /// + /// The table header for the EFI Boot Services Table. + /// + EFI_TABLE_HEADER Hdr; + + // + // Task Priority Services + // + EFI_RAISE_TPL RaiseTPL; + EFI_RESTORE_TPL RestoreTPL; + + // + // Memory Services + // + EFI_ALLOCATE_PAGES AllocatePages; + EFI_FREE_PAGES FreePages; + EFI_GET_MEMORY_MAP GetMemoryMap; + EFI_ALLOCATE_POOL AllocatePool; + EFI_FREE_POOL FreePool; + + // + // Event & Timer Services + // + EFI_CREATE_EVENT CreateEvent; + EFI_SET_TIMER SetTimer; + EFI_WAIT_FOR_EVENT WaitForEvent; + EFI_SIGNAL_EVENT SignalEvent; + EFI_CLOSE_EVENT CloseEvent; + EFI_CHECK_EVENT CheckEvent; + + // + // Protocol Handler Services + // + EFI_INSTALL_PROTOCOL_INTERFACE InstallProtocolInterface; + EFI_REINSTALL_PROTOCOL_INTERFACE ReinstallProtocolInterface; + EFI_UNINSTALL_PROTOCOL_INTERFACE UninstallProtocolInterface; + EFI_HANDLE_PROTOCOL HandleProtocol; + VOID *Reserved; + EFI_REGISTER_PROTOCOL_NOTIFY RegisterProtocolNotify; + EFI_LOCATE_HANDLE LocateHandle; + EFI_LOCATE_DEVICE_PATH LocateDevicePath; + EFI_INSTALL_CONFIGURATION_TABLE InstallConfigurationTable; + + // + // Image Services + // + EFI_IMAGE_LOAD LoadImage; + EFI_IMAGE_START StartImage; + EFI_EXIT Exit; + EFI_IMAGE_UNLOAD UnloadImage; + EFI_EXIT_BOOT_SERVICES ExitBootServices; + + // + // Miscellaneous Services + // + EFI_GET_NEXT_MONOTONIC_COUNT GetNextMonotonicCount; + EFI_STALL Stall; + EFI_SET_WATCHDOG_TIMER SetWatchdogTimer; + + // + // DriverSupport Services + // + EFI_CONNECT_CONTROLLER ConnectController; + EFI_DISCONNECT_CONTROLLER DisconnectController; + + // + // Open and Close Protocol Services + // + EFI_OPEN_PROTOCOL OpenProtocol; + EFI_CLOSE_PROTOCOL CloseProtocol; + EFI_OPEN_PROTOCOL_INFORMATION OpenProtocolInformation; + + // + // Library Services + // + EFI_PROTOCOLS_PER_HANDLE ProtocolsPerHandle; + EFI_LOCATE_HANDLE_BUFFER LocateHandleBuffer; + EFI_LOCATE_PROTOCOL LocateProtocol; +// EFI_INSTALL_MULTIPLE_PROTOCOL_INTERFACES InstallMultipleProtocolInterfaces; +// EFI_UNINSTALL_MULTIPLE_PROTOCOL_INTERFACES UninstallMultipleProtocolInterfaces; +// +// // +// // 32-bit CRC Services +// // +// EFI_CALCULATE_CRC32 CalculateCrc32; +// +// // +// // Miscellaneous Services +// // +// EFI_COPY_MEM CopyMem; +// EFI_SET_MEM SetMem; +// EFI_CREATE_EVENT_EX CreateEventEx; +} MY_BOOT_SERVICES; + +// Below is from http://git.etherboot.org/?p=mirror/efi/shell/.git;a=commitdiff;h=b1b0c63423cac54dc964c2930e04aebb46a946ec; +// Seems to have been replaced by ParseHandleDatabaseByRelationshipWithType(), but the latter isn't working for me.... +EFI_STATUS +LibScanHandleDatabase ( + EFI_HANDLE DriverBindingHandle, OPTIONAL + UINT32 *DriverBindingHandleIndex, OPTIONAL + EFI_HANDLE ControllerHandle, OPTIONAL + UINT32 *ControllerHandleIndex, OPTIONAL + UINTN *HandleCount, + EFI_HANDLE **HandleBuffer, + UINT32 **HandleType + ); + +extern MY_BOOT_SERVICES *gBS; + +#define EFI_HANDLE_TYPE_UNKNOWN 0x000 +#define EFI_HANDLE_TYPE_IMAGE_HANDLE 0x001 +#define EFI_HANDLE_TYPE_DRIVER_BINDING_HANDLE 0x002 +#define EFI_HANDLE_TYPE_DEVICE_DRIVER 0x004 +#define EFI_HANDLE_TYPE_BUS_DRIVER 0x008 +#define EFI_HANDLE_TYPE_DRIVER_CONFIGURATION_HANDLE 0x010 +#define EFI_HANDLE_TYPE_DRIVER_DIAGNOSTICS_HANDLE 0x020 +#define EFI_HANDLE_TYPE_COMPONENT_NAME_HANDLE 0x040 +#define EFI_HANDLE_TYPE_DEVICE_HANDLE 0x080 +#define EFI_HANDLE_TYPE_PARENT_HANDLE 0x100 +#define EFI_HANDLE_TYPE_CONTROLLER_HANDLE 0x200 +#define EFI_HANDLE_TYPE_CHILD_HANDLE 0x400 + + +// Below from EfiApi.h +#define EFI_OPEN_PROTOCOL_BY_HANDLE_PROTOCOL 0x00000001 +#define EFI_OPEN_PROTOCOL_GET_PROTOCOL 0x00000002 +#define EFI_OPEN_PROTOCOL_TEST_PROTOCOL 0x00000004 +#define EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER 0x00000008 +#define EFI_OPEN_PROTOCOL_BY_DRIVER 0x00000010 +#define EFI_OPEN_PROTOCOL_EXCLUSIVE 0x00000020 + + +#endif