| /*++ |
| |
| 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 |
| // |
| |
| Status = EFI_SUCCESS; |
| 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 |
| // |
| |
| Status = EFI_SUCCESS; |
| 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 |
| // |
| |
| Status = EFI_SUCCESS; |
| 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 |
| // |
| |
| Status = EFI_SUCCESS; |
| 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; |
| } |