]> git.proxmox.com Git - mirror_edk2.git/blobdiff - EdkUnixPkg/Dxe/PlatformBds/Generic/BootMaint/BmLib.c
Unix version of EFI emulator
[mirror_edk2.git] / EdkUnixPkg / Dxe / PlatformBds / Generic / BootMaint / BmLib.c
diff --git a/EdkUnixPkg/Dxe/PlatformBds/Generic/BootMaint/BmLib.c b/EdkUnixPkg/Dxe/PlatformBds/Generic/BootMaint/BmLib.c
new file mode 100644 (file)
index 0000000..6f46386
--- /dev/null
@@ -0,0 +1,626 @@
+/*++\r
+\r
+Copyright (c) 2006, 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
+  HandleBufferLength  = 0x1000;\r
+  HiiHandleBuffer     = NULL;\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
+  HiiHandleBuffer = AllocateZeroPool (HandleBufferLength);\r
+  ASSERT (HiiHandleBuffer != NULL);\r
+\r
+  Status = Hii->FindHandles (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
+  gBS->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