gnu-efi/lib/hand.c

637 lines
14 KiB
C
Raw Normal View History

2013-01-31 01:25:25 +04:00
/*++
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 *Next, *DevPath;
2013-01-31 01:25:25 +04:00
HARDDRIVE_DEVICE_PATH *HardDriveDevicePath;
BOOLEAN Match;
BOOLEAN PreviousNodeIsHardDriveDevicePath;
//
// Initialize for GrowBuffer loop
//
Status = EFI_SUCCESS;
2013-01-31 01:25:25 +04:00
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;
//
// 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;
2013-01-31 01:25:25 +04:00
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;
2013-01-31 01:25:25 +04:00
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;
2013-01-31 01:25:25 +04:00
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;
}