summaryrefslogtreecommitdiff
path: root/gnu-efi-3.0/lib/hand.c
diff options
context:
space:
mode:
Diffstat (limited to 'gnu-efi-3.0/lib/hand.c')
-rw-r--r--gnu-efi-3.0/lib/hand.c633
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;
+}