620 lines
14 KiB
C
620 lines
14 KiB
C
/*++
|
|
|
|
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 = BS->HandleProtocol (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
|
|
*/
|
|
|
|
*Buffer = NULL;
|
|
BufferSize = 50 * sizeof(EFI_HANDLE);
|
|
|
|
/*
|
|
* Call the real function
|
|
*/
|
|
|
|
while (GrowBuffer (&Status, (VOID **) Buffer, BufferSize)) {
|
|
|
|
Status = BS->LocateHandle (
|
|
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 = BS->LocateHandle (
|
|
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 = BS->HandleProtocol (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 = BS->HandleProtocol (DeviceHandle, &FileSystemProtocol, (VOID*)&Volume);
|
|
|
|
/*
|
|
* Open the root directory of the volume
|
|
*/
|
|
|
|
if (!EFI_ERROR(Status)) {
|
|
Status = Volume->OpenVolume(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 = FHand->GetInfo (
|
|
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 = FHand->GetInfo (
|
|
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 = FHand->GetInfo (
|
|
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 = BS->RaiseTPL(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 = BS->InstallProtocolInterface (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 *);
|
|
BS->UninstallProtocolInterface (*Handle, Protocol, Interface);
|
|
|
|
Index -= 1;
|
|
}
|
|
|
|
*Handle = OldHandle;
|
|
}
|
|
|
|
/*
|
|
* Done
|
|
*/
|
|
|
|
BS->RestoreTPL(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 = BS->UninstallProtocolInterface (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 = BS->RaiseTPL(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 = BS->ReinstallProtocolInterface (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 *);
|
|
|
|
BS->ReinstallProtocolInterface (Handle, Protocol, NewInterface, OldInterface);
|
|
|
|
Index -= 1;
|
|
}
|
|
}
|
|
|
|
/*
|
|
* Done
|
|
*/
|
|
|
|
BS->RestoreTPL(OldTpl);
|
|
return Status;
|
|
}
|