+++ /dev/null
-/*++\r
-\r
-Copyright (c) 2006 - 2007, Intel Corporation\r
-All rights reserved. This program and the accompanying materials\r
-are licensed and made available under the terms and conditions of the BSD License\r
-which accompanies this distribution. The full text of the license may be found at\r
-http://opensource.org/licenses/bsd-license.php\r
-\r
-THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
-WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
-\r
-Module Name:\r
-\r
- BmLib.c\r
-\r
-AgBStract:\r
-\r
- Boot Maintainence Helper functions\r
-\r
---*/\r
-\r
-#include "BootMaint.h"\r
-\r
-EFI_STATUS\r
-EfiLibLocateProtocol (\r
- IN EFI_GUID *ProtocolGuid,\r
- OUT VOID **Interface\r
- )\r
-/*++\r
-\r
-Routine Description:\r
-\r
- Find the first instance of this Protocol\r
- in the system and return it's interface\r
-\r
-Arguments:\r
-\r
- ProtocolGuid - Provides the protocol to search for\r
- Interface - On return, a pointer to the first interface\r
- that matches ProtocolGuid\r
-\r
-Returns:\r
-\r
- EFI_SUCCESS - A protocol instance matching ProtocolGuid was found\r
-\r
- EFI_NOT_FOUND - No protocol instances were found that match ProtocolGuid\r
-\r
---*/\r
-{\r
- EFI_STATUS Status;\r
-\r
- Status = gBS->LocateProtocol (\r
- ProtocolGuid,\r
- NULL,\r
- Interface\r
- );\r
- return Status;\r
-}\r
-\r
-EFI_FILE_HANDLE\r
-EfiLibOpenRoot (\r
- IN EFI_HANDLE DeviceHandle\r
- )\r
-/*++\r
-\r
-Routine Description:\r
-\r
- Function opens and returns a file handle to the root directory of a volume.\r
-\r
-Arguments:\r
-\r
- DeviceHandle - A handle for a device\r
-\r
-Returns:\r
-\r
- A valid file handle or NULL is returned\r
-\r
---*/\r
-{\r
- EFI_STATUS Status;\r
- EFI_SIMPLE_FILE_SYSTEM_PROTOCOL *Volume;\r
- EFI_FILE_HANDLE File;\r
-\r
- File = NULL;\r
-\r
- //\r
- // File the file system interface to the device\r
- //\r
- Status = gBS->HandleProtocol (\r
- DeviceHandle,\r
- &gEfiSimpleFileSystemProtocolGuid,\r
- (VOID *) &Volume\r
- );\r
-\r
- //\r
- // Open the root directory of the volume\r
- //\r
- if (!EFI_ERROR (Status)) {\r
- Status = Volume->OpenVolume (\r
- Volume,\r
- &File\r
- );\r
- }\r
- //\r
- // Done\r
- //\r
- return EFI_ERROR (Status) ? NULL : File;\r
-}\r
-\r
-BOOLEAN\r
-EfiGrowBuffer (\r
- IN OUT EFI_STATUS *Status,\r
- IN OUT VOID **Buffer,\r
- IN UINTN BufferSize\r
- )\r
-/*++\r
-\r
-Routine Description:\r
-\r
- Helper function called as part of the code needed\r
- to allocate the proper sized buffer for various\r
- EFI interfaces.\r
-\r
-Arguments:\r
-\r
- Status - Current status\r
-\r
- Buffer - Current allocated buffer, or NULL\r
-\r
- BufferSize - Current buffer size needed\r
-\r
-Returns:\r
-\r
- TRUE - if the buffer was reallocated and the caller\r
- should try the API again.\r
-\r
---*/\r
-{\r
- BOOLEAN TryAgain;\r
-\r
- //\r
- // If this is an initial request, buffer will be null with a new buffer size\r
- //\r
- if (!*Buffer && BufferSize) {\r
- *Status = EFI_BUFFER_TOO_SMALL;\r
- }\r
- //\r
- // If the status code is "buffer too small", resize the buffer\r
- //\r
- TryAgain = FALSE;\r
- if (*Status == EFI_BUFFER_TOO_SMALL) {\r
-\r
- SafeFreePool (*Buffer);\r
-\r
- *Buffer = AllocateZeroPool (BufferSize);\r
-\r
- if (*Buffer) {\r
- TryAgain = TRUE;\r
- } else {\r
- *Status = EFI_OUT_OF_RESOURCES;\r
- }\r
- }\r
- //\r
- // If there's an error, free the buffer\r
- //\r
- if (!TryAgain && EFI_ERROR (*Status) && *Buffer) {\r
- SafeFreePool (*Buffer);\r
- *Buffer = NULL;\r
- }\r
-\r
- return TryAgain;\r
-}\r
-\r
-VOID *\r
-EfiLibGetVariable (\r
- IN CHAR16 *Name,\r
- IN EFI_GUID *VendorGuid\r
- )\r
-/*++\r
-\r
-Routine Description:\r
- Function returns the value of the specified variable.\r
-\r
-Arguments:\r
- Name - A Null-terminated Unicode string that is\r
- the name of the vendor's variable.\r
-\r
- VendorGuid - A unique identifier for the vendor.\r
-\r
-Returns:\r
-\r
- None\r
-\r
---*/\r
-{\r
- UINTN VarSize;\r
-\r
- return BdsLibGetVariableAndSize (Name, VendorGuid, &VarSize);\r
-}\r
-\r
-EFI_STATUS\r
-EfiLibDeleteVariable (\r
- IN CHAR16 *VarName,\r
- IN EFI_GUID *VarGuid\r
- )\r
-/*++\r
-\r
-Routine Description:\r
- Function deletes the variable specified by VarName and VarGuid.\r
-\r
-Arguments:\r
- VarName - A Null-terminated Unicode string that is\r
- the name of the vendor's variable.\r
-\r
- VendorGuid - A unique identifier for the vendor.\r
-\r
-Returns:\r
-\r
- EFI_SUCCESS - The variable was found and removed\r
-\r
- EFI_UNSUPPORTED - The variable store was inaccessible\r
-\r
- EFI_OUT_OF_RESOURCES - The temporary buffer was not available\r
-\r
- EFI_NOT_FOUND - The variable was not found\r
-\r
---*/\r
-{\r
- VOID *VarBuf;\r
- EFI_STATUS Status;\r
-\r
- VarBuf = EfiLibGetVariable (VarName, VarGuid);\r
- Status = EFI_NOT_FOUND;\r
-\r
- if (VarBuf) {\r
- //\r
- // Delete variable from Storage\r
- //\r
- Status = gRT->SetVariable (VarName, VarGuid, VAR_FLAG, 0, NULL);\r
- ASSERT (!EFI_ERROR (Status));\r
- SafeFreePool (VarBuf);\r
- }\r
-\r
- return Status;\r
-}\r
-\r
-EFI_FILE_SYSTEM_VOLUME_LABEL_INFO *\r
-EfiLibFileSystemVolumeLabelInfo (\r
- IN EFI_FILE_HANDLE FHand\r
- )\r
-/*++\r
-\r
-Routine Description:\r
-\r
- Function gets the file system information from an open file descriptor,\r
- and stores it in a buffer allocated from pool.\r
-\r
-Arguments:\r
-\r
- Fhand - A file handle\r
-\r
-Returns:\r
-\r
- A pointer to a buffer with file information or NULL is returned\r
-\r
---*/\r
-{\r
- EFI_STATUS Status;\r
- EFI_FILE_SYSTEM_VOLUME_LABEL_INFO *Buffer;\r
- UINTN BufferSize;\r
- //\r
- // Initialize for GrowBuffer loop\r
- //\r
- Buffer = NULL;\r
- BufferSize = SIZE_OF_EFI_FILE_SYSTEM_VOLUME_LABEL_INFO + 200;\r
-\r
- //\r
- // Call the real function\r
- //\r
- while (EfiGrowBuffer (&Status, (VOID **) &Buffer, BufferSize)) {\r
- Status = FHand->GetInfo (\r
- FHand,\r
- &gEfiFileSystemVolumeLabelInfoIdGuid,\r
- &BufferSize,\r
- Buffer\r
- );\r
- }\r
-\r
- return Buffer;\r
-}\r
-\r
-CHAR16 *\r
-EfiStrDuplicate (\r
- IN CHAR16 *Src\r
- )\r
-{\r
- CHAR16 *Dest;\r
- UINTN Size;\r
-\r
- Size = StrSize (Src);\r
- Dest = AllocateZeroPool (Size);\r
- ASSERT (Dest != NULL);\r
- if (Dest) {\r
- CopyMem (Dest, Src, Size);\r
- }\r
-\r
- return Dest;\r
-}\r
-\r
-EFI_FILE_INFO *\r
-EfiLibFileInfo (\r
- IN EFI_FILE_HANDLE FHand\r
- )\r
-/*++\r
-\r
-Routine Description:\r
-\r
- Function gets the file information from an open file descriptor, and stores it\r
- in a buffer allocated from pool.\r
-\r
-Arguments:\r
-\r
- Fhand - A file handle\r
-\r
-Returns:\r
-\r
- A pointer to a buffer with file information or NULL is returned\r
-\r
---*/\r
-{\r
- EFI_STATUS Status;\r
- EFI_FILE_INFO *Buffer;\r
- UINTN BufferSize;\r
-\r
- //\r
- // Initialize for GrowBuffer loop\r
- //\r
- Buffer = NULL;\r
- BufferSize = SIZE_OF_EFI_FILE_INFO + 200;\r
-\r
- //\r
- // Call the real function\r
- //\r
- while (EfiGrowBuffer (&Status, (VOID **) &Buffer, BufferSize)) {\r
- Status = FHand->GetInfo (\r
- FHand,\r
- &gEfiFileInfoGuid,\r
- &BufferSize,\r
- Buffer\r
- );\r
- }\r
-\r
- return Buffer;\r
-}\r
-\r
-UINTN\r
-EfiDevicePathInstanceCount (\r
- IN EFI_DEVICE_PATH_PROTOCOL *DevicePath\r
- )\r
-/*++\r
-\r
-Routine Description:\r
- Function is used to determine the number of device path instances\r
- that exist in a device path.\r
-\r
-Arguments:\r
- DevicePath - A pointer to a device path data structure.\r
-\r
-Returns:\r
-\r
- This function counts and returns the number of device path instances\r
- in DevicePath.\r
-\r
---*/\r
-{\r
- UINTN Count;\r
- UINTN Size;\r
-\r
- Count = 0;\r
- while (GetNextDevicePathInstance (&DevicePath, &Size)) {\r
- Count += 1;\r
- }\r
-\r
- return Count;\r
-}\r
-\r
-VOID *\r
-EfiReallocatePool (\r
- IN VOID *OldPool,\r
- IN UINTN OldSize,\r
- IN UINTN NewSize\r
- )\r
-/*++\r
-\r
-Routine Description:\r
- Adjusts the size of a previously allocated buffer.\r
-\r
-Arguments:\r
- OldPool - A pointer to the buffer whose size is being adjusted.\r
- OldSize - The size of the current buffer.\r
- NewSize - The size of the new buffer.\r
-\r
-Returns:\r
-\r
- EFI_SUCEESS - The requested number of bytes were allocated.\r
-\r
- EFI_OUT_OF_RESOURCES - The pool requested could not be allocated.\r
-\r
- EFI_INVALID_PARAMETER - The buffer was invalid.\r
-\r
---*/\r
-{\r
- VOID *NewPool;\r
-\r
- NewPool = NULL;\r
- if (NewSize) {\r
- NewPool = AllocateZeroPool (NewSize);\r
- }\r
-\r
- if (OldPool) {\r
- if (NewPool) {\r
- CopyMem (NewPool, OldPool, OldSize < NewSize ? OldSize : NewSize);\r
- }\r
-\r
- SafeFreePool (OldPool);\r
- }\r
-\r
- return NewPool;\r
-}\r
-\r
-EFI_STATUS\r
-EfiLibGetStringFromToken (\r
- IN EFI_GUID *ProducerGuid,\r
- IN STRING_REF Token,\r
- OUT CHAR16 **String\r
- )\r
-/*++\r
-\r
-Routine Description:\r
-\r
- Acquire the string associated with the ProducerGuid and return it.\r
-\r
-Arguments:\r
-\r
- ProducerGuid - The Guid to search the HII database for\r
- Token - The token value of the string to extract\r
- String - The string that is extracted\r
-\r
-Returns:\r
-\r
- EFI_SUCCESS - Buffer filled with the requested forms. BufferLength\r
- was updated.\r
- EFI_BUFFER_TOO_SMALL - The buffer provided was not large enough to allow the form to be stored.\r
-\r
---*/\r
-{\r
- EFI_STATUS Status;\r
- UINT16 HandleBufferLength;\r
- EFI_HII_HANDLE *HiiHandleBuffer;\r
- UINTN StringBufferLength;\r
- UINTN NumberOfHiiHandles;\r
- UINTN Index;\r
- UINT16 Length;\r
- EFI_GUID HiiGuid;\r
- EFI_HII_PROTOCOL *Hii;\r
-\r
- //\r
- // Initialize params.\r
- //\r
- HandleBufferLength = 0;\r
- HiiHandleBuffer = NULL;\r
-\r
- Status = gBS->LocateProtocol (\r
- &gEfiHiiProtocolGuid,\r
- NULL,\r
- &Hii\r
- );\r
- if (EFI_ERROR (Status)) {\r
- *String = NULL;\r
- return Status;\r
- }\r
- //\r
- // Get all the Hii handles\r
- //\r
- Status = BdsLibGetHiiHandles (Hii, &HandleBufferLength, &HiiHandleBuffer);\r
- ASSERT_EFI_ERROR (Status);\r
-\r
- //\r
- // Get the Hii Handle that matches the StructureNode->ProducerName\r
- //\r
- NumberOfHiiHandles = HandleBufferLength / sizeof (EFI_HII_HANDLE);\r
- for (Index = 0; Index < NumberOfHiiHandles; Index++) {\r
- Length = 0;\r
- Status = ExtractDataFromHiiHandle (\r
- HiiHandleBuffer[Index],\r
- &Length,\r
- NULL,\r
- &HiiGuid\r
- );\r
- if (CompareGuid (ProducerGuid, &HiiGuid)) {\r
- break;\r
- }\r
- }\r
- //\r
- // Find the string based on the current language\r
- //\r
- StringBufferLength = 0x100;\r
- *String = AllocateZeroPool (0x100);\r
- ASSERT (*String != NULL);\r
-\r
- Status = Hii->GetString (\r
- Hii,\r
- HiiHandleBuffer[Index],\r
- Token,\r
- FALSE,\r
- NULL,\r
- &StringBufferLength,\r
- *String\r
- );\r
-\r
- FreePool (HiiHandleBuffer);\r
-\r
- return Status;\r
-}\r
-\r
-BOOLEAN\r
-TimeCompare (\r
- IN EFI_TIME *FirstTime,\r
- IN EFI_TIME *SecondTime\r
- )\r
-/*++\r
-\r
-Routine Description:\r
- Compare two EFI_TIME data.\r
-\r
-Arguments:\r
-\r
- FirstTime - A pointer to the first EFI_TIME data.\r
- SecondTime - A pointer to the second EFI_TIME data.\r
-\r
-Returns:\r
- TRUE The FirstTime is not later than the SecondTime.\r
- FALSE The FirstTime is later than the SecondTime.\r
-\r
---*/\r
-{\r
- if (FirstTime->Year != SecondTime->Year) {\r
- return (BOOLEAN) (FirstTime->Year < SecondTime->Year);\r
- } else if (FirstTime->Month != SecondTime->Month) {\r
- return (BOOLEAN) (FirstTime->Month < SecondTime->Month);\r
- } else if (FirstTime->Day != SecondTime->Day) {\r
- return (BOOLEAN) (FirstTime->Day < SecondTime->Day);\r
- } else if (FirstTime->Hour != SecondTime->Hour) {\r
- return (BOOLEAN) (FirstTime->Hour < SecondTime->Hour);\r
- } else if (FirstTime->Minute != SecondTime->Minute) {\r
- return (BOOLEAN) (FirstTime->Minute < FirstTime->Minute);\r
- } else if (FirstTime->Second != SecondTime->Second) {\r
- return (BOOLEAN) (FirstTime->Second < SecondTime->Second);\r
- }\r
-\r
- return (BOOLEAN) (FirstTime->Nanosecond <= SecondTime->Nanosecond);\r
-}\r
-\r
-UINT16 *\r
-EfiLibStrFromDatahub (\r
- IN EFI_DEVICE_PATH_PROTOCOL *DevPath\r
- )\r
-{\r
- EFI_STATUS Status;\r
- UINT16 *Desc;\r
- EFI_DATA_HUB_PROTOCOL *Datahub;\r
- UINT64 Count;\r
- EFI_DATA_RECORD_HEADER *Record;\r
- EFI_SUBCLASS_TYPE1_HEADER *DataHdr;\r
- EFI_GUID MiscGuid = EFI_MISC_SUBCLASS_GUID;\r
- EFI_MISC_ONBOARD_DEVICE_DATA *ob;\r
- EFI_MISC_PORT_INTERNAL_CONNECTOR_DESIGNATOR_DATA *Port;\r
- EFI_TIME CurTime;\r
-\r
- Status = gBS->LocateProtocol (\r
- &gEfiDataHubProtocolGuid,\r
- NULL,\r
- &Datahub\r
- );\r
- if (EFI_ERROR (Status)) {\r
- return NULL;\r
- }\r
-\r
- Status = gRT->GetTime (&CurTime, NULL);\r
- if (EFI_ERROR (Status)) {\r
- return NULL;\r
- }\r
-\r
- Count = 0;\r
- do {\r
- Status = Datahub->GetNextRecord (Datahub, &Count, NULL, &Record);\r
-\r
- if (EFI_ERROR (Status)) {\r
- break;\r
- }\r
-\r
- if (Record->DataRecordClass == EFI_DATA_RECORD_CLASS_DATA && CompareGuid (&Record->DataRecordGuid, &MiscGuid)) {\r
- //\r
- // This record is what we need\r
- //\r
- DataHdr = (EFI_SUBCLASS_TYPE1_HEADER *) (Record + 1);\r
- if (EFI_MISC_ONBOARD_DEVICE_RECORD_NUMBER == DataHdr->RecordType) {\r
- ob = (EFI_MISC_ONBOARD_DEVICE_DATA *) (DataHdr + 1);\r
- if (BdsLibMatchDevicePaths ((EFI_DEVICE_PATH_PROTOCOL *) &ob->OnBoardDevicePath, DevPath)) {\r
- EfiLibGetStringFromToken (&Record->ProducerName, ob->OnBoardDeviceDescription, &Desc);\r
- return Desc;\r
- }\r
- }\r
-\r
- if (EFI_MISC_PORT_INTERNAL_CONNECTOR_DESIGNATOR_RECORD_NUMBER == DataHdr->RecordType) {\r
- Port = (EFI_MISC_PORT_INTERNAL_CONNECTOR_DESIGNATOR_DATA *) (DataHdr + 1);\r
- if (BdsLibMatchDevicePaths ((EFI_DEVICE_PATH_PROTOCOL *) &Port->PortPath, DevPath)) {\r
- EfiLibGetStringFromToken (&Record->ProducerName, Port->PortExternalConnectorDesignator, &Desc);\r
- return Desc;\r
- }\r
- }\r
- }\r
-\r
- } while (TimeCompare (&Record->LogTime, &CurTime) && Count != 0);\r
-\r
- return NULL;\r
-}\r