]> git.proxmox.com Git - mirror_edk2.git/blobdiff - EmbeddedPkg/Library/EfiFileLib/EfiFileLib.c
EmbeddedPkg Omap35xxPkg: remove EBL and associated libraries
[mirror_edk2.git] / EmbeddedPkg / Library / EfiFileLib / EfiFileLib.c
diff --git a/EmbeddedPkg/Library/EfiFileLib/EfiFileLib.c b/EmbeddedPkg/Library/EfiFileLib/EfiFileLib.c
deleted file mode 100644 (file)
index 8c38d22..0000000
+++ /dev/null
@@ -1,1784 +0,0 @@
-/** @file\r
-File IO routines inspired by Streams with an EFI flavor\r
-\r
-Copyright (c) 2007, Intel Corporation. All rights reserved.<BR>\r
-Portions copyright (c) 2008 - 2009, Apple Inc. All rights reserved.<BR>\r
-\r
-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
-Basic support for opening files on different device types. The device string\r
-is in the form of DevType:Path. Current DevType is required as there is no\r
-current mounted device concept of current working directory concept implement\r
-by this library.\r
-\r
-Device names are case insensitive and only check the leading characters for\r
-unique matches. Thus the following are all the same:\r
-LoadFile0:\r
-l0:\r
-L0:\r
-Lo0:\r
-\r
-Supported Device Names:\r
-A0x1234:0x12 - A memory buffer starting at address 0x1234 for 0x12 bytes\r
-l1:          - EFI LoadFile device one.\r
-B0:          - EFI BlockIo zero.\r
-fs3:         - EFI Simple File System device 3\r
-Fv2:         - EFI Firmware VOlume device 2\r
-10.0.1.102:  - TFTP service IP followed by the file name\r
-**/\r
-\r
-#include <PiDxe.h>\r
-#include <Protocol/BlockIo.h>\r
-#include <Protocol/DiskIo.h>\r
-#include <Protocol/SimpleFileSystem.h>\r
-#include <Protocol/FirmwareVolume2.h>\r
-#include <Protocol/LoadFile.h>\r
-#include <Protocol/FirmwareVolumeBlock.h>\r
-\r
-#include <Guid/FileInfo.h>\r
-#include <Guid/ZeroGuid.h>\r
-\r
-#include <Library/BaseLib.h>\r
-#include <Library/MemoryAllocationLib.h>\r
-#include <Library/DevicePathLib.h>\r
-#include <Library/PrintLib.h>\r
-#include <Library/BaseMemoryLib.h>\r
-#include <Library/UefiLib.h>\r
-#include <Library/UefiBootServicesTableLib.h>\r
-#include <Library/UefiRuntimeServicesTableLib.h>\r
-#include <Library/DebugLib.h>\r
-#include <Library/EfiFileLib.h>\r
-#include <Library/PcdLib.h>\r
-#include <Library/EblNetworkLib.h>\r
-\r
-\r
-CHAR8 *gCwd = NULL;\r
-\r
-#define EFI_OPEN_FILE_GUARD_HEADER  0x4B4D4641\r
-#define EFI_OPEN_FILE_GUARD_FOOTER  0x444D5A56\r
-\r
-// Need to defend against this overflowing\r
-#define MAX_CMD_LINE  0x200\r
-\r
-typedef struct {\r
-  UINT32            Header;\r
-  EFI_OPEN_FILE     File;\r
-  UINT32            Footer;\r
-} EFI_OPEN_FILE_GUARD;\r
-\r
-\r
-// globals to store current open device info\r
-EFI_HANDLE            *mBlkIo = NULL;\r
-UINTN                 mBlkIoCount = 0;\r
-\r
-EFI_HANDLE            *mFs = NULL;\r
-UINTN                 mFsCount = 0;\r
-// mFsInfo[] array entries must match mFs[] handles\r
-EFI_FILE_SYSTEM_INFO  **mFsInfo = NULL;\r
-\r
-EFI_HANDLE            *mFv = NULL;\r
-UINTN                 mFvCount = 0;\r
-EFI_HANDLE            *mLoadFile = NULL;\r
-UINTN                 mLoadFileCount = 0;\r
-\r
-\r
-\r
-/**\r
-Internal worker function to validate a File handle.\r
-\r
-@param  File    Open File Handle\r
-\r
-@return TRUE    File is valid\r
-@return FALSE   File is not valid\r
-\r
-\r
-**/\r
-BOOLEAN\r
-FileHandleValid (\r
-  IN EFI_OPEN_FILE  *File\r
-  )\r
-{\r
-  EFI_OPEN_FILE_GUARD  *GuardFile;\r
-\r
-  // Look right before and after file structure for the correct signatures\r
-  GuardFile = BASE_CR (File, EFI_OPEN_FILE_GUARD, File);\r
-  if ((GuardFile->Header != EFI_OPEN_FILE_GUARD_HEADER) ||\r
-    (GuardFile->Footer != EFI_OPEN_FILE_GUARD_FOOTER) ) {\r
-      return FALSE;\r
-    }\r
-\r
-    return TRUE;\r
-}\r
-\r
-/**\r
-Internal worker function. If Buffer is not NULL free it.\r
-\r
-@param  Buffer    Buffer to FreePool()\r
-\r
-**/\r
-VOID\r
-EblFreePool (\r
-  IN  VOID  *Buffer\r
-  )\r
-{\r
-  if (Buffer != NULL) {\r
-    FreePool (Buffer);\r
-  }\r
-}\r
-\r
-/**\r
-Update Device List Global Variables\r
-\r
-**/\r
-VOID\r
-EblUpdateDeviceLists (\r
-  VOID\r
-  )\r
-{\r
-  EFI_STATUS                        Status;\r
-  UINTN                             Size;\r
-  EFI_SIMPLE_FILE_SYSTEM_PROTOCOL   *Fs;\r
-  EFI_FILE_HANDLE                   Root;\r
-  UINTN                             Index;\r
-\r
-  if (mBlkIo != NULL) {\r
-    FreePool (mBlkIo);\r
-  }\r
-  gBS->LocateHandleBuffer (ByProtocol, &gEfiBlockIoProtocolGuid, NULL, &mBlkIoCount, &mBlkIo);\r
-\r
-\r
-\r
-  if (mFv != NULL) {\r
-    FreePool (mFv);\r
-  }\r
-  gBS->LocateHandleBuffer (ByProtocol, &gEfiFirmwareVolume2ProtocolGuid, NULL, &mFvCount, &mFv);\r
-\r
-  if (mLoadFile != NULL) {\r
-    FreePool (mLoadFile);\r
-  }\r
-  gBS->LocateHandleBuffer (ByProtocol, &gEfiLoadFileProtocolGuid, NULL, &mLoadFileCount, &mLoadFile);\r
-\r
-  if (mFs != NULL) {\r
-    FreePool (mFs);\r
-  }\r
-\r
-  if (&mFsInfo[0] != NULL) {\r
-    // Need to Free the mFsInfo prior to recalculating mFsCount so don't move this code\r
-    for (Index = 0; Index < mFsCount; Index++) {\r
-      if (mFsInfo[Index] != NULL) {\r
-        FreePool (mFsInfo[Index]);\r
-      }\r
-    }\r
-    FreePool (mFsInfo);\r
-  }\r
-\r
-  gBS->LocateHandleBuffer (ByProtocol, &gEfiSimpleFileSystemProtocolGuid, NULL, &mFsCount, &mFs);\r
-\r
-\r
-  mFsInfo = AllocateZeroPool (mFsCount * sizeof (EFI_FILE_SYSTEM_INFO *));\r
-  if (mFsInfo == NULL) {\r
-    // If we can't do this then we can't support file system entries\r
-    mFsCount = 0;\r
-  } else {\r
-    // Loop through all the file system structures and cache the file system info data\r
-    for (Index =0; Index < mFsCount; Index++) {\r
-      Status = gBS->HandleProtocol (mFs[Index], &gEfiSimpleFileSystemProtocolGuid, (VOID **)&Fs);\r
-      if (!EFI_ERROR (Status)) {\r
-        Status = Fs->OpenVolume (Fs, &Root);\r
-        if (!EFI_ERROR (Status)) {\r
-          // Get information about the volume\r
-          Size = 0;\r
-          Status = Root->GetInfo (Root, &gEfiFileSystemInfoGuid, &Size, mFsInfo[Index]);\r
-          if (Status == EFI_BUFFER_TOO_SMALL) {\r
-            mFsInfo[Index] = AllocatePool (Size);\r
-            Status = Root->GetInfo (Root, &gEfiFileSystemInfoGuid, &Size, mFsInfo[Index]);\r
-          }\r
-\r
-          Root->Close (Root);\r
-        }\r
-      }\r
-    }\r
-  }\r
-}\r
-\r
-\r
-/**\r
-PathName is in the form <device name>:<path> for example fs1:\ or ROOT:\.\r
-Return TRUE if the <devce name> prefix of PathName matches a file system\r
-Volume Name. MatchIndex is the array  index in mFsInfo[] of the match,\r
-and it can be used with mFs[] to find the handle that needs to be opened\r
-\r
-@param  PathName      PathName to check\r
-@param  FileStart     Index of the first character of the <path>\r
-@param  MatchIndex    Index in mFsInfo[] that matches\r
-\r
-@return TRUE      PathName matches a Volume Label and MatchIndex is valid\r
-@return FALSE     PathName does not match a Volume Label MatchIndex undefined\r
-\r
-**/\r
-BOOLEAN\r
-EblMatchVolumeName (\r
-  IN  CHAR8   *PathName,\r
-  IN  UINTN   FileStart,\r
-  OUT UINTN   *MatchIndex\r
-  )\r
-{\r
-  UINTN   Index;\r
-  UINTN   Compare;\r
-  UINTN   VolStrLen;\r
-  BOOLEAN Match;\r
-\r
-  for (Index =0; Index < mFsCount; Index++) {\r
-    if (mFsInfo[Index] == NULL) {\r
-      // FsInfo is not valid so skip it\r
-      continue;\r
-    }\r
-    VolStrLen = StrLen (mFsInfo[Index]->VolumeLabel);\r
-    for (Compare = 0, Match = TRUE; Compare < (FileStart - 1); Compare++) {\r
-      if (Compare > VolStrLen) {\r
-        Match = FALSE;\r
-        break;\r
-      }\r
-      if (PathName[Compare] != (CHAR8)mFsInfo[Index]->VolumeLabel[Compare]) {\r
-        // If the VolumeLabel has a space allow a _ to match with it in addition to ' '\r
-        if (!((PathName[Compare] == '_') && (mFsInfo[Index]->VolumeLabel[Compare] == L' '))) {\r
-          Match = FALSE;\r
-          break;\r
-        }\r
-      }\r
-    }\r
-    if (Match) {\r
-      *MatchIndex = Index;\r
-      return TRUE;\r
-    }\r
-  }\r
-\r
-  return FALSE;\r
-}\r
-\r
-\r
-/**\r
-Return the number of devices of the current type active in the system\r
-\r
-@param  Type      Device type to check\r
-\r
-@return 0         Invalid type\r
-\r
-**/\r
-UINTN\r
-EfiGetDeviceCounts (\r
-  IN  EFI_OPEN_FILE_TYPE     DeviceType\r
-  )\r
-{\r
-  switch (DeviceType) {\r
-  case EfiOpenLoadFile:\r
-    return mLoadFileCount;\r
-  case EfiOpenFirmwareVolume:\r
-    return mFvCount;\r
-  case EfiOpenFileSystem:\r
-    return mFsCount;\r
-  case EfiOpenBlockIo:\r
-    return mBlkIoCount;\r
-  default:\r
-    return 0;\r
-  }\r
-}\r
-\r
-EFI_STATUS\r
-ConvertIpStringToEfiIp (\r
-  IN  CHAR8           *PathName,\r
-  OUT EFI_IP_ADDRESS  *ServerIp\r
-  )\r
-{\r
-  CHAR8     *Str;\r
-\r
-  Str = PathName;\r
-  ServerIp->v4.Addr[0] = (UINT8)AsciiStrDecimalToUintn (Str);\r
-\r
-  Str = AsciiStrStr (Str, ".");\r
-  if (Str == NULL) {\r
-    return EFI_DEVICE_ERROR;\r
-  }\r
-\r
-  ServerIp->v4.Addr[1] = (UINT8)AsciiStrDecimalToUintn (++Str);\r
-\r
-  Str = AsciiStrStr (Str, ".");\r
-  if (Str == NULL) {\r
-    return EFI_DEVICE_ERROR;\r
-  }\r
-\r
-  ServerIp->v4.Addr[2] = (UINT8)AsciiStrDecimalToUintn (++Str);\r
-\r
-  Str = AsciiStrStr (Str, ".");\r
-  if (Str == NULL) {\r
-    return EFI_DEVICE_ERROR;\r
-  }\r
-\r
-  ServerIp->v4.Addr[3] = (UINT8)AsciiStrDecimalToUintn (++Str);\r
-\r
-  return EFI_SUCCESS;\r
-}\r
-\r
-\r
-/**\r
-Internal work function to extract a device number from a string skipping\r
-text. Easy way to extract numbers from strings like blk7:.\r
-\r
-@param  Str   String to extract device number form\r
-\r
-@return -1    Device string is not valid\r
-@return       Device #\r
-\r
-**/\r
-UINTN\r
-EblConvertDevStringToNumber (\r
-  IN  CHAR8   *Str\r
-  )\r
-{\r
-  UINTN   Max;\r
-  UINTN   Index;\r
-\r
-\r
-  // Find the first digit\r
-  Max = AsciiStrLen (Str);\r
-  for  (Index = 0; !((*Str >= '0') && (*Str <= '9')) && (Index < Max); Index++) {\r
-    Str++;\r
-  }\r
-  if (Index == Max) {\r
-    return (UINTN)-1;\r
-  }\r
-\r
-  return AsciiStrDecimalToUintn (Str);\r
-}\r
-\r
-\r
-/**\r
-Internal work function to fill in EFI_OPEN_FILE information for the Fs and BlkIo\r
-\r
-@param  File        Open file handle\r
-@param  FileName    Name of file after device stripped off\r
-\r
-\r
-**/\r
-EFI_STATUS\r
-EblFileDevicePath (\r
-  IN OUT EFI_OPEN_FILE  *File,\r
-  IN  CHAR8             *FileName,\r
-  IN  CONST UINT64      OpenMode\r
-  )\r
-{\r
-  EFI_STATUS                        Status;\r
-  UINTN                             Size;\r
-  FILEPATH_DEVICE_PATH              *FilePath;\r
-  EFI_DEVICE_PATH_PROTOCOL          *FileDevicePath;\r
-  CHAR16                            UnicodeFileName[MAX_PATHNAME];\r
-  EFI_BLOCK_IO_PROTOCOL             *BlkIo;\r
-  EFI_SIMPLE_FILE_SYSTEM_PROTOCOL   *Fs;\r
-  EFI_FILE_HANDLE                   Root;\r
-\r
-\r
-  if ( *FileName != 0 ) {\r
-    AsciiStrToUnicodeStrS (FileName, UnicodeFileName,\r
-      ARRAY_SIZE (UnicodeFileName));\r
-  } else {\r
-    AsciiStrToUnicodeStrS ("\\", UnicodeFileName, ARRAY_SIZE (UnicodeFileName));\r
-  }\r
-\r
-  Size = StrSize (UnicodeFileName);\r
-  FileDevicePath = AllocatePool (Size + SIZE_OF_FILEPATH_DEVICE_PATH + sizeof (EFI_DEVICE_PATH_PROTOCOL));\r
-  if (FileDevicePath != NULL) {\r
-    FilePath = (FILEPATH_DEVICE_PATH *) FileDevicePath;\r
-    FilePath->Header.Type    = MEDIA_DEVICE_PATH;\r
-    FilePath->Header.SubType = MEDIA_FILEPATH_DP;\r
-    CopyMem (&FilePath->PathName, UnicodeFileName, Size);\r
-    SetDevicePathNodeLength (&FilePath->Header, Size + SIZE_OF_FILEPATH_DEVICE_PATH);\r
-    SetDevicePathEndNode (NextDevicePathNode (&FilePath->Header));\r
-\r
-    if (File->EfiHandle != NULL) {\r
-      File->DevicePath = DevicePathFromHandle (File->EfiHandle);\r
-    }\r
-\r
-    File->DevicePath = AppendDevicePath (File->DevicePath, FileDevicePath);\r
-    FreePool (FileDevicePath);\r
-  }\r
-\r
-  Status = gBS->HandleProtocol (File->EfiHandle, &gEfiBlockIoProtocolGuid, (VOID **)&BlkIo);\r
-  if (!EFI_ERROR (Status)) {\r
-    File->FsBlockIoMedia = BlkIo->Media;\r
-    File->FsBlockIo = BlkIo;\r
-\r
-    // If we are not opening the device this will get over written with file info\r
-    File->MaxPosition = MultU64x32 (BlkIo->Media->LastBlock + 1, BlkIo->Media->BlockSize);\r
-  }\r
-\r
-  if (File->Type == EfiOpenFileSystem) {\r
-    Status = gBS->HandleProtocol (File->EfiHandle, &gEfiSimpleFileSystemProtocolGuid, (VOID **)&Fs);\r
-    if (!EFI_ERROR (Status)) {\r
-      Status = Fs->OpenVolume (Fs, &Root);\r
-      if (!EFI_ERROR (Status)) {\r
-        // Get information about the volume\r
-        Size = 0;\r
-        Status = Root->GetInfo (Root, &gEfiFileSystemInfoGuid, &Size, File->FsInfo);\r
-        if (Status == EFI_BUFFER_TOO_SMALL) {\r
-          File->FsInfo = AllocatePool (Size);\r
-          Status = Root->GetInfo (Root, &gEfiFileSystemInfoGuid, &Size, File->FsInfo);\r
-        }\r
-\r
-        // Get information about the file\r
-        Status = Root->Open (Root, &File->FsFileHandle, UnicodeFileName, OpenMode, 0);\r
-        if (!EFI_ERROR (Status)) {\r
-          Size = 0;\r
-          Status = File->FsFileHandle->GetInfo (File->FsFileHandle, &gEfiFileInfoGuid, &Size, NULL);\r
-          if (Status == EFI_BUFFER_TOO_SMALL) {\r
-            File->FsFileInfo = AllocatePool (Size);\r
-            Status = File->FsFileHandle->GetInfo (File->FsFileHandle, &gEfiFileInfoGuid, &Size, File->FsFileInfo);\r
-            if (!EFI_ERROR (Status)) {\r
-              File->Size = (UINTN)File->FsFileInfo->FileSize;\r
-              File->MaxPosition = (UINT64)File->Size;\r
-            }\r
-          }\r
-        }\r
-\r
-        Root->Close (Root);\r
-      }\r
-    }\r
-  } else if (File->Type == EfiOpenBlockIo) {\r
-    File->Size = (UINTN)File->MaxPosition;\r
-  }\r
-\r
-  return Status;\r
-}\r
-\r
-#define ToUpper(a)  ((((a) >= 'a') && ((a) <= 'z')) ? ((a) - 'a' + 'A') : (a))\r
-\r
-EFI_STATUS\r
-CompareGuidToString (\r
-  IN  EFI_GUID    *Guid,\r
-  IN  CHAR8       *String\r
-  )\r
-{\r
-  CHAR8       AsciiGuid[64];\r
-  CHAR8       *StringPtr;\r
-  CHAR8       *GuidPtr;\r
-\r
-  AsciiSPrint (AsciiGuid, sizeof(AsciiGuid), "%g", Guid);\r
-\r
-  StringPtr = String;\r
-  GuidPtr   = AsciiGuid;\r
-\r
-  while ((*StringPtr != '\0') && (*GuidPtr != '\0')) {\r
-    // Skip dashes\r
-    if (*StringPtr == '-') {\r
-      StringPtr++;\r
-      continue;\r
-    }\r
-\r
-    if (*GuidPtr == '-') {\r
-      GuidPtr++;\r
-      continue;\r
-    }\r
-\r
-    if (ToUpper(*StringPtr) != ToUpper(*GuidPtr)) {\r
-      return EFI_NOT_FOUND;\r
-    }\r
-\r
-    StringPtr++;\r
-    GuidPtr++;\r
-  }\r
-\r
-  return EFI_SUCCESS;\r
-}\r
-\r
-\r
-/**\r
-Internal work function to fill in EFI_OPEN_FILE information for the FV\r
-\r
-@param  File        Open file handle\r
-@param  FileName    Name of file after device stripped off\r
-\r
-\r
-**/\r
-EFI_STATUS\r
-EblFvFileDevicePath (\r
-  IN OUT EFI_OPEN_FILE  *File,\r
-  IN  CHAR8             *FileName,\r
-  IN  CONST UINT64      OpenMode\r
-  )\r
-{\r
-  EFI_STATUS                          Status;\r
-  EFI_STATUS                          GetNextFileStatus;\r
-  MEDIA_FW_VOL_FILEPATH_DEVICE_PATH   DevicePathNode;\r
-  EFI_DEVICE_PATH_PROTOCOL            *DevicePath;\r
-  UINTN                               Key;\r
-  UINT32                              AuthenticationStatus;\r
-  CHAR8                               AsciiSection[MAX_PATHNAME];\r
-  VOID                                *Section;\r
-  UINTN                               SectionSize;\r
-  EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL  *Fvb;\r
-  EFI_LBA                             Lba;\r
-  UINTN                               BlockSize;\r
-  UINTN                               NumberOfBlocks;\r
-  EFI_FIRMWARE_VOLUME_HEADER          *FvHeader = NULL;\r
-  UINTN                               Index;\r
-\r
-\r
-  Status = gBS->HandleProtocol (File->EfiHandle, &gEfiFirmwareVolume2ProtocolGuid, (VOID **)&File->Fv);\r
-  if (EFI_ERROR (Status)) {\r
-    return Status;\r
-  }\r
-\r
-  // Get FVB Info about the handle\r
-  Status = gBS->HandleProtocol (File->EfiHandle, &gEfiFirmwareVolumeBlockProtocolGuid, (VOID **)&Fvb);\r
-  if (!EFI_ERROR (Status)) {\r
-    Status = Fvb->GetPhysicalAddress (Fvb, &File->FvStart);\r
-    if (!EFI_ERROR (Status)) {\r
-      FvHeader = (EFI_FIRMWARE_VOLUME_HEADER *)(UINTN)File->FvStart;\r
-      File->FvHeaderSize = sizeof (EFI_FIRMWARE_VOLUME_HEADER);\r
-      for (Index = 0; FvHeader->BlockMap[Index].Length !=0; Index++) {\r
-        File->FvHeaderSize += sizeof (EFI_FV_BLOCK_MAP_ENTRY);\r
-      }\r
-\r
-      for (Lba = 0, File->FvSize = 0, NumberOfBlocks = 0; ; File->FvSize += (BlockSize * NumberOfBlocks), Lba += NumberOfBlocks) {\r
-        Status = Fvb->GetBlockSize (Fvb, Lba, &BlockSize, &NumberOfBlocks);\r
-        if (EFI_ERROR (Status)) {\r
-          break;\r
-        }\r
-      }\r
-    }\r
-  }\r
-\r
-\r
-  DevicePath = DevicePathFromHandle (File->EfiHandle);\r
-\r
-  if (*FileName == '\0') {\r
-    File->DevicePath = DuplicateDevicePath (DevicePath);\r
-    File->Size = File->FvSize;\r
-    File->MaxPosition = File->Size;\r
-  } else {\r
-    Key = 0;\r
-    do {\r
-      File->FvType = EFI_FV_FILETYPE_ALL;\r
-      GetNextFileStatus = File->Fv->GetNextFile (\r
-        File->Fv,\r
-        &Key,\r
-        &File->FvType,\r
-        &File->FvNameGuid,\r
-        &File->FvAttributes,\r
-        &File->Size\r
-        );\r
-      if (!EFI_ERROR (GetNextFileStatus)) {\r
-        // Compare GUID first\r
-        Status = CompareGuidToString (&File->FvNameGuid, FileName);\r
-        if (!EFI_ERROR(Status)) {\r
-          break;\r
-        }\r
-\r
-        Section = NULL;\r
-        Status = File->Fv->ReadSection (\r
-          File->Fv,\r
-          &File->FvNameGuid,\r
-          EFI_SECTION_USER_INTERFACE,\r
-          0,\r
-          &Section,\r
-          &SectionSize,\r
-          &AuthenticationStatus\r
-          );\r
-        if (!EFI_ERROR (Status)) {\r
-          UnicodeStrToAsciiStrS (Section, AsciiSection, MAX_PATHNAME);\r
-          if (AsciiStriCmp (FileName, AsciiSection) == 0) {\r
-            FreePool (Section);\r
-            break;\r
-          }\r
-          FreePool (Section);\r
-        }\r
-      }\r
-    } while (!EFI_ERROR (GetNextFileStatus));\r
-\r
-    if (EFI_ERROR (GetNextFileStatus)) {\r
-      return GetNextFileStatus;\r
-    }\r
-\r
-    if (OpenMode != EFI_SECTION_ALL) {\r
-      // Calculate the size of the section we are targeting\r
-      Section = NULL;\r
-      File->Size = 0;\r
-      Status = File->Fv->ReadSection (\r
-        File->Fv,\r
-        &File->FvNameGuid,\r
-        (EFI_SECTION_TYPE)OpenMode,\r
-        0,\r
-        &Section,\r
-        &File->Size,\r
-        &AuthenticationStatus\r
-        );\r
-      if (EFI_ERROR (Status)) {\r
-        return Status;\r
-      }\r
-    }\r
-\r
-    File->MaxPosition = File->Size;\r
-    EfiInitializeFwVolDevicepathNode (&DevicePathNode, &File->FvNameGuid);\r
-    File->DevicePath = AppendDevicePathNode (DevicePath, (EFI_DEVICE_PATH_PROTOCOL *)&DevicePathNode);\r
-  }\r
-\r
-\r
-  // FVB not required if FV was soft loaded...\r
-  return EFI_SUCCESS;\r
-}\r
-\r
-\r
-\r
-\r
-/**\r
-Open a device named by PathName. The PathName includes a device name and\r
-path separated by a :. See file header for more details on the PathName\r
-syntax. There is no checking to prevent a file from being opened more than\r
-one type.\r
-\r
-SectionType is only used to open an FV. Each file in an FV contains multiple\r
-sections and only the SectionType section is opened.\r
-\r
-For any file that is opened with EfiOpen() must be closed with EfiClose().\r
-\r
-@param  PathName    Path to parse to open\r
-@param  OpenMode    Same as EFI_FILE.Open()\r
-@param  SectionType Section in FV to open.\r
-\r
-@return NULL  Open failed\r
-@return Valid EFI_OPEN_FILE handle\r
-\r
-**/\r
-EFI_OPEN_FILE *\r
-EfiOpen (\r
-  IN        CHAR8               *PathName,\r
-  IN  CONST UINT64              OpenMode,\r
-  IN  CONST EFI_SECTION_TYPE    SectionType\r
-  )\r
-{\r
-  EFI_STATUS                Status;\r
-  EFI_OPEN_FILE             *File;\r
-  EFI_OPEN_FILE             FileData;\r
-  UINTN                     StrLen;\r
-  UINTN                     FileStart;\r
-  UINTN                     DevNumber = 0;\r
-  EFI_OPEN_FILE_GUARD       *GuardFile;\r
-  BOOLEAN                   VolumeNameMatch;\r
-  EFI_DEVICE_PATH_PROTOCOL  *DevicePath;\r
-  UINTN                     Size;\r
-  EFI_IP_ADDRESS            Ip;\r
-  CHAR8                     *CwdPlusPathName;\r
-  UINTN                     Index;\r
-  EFI_SECTION_TYPE          ModifiedSectionType;\r
-  UINTN                     AsciiLength;\r
-\r
-  EblUpdateDeviceLists ();\r
-\r
-  File = &FileData;\r
-  ZeroMem (File, sizeof (EFI_OPEN_FILE));\r
-\r
-  StrLen = AsciiStrSize (PathName);\r
-  if (StrLen <= 1) {\r
-    // Smallest valid path is 1 char and a null\r
-    return NULL;\r
-  }\r
-\r
-  for (FileStart = 0; FileStart < StrLen; FileStart++) {\r
-    if (PathName[FileStart] == ':') {\r
-      FileStart++;\r
-      break;\r
-    }\r
-  }\r
-\r
-  //\r
-  // Matching volume name has precedence over handle based names\r
-  //\r
-  VolumeNameMatch = EblMatchVolumeName (PathName, FileStart, &DevNumber);\r
-  if (!VolumeNameMatch) {\r
-    if (FileStart == StrLen) {\r
-      // No Volume name or device name, so try Current Working Directory\r
-      if (gCwd == NULL) {\r
-        // No CWD\r
-        return NULL;\r
-      }\r
-\r
-      // We could add a current working directory concept\r
-      AsciiLength = AsciiStrSize (gCwd) + AsciiStrSize (PathName);\r
-      CwdPlusPathName = AllocatePool (AsciiLength);\r
-      if (CwdPlusPathName == NULL) {\r
-        return NULL;\r
-      }\r
-\r
-      if ((PathName[0] == '/') || (PathName[0] == '\\')) {\r
-        // PathName starts in / so this means we go to the root of the device in the CWD.\r
-        CwdPlusPathName[0] = '\0';\r
-        for (FileStart = 0; gCwd[FileStart] != '\0'; FileStart++) {\r
-          CwdPlusPathName[FileStart] = gCwd[FileStart];\r
-          if (gCwd[FileStart] == ':') {\r
-            FileStart++;\r
-            CwdPlusPathName[FileStart] = '\0';\r
-            break;\r
-          }\r
-        }\r
-      } else {\r
-        AsciiStrCpyS (CwdPlusPathName, AsciiLength, gCwd);\r
-        StrLen = AsciiStrLen (gCwd);\r
-        if ((*PathName != '/') && (*PathName != '\\') && (gCwd[StrLen-1] != '/') && (gCwd[StrLen-1] != '\\')) {\r
-          AsciiStrCatS (CwdPlusPathName, AsciiLength, "\\");\r
-        }\r
-      }\r
-\r
-      AsciiStrCatS (CwdPlusPathName, AsciiLength, PathName);\r
-      if (AsciiStrStr (CwdPlusPathName, ":") == NULL) {\r
-        // Extra error check to make sure we don't recurse and blow stack\r
-        return NULL;\r
-      }\r
-\r
-      File = EfiOpen (CwdPlusPathName, OpenMode, SectionType);\r
-      FreePool (CwdPlusPathName);\r
-      return File;\r
-    }\r
-\r
-    DevNumber = EblConvertDevStringToNumber ((CHAR8 *)PathName);\r
-  }\r
-\r
-  File->DeviceName = AllocatePool (StrLen);\r
-  AsciiStrCpyS (File->DeviceName, StrLen, PathName);\r
-  File->DeviceName[FileStart - 1] = '\0';\r
-  File->FileName = &File->DeviceName[FileStart];\r
-  if (File->FileName[0] == '\0') {\r
-    // if it is just a file name use / as root\r
-    File->FileName = "\\";\r
-  }\r
-\r
-  //\r
-  // Use best match algorithm on the dev names so we only need to look at the\r
-  // first few charters to match the full device name. Short name forms are\r
-  // legal from the caller.\r
-  //\r
-  Status = EFI_SUCCESS;\r
-  if (*PathName == 'f' || *PathName == 'F' || VolumeNameMatch) {\r
-    if (PathName[1] == 's' || PathName[1] == 'S' || VolumeNameMatch) {\r
-      if (DevNumber >= mFsCount) {\r
-        goto ErrorExit;\r
-      }\r
-      File->Type = EfiOpenFileSystem;\r
-      File->EfiHandle = mFs[DevNumber];\r
-      Status = EblFileDevicePath (File, &PathName[FileStart], OpenMode);\r
-\r
-    } else if (PathName[1] == 'v' || PathName[1] == 'V') {\r
-      if (DevNumber >= mFvCount) {\r
-        goto ErrorExit;\r
-      }\r
-      File->Type = EfiOpenFirmwareVolume;\r
-      File->EfiHandle = mFv[DevNumber];\r
-\r
-      if ((PathName[FileStart] == '/') || (PathName[FileStart] == '\\')) {\r
-        // Skip leading / as its not really needed for the FV since no directories are supported\r
-        FileStart++;\r
-      }\r
-\r
-      // Check for 2nd :\r
-      ModifiedSectionType = SectionType;\r
-      for (Index = FileStart; PathName[Index] != '\0'; Index++) {\r
-        if (PathName[Index] == ':') {\r
-          // Support fv0:\DxeCore:0x10\r
-          // This means open the PE32 Section of the file\r
-          ModifiedSectionType = (EFI_SECTION_TYPE)AsciiStrHexToUintn (&PathName[Index + 1]);\r
-          PathName[Index] = '\0';\r
-        }\r
-      }\r
-      File->FvSectionType = ModifiedSectionType;\r
-      Status = EblFvFileDevicePath (File, &PathName[FileStart], ModifiedSectionType);\r
-    }\r
-  } else if ((*PathName == 'A') || (*PathName == 'a')) {\r
-    // Handle a:0x10000000:0x1234 address form a:ADDRESS:SIZE\r
-    File->Type = EfiOpenMemoryBuffer;\r
-    // 1st colon is at PathName[FileStart - 1]\r
-    File->Buffer = (VOID *)AsciiStrHexToUintn (&PathName[FileStart]);\r
-\r
-    // Find 2nd colon\r
-    while ((PathName[FileStart] != ':') && (PathName[FileStart] != '\0')) {\r
-      FileStart++;\r
-    }\r
-\r
-    // If we ran out of string, there's no extra data\r
-    if (PathName[FileStart] == '\0') {\r
-      File->Size = 0;\r
-    } else {\r
-      File->Size = AsciiStrHexToUintn (&PathName[FileStart + 1]);\r
-    }\r
-\r
-    // if there's no number after the second colon, default\r
-    // the end of memory\r
-    if (File->Size == 0) {\r
-      File->Size =  (UINTN)(0 - (UINTN)File->Buffer);\r
-    }\r
-\r
-    File->MaxPosition = File->Size;\r
-    File->BaseOffset = (UINTN)File->Buffer;\r
-\r
-  } else if (*PathName== 'l' || *PathName == 'L') {\r
-    if (DevNumber >= mLoadFileCount) {\r
-      goto ErrorExit;\r
-    }\r
-    File->Type = EfiOpenLoadFile;\r
-    File->EfiHandle = mLoadFile[DevNumber];\r
-\r
-    Status = gBS->HandleProtocol (File->EfiHandle, &gEfiLoadFileProtocolGuid, (VOID **)&File->LoadFile);\r
-    if (EFI_ERROR (Status)) {\r
-      goto ErrorExit;\r
-    }\r
-\r
-    Status = gBS->HandleProtocol (File->EfiHandle, &gEfiDevicePathProtocolGuid, (VOID **)&DevicePath);\r
-    if (EFI_ERROR (Status)) {\r
-      goto ErrorExit;\r
-    }\r
-    File->DevicePath = DuplicateDevicePath (DevicePath);\r
-\r
-  } else if (*PathName == 'b' || *PathName == 'B') {\r
-    // Handle b#:0x10000000:0x1234 address form b#:ADDRESS:SIZE\r
-    if (DevNumber >= mBlkIoCount) {\r
-      goto ErrorExit;\r
-    }\r
-    File->Type = EfiOpenBlockIo;\r
-    File->EfiHandle = mBlkIo[DevNumber];\r
-    EblFileDevicePath (File, "", OpenMode);\r
-\r
-    // 1st colon is at PathName[FileStart - 1]\r
-    File->DiskOffset = AsciiStrHexToUintn (&PathName[FileStart]);\r
-\r
-    // Find 2nd colon\r
-    while ((PathName[FileStart] != ':') && (PathName[FileStart] != '\0')) {\r
-      FileStart++;\r
-    }\r
-\r
-    // If we ran out of string, there's no extra data\r
-    if (PathName[FileStart] == '\0') {\r
-      Size = 0;\r
-    } else {\r
-      Size = AsciiStrHexToUintn (&PathName[FileStart + 1]);\r
-    }\r
-\r
-    // if a zero size is passed in (or the size is left out entirely),\r
-    // go to the end of the device.\r
-    if (Size == 0) {\r
-      File->Size = File->Size - File->DiskOffset;\r
-    } else {\r
-      File->Size = Size;\r
-    }\r
-\r
-    File->MaxPosition = File->Size;\r
-    File->BaseOffset = File->DiskOffset;\r
-  } else if ((*PathName) >= '0' && (*PathName <= '9')) {\r
-\r
-    // Get current IP address\r
-    Status = EblGetCurrentIpAddress (&Ip);\r
-    if (EFI_ERROR(Status)) {\r
-      AsciiPrint("Device IP Address is not configured.\n");\r
-      goto ErrorExit;\r
-    }\r
-\r
-\r
-    // Parse X.X.X.X:Filename, only support IPv4 TFTP for now...\r
-    File->Type = EfiOpenTftp;\r
-    File->IsDirty = FALSE;\r
-    File->IsBufferValid = FALSE;\r
-\r
-    Status = ConvertIpStringToEfiIp (PathName, &File->ServerIp);\r
-  }\r
-\r
-  if (EFI_ERROR (Status)) {\r
-    goto ErrorExit;\r
-  }\r
-\r
-  GuardFile = (EFI_OPEN_FILE_GUARD *)AllocateZeroPool (sizeof (EFI_OPEN_FILE_GUARD));\r
-  if (GuardFile == NULL) {\r
-    goto ErrorExit;\r
-  }\r
-\r
-  GuardFile->Header = EFI_OPEN_FILE_GUARD_HEADER;\r
-  CopyMem (&(GuardFile->File), &FileData, sizeof (EFI_OPEN_FILE));\r
-  GuardFile->Footer = EFI_OPEN_FILE_GUARD_FOOTER;\r
-\r
-  return &(GuardFile->File);\r
-\r
-ErrorExit:\r
-  FreePool (File->DeviceName);\r
-  return NULL;\r
-}\r
-\r
-#define FILE_COPY_CHUNK 0x01000000\r
-\r
-EFI_STATUS\r
-EfiCopyFile (\r
-  IN        CHAR8               *DestinationFile,\r
-  IN        CHAR8               *SourceFile\r
-  )\r
-{\r
-  EFI_OPEN_FILE *Source      = NULL;\r
-  EFI_OPEN_FILE *Destination = NULL;\r
-  EFI_STATUS    Status       = EFI_SUCCESS;\r
-  VOID          *Buffer      = NULL;\r
-  UINTN         Size;\r
-  UINTN         Offset;\r
-  UINTN         Chunk = FILE_COPY_CHUNK;\r
-\r
-  Source = EfiOpen (SourceFile, EFI_FILE_MODE_READ, 0);\r
-  if (Source == NULL) {\r
-    AsciiPrint("Source file open error.\n");\r
-    Status = EFI_NOT_FOUND;\r
-    goto Exit;\r
-  }\r
-\r
-  Destination = EfiOpen (DestinationFile, EFI_FILE_MODE_WRITE | EFI_FILE_MODE_CREATE, 0);\r
-  if (Destination == NULL) {\r
-    AsciiPrint("Destination file open error.\n");\r
-    Status = EFI_NOT_FOUND;\r
-    goto Exit;\r
-  }\r
-\r
-  Buffer = AllocatePool(FILE_COPY_CHUNK);\r
-  if (Buffer == NULL) {\r
-    Status = EFI_OUT_OF_RESOURCES;\r
-    goto Exit;\r
-  }\r
-\r
-  Size = EfiTell(Source, NULL);\r
-\r
-  for (Offset = 0; Offset + FILE_COPY_CHUNK <= Size; Offset += Chunk) {\r
-    Chunk = FILE_COPY_CHUNK;\r
-\r
-    Status = EfiRead(Source, Buffer, &Chunk);\r
-    if (EFI_ERROR(Status)) {\r
-      AsciiPrint("Read file error %r\n", Status);\r
-      goto Exit;\r
-    }\r
-\r
-    Status = EfiWrite(Destination, Buffer, &Chunk);\r
-    if (EFI_ERROR(Status)) {\r
-      AsciiPrint("Write file error %r\n", Status);\r
-      goto Exit;\r
-    }\r
-  }\r
-\r
-  // Any left over?\r
-  if (Offset < Size) {\r
-    Chunk = Size - Offset;\r
-\r
-    Status = EfiRead(Source, Buffer, &Chunk);\r
-    if (EFI_ERROR(Status)) {\r
-      AsciiPrint("Read file error\n");\r
-      goto Exit;\r
-    }\r
-\r
-    Status = EfiWrite(Destination, Buffer, &Chunk);\r
-    if (EFI_ERROR(Status)) {\r
-      AsciiPrint("Write file error\n");\r
-      goto Exit;\r
-    }\r
-  }\r
-\r
-Exit:\r
-  if (Source != NULL) {\r
-    Status = EfiClose(Source);\r
-    if (EFI_ERROR(Status)) {\r
-      AsciiPrint("Source close error");\r
-    }\r
-  }\r
-\r
-  if (Destination != NULL) {\r
-    Status = EfiClose(Destination);\r
-    if (EFI_ERROR(Status)) {\r
-      AsciiPrint("Destination close error");\r
-    }\r
-  }\r
-\r
-  if (Buffer != NULL) {\r
-    FreePool(Buffer);\r
-  }\r
-\r
-  return Status;\r
-}\r
-\r
-/**\r
-Use DeviceType and Index to form a valid PathName and try and open it.\r
-\r
-@param  DeviceType  Device type to open\r
-@param  Index       Device Index to use. Zero relative.\r
-\r
-@return NULL  Open failed\r
-@return Valid EFI_OPEN_FILE handle\r
-\r
-**/\r
-EFI_OPEN_FILE  *\r
-EfiDeviceOpenByType (\r
-  IN  EFI_OPEN_FILE_TYPE    DeviceType,\r
-  IN  UINTN                 Index\r
-  )\r
-{\r
-  CHAR8   *DevStr;\r
-  CHAR8   Path[MAX_CMD_LINE];\r
-\r
-  switch (DeviceType) {\r
-  case EfiOpenLoadFile:\r
-    DevStr = "loadfile%d:";\r
-    break;\r
-  case EfiOpenFirmwareVolume:\r
-    DevStr = "fv%d:";\r
-    break;\r
-  case EfiOpenFileSystem:\r
-    DevStr = "fs%d:";\r
-    break;\r
-  case EfiOpenBlockIo:\r
-    DevStr = "blk%d:";\r
-    break;\r
-  case EfiOpenMemoryBuffer:\r
-    DevStr = "a%d:";\r
-    break;\r
-  default:\r
-    return NULL;\r
-  }\r
-\r
-  AsciiSPrint (Path, MAX_PATHNAME, DevStr, Index);\r
-\r
-  return EfiOpen (Path, EFI_FILE_MODE_READ, 0);\r
-}\r
-\r
-\r
-/**\r
-Close a file handle opened by EfiOpen() and free all resources allocated by\r
-EfiOpen().\r
-\r
-@param  Stream    Open File Handle\r
-\r
-@return EFI_INVALID_PARAMETER  Stream is not an Open File\r
-@return EFI_SUCCESS            Steam closed\r
-\r
-**/\r
-EFI_STATUS\r
-EfiClose (\r
-  IN  EFI_OPEN_FILE     *File\r
-  )\r
-{\r
-  EFI_STATUS          Status;\r
-  UINT64              TftpBufferSize;\r
-\r
-  if (!FileHandleValid (File)) {\r
-    return EFI_INVALID_PARAMETER;\r
-  }\r
-\r
-  //Write the buffer contents to TFTP file.\r
-  if ((File->Type == EfiOpenTftp) && (File->IsDirty)) {\r
-\r
-    TftpBufferSize = File->Size;\r
-    Status = EblMtftp (\r
-      EFI_PXE_BASE_CODE_TFTP_WRITE_FILE,\r
-      File->Buffer,\r
-      TRUE,\r
-      &TftpBufferSize,\r
-      NULL,\r
-      &File->ServerIp,\r
-      (UINT8 *)File->FileName,\r
-      NULL,\r
-      FALSE\r
-      );\r
-    if (EFI_ERROR(Status)) {\r
-      AsciiPrint("TFTP error during APPLE_NSP_TFTP_WRITE_FILE: %r\n", Status);\r
-      return Status;\r
-    }\r
-  }\r
-\r
-  if ((File->Type == EfiOpenLoadFile) ||\r
-    ((File->Type == EfiOpenTftp) && (File->IsBufferValid == TRUE)) ||\r
-    ((File->Type == EfiOpenFirmwareVolume) && (File->IsBufferValid == TRUE))) {\r
-    EblFreePool(File->Buffer);\r
-  }\r
-\r
-  EblFreePool (File->DevicePath);\r
-  EblFreePool (File->DeviceName);\r
-  EblFreePool (File->FsFileInfo);\r
-  EblFreePool (File->FsInfo);\r
-\r
-  if (File->FsFileHandle != NULL) {\r
-    File->FsFileHandle->Close (File->FsFileHandle);\r
-  }\r
-\r
-  // Need to free File and it's Guard structures\r
-  EblFreePool (BASE_CR (File, EFI_OPEN_FILE_GUARD, File));\r
-  return EFI_SUCCESS;\r
-}\r
-\r
-\r
-/**\r
-Return the size of the file represented by Stream. Also return the current\r
-Seek position. Opening a file will enable a valid file size to be returned.\r
-LoadFile is an exception as a load file size is set to zero.\r
-\r
-@param  Stream    Open File Handle\r
-\r
-@return 0         Stream is not an Open File or a valid LoadFile handle\r
-\r
-**/\r
-UINTN\r
-EfiTell (\r
-  IN  EFI_OPEN_FILE     *File,\r
-  OUT EFI_LBA           *CurrentPosition    OPTIONAL\r
-  )\r
-{\r
-  EFI_STATUS Status;\r
-  UINT64     BufferSize = 0;\r
-\r
-  if (!FileHandleValid (File)) {\r
-    return 0;\r
-  }\r
-\r
-  if (CurrentPosition != NULL) {\r
-    *CurrentPosition = File->CurrentPosition;\r
-  }\r
-\r
-  if (File->Type == EfiOpenLoadFile) {\r
-    // Figure out the File->Size\r
-    File->Buffer = NULL;\r
-    File->Size   = 0;\r
-    Status = File->LoadFile->LoadFile (File->LoadFile, File->DevicePath, FALSE, &File->Size, File->Buffer);\r
-    if (Status != EFI_BUFFER_TOO_SMALL) {\r
-      return 0;\r
-    }\r
-\r
-    File->MaxPosition = (UINT64)File->Size;\r
-  } else if (File->Type == EfiOpenTftp) {\r
-\r
-    Status = EblMtftp (\r
-      EFI_PXE_BASE_CODE_TFTP_GET_FILE_SIZE,\r
-      NULL,\r
-      FALSE,\r
-      &BufferSize,\r
-      NULL,\r
-      &File->ServerIp,\r
-      (UINT8 *)File->FileName,\r
-      NULL,\r
-      TRUE\r
-      );\r
-    if (EFI_ERROR(Status)) {\r
-      AsciiPrint("TFTP error during APPLE_NSP_TFTP_GET_FILE_SIZE: %r\n", Status);\r
-      return 0;\r
-    }\r
-\r
-    File->Size        = (UINTN)BufferSize;\r
-    File->MaxPosition = File->Size;\r
-  }\r
-\r
-  return File->Size;\r
-}\r
-\r
-\r
-/**\r
-Seek to the Offset location in the file. LoadFile and FV device types do\r
-not support EfiSeek(). It is not possible to grow the file size using\r
-EfiSeek().\r
-\r
-SeekType defines how use Offset to calculate the new file position:\r
-EfiSeekStart  : Position = Offset\r
-EfiSeekCurrent: Position is Offset bytes from the current position\r
-EfiSeekEnd    : Only supported if Offset is zero to seek to end of file.\r
-\r
-@param  Stream    Open File Handle\r
-@param  Offset    Offset to seek too.\r
-@param  SeekType  Type of seek to perform\r
-\r
-\r
-@return EFI_INVALID_PARAMETER  Stream is not an Open File\r
-@return EFI_UNSUPPORTED        LoadFile and FV do not support Seek\r
-@return EFI_NOT_FOUND          Seek past the end of the file.\r
-@return EFI_SUCCESS            Steam closed\r
-\r
-**/\r
-EFI_STATUS\r
-EfiSeek (\r
-  IN  EFI_OPEN_FILE     *File,\r
-  IN  EFI_LBA           Offset,\r
-  IN  EFI_SEEK_TYPE     SeekType\r
-  )\r
-{\r
-  EFI_STATUS    Status;\r
-  UINT64        CurrentPosition;\r
-\r
-  if (!FileHandleValid (File)) {\r
-    return EFI_INVALID_PARAMETER;\r
-  }\r
-\r
-  if (File->Type == EfiOpenLoadFile) {\r
-    // LoadFile does not support Seek\r
-    return EFI_UNSUPPORTED;\r
-  }\r
-\r
-  CurrentPosition = File->CurrentPosition;\r
-  switch (SeekType) {\r
-  case EfiSeekStart:\r
-    if (Offset > File->MaxPosition) {\r
-      return EFI_NOT_FOUND;\r
-    }\r
-    CurrentPosition = Offset;\r
-    break;\r
-\r
-  case EfiSeekCurrent:\r
-    if ((File->CurrentPosition + Offset) > File->MaxPosition) {\r
-      return EFI_NOT_FOUND;\r
-    }\r
-    CurrentPosition += Offset;\r
-    break;\r
-\r
-  case EfiSeekEnd:\r
-    if (Offset != 0) {\r
-      // We don't support growing file size via seeking past end of file\r
-      return EFI_UNSUPPORTED;\r
-    }\r
-    CurrentPosition = File->MaxPosition;\r
-    break;\r
-\r
-  default:\r
-    return EFI_NOT_FOUND;\r
-  }\r
-\r
-  Status = EFI_SUCCESS;\r
-  if (File->FsFileHandle != NULL) {\r
-    Status = File->FsFileHandle->SetPosition (File->FsFileHandle, CurrentPosition);\r
-  }\r
-\r
-  if (!EFI_ERROR (Status)) {\r
-    File->CurrentPosition = CurrentPosition;\r
-  }\r
-\r
-  return Status;\r
-}\r
-\r
-EFI_STATUS\r
-CacheTftpFile (\r
-  IN OUT  EFI_OPEN_FILE *File\r
-  )\r
-{\r
-  EFI_STATUS          Status;\r
-  UINT64              TftpBufferSize;\r
-\r
-  if (File->IsBufferValid) {\r
-    return EFI_SUCCESS;\r
-  }\r
-\r
-  // Make sure the file size is set.\r
-  EfiTell (File, NULL);\r
-\r
-  //Allocate a buffer to hold the whole file.\r
-  File->Buffer = AllocatePool(File->Size);\r
-  if (File->Buffer == NULL) {\r
-    return EFI_OUT_OF_RESOURCES;\r
-  }\r
-\r
-  TftpBufferSize = File->Size;\r
-\r
-  Status = EblMtftp (\r
-    EFI_PXE_BASE_CODE_TFTP_READ_FILE,\r
-    File->Buffer,\r
-    FALSE,\r
-    &TftpBufferSize,\r
-    NULL,\r
-    &File->ServerIp,\r
-    (UINT8 *)File->FileName,\r
-    NULL,\r
-    FALSE);\r
-  if (EFI_ERROR(Status)) {\r
-    AsciiPrint("TFTP error during APPLE_NSP_TFTP_READ_FILE: %r\n", Status);\r
-    FreePool(File->Buffer);\r
-    return Status;\r
-  }\r
-\r
-  // Set the buffer valid flag.\r
-  File->IsBufferValid = TRUE;\r
-\r
-  return Status;\r
-}\r
-\r
-/**\r
-Read BufferSize bytes from the current location in the file. For load file,\r
-FV, and TFTP case you must read the entire file.\r
-\r
-@param  Stream      Open File Handle\r
-@param  Buffer      Caller allocated buffer.\r
-@param  BufferSize  Size of buffer in bytes.\r
-\r
-\r
-@return EFI_SUCCESS           Stream is not an Open File\r
-@return EFI_END_OF_FILE Tried to read past the end of the file\r
-@return EFI_INVALID_PARAMETER Stream is not an open file handle\r
-@return EFI_BUFFER_TOO_SMALL  Buffer is not big enough to do the read\r
-@return "other"               Error returned from device read\r
-\r
-**/\r
-EFI_STATUS\r
-EfiRead (\r
-  IN  EFI_OPEN_FILE       *File,\r
-  OUT VOID                *Buffer,\r
-  OUT UINTN               *BufferSize\r
-  )\r
-{\r
-  EFI_STATUS            Status;\r
-  UINT32                AuthenticationStatus;\r
-  EFI_DISK_IO_PROTOCOL  *DiskIo;\r
-\r
-  if (!FileHandleValid (File)) {\r
-    return EFI_INVALID_PARAMETER;\r
-  }\r
-\r
-  // Don't read past the end of the file.\r
-  if ((File->CurrentPosition + *BufferSize) > File->MaxPosition) {\r
-    return EFI_END_OF_FILE;\r
-  }\r
-\r
-  switch (File->Type) {\r
-  case EfiOpenLoadFile:\r
-    // Figure out the File->Size\r
-    EfiTell (File, NULL);\r
-\r
-    Status = File->LoadFile->LoadFile (File->LoadFile, File->DevicePath, FALSE, BufferSize, Buffer);\r
-    break;\r
-\r
-  case EfiOpenFirmwareVolume:\r
-    if (CompareGuid (&File->FvNameGuid, &gZeroGuid)) {\r
-      // This is the entire FV device, so treat like a memory buffer\r
-      CopyMem (Buffer, (VOID *)(UINTN)(File->FvStart + File->CurrentPosition), *BufferSize);\r
-      File->CurrentPosition += *BufferSize;\r
-      Status = EFI_SUCCESS;\r
-    } else {\r
-      if (File->Buffer == NULL) {\r
-        if (File->FvSectionType == EFI_SECTION_ALL) {\r
-          Status = File->Fv->ReadFile (\r
-            File->Fv,\r
-            &File->FvNameGuid,\r
-            (VOID **)&File->Buffer,\r
-            &File->Size,\r
-            &File->FvType,\r
-            &File->FvAttributes,\r
-            &AuthenticationStatus\r
-            );\r
-        } else {\r
-          Status = File->Fv->ReadSection (\r
-            File->Fv,\r
-            &File->FvNameGuid,\r
-            File->FvSectionType,\r
-            0,\r
-            (VOID **)&File->Buffer,\r
-            &File->Size,\r
-            &AuthenticationStatus\r
-            );\r
-        }\r
-        if (EFI_ERROR (Status)) {\r
-          return Status;\r
-        }\r
-        File->IsBufferValid = TRUE;\r
-      }\r
-      // Operate on the cached buffer so Seek will work\r
-      CopyMem (Buffer, File->Buffer + File->CurrentPosition, *BufferSize);\r
-      File->CurrentPosition += *BufferSize;\r
-      Status = EFI_SUCCESS;\r
-    }\r
-    break;\r
-\r
-  case EfiOpenMemoryBuffer:\r
-    CopyMem (Buffer, File->Buffer + File->CurrentPosition, *BufferSize);\r
-    File->CurrentPosition += *BufferSize;\r
-    Status = EFI_SUCCESS;\r
-    break;\r
-\r
-  case EfiOpenFileSystem:\r
-    Status = File->FsFileHandle->Read (File->FsFileHandle, BufferSize, Buffer);\r
-    File->CurrentPosition += *BufferSize;\r
-    break;\r
-\r
-  case EfiOpenBlockIo:\r
-    Status = gBS->HandleProtocol(File->EfiHandle, &gEfiDiskIoProtocolGuid, (VOID **)&DiskIo);\r
-    if (!EFI_ERROR(Status)) {\r
-      Status = DiskIo->ReadDisk(DiskIo, File->FsBlockIoMedia->MediaId, File->DiskOffset + File->CurrentPosition, *BufferSize, Buffer);\r
-    }\r
-    File->CurrentPosition += *BufferSize;\r
-    break;\r
-\r
-  case EfiOpenTftp:\r
-    // Cache the file if it hasn't been cached yet.\r
-    if (File->IsBufferValid == FALSE) {\r
-      Status = CacheTftpFile (File);\r
-      if (EFI_ERROR (Status)) {\r
-        return Status;\r
-      }\r
-    }\r
-\r
-    // Copy out the requested data\r
-    CopyMem (Buffer, File->Buffer + File->CurrentPosition, *BufferSize);\r
-    File->CurrentPosition += *BufferSize;\r
-\r
-    Status = EFI_SUCCESS;\r
-    break;\r
-\r
-  default:\r
-    return EFI_INVALID_PARAMETER;\r
-  };\r
-\r
-  return Status;\r
-}\r
-\r
-\r
-/**\r
-Read the entire file into a buffer. This routine allocates the buffer and\r
-returns it to the user full of the read data.\r
-\r
-This is very useful for load file where it's hard to know how big the buffer\r
-must be.\r
-\r
-@param  Stream      Open File Handle\r
-@param  Buffer      Pointer to buffer to return.\r
-@param  BufferSize  Pointer to Size of buffer return..\r
-\r
-\r
-@return EFI_SUCCESS           Stream is not an Open File\r
-@return EFI_END_OF_FILE       Tried to read past the end of the file\r
-@return EFI_INVALID_PARAMETER Stream is not an open file handle\r
-@return EFI_BUFFER_TOO_SMALL  Buffer is not big enough to do the read\r
-@return "other"               Error returned from device read\r
-\r
-**/\r
-EFI_STATUS\r
-EfiReadAllocatePool (\r
-  IN  EFI_OPEN_FILE     *File,\r
-  OUT VOID              **Buffer,\r
-  OUT UINTN             *BufferSize\r
-  )\r
-{\r
-  if (!FileHandleValid (File)) {\r
-    return EFI_INVALID_PARAMETER;\r
-  }\r
-\r
-  // Loadfile defers file size determination on Open so use tell to find it\r
-  EfiTell (File, NULL);\r
-\r
-  *BufferSize = File->Size;\r
-  *Buffer = AllocatePool (*BufferSize);\r
-  if (*Buffer == NULL) {\r
-    return EFI_NOT_FOUND;\r
-  }\r
-\r
-  return EfiRead (File, *Buffer, BufferSize);\r
-}\r
-\r
-\r
-/**\r
-Write data back to the file. For TFTP case you must write the entire file.\r
-\r
-@param  Stream      Open File Handle\r
-@param  Buffer      Pointer to buffer to return.\r
-@param  BufferSize  Pointer to Size of buffer return..\r
-\r
-\r
-@return EFI_SUCCESS           Stream is not an Open File\r
-@return EFI_END_OF_FILE       Tried to read past the end of the file\r
-@return EFI_INVALID_PARAMETER Stream is not an open file handle\r
-@return EFI_BUFFER_TOO_SMALL  Buffer is not big enough to do the read\r
-@return "other"               Error returned from device write\r
-\r
-**/\r
-EFI_STATUS\r
-EfiWrite (\r
-  IN  EFI_OPEN_FILE   *File,\r
-  OUT VOID            *Buffer,\r
-  OUT UINTN           *BufferSize\r
-  )\r
-{\r
-  EFI_STATUS              Status;\r
-  EFI_FV_WRITE_FILE_DATA  FileData;\r
-  EFI_DISK_IO_PROTOCOL    *DiskIo;\r
-\r
-  if (!FileHandleValid (File)) {\r
-    return EFI_INVALID_PARAMETER;\r
-  }\r
-\r
-  switch (File->Type) {\r
-  case EfiOpenMemoryBuffer:\r
-    if ((File->CurrentPosition + *BufferSize) > File->MaxPosition) {\r
-      return EFI_END_OF_FILE;\r
-    }\r
-\r
-    CopyMem (File->Buffer + File->CurrentPosition, Buffer, *BufferSize);\r
-    File->CurrentPosition += *BufferSize;\r
-    Status = EFI_SUCCESS;\r
-\r
-  case EfiOpenLoadFile:\r
-    // LoadFile device is read only be definition\r
-    Status = EFI_UNSUPPORTED;\r
-\r
-  case EfiOpenFirmwareVolume:\r
-    if (File->FvSectionType != EFI_SECTION_ALL) {\r
-      // Writes not support to a specific section. You have to update entire file\r
-      return EFI_UNSUPPORTED;\r
-    }\r
-\r
-    FileData.NameGuid       = &(File->FvNameGuid);\r
-    FileData.Type           = File->FvType;\r
-    FileData.FileAttributes = File->FvAttributes;\r
-    FileData.Buffer         = Buffer;\r
-    FileData.BufferSize     = (UINT32)*BufferSize;\r
-    Status = File->Fv->WriteFile (File->Fv, 1, EFI_FV_UNRELIABLE_WRITE, &FileData);\r
-    break;\r
-\r
-  case EfiOpenFileSystem:\r
-    Status = File->FsFileHandle->Write (File->FsFileHandle, BufferSize, Buffer);\r
-    File->CurrentPosition += *BufferSize;\r
-    break;\r
-\r
-  case EfiOpenBlockIo:\r
-    if ((File->CurrentPosition + *BufferSize) > File->MaxPosition) {\r
-      return EFI_END_OF_FILE;\r
-    }\r
-\r
-    Status = gBS->HandleProtocol (File->EfiHandle, &gEfiDiskIoProtocolGuid, (VOID **)&DiskIo);\r
-    if (!EFI_ERROR(Status)) {\r
-      Status = DiskIo->WriteDisk (DiskIo, File->FsBlockIoMedia->MediaId, File->DiskOffset + File->CurrentPosition, *BufferSize, Buffer);\r
-    }\r
-    File->CurrentPosition += *BufferSize;\r
-    break;\r
-\r
-  case EfiOpenTftp:\r
-    // Cache the file if it hasn't been cached yet.\r
-    if (File->IsBufferValid == FALSE) {\r
-      Status = CacheTftpFile(File);\r
-      if (EFI_ERROR(Status)) {\r
-        return Status;\r
-      }\r
-    }\r
-\r
-    // Don't overwrite the buffer\r
-    if ((File->CurrentPosition + *BufferSize) > File->MaxPosition) {\r
-      UINT8 *TempBuffer;\r
-\r
-      TempBuffer = File->Buffer;\r
-\r
-      File->Buffer = AllocatePool ((UINTN)(File->CurrentPosition + *BufferSize));\r
-      if (File->Buffer == NULL) {\r
-        return EFI_OUT_OF_RESOURCES;\r
-      }\r
-\r
-      CopyMem (File->Buffer, TempBuffer, File->Size);\r
-\r
-      FreePool (TempBuffer);\r
-\r
-      File->Size = (UINTN)(File->CurrentPosition + *BufferSize);\r
-      File->MaxPosition = (UINT64)File->Size;\r
-    }\r
-\r
-    // Copy in the requested data\r
-    CopyMem (File->Buffer + File->CurrentPosition, Buffer, *BufferSize);\r
-    File->CurrentPosition += *BufferSize;\r
-\r
-    // Mark the file dirty\r
-    File->IsDirty = TRUE;\r
-\r
-    Status = EFI_SUCCESS;\r
-    break;\r
-\r
-  default:\r
-    Status = EFI_INVALID_PARAMETER;\r
-  };\r
-\r
-  return Status;\r
-}\r
-\r
-\r
-/**\r
-Given Cwd expand Path to remove .. and replace them with real\r
-directory names.\r
-\r
-@param  Cwd     Current Working Directory\r
-@param  Path    Path to expand\r
-\r
-@return NULL     Cwd or Path are not valid\r
-@return 'other'  Path with .. expanded\r
-\r
-**/\r
-CHAR8 *\r
-ExpandPath (\r
-  IN CHAR8    *Cwd,\r
-  IN CHAR8    *Path\r
-  )\r
-{\r
-  CHAR8   *NewPath;\r
-  CHAR8   *Work, *Start, *End;\r
-  UINTN   StrLen, AllocLen;\r
-  INTN    i;\r
-\r
-  if (Cwd == NULL || Path == NULL) {\r
-    return NULL;\r
-  }\r
-\r
-  StrLen = AsciiStrSize (Cwd);\r
-  if (StrLen <= 2) {\r
-    // Smallest valid path is 1 char and a null\r
-    return NULL;\r
-  }\r
-\r
-  StrLen = AsciiStrSize (Path);\r
-  AllocLen = AsciiStrSize (Cwd) + StrLen + 1;\r
-  NewPath = AllocatePool (AllocLen);\r
-  if (NewPath == NULL) {\r
-    return NULL;\r
-  }\r
-  AsciiStrCpyS (NewPath, AllocLen, Cwd);\r
-\r
-  End = Path + StrLen;\r
-  for (Start = Path ;;) {\r
-    Work = AsciiStrStr (Start, "..") ;\r
-    if (Work == NULL) {\r
-      // Remaining part of Path contains no more ..\r
-      break;\r
-    }\r
-\r
-    // append path prior to ..\r
-    AsciiStrnCatS (NewPath, AllocLen, Start, Work - Start);\r
-    StrLen = AsciiStrLen (NewPath);\r
-    for (i = StrLen; i >= 0; i--) {\r
-      if (NewPath[i] == ':') {\r
-        // too many ..\r
-        return NULL;\r
-      }\r
-      if (NewPath[i] == '/' || NewPath[i] == '\\') {\r
-        if ((i > 0) && (NewPath[i-1] == ':')) {\r
-          // leave the / before a :\r
-          NewPath[i+1] = '\0';\r
-        } else {\r
-          // replace / will Null to remove trailing file/dir reference\r
-          NewPath[i] = '\0';\r
-        }\r
-        break;\r
-      }\r
-    }\r
-\r
-    Start = Work + 3;\r
-  }\r
-\r
-  // Handle the path that remains after the ..\r
-  AsciiStrnCatS (NewPath, AllocLen, Start, End - Start);\r
-\r
-  return NewPath;\r
-}\r
-\r
-\r
-/**\r
-Set the Current Working Directory (CWD). If a call is made to EfiOpen () and\r
-the path does not contain a device name, The CWD is prepended to the path.\r
-\r
-@param  Cwd     Current Working Directory to set\r
-\r
-\r
-@return EFI_SUCCESS           CWD is set\r
-@return EFI_INVALID_PARAMETER Cwd is not a valid device:path\r
-\r
-**/\r
-EFI_STATUS\r
-EfiSetCwd (\r
-  IN  CHAR8   *Cwd\r
-  )\r
-{\r
-  EFI_OPEN_FILE *File;\r
-  UINTN         Len, AllocLen;\r
-  CHAR8         *Path;\r
-\r
-  if (Cwd == NULL) {\r
-    return EFI_INVALID_PARAMETER;\r
-  }\r
-\r
-  if (AsciiStrCmp (Cwd, ".") == 0) {\r
-    // cd . is a no-op\r
-    return EFI_SUCCESS;\r
-  }\r
-\r
-  Path = Cwd;\r
-  if (AsciiStrStr (Cwd, "..") != NULL) {\r
-    if (gCwd == NULL) {\r
-      // no parent\r
-      return EFI_SUCCESS;\r
-    }\r
-\r
-    Len = AsciiStrLen (gCwd);\r
-    if ((gCwd[Len-2] == ':') && ((gCwd[Len-1] == '/') || (gCwd[Len-1] == '\\'))) {\r
-      // parent is device so nothing to do\r
-      return EFI_SUCCESS;\r
-    }\r
-\r
-    // Expand .. in Cwd, given we know current working directory\r
-    Path = ExpandPath (gCwd, Cwd);\r
-    if (Path == NULL) {\r
-      return EFI_NOT_FOUND;\r
-    }\r
-  }\r
-\r
-  File = EfiOpen (Path, EFI_FILE_MODE_READ, 0);\r
-  if (File == NULL) {\r
-    return EFI_INVALID_PARAMETER;\r
-  }\r
-\r
-  if (gCwd != NULL) {\r
-    FreePool (gCwd);\r
-  }\r
-\r
-  // Use the info returned from EfiOpen as it can add in CWD if needed. So Cwd could be\r
-  // relative to the current gCwd or not.\r
-  AllocLen = AsciiStrSize (File->DeviceName) + AsciiStrSize (File->FileName) + 10;\r
-  gCwd = AllocatePool (AllocLen);\r
-  if (gCwd == NULL) {\r
-    return EFI_INVALID_PARAMETER;\r
-  }\r
-\r
-  AsciiStrCpyS (gCwd, AllocLen, File->DeviceName);\r
-  if (File->FileName == NULL) {\r
-    AsciiStrCatS (gCwd, AllocLen, ":\\");\r
-  } else {\r
-    AsciiStrCatS (gCwd, AllocLen, ":");\r
-    AsciiStrCatS (gCwd, AllocLen, File->FileName);\r
-  }\r
-\r
-\r
-  EfiClose (File);\r
-  if (Path != Cwd) {\r
-    FreePool (Path);\r
-  }\r
-  return EFI_SUCCESS;\r
-}\r
-\r
-\r
-/**\r
-Set the Current Working Directory (CWD). If a call is made to EfiOpen () and\r
-the path does not contain a device name, The CWD is prepended to the path.\r
-The CWD buffer is only valid until a new call is made to EfiSetCwd(). After\r
-a call to EfiSetCwd() it is not legal to use the pointer returned by\r
-this function.\r
-\r
-@param  Cwd     Current Working Directory\r
-\r
-\r
-@return ""      No CWD set\r
-@return 'other' Returns buffer that contains CWD.\r
-\r
-**/\r
-CHAR8 *\r
-EfiGetCwd (\r
-  VOID\r
-  )\r
-{\r
-  if (gCwd == NULL) {\r
-    return "";\r
-  }\r
-  return gCwd;\r
-}\r
-\r
-\r