diff options
Diffstat (limited to 'gnu-efi-3.0/lib/hand.c')
-rw-r--r-- | gnu-efi-3.0/lib/hand.c | 633 |
1 files changed, 633 insertions, 0 deletions
diff --git a/gnu-efi-3.0/lib/hand.c b/gnu-efi-3.0/lib/hand.c new file mode 100644 index 0000000..c41c729 --- /dev/null +++ b/gnu-efi-3.0/lib/hand.c @@ -0,0 +1,633 @@ +/*++ + +Copyright (c) 1998 Intel Corporation + +Module Name: + + hand.c + +Abstract: + + + + +Revision History + +--*/ + +#include "lib.h" +#include "efistdarg.h" // !!! + + +EFI_STATUS +LibLocateProtocol ( + IN EFI_GUID *ProtocolGuid, + OUT VOID **Interface + ) +// +// Find the first instance of this Protocol in the system and return it's interface +// +{ + EFI_STATUS Status; + UINTN NumberHandles, Index; + EFI_HANDLE *Handles; + + + *Interface = NULL; + Status = LibLocateHandle (ByProtocol, ProtocolGuid, NULL, &NumberHandles, &Handles); + if (EFI_ERROR(Status)) { + DEBUG((D_INFO, "LibLocateProtocol: Handle not found\n")); + return Status; + } + + for (Index=0; Index < NumberHandles; Index++) { + Status = uefi_call_wrapper(BS->HandleProtocol, 3, Handles[Index], ProtocolGuid, Interface); + if (!EFI_ERROR(Status)) { + break; + } + } + + if (Handles) { + FreePool (Handles); + } + + return Status; +} + +EFI_STATUS +LibLocateHandle ( + IN EFI_LOCATE_SEARCH_TYPE SearchType, + IN EFI_GUID *Protocol OPTIONAL, + IN VOID *SearchKey OPTIONAL, + IN OUT UINTN *NoHandles, + OUT EFI_HANDLE **Buffer + ) + +{ + EFI_STATUS Status; + UINTN BufferSize; + + // + // Initialize for GrowBuffer loop + // + + Status = EFI_SUCCESS; + *Buffer = NULL; + BufferSize = 50 * sizeof(EFI_HANDLE); + + // + // Call the real function + // + + while (GrowBuffer (&Status, (VOID **) Buffer, BufferSize)) { + + Status = uefi_call_wrapper( + BS->LocateHandle, + 5, + SearchType, + Protocol, + SearchKey, + &BufferSize, + *Buffer + ); + + } + + *NoHandles = BufferSize / sizeof (EFI_HANDLE); + if (EFI_ERROR(Status)) { + *NoHandles = 0; + } + + return Status; +} + +EFI_STATUS +LibLocateHandleByDiskSignature ( + IN UINT8 MBRType, + IN UINT8 SignatureType, + IN VOID *Signature, + IN OUT UINTN *NoHandles, + OUT EFI_HANDLE **Buffer + ) + +{ + EFI_STATUS Status; + UINTN BufferSize; + UINTN NoBlockIoHandles; + EFI_HANDLE *BlockIoBuffer; + EFI_DEVICE_PATH *DevicePath; + UINTN Index; + EFI_DEVICE_PATH *Start, *Next, *DevPath; + HARDDRIVE_DEVICE_PATH *HardDriveDevicePath; + BOOLEAN Match; + BOOLEAN PreviousNodeIsHardDriveDevicePath; + + // + // Initialize for GrowBuffer loop + // + + BlockIoBuffer = NULL; + BufferSize = 50 * sizeof(EFI_HANDLE); + + // + // Call the real function + // + + while (GrowBuffer (&Status, (VOID **)&BlockIoBuffer, BufferSize)) { + + // + // Get list of device handles that support the BLOCK_IO Protocol. + // + + Status = uefi_call_wrapper( + BS->LocateHandle, + 5, + ByProtocol, + &BlockIoProtocol, + NULL, + &BufferSize, + BlockIoBuffer + ); + + } + + NoBlockIoHandles = BufferSize / sizeof (EFI_HANDLE); + if (EFI_ERROR(Status)) { + NoBlockIoHandles = 0; + } + + // + // If there was an error or there are no device handles that support + // the BLOCK_IO Protocol, then return. + // + + if (NoBlockIoHandles == 0) { + FreePool(BlockIoBuffer); + *NoHandles = 0; + *Buffer = NULL; + return Status; + } + + // + // Loop through all the device handles that support the BLOCK_IO Protocol + // + + *NoHandles = 0; + + for(Index=0;Index<NoBlockIoHandles;Index++) { + + Status = uefi_call_wrapper( + BS->HandleProtocol, + 3, + BlockIoBuffer[Index], + &DevicePathProtocol, + (VOID*)&DevicePath + ); + + // + // Search DevicePath for a Hard Drive Media Device Path node. + // If one is found, then see if it matches the signature that was + // passed in. If it does match, and the next node is the End of the + // device path, and the previous node is not a Hard Drive Media Device + // Path, then we have found a match. + // + + Match = FALSE; + + if (DevicePath != NULL) { + + PreviousNodeIsHardDriveDevicePath = FALSE; + + DevPath = DevicePath; + Start = DevPath; + + // + // Check for end of device path type + // + + for (; ;) { + + if ((DevicePathType(DevPath) == MEDIA_DEVICE_PATH) && + (DevicePathSubType(DevPath) == MEDIA_HARDDRIVE_DP)) { + + HardDriveDevicePath = (HARDDRIVE_DEVICE_PATH *)(DevPath); + + if (PreviousNodeIsHardDriveDevicePath == FALSE) { + + Next = NextDevicePathNode(DevPath); + if (IsDevicePathEndType(Next)) { + if ((HardDriveDevicePath->MBRType == MBRType) && + (HardDriveDevicePath->SignatureType == SignatureType)) { + switch(SignatureType) { + case SIGNATURE_TYPE_MBR: + if (*((UINT32 *)(Signature)) == *(UINT32 *)(&(HardDriveDevicePath->Signature[0]))) { + Match = TRUE; + } + break; + case SIGNATURE_TYPE_GUID: + if (CompareGuid((EFI_GUID *)Signature,(EFI_GUID *)(&(HardDriveDevicePath->Signature[0]))) == 0) { + Match = TRUE; + } + break; + } + } + } + } + PreviousNodeIsHardDriveDevicePath = TRUE; + } else { + PreviousNodeIsHardDriveDevicePath = FALSE; + } + + if (IsDevicePathEnd(DevPath)) { + break; + } + + DevPath = NextDevicePathNode(DevPath); + } + + } + + if (Match == FALSE) { + BlockIoBuffer[Index] = NULL; + } else { + *NoHandles = *NoHandles + 1; + } + } + + // + // If there are no matches, then return + // + + if (*NoHandles == 0) { + FreePool(BlockIoBuffer); + *NoHandles = 0; + *Buffer = NULL; + return EFI_SUCCESS; + } + + // + // Allocate space for the return buffer of device handles. + // + + *Buffer = AllocatePool(*NoHandles * sizeof(EFI_HANDLE)); + + if (*Buffer == NULL) { + FreePool(BlockIoBuffer); + *NoHandles = 0; + *Buffer = NULL; + return EFI_OUT_OF_RESOURCES; + } + + // + // Build list of matching device handles. + // + + *NoHandles = 0; + for(Index=0;Index<NoBlockIoHandles;Index++) { + if (BlockIoBuffer[Index] != NULL) { + (*Buffer)[*NoHandles] = BlockIoBuffer[Index]; + *NoHandles = *NoHandles + 1; + } + } + + FreePool(BlockIoBuffer); + + return EFI_SUCCESS; +} + +EFI_FILE_HANDLE +LibOpenRoot ( + IN EFI_HANDLE DeviceHandle + ) +{ + EFI_STATUS Status; + EFI_FILE_IO_INTERFACE *Volume; + EFI_FILE_HANDLE File; + + + // + // File the file system interface to the device + // + + Status = uefi_call_wrapper(BS->HandleProtocol, 3, DeviceHandle, &FileSystemProtocol, (VOID*)&Volume); + + // + // Open the root directory of the volume + // + + if (!EFI_ERROR(Status)) { + Status = uefi_call_wrapper(Volume->OpenVolume, 2, Volume, &File); + } + + // + // Done + // + + return EFI_ERROR(Status) ? NULL : File; +} + +EFI_FILE_INFO * +LibFileInfo ( + IN EFI_FILE_HANDLE FHand + ) +{ + EFI_STATUS Status; + EFI_FILE_INFO *Buffer; + UINTN BufferSize; + + // + // Initialize for GrowBuffer loop + // + + Buffer = NULL; + BufferSize = SIZE_OF_EFI_FILE_INFO + 200; + + // + // Call the real function + // + + while (GrowBuffer (&Status, (VOID **) &Buffer, BufferSize)) { + Status = uefi_call_wrapper( + FHand->GetInfo, + 4, + FHand, + &GenericFileInfo, + &BufferSize, + Buffer + ); + } + + return Buffer; +} + + +EFI_FILE_SYSTEM_INFO * +LibFileSystemInfo ( + IN EFI_FILE_HANDLE FHand + ) +{ + EFI_STATUS Status; + EFI_FILE_SYSTEM_INFO *Buffer; + UINTN BufferSize; + + // + // Initialize for GrowBuffer loop + // + + Buffer = NULL; + BufferSize = SIZE_OF_EFI_FILE_SYSTEM_INFO + 200; + + // + // Call the real function + // + + while (GrowBuffer (&Status, (VOID **) &Buffer, BufferSize)) { + Status = uefi_call_wrapper( + FHand->GetInfo, + 4, + FHand, + &FileSystemInfo, + &BufferSize, + Buffer + ); + } + + return Buffer; +} + +EFI_FILE_SYSTEM_VOLUME_LABEL_INFO * +LibFileSystemVolumeLabelInfo ( + IN EFI_FILE_HANDLE FHand + ) +{ + EFI_STATUS Status; + EFI_FILE_SYSTEM_VOLUME_LABEL_INFO *Buffer; + UINTN BufferSize; + + // + // Initialize for GrowBuffer loop + // + + Buffer = NULL; + BufferSize = SIZE_OF_EFI_FILE_SYSTEM_VOLUME_LABEL_INFO + 200; + + // + // Call the real function + // + + while (GrowBuffer (&Status, (VOID **) &Buffer, BufferSize)) { + Status = uefi_call_wrapper( + FHand->GetInfo, + 4, + FHand, + &FileSystemVolumeLabelInfo, + &BufferSize, + Buffer + ); + } + + return Buffer; +} + + + +EFI_STATUS +LibInstallProtocolInterfaces ( + IN OUT EFI_HANDLE *Handle, + ... + ) +{ + va_list args; + EFI_STATUS Status; + EFI_GUID *Protocol; + VOID *Interface; + EFI_TPL OldTpl; + UINTN Index; + EFI_HANDLE OldHandle; + + // + // Syncronize with notifcations + // + + OldTpl = uefi_call_wrapper(BS->RaiseTPL, 1, TPL_NOTIFY); + OldHandle = *Handle; + + // + // Install the protocol interfaces + // + + Index = 0; + Status = EFI_SUCCESS; + va_start (args, Handle); + + while (!EFI_ERROR(Status)) { + + // + // If protocol is NULL, then it's the end of the list + // + + Protocol = va_arg(args, EFI_GUID *); + if (!Protocol) { + break; + } + + Interface = va_arg(args, VOID *); + + // + // Install it + // + + DEBUG((D_INFO, "LibInstallProtocolInterface: %d %x\n", Protocol, Interface)); + Status = uefi_call_wrapper(BS->InstallProtocolInterface, 4, Handle, Protocol, EFI_NATIVE_INTERFACE, Interface); + if (EFI_ERROR(Status)) { + break; + } + + Index += 1; + } + + // + // If there was an error, remove all the interfaces that were + // installed without any errors + // + + if (EFI_ERROR(Status)) { + va_start (args, Handle); + while (Index) { + + Protocol = va_arg(args, EFI_GUID *); + Interface = va_arg(args, VOID *); + uefi_call_wrapper(BS->UninstallProtocolInterface, 3, *Handle, Protocol, Interface); + + Index -= 1; + } + + *Handle = OldHandle; + } + + // + // Done + // + + uefi_call_wrapper(BS->RestoreTPL, 1, OldTpl); + return Status; +} + + +VOID +LibUninstallProtocolInterfaces ( + IN EFI_HANDLE Handle, + ... + ) +{ + va_list args; + EFI_STATUS Status; + EFI_GUID *Protocol; + VOID *Interface; + + + va_start (args, Handle); + for (; ;) { + + // + // If protocol is NULL, then it's the end of the list + // + + Protocol = va_arg(args, EFI_GUID *); + if (!Protocol) { + break; + } + + Interface = va_arg(args, VOID *); + + // + // Uninstall it + // + + Status = uefi_call_wrapper(BS->UninstallProtocolInterface, 3, Handle, Protocol, Interface); + if (EFI_ERROR(Status)) { + DEBUG((D_ERROR, "LibUninstallProtocolInterfaces: failed %g, %r\n", Protocol, Handle)); + } + } +} + + +EFI_STATUS +LibReinstallProtocolInterfaces ( + IN OUT EFI_HANDLE *Handle, + ... + ) +{ + va_list args; + EFI_STATUS Status; + EFI_GUID *Protocol; + VOID *OldInterface, *NewInterface; + EFI_TPL OldTpl; + UINTN Index; + + // + // Syncronize with notifcations + // + + OldTpl = uefi_call_wrapper(BS->RaiseTPL, 1, TPL_NOTIFY); + + // + // Install the protocol interfaces + // + + Index = 0; + Status = EFI_SUCCESS; + va_start (args, Handle); + + while (!EFI_ERROR(Status)) { + + // + // If protocol is NULL, then it's the end of the list + // + + Protocol = va_arg(args, EFI_GUID *); + if (!Protocol) { + break; + } + + OldInterface = va_arg(args, VOID *); + NewInterface = va_arg(args, VOID *); + + // + // Reinstall it + // + + Status = uefi_call_wrapper(BS->ReinstallProtocolInterface, 4, Handle, Protocol, OldInterface, NewInterface); + if (EFI_ERROR(Status)) { + break; + } + + Index += 1; + } + + // + // If there was an error, undo all the interfaces that were + // reinstalled without any errors + // + + if (EFI_ERROR(Status)) { + va_start (args, Handle); + while (Index) { + + Protocol = va_arg(args, EFI_GUID *); + OldInterface = va_arg(args, VOID *); + NewInterface = va_arg(args, VOID *); + + uefi_call_wrapper(BS->ReinstallProtocolInterface, 4, Handle, Protocol, NewInterface, OldInterface); + + Index -= 1; + } + } + + // + // Done + // + + uefi_call_wrapper(BS->RestoreTPL, 1, OldTpl); + return Status; +} |