Syncboot/gnu-efi/lib/hand.c
Curle d588e232c4 Major overhaul of this branch.
This branch has been dedicated to purely the UEFI bootloader.
As such, all other code has been removed.

This code can be compiled with Visual Studio, gcc or llvm.
2019-07-17 21:10:29 +01:00

637 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 = 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;
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;
//
// 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;
}