/** @file
  File IO routines inspired by Streams with an EFI flavor

  Copyright (c) 2007, Intel Corporation<BR>
  Portions copyright (c) 2008-2009, Apple Inc. All rights reserved.

  All rights reserved. This program and the accompanying materials
  are licensed and made available under the terms and conditions of the BSD License
  which accompanies this distribution.  The full text of the license may be found at
  http://opensource.org/licenses/bsd-license.php

  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.

  Basic support for opening files on different device types. The device string
  is in the form of DevType:Path. Current DevType is required as there is no
  current mounted device concept of current working directory concept implement
  by this library.

  Device names are case insensative and only check the leading characters for 
  unique matches. Thus the following are all the same:
    LoadFile0:
    l0:
    L0:
    Lo0:

  Supported Device Names:
  A0x1234:0x12 - A memory buffer starting at address 0x1234 for 0x12 bytes
  l1:          - EFI LoadFile device one.
  B0:          - EFI BlockIo zero.
  fs3:         - EFI Simple File System device 3
  Fv2:         - EFI Firmware VOlume device 2
  10.0.1.102:  - TFTP service IP followed by the file name
**/

#include <PiDxe.h>
#include <Protocol/BlockIo.h>             
#include <Protocol/DiskIo.h>             
#include <Protocol/SimpleFileSystem.h>      
#include <Protocol/FirmwareVolume2.h>        
#include <Protocol/LoadFile.h>
#include <Protocol/FirmwareVolumeBlock.h>  
#include <Guid/FileInfo.h>
#include <Library/BaseLib.h>
#include <Library/MemoryAllocationLib.h>
#include <Library/DevicePathLib.h>
#include <Library/PrintLib.h>
#include <Library/BaseMemoryLib.h>
#include <Library/UefiLib.h>   
#include <Library/UefiBootServicesTableLib.h>
#include <Library/UefiRuntimeServicesTableLib.h>
#include <Library/DebugLib.h>
#include <Library/EfiFileLib.h>
#include <Library/PcdLib.h>
#include <Library/EblNetworkLib.h>


CHAR8 *gCwd = NULL;

CONST EFI_GUID gZeroGuid  = { 0, 0, 0, { 0, 0, 0, 0, 0, 0, 0, 0 } };

#define EFI_OPEN_FILE_GUARD_HEADER  0x4B4D4641
#define EFI_OPEN_FILE_GUARD_FOOTER  0x444D5A56

// Need to defend against this overflowing
#define MAX_CMD_LINE  0x200

typedef struct {
  UINT32            Header;
  EFI_OPEN_FILE     File;
  UINT32            Footer;
} EFI_OPEN_FILE_GUARD;


// globals to store current open device info
EFI_HANDLE            *mBlkIo = NULL;
UINTN                 mBlkIoCount = 0;

EFI_HANDLE            *mFs = NULL;
UINTN                 mFsCount = 0;
// mFsInfo[] array entries must match mFs[] handles
EFI_FILE_SYSTEM_INFO  **mFsInfo = NULL;

EFI_HANDLE            *mFv = NULL;
UINTN                 mFvCount = 0;
EFI_HANDLE            *mLoadFile = NULL;
UINTN                 mLoadFileCount = 0;



/**
  Internal worker function to validate a File handle.

  @param  File    Open File Handle

  @return TRUE    File is valid
  @return FALSE   File is not valid


**/
BOOLEAN
FileHandleValid (
  IN EFI_OPEN_FILE  *File
  )
{
  EFI_OPEN_FILE_GUARD  *GuardFile;

  // Look right before and after file structure for the correct signatures
  GuardFile = BASE_CR (File, EFI_OPEN_FILE_GUARD, File);
  if ((GuardFile->Header != EFI_OPEN_FILE_GUARD_HEADER) ||
      (GuardFile->Footer != EFI_OPEN_FILE_GUARD_FOOTER) ) {
    return FALSE;
  }

  return TRUE;
}

/**
  Internal worker function. If Buffer is not NULL free it.

  @param  Buffer    Buffer to FreePool()

**/
VOID
EblFreePool (
  IN  VOID  *Buffer
  )
{
  if (Buffer != NULL) {
    FreePool (Buffer);
  }
}

/**
  Update Device List Global Variables

**/
VOID
EblUpdateDeviceLists (
  VOID
  )
{
  EFI_STATUS                        Status;
  UINTN                             Size;
  EFI_SIMPLE_FILE_SYSTEM_PROTOCOL   *Fs;
  EFI_FILE_HANDLE                   Root;
  UINTN                             Index;

  if (mBlkIo != NULL) {
    FreePool (mBlkIo);
  }
  gBS->LocateHandleBuffer (ByProtocol, &gEfiBlockIoProtocolGuid, NULL, &mBlkIoCount, &mBlkIo);

  if (mFv != NULL) {
    FreePool (mFv);
  }
  gBS->LocateHandleBuffer (ByProtocol, &gEfiFirmwareVolume2ProtocolGuid, NULL, &mFvCount, &mFv);
  
  if (mLoadFile != NULL) {
    FreePool (mLoadFile);
  }
  gBS->LocateHandleBuffer (ByProtocol, &gEfiLoadFileProtocolGuid, NULL, &mLoadFileCount, &mLoadFile);

  if (mFs != NULL) {
    FreePool (mFs);
  }

  if (&mFsInfo[0] != NULL) {
    // Need to Free the mFsInfo prior to reclaculating mFsCount so don't move this code
    for (Index = 0; Index < mFsCount; Index++) {
      if (mFsInfo[Index] != NULL) {
        FreePool (mFsInfo[Index]);
      }
    }
    FreePool (mFsInfo);
  }

  gBS->LocateHandleBuffer (ByProtocol, &gEfiSimpleFileSystemProtocolGuid, NULL, &mFsCount, &mFs);


  mFsInfo = AllocateZeroPool (mFsCount * sizeof (EFI_FILE_SYSTEM_INFO *));
  if (mFsInfo == NULL) {
    // If we can't do this then we can't support file system entries
    mFsCount = 0;
  } else {
    // Loop through all the file system structures and cache the file system info data
    for (Index =0; Index < mFsCount; Index++) {
      Status = gBS->HandleProtocol (mFs[Index], &gEfiSimpleFileSystemProtocolGuid, (VOID **)&Fs);
      if (!EFI_ERROR (Status)) {
        Status = Fs->OpenVolume (Fs, &Root);
        if (!EFI_ERROR (Status)) {
          // Get information about the volume
          Size = 0;
          Status = Root->GetInfo (Root, &gEfiFileSystemInfoGuid, &Size, mFsInfo[Index]);
          if (Status == EFI_BUFFER_TOO_SMALL) {
            mFsInfo[Index] = AllocatePool (Size);
            Status = Root->GetInfo (Root, &gEfiFileSystemInfoGuid, &Size, mFsInfo[Index]);
          }

          Root->Close (Root);
        }
      }
    }
  }
}


/**
  PathName is in the form <device name>:<path> for example fs1:\ or ROOT:\.
  Return TRUE if the <devce name> prefix of PathName matches a file system
  Volume Name. MatchIndex is the array  index in mFsInfo[] of the match, 
  and it can be used with mFs[] to find the handle that needs to be opened

  @param  PathName      PathName to check
  @param  FileStart     Index of the first character of the <path>
  @param  MatchIndex    Index in mFsInfo[] that matches

  @return TRUE      PathName matches a Volume Label and MatchIndex is valid
  @return FALSE     PathName does not match a Volume Label MatchIndex undefined

**/
BOOLEAN
EblMatchVolumeName (
  IN  CHAR8   *PathName,
  IN  UINTN   FileStart,
  OUT UINTN   *MatchIndex
  )
{
  UINTN   Index;
  UINTN   Compare;
  UINTN   VolStrLen;
  BOOLEAN Match;

  for (Index =0; Index < mFsCount; Index++) {
    if (mFsInfo[Index] == NULL) {
      // FsInfo is not valid so skip it
      continue;
    }
    VolStrLen = StrLen (mFsInfo[Index]->VolumeLabel);
    for (Compare = 0, Match = TRUE; Compare < (FileStart - 1); Compare++) {
      if (Compare > VolStrLen) {
        Match = FALSE;
        break;
      }
      if (PathName[Compare] != (CHAR8)mFsInfo[Index]->VolumeLabel[Compare]) {
        // If the VolumeLabel has a space allow a _ to match with it in addition to ' '
        if (!((PathName[Compare] == '_') && (mFsInfo[Index]->VolumeLabel[Compare] == L' '))) {
          Match = FALSE;
          break;
        }
      }
    }
    if (Match) {
      *MatchIndex = Index;
      return TRUE;
    }
  }

  return FALSE;
}


/**
  Return the number of devices of the current type active in the system

  @param  Type      Device type to check

  @return 0         Invalid type

**/
UINTN
EfiGetDeviceCounts (
  IN  EFI_OPEN_FILE_TYPE     DeviceType
  )
{
  switch (DeviceType) {
  case EfiOpenLoadFile:
    return mLoadFileCount;
  case EfiOpenFirmwareVolume:
    return mFvCount;
  case EfiOpenFileSystem:
    return mFsCount;
  case EfiOpenBlockIo:
    return mBlkIoCount;
  default:
    return 0;
  }
}

EFI_STATUS
ConvertIpStringToEfiIp (
  IN  CHAR8           *PathName, 
  OUT EFI_IP_ADDRESS  *ServerIp
  )
{
  CHAR8     *Str;

  Str = PathName;
  ServerIp->v4.Addr[0] = (UINT8)AsciiStrDecimalToUintn (Str);

  Str = AsciiStrStr (Str, ".");
  if (Str == NULL) {
    return EFI_DEVICE_ERROR;
  }

  ServerIp->v4.Addr[1] = (UINT8)AsciiStrDecimalToUintn (++Str);

  Str = AsciiStrStr (Str, ".");
  if (Str == NULL) {
    return EFI_DEVICE_ERROR;
  }

  ServerIp->v4.Addr[2] = (UINT8)AsciiStrDecimalToUintn (++Str);

  Str = AsciiStrStr (Str, ".");
  if (Str == NULL) {
    return EFI_DEVICE_ERROR;
  }

  ServerIp->v4.Addr[3] = (UINT8)AsciiStrDecimalToUintn (++Str);
 
  return EFI_SUCCESS;
}


/**
  Internal work function to extract a device number from a string skipping 
  text. Easy way to extract numbers from strings like blk7:.

  @param  Str   String to extract device number form

  @return -1    Device string is not valid
  @return       Device #

**/
UINTN
EblConvertDevStringToNumber (
  IN  CHAR8   *Str
  )
{
  UINTN   Max;
  UINTN   Index;


  // Find the first digit 
  Max = AsciiStrLen (Str);
  for  (Index = 0; !((*Str >= '0') && (*Str <= '9')) && (Index < Max); Index++) {
    Str++;
  }
  if (Index == Max) {
    return (UINTN)-1;
  }

  return AsciiStrDecimalToUintn (Str);
}


/**
  Internal work function to fill in EFI_OPEN_FILE information for the Fs and BlkIo

  @param  File        Open file handle
  @param  FileName    Name of file after device stripped off


**/
EFI_STATUS
EblFileDevicePath (
  IN OUT EFI_OPEN_FILE  *File,
  IN  CHAR8             *FileName,
  IN  CONST UINT64      OpenMode
  )
{
  EFI_STATUS                        Status;
  UINTN                             Size;
  FILEPATH_DEVICE_PATH              *FilePath;
  EFI_DEVICE_PATH_PROTOCOL          *FileDevicePath;
  CHAR16                            UnicodeFileName[MAX_PATHNAME];
  EFI_BLOCK_IO_PROTOCOL             *BlkIo;
  EFI_SIMPLE_FILE_SYSTEM_PROTOCOL   *Fs;
  EFI_FILE_HANDLE                   Root;


  if ( *FileName != 0 ) {
    AsciiStrToUnicodeStr (FileName, UnicodeFileName);
  } else {
    AsciiStrToUnicodeStr ("\\", UnicodeFileName);
  }

  Size = StrSize (UnicodeFileName);
  FileDevicePath = AllocatePool (Size + SIZE_OF_FILEPATH_DEVICE_PATH + sizeof (EFI_DEVICE_PATH_PROTOCOL));
  if (FileDevicePath != NULL) {
    FilePath = (FILEPATH_DEVICE_PATH *) FileDevicePath;
    FilePath->Header.Type    = MEDIA_DEVICE_PATH;
    FilePath->Header.SubType = MEDIA_FILEPATH_DP;
    CopyMem (&FilePath->PathName, UnicodeFileName, Size);
    SetDevicePathNodeLength (&FilePath->Header, Size + SIZE_OF_FILEPATH_DEVICE_PATH);
    SetDevicePathEndNode (NextDevicePathNode (&FilePath->Header));

    if (File->EfiHandle != NULL) {
      File->DevicePath = DevicePathFromHandle (File->EfiHandle);
    }

    File->DevicePath = AppendDevicePath (File->DevicePath, FileDevicePath);
    FreePool (FileDevicePath);
  }

  Status = gBS->HandleProtocol (File->EfiHandle, &gEfiBlockIoProtocolGuid, (VOID **)&BlkIo);
  if (!EFI_ERROR (Status)) {
    CopyMem (&File->FsBlockIoMedia, BlkIo->Media, sizeof (EFI_BLOCK_IO_MEDIA));

    // If we are not opening the device this will get over written with file info
    File->MaxPosition = MultU64x32 (BlkIo->Media->LastBlock + 1, BlkIo->Media->BlockSize);
  }

  if (File->Type == EfiOpenFileSystem) {
    Status = gBS->HandleProtocol (File->EfiHandle, &gEfiSimpleFileSystemProtocolGuid, (VOID **)&Fs);
    if (!EFI_ERROR (Status)) {
      Status = Fs->OpenVolume (Fs, &Root);
      if (!EFI_ERROR (Status)) {
        // Get information about the volume
        Size = 0;
        Status = Root->GetInfo (Root, &gEfiFileSystemInfoGuid, &Size, File->FsInfo);
        if (Status == EFI_BUFFER_TOO_SMALL) {
          File->FsInfo = AllocatePool (Size);
          Status = Root->GetInfo (Root, &gEfiFileSystemInfoGuid, &Size, File->FsInfo);
        }
  
        // Get information about the file
        Status = Root->Open (Root, &File->FsFileHandle, UnicodeFileName, OpenMode, 0);
        if (!EFI_ERROR (Status)) {
          Size = 0;
          Status = File->FsFileHandle->GetInfo (File->FsFileHandle, &gEfiFileInfoGuid, &Size, NULL);
          if (Status == EFI_BUFFER_TOO_SMALL) {
            File->FsFileInfo = AllocatePool (Size);
            Status = File->FsFileHandle->GetInfo (File->FsFileHandle, &gEfiFileInfoGuid, &Size, File->FsFileInfo);
            if (!EFI_ERROR (Status)) {
              File->Size = (UINTN)File->FsFileInfo->FileSize;
              File->MaxPosition = (UINT64)File->Size;
            }
          }
        }

        Root->Close (Root);
      }
    }
  } else if (File->Type == EfiOpenBlockIo) {
    File->Size = (UINTN)File->MaxPosition;
  }
  
  return Status;
}

#define ToUpper(a)  ((((a) >= 'a') && ((a) <= 'z')) ? ((a) - 'a' + 'A') : (a))

EFI_STATUS
CompareGuidToString (
  IN  EFI_GUID    *Guid,
  IN  CHAR8       *String
  )
{
  CHAR8       AsciiGuid[64];
  CHAR8       *StringPtr;
  CHAR8       *GuidPtr;

  AsciiSPrint (AsciiGuid, sizeof(AsciiGuid), "%g", Guid);

  StringPtr = String;
  GuidPtr   = AsciiGuid;

  while ((*StringPtr != '\0') && (*GuidPtr != '\0')) {
    // Skip dashes
    if (*StringPtr == '-') {
      StringPtr++;
      continue;
    }

    if (*GuidPtr == '-') {
      GuidPtr++;
      continue;
    }

    if (ToUpper(*StringPtr) != ToUpper(*GuidPtr)) {
      return EFI_NOT_FOUND;
    }

    StringPtr++;
    GuidPtr++;
  }

  return EFI_SUCCESS;
}


/**
  Internal work function to fill in EFI_OPEN_FILE information for the FV

  @param  File        Open file handle
  @param  FileName    Name of file after device stripped off


**/
EFI_STATUS
EblFvFileDevicePath (
  IN OUT EFI_OPEN_FILE  *File,
  IN  CHAR8             *FileName,
  IN  CONST UINT64      OpenMode
  )
{
  EFI_STATUS                          Status;
  EFI_STATUS                          GetNextFileStatus;
  MEDIA_FW_VOL_FILEPATH_DEVICE_PATH   DevicePathNode;
  EFI_DEVICE_PATH_PROTOCOL            *DevicePath;
  UINTN                               Key;
  UINT32                              AuthenticationStatus;
  CHAR8                               AsciiSection[MAX_PATHNAME];
  VOID                                *Section;
  UINTN                               SectionSize;
  EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL  *Fvb;
  EFI_LBA                             Lba;
  UINTN                               BlockSize;
  UINTN                               NumberOfBlocks;
  EFI_FIRMWARE_VOLUME_HEADER          *FvHeader = NULL;
  UINTN                               Index;


  Status = gBS->HandleProtocol (File->EfiHandle, &gEfiFirmwareVolume2ProtocolGuid, (VOID **)&File->Fv);
  if (EFI_ERROR (Status)) {
    return Status;
  }

  // Get FVB Info about the handle
  Status = gBS->HandleProtocol (File->EfiHandle, &gEfiFirmwareVolumeBlockProtocolGuid, (VOID **)&Fvb);
  if (!EFI_ERROR (Status)) {
    Status = Fvb->GetPhysicalAddress (Fvb, &File->FvStart);
    if (!EFI_ERROR (Status)) {
      FvHeader = (EFI_FIRMWARE_VOLUME_HEADER *)(UINTN)File->FvStart;
      File->FvHeaderSize = sizeof (EFI_FIRMWARE_VOLUME_HEADER);
      for (Index = 0; FvHeader->BlockMap[Index].Length !=0; Index++) {
        File->FvHeaderSize += sizeof (EFI_FV_BLOCK_MAP_ENTRY);
      }
      
      for (Lba = 0, File->FvSize = 0, NumberOfBlocks = 0; ; File->FvSize += (BlockSize * NumberOfBlocks), Lba += NumberOfBlocks) {
        Status = Fvb->GetBlockSize (Fvb, Lba, &BlockSize, &NumberOfBlocks);
        if (EFI_ERROR (Status)) {
          break;
        }
      }
    }
  }


  DevicePath = DevicePathFromHandle (File->EfiHandle);

  if (*FileName == '\0') {
    File->DevicePath = DuplicateDevicePath (DevicePath);
    File->Size = File->FvSize;
    File->MaxPosition = File->Size;
  } else {
    Key = 0;
    do {
      File->FvType = EFI_FV_FILETYPE_ALL;
      GetNextFileStatus = File->Fv->GetNextFile (
                                      File->Fv, 
                                      &Key,
                                      &File->FvType,  
                                      &File->FvNameGuid, 
                                      &File->FvAttributes, 
                                      &File->Size
                                      );
      if (!EFI_ERROR (GetNextFileStatus)) {
        // Compare GUID first
        Status = CompareGuidToString (&File->FvNameGuid, FileName);
        if (!EFI_ERROR(Status)) {
          break;
        }
            
        Section = NULL;
        Status = File->Fv->ReadSection (
                            File->Fv,
                            &File->FvNameGuid,
                            EFI_SECTION_USER_INTERFACE,
                            0,
                            &Section,
                            &SectionSize,
                            &AuthenticationStatus
                            );
        if (!EFI_ERROR (Status)) {
          UnicodeStrToAsciiStr (Section, AsciiSection);
          if (AsciiStriCmp (FileName, AsciiSection) == 0) {
            FreePool (Section);
            break;
          }
          FreePool (Section);
        }
      }
    } while (!EFI_ERROR (GetNextFileStatus));

    if (EFI_ERROR (GetNextFileStatus)) {
      return GetNextFileStatus;
    }

    if (OpenMode != EFI_SECTION_ALL) {
      // Calculate the size of the section we are targeting
      Section = NULL;
      File->Size = 0;
      Status = File->Fv->ReadSection (
                          File->Fv,
                          &File->FvNameGuid,
                          OpenMode,
                          0,
                          &Section,
                          &File->Size,
                          &AuthenticationStatus
                          );
      if (EFI_ERROR (Status)) {
        return Status;
      }
    }

    File->MaxPosition = File->Size;
    EfiInitializeFwVolDevicepathNode (&DevicePathNode, &File->FvNameGuid);
    File->DevicePath = AppendDevicePathNode (DevicePath, (EFI_DEVICE_PATH_PROTOCOL *)&DevicePathNode);
  }

    
  // FVB not required if FV was soft loaded...
  return EFI_SUCCESS;
}




/**
  Open a device named by PathName. The PathName includes a device name and 
  path seperated by a :. See file header for more details on the PathName 
  syntax. There is no checking to prevent a file from being opened more than
  one type. 

  SectionType is only used to open an FV. Each file in an FV contains multiple
  secitons and only the SectionType section is opened. 

  For any file that is opened with EfiOpen() must be closed with EfiClose().

  @param  PathName    Path to parse to open 
  @param  OpenMode    Same as EFI_FILE.Open()
  @param  SectionType Section in FV to open.

  @return NULL  Open failed
  @return Valid EFI_OPEN_FILE handle

**/
EFI_OPEN_FILE *
EfiOpen (
  IN        CHAR8               *PathName,
  IN  CONST UINT64              OpenMode,
  IN  CONST EFI_SECTION_TYPE    SectionType
  )
{
  EFI_STATUS                Status;
  EFI_OPEN_FILE             *File;
  EFI_OPEN_FILE             FileData;
  UINTN                     StrLen;
  UINTN                     FileStart;
  UINTN                     DevNumber = 0;
  EFI_OPEN_FILE_GUARD       *GuardFile;
  BOOLEAN                   VolumeNameMatch;
  EFI_DEVICE_PATH_PROTOCOL  *DevicePath;
  UINTN                     Size;
  EFI_IP_ADDRESS            Ip;
  CHAR8                     *CwdPlusPathName;
  UINTN                     Index;
  EFI_SECTION_TYPE          ModifiedSectionType;

  EblUpdateDeviceLists ();
 
  File = &FileData;
  ZeroMem (File, sizeof (EFI_OPEN_FILE));

  StrLen = AsciiStrSize (PathName);
  if (StrLen <= 1) {
    // Smallest valid path is 1 char and a null
    return NULL;
  }

  for (FileStart = 0; FileStart < StrLen; FileStart++) {
    if (PathName[FileStart] == ':') {
      FileStart++;
      break;
    }
  }

  //
  // Matching volume name has precedence over handle based names
  //
  VolumeNameMatch = EblMatchVolumeName (PathName, FileStart, &DevNumber);
  if (!VolumeNameMatch) {
    if (FileStart == StrLen) {
      // No Volume name or device name, so try Current Working Directory
      if (gCwd == NULL) {
        // No CWD
        return NULL;
      }
      
      // We could add a current working diretory concept 
      CwdPlusPathName = AllocatePool (AsciiStrSize (gCwd) + AsciiStrSize (PathName));
      if (CwdPlusPathName == NULL) {
        return NULL;
      }
      
      if ((PathName[0] == '/') || (PathName[0] == '\\')) {
        // PathName starts in / so this means we go to the root of the device in the CWD. 
        CwdPlusPathName[0] = '\0';
        for (FileStart = 0; gCwd[FileStart] != '\0'; FileStart++) {
          CwdPlusPathName[FileStart] = gCwd[FileStart];
          if (gCwd[FileStart] == ':') {
            FileStart++;
            CwdPlusPathName[FileStart] = '\0';
            break;
          }
        }
      } else {
        AsciiStrCpy (CwdPlusPathName, gCwd);
        StrLen = AsciiStrLen (gCwd);
        if ((*PathName != '/') && (*PathName != '\\') && (gCwd[StrLen-1] != '/') && (gCwd[StrLen-1] != '\\')) {
          AsciiStrCat (CwdPlusPathName, "\\");
        }
      }
      
      AsciiStrCat (CwdPlusPathName, PathName);
      if (AsciiStrStr (CwdPlusPathName, ":") == NULL) {
        // Extra error check to make sure we don't recusre and blow stack
        return NULL;
      }
          
      File = EfiOpen (CwdPlusPathName, OpenMode, SectionType);
      FreePool (CwdPlusPathName);
      return File;
    }

    DevNumber = EblConvertDevStringToNumber ((CHAR8 *)PathName); 
  }

  File->DeviceName = AllocatePool (StrLen);
  AsciiStrCpy (File->DeviceName, PathName);
  File->DeviceName[FileStart - 1] = '\0';
  File->FileName = &File->DeviceName[FileStart];
  if (File->FileName[0] == '\0') {
    // if it is just a file name use / as root
    File->FileName = "\\";
  } 

  //
  // Use best match algorithm on the dev names so we only need to look at the
  // first few charters to match the full device name. Short name forms are 
  // legal from the caller.
  //
  Status = EFI_SUCCESS;
  if (*PathName == 'f' || *PathName == 'F' || VolumeNameMatch) {
    if (PathName[1] == 's' || PathName[1] == 'S' || VolumeNameMatch) {
      if (DevNumber >= mFsCount) {
        goto ErrorExit;
      }
      File->Type = EfiOpenFileSystem;
      File->EfiHandle = mFs[DevNumber];
      Status = EblFileDevicePath (File, &PathName[FileStart], OpenMode);
   
    } else if (PathName[1] == 'v' || PathName[1] == 'V') { 
      if (DevNumber >= mFvCount) {
        goto ErrorExit;
      }
      File->Type = EfiOpenFirmwareVolume;
      File->EfiHandle = mFv[DevNumber];

      if ((PathName[FileStart] == '/') || (PathName[FileStart] == '\\')) {
        // Skip leading / as its not really needed for the FV since no directories are supported
        FileStart++;
      }
      
      // Check for 2nd :
      ModifiedSectionType = SectionType;
      for (Index = FileStart; PathName[Index] != '\0'; Index++) {
        if (PathName[Index] == ':') {
          // Support fv0:\DxeCore:0x10
          // This means open the PE32 Section of the file 
          ModifiedSectionType = AsciiStrHexToUintn (&PathName[Index + 1]);
          PathName[Index] = '\0';
        }
      }
      File->FvSectionType = ModifiedSectionType;
      Status = EblFvFileDevicePath (File, &PathName[FileStart], ModifiedSectionType);
    }
  } else if ((*PathName == 'A') || (*PathName == 'a')) {
    // Handle a:0x10000000:0x1234 address form a:ADDRESS:SIZE
    File->Type = EfiOpenMemoryBuffer;
    // 1st colon is at PathName[FileStart - 1]
    File->Buffer = (VOID *)AsciiStrHexToUintn (&PathName[FileStart]);

    // Find 2nd colon
    while ((PathName[FileStart] != ':') && (PathName[FileStart] != '\0')) {
      FileStart++;
    }
    
    // If we ran out of string, there's no extra data
    if (PathName[FileStart] == '\0') {
      File->Size = 0;
    } else {
      File->Size = AsciiStrHexToUintn (&PathName[FileStart + 1]);
    }
    
    // if there's no number after the second colon, default
    // the end of memory
    if (File->Size == 0) {
      File->Size =  (UINTN)(0 - (UINTN)File->Buffer);
    }
    
    File->MaxPosition = File->Size;
    File->BaseOffset = (UINTN)File->Buffer;

  } else if (*PathName== 'l' || *PathName == 'L') {
    if (DevNumber >= mLoadFileCount) {
      goto ErrorExit;
    }
    File->Type = EfiOpenLoadFile;
    File->EfiHandle = mLoadFile[DevNumber];
    
    Status = gBS->HandleProtocol (File->EfiHandle, &gEfiLoadFileProtocolGuid, (VOID **)&File->LoadFile);
    if (EFI_ERROR (Status)) {
      goto ErrorExit;
    }

    Status = gBS->HandleProtocol (File->EfiHandle, &gEfiDevicePathProtocolGuid, (VOID **)&DevicePath);
    if (EFI_ERROR (Status)) {
      goto ErrorExit;
    }
    File->DevicePath = DuplicateDevicePath (DevicePath);
  
  } else if (*PathName == 'b' || *PathName == 'B') {
    // Handle b#:0x10000000:0x1234 address form b#:ADDRESS:SIZE
    if (DevNumber >= mBlkIoCount) {
      goto ErrorExit;
    }
    File->Type = EfiOpenBlockIo;
    File->EfiHandle = mBlkIo[DevNumber];
    EblFileDevicePath (File, "", OpenMode);

    // 1st colon is at PathName[FileStart - 1]
    File->DiskOffset = AsciiStrHexToUintn (&PathName[FileStart]);

    // Find 2nd colon
    while ((PathName[FileStart] != ':') && (PathName[FileStart] != '\0')) {
      FileStart++;
    }

    // If we ran out of string, there's no extra data
    if (PathName[FileStart] == '\0') {
      Size = 0;
    } else {
      Size = AsciiStrHexToUintn (&PathName[FileStart + 1]);
    }
    
    // if a zero size is passed in (or the size is left out entirely),
    // go to the end of the device.
    if (Size == 0) {
      File->Size = File->Size - File->DiskOffset;
    } else {
      File->Size = Size;
    }
    
    File->MaxPosition = File->Size;
    File->BaseOffset = File->DiskOffset;
  } else if ((*PathName) >= '0' && (*PathName <= '9')) {

    // Get current IP address
    Status = EblGetCurrentIpAddress (&Ip);
    if (EFI_ERROR(Status)) {
      AsciiPrint("Device IP Address is not configured.\n");
      goto ErrorExit;
    }
    

    // Parse X.X.X.X:Filename, only support IPv4 TFTP for now...
    File->Type = EfiOpenTftp;
    File->IsDirty = FALSE;
    File->IsBufferValid = FALSE;

    Status = ConvertIpStringToEfiIp (PathName, &File->ServerIp);
  }

  if (EFI_ERROR (Status)) {
    goto ErrorExit;
  }

  GuardFile = (EFI_OPEN_FILE_GUARD *)AllocateZeroPool (sizeof (EFI_OPEN_FILE_GUARD));
  if (GuardFile == NULL) {
    goto ErrorExit;
  }

  GuardFile->Header = EFI_OPEN_FILE_GUARD_HEADER;
  CopyMem (&(GuardFile->File), &FileData, sizeof (EFI_OPEN_FILE));
  GuardFile->Footer = EFI_OPEN_FILE_GUARD_FOOTER;

  return &(GuardFile->File);

ErrorExit:
  FreePool (File->DeviceName);
  return NULL;
}

#define FILE_COPY_CHUNK 0x01000000

EFI_STATUS
EfiCopyFile (
  IN        CHAR8               *DestinationFile,
  IN        CHAR8               *SourceFile
  )
{
  EFI_OPEN_FILE *Source      = NULL;
  EFI_OPEN_FILE *Destination = NULL;
  EFI_STATUS    Status       = EFI_SUCCESS;
  VOID          *Buffer      = NULL;
  UINTN         Size;
  UINTN         Offset;
  UINTN         Chunk = FILE_COPY_CHUNK;
  
  Source = EfiOpen (SourceFile, EFI_FILE_MODE_READ, 0);
  if (Source == NULL) {
    AsciiPrint("Source file open error.\n");
    Status = EFI_NOT_FOUND;
    goto Exit;
  }
  
  Destination = EfiOpen (DestinationFile, EFI_FILE_MODE_WRITE | EFI_FILE_MODE_CREATE, 0);
  if (Destination == NULL) {
    AsciiPrint("Destination file open error.\n");
    Status = EFI_NOT_FOUND;
    goto Exit;
  }

  Buffer = AllocatePool(FILE_COPY_CHUNK);
  if (Buffer == NULL) {
    Status = EFI_OUT_OF_RESOURCES;
    goto Exit;
  }
  
  Size = EfiTell(Source, NULL);

  for (Offset = 0; Offset + FILE_COPY_CHUNK <= Size; Offset += Chunk) {
    Chunk = FILE_COPY_CHUNK;
    
    Status = EfiRead(Source, Buffer, &Chunk);
    if (EFI_ERROR(Status)) {
      AsciiPrint("Read file error\n");
      goto Exit;
    }

    Status = EfiWrite(Destination, Buffer, &Chunk);
    if (EFI_ERROR(Status)) {
      AsciiPrint("Write file error\n");
      goto Exit;
    }    
  }
  
  // Any left over?
  if (Offset < Size) {
    Chunk = Size - Offset;
    
    Status = EfiRead(Source, Buffer, &Chunk);
    if (EFI_ERROR(Status)) {
      AsciiPrint("Read file error\n");
      goto Exit;
    }

    Status = EfiWrite(Destination, Buffer, &Chunk);
    if (EFI_ERROR(Status)) {
      AsciiPrint("Write file error\n");
      goto Exit;
    }    
  }

Exit:
  if (Source != NULL) {
    Status = EfiClose(Source);
    if (EFI_ERROR(Status)) {
      AsciiPrint("Source close error");
    }
  }
  
  if (Destination != NULL) {
    Status = EfiClose(Destination);
    if (EFI_ERROR(Status)) {
      AsciiPrint("Destination close error");
    }
  }
  
  if (Buffer != NULL) {
    FreePool(Buffer);
  }
  
  return Status;
}

/**
  Use DeviceType and Index to form a valid PathName and try and open it.

  @param  DeviceType  Device type to open
  @param  Index       Device Index to use. Zero relative.

  @return NULL  Open failed
  @return Valid EFI_OPEN_FILE handle

**/
EFI_OPEN_FILE  *
EfiDeviceOpenByType (
  IN  EFI_OPEN_FILE_TYPE    DeviceType,
  IN  UINTN                 Index
  )
{
  CHAR8   *DevStr;
  CHAR8   Path[MAX_CMD_LINE];

  switch (DeviceType) {
  case EfiOpenLoadFile:
    DevStr = "loadfile%d:";
    break;
  case EfiOpenFirmwareVolume:
    DevStr = "fv%d:";    
    break;
  case EfiOpenFileSystem:
    DevStr = "fs%d:";    
    break;
  case EfiOpenBlockIo:
    DevStr = "blk%d:";    
    break;
  case EfiOpenMemoryBuffer:
    DevStr = "a%d:";    
    break;
  default:
    return NULL;
  }

  AsciiSPrint (Path, MAX_PATHNAME, DevStr, Index);

  return EfiOpen (Path, EFI_FILE_MODE_READ, 0);
}


/**
  Close a file handle opened by EfiOpen() and free all resources allocated by
  EfiOpen().

  @param  Stream    Open File Handle

  @return EFI_INVALID_PARAMETER  Stream is not an Open File
  @return EFI_SUCCESS            Steam closed

**/
EFI_STATUS
EfiClose (
  IN  EFI_OPEN_FILE     *File
  )
{
  EFI_STATUS          Status;
  UINT64              TftpBufferSize;

  if (!FileHandleValid (File)) {
    return EFI_INVALID_PARAMETER;
  }

  //Write the buffer contents to TFTP file.
  if ((File->Type == EfiOpenTftp) && (File->IsDirty)) {

    TftpBufferSize = File->Size;
    Status = EblMtftp (
                    EFI_PXE_BASE_CODE_TFTP_WRITE_FILE, 
                    File->Buffer, 
                    TRUE, 
                    &TftpBufferSize, 
                    NULL, 
                    &File->ServerIp, 
                    (UINT8 *)File->FileName, 
                    NULL, 
                    FALSE
                    );
    if (EFI_ERROR(Status)) {
      AsciiPrint("TFTP error during APPLE_NSP_TFTP_WRITE_FILE: %r\n", Status);
      return Status;
    }
  }

  if ((File->Type == EfiOpenLoadFile) || 
      ((File->Type == EfiOpenTftp) && (File->IsBufferValid == TRUE)) ||
      ((File->Type == EfiOpenFirmwareVolume) && (File->IsBufferValid == TRUE))) {
    EblFreePool(File->Buffer);
  }

  EblFreePool (File->DevicePath);
  EblFreePool (File->DeviceName);
  EblFreePool (File->FsFileInfo);
  EblFreePool (File->FsInfo);
  
  if (File->FsFileHandle != NULL) {
    File->FsFileHandle->Close (File->FsFileHandle);
  }

  // Need to free File and it's Guard structures
  EblFreePool (BASE_CR (File, EFI_OPEN_FILE_GUARD, File));
  return EFI_SUCCESS;
}


/**
  Return the size of the file represented by Stream. Also return the current 
  Seek position. Opening a file will enable a valid file size to be returned.
  LoadFile is an exception as a load file size is set to zero. 

  @param  Stream    Open File Handle

  @return 0         Stream is not an Open File or a valid LoadFile handle

**/
UINTN
EfiTell (
  IN  EFI_OPEN_FILE     *File,
  OUT EFI_LBA           *CurrentPosition    OPTIONAL
  )
{
  EFI_STATUS Status;
  UINT64     BufferSize = 0;
  
  if (!FileHandleValid (File)) {
    return 0;
  }

  if (CurrentPosition != NULL) {
    *CurrentPosition = File->CurrentPosition;
  }

  if (File->Type == EfiOpenLoadFile) {
    // Figure out the File->Size
    File->Buffer = NULL;
    File->Size   = 0;
    Status = File->LoadFile->LoadFile (File->LoadFile, File->DevicePath, FALSE, &File->Size, File->Buffer);
    if (Status != EFI_BUFFER_TOO_SMALL) {
      return 0;
    }
   
    File->MaxPosition = (UINT64)File->Size;
  } else if (File->Type == EfiOpenTftp) {
    
    Status = EblMtftp (
                    EFI_PXE_BASE_CODE_TFTP_GET_FILE_SIZE,
                    NULL,
                    FALSE,
                    &BufferSize,
                    NULL,
                    &File->ServerIp,
                    (UINT8 *)File->FileName,
                    NULL,
                    TRUE
                    );
    if (EFI_ERROR(Status)) {
      AsciiPrint("TFTP error during APPLE_NSP_TFTP_GET_FILE_SIZE: %r\n", Status);
      return 0;
    }

    File->Size        = (UINTN)BufferSize;
    File->MaxPosition = File->Size;
  }

  return File->Size;
}


/**
  Seek to the Offset locaiton in the file. LoadFile and FV device types do
  not support EfiSeek(). It is not possible to grow the file size using 
  EfiSeek().
  
  SeekType defines how use Offset to calculate the new file position:
  EfiSeekStart  : Position = Offset
  EfiSeekCurrent: Position is Offset bytes from the current position
  EfiSeekEnd    : Only supported if Offset is zero to seek to end of file.

  @param  Stream    Open File Handle
  @param  Offset    Offset to seek too. 
  @param  SeekType  Type of seek to perform


  @return EFI_INVALID_PARAMETER  Stream is not an Open File
  @return EFI_UNSUPPORTED        LoadFile and FV doe not support Seek
  @return EFI_NOT_FOUND          Seek past the end of the file.
  @return EFI_SUCCESS            Steam closed

**/
EFI_STATUS
EfiSeek (
  IN  EFI_OPEN_FILE     *File,
  IN  EFI_LBA           Offset,
  IN  EFI_SEEK_TYPE     SeekType
  )
{
  EFI_STATUS    Status;
  UINT64        CurrentPosition;

  if (!FileHandleValid (File)) {
    return EFI_INVALID_PARAMETER;
  }

  if (File->Type == EfiOpenLoadFile) {
    // LoadFile does not support Seek
    return EFI_UNSUPPORTED;
  }

  CurrentPosition = File->CurrentPosition;
  switch (SeekType) {
  case EfiSeekStart:
    if (Offset > File->MaxPosition) {
      return EFI_NOT_FOUND;
    }
    CurrentPosition = Offset;
    break;

  case EfiSeekCurrent:
    if ((File->CurrentPosition + Offset) > File->MaxPosition) {
      return EFI_NOT_FOUND;
    }
    CurrentPosition += Offset;
    break;

  case EfiSeekEnd:
    if (Offset != 0) {
      // We don't support growing file size via seeking past end of file
      return EFI_UNSUPPORTED;
    }
    CurrentPosition = File->MaxPosition;
    break;

  default:
    return EFI_NOT_FOUND;
  }

  Status = EFI_SUCCESS;
  if (File->FsFileHandle != NULL) {
    Status = File->FsFileHandle->SetPosition (File->FsFileHandle, CurrentPosition);
  }

  if (!EFI_ERROR (Status)) {
    File->CurrentPosition = CurrentPosition;
  }

  return Status;
}

EFI_STATUS
CacheTftpFile (
  IN OUT  EFI_OPEN_FILE *File
  )
{
  EFI_STATUS          Status;
  UINT64              TftpBufferSize;

  if (File->IsBufferValid) {
    return EFI_SUCCESS;
  }

  // Make sure the file size is set.
  EfiTell (File, NULL);

  //Allocate a buffer to hold the whole file.
  File->Buffer = AllocatePool(File->Size);
  if (File->Buffer == NULL) {
    return EFI_OUT_OF_RESOURCES;
  }

  TftpBufferSize = File->Size;

  Status = EblMtftp (
                  EFI_PXE_BASE_CODE_TFTP_READ_FILE, 
                  File->Buffer, 
                  FALSE, 
                  &TftpBufferSize, 
                  NULL, 
                  &File->ServerIp, 
                  (UINT8 *)File->FileName, 
                  NULL, 
                  FALSE);
  if (EFI_ERROR(Status)) {
    AsciiPrint("TFTP error during APPLE_NSP_TFTP_READ_FILE: %r\n", Status);
    FreePool(File->Buffer);
    return Status;
  }

  // Set the buffer valid flag.
  File->IsBufferValid = TRUE;

  return Status;
}

/**
  Read BufferSize bytes from the current locaiton in the file. For load file,
  FV, and TFTP case you must read the entire file. 

  @param  Stream      Open File Handle
  @param  Buffer      Caller allocated buffer. 
  @param  BufferSize  Size of buffer in bytes.


  @return EFI_SUCCESS           Stream is not an Open File
  @return EFI_END_OF_FILE Tried to read past the end of the file
  @return EFI_INVALID_PARAMETER Stream is not an open file handle
  @return EFI_BUFFER_TOO_SMALL  Buffer is not big enough to do the read
  @return "other"               Error returned from device read

**/
EFI_STATUS
EfiRead (
  IN  EFI_OPEN_FILE       *File,
  OUT VOID                *Buffer,
  OUT UINTN               *BufferSize
  )
{
  EFI_STATUS            Status;
  UINT32                AuthenticationStatus;
  EFI_DISK_IO_PROTOCOL  *DiskIo;

  if (!FileHandleValid (File)) {
    return EFI_INVALID_PARAMETER;
  }

  // Don't read past the end of the file.
  if ((File->CurrentPosition + *BufferSize) > File->MaxPosition) {
    return EFI_END_OF_FILE;
  }

  switch (File->Type) {
  case EfiOpenLoadFile:
    // Figure out the File->Size
    EfiTell (File, NULL);

    Status = File->LoadFile->LoadFile (File->LoadFile, File->DevicePath, FALSE, BufferSize, Buffer);
    break;
  
  case EfiOpenFirmwareVolume:
    if (CompareGuid (&File->FvNameGuid, &gZeroGuid)) {
      // This is the entire FV device, so treat like a memory buffer 
      CopyMem (Buffer, (VOID *)(UINTN)(File->FvStart + File->CurrentPosition), *BufferSize);
      File->CurrentPosition += *BufferSize;
      Status = EFI_SUCCESS;
    } else {
      if (File->Buffer == NULL) {
        if (File->FvSectionType == EFI_SECTION_ALL) {
          Status = File->Fv->ReadFile (
                                File->Fv,
                                &File->FvNameGuid,
                                (VOID **)&File->Buffer,
                                &File->Size,
                                &File->FvType,
                                &File->FvAttributes,
                                &AuthenticationStatus
                                );
        } else {
          Status = File->Fv->ReadSection (
                                File->Fv,
                                &File->FvNameGuid,
                                File->FvSectionType,
                                0,
                                (VOID **)&File->Buffer,
                                &File->Size,
                                &AuthenticationStatus
                                );
        }
        if (EFI_ERROR (Status)) {
          return Status;
        }
        File->IsBufferValid = TRUE;
      }
      // Operate on the cached buffer so Seek will work
      CopyMem (Buffer, File->Buffer + File->CurrentPosition, *BufferSize);
      File->CurrentPosition += *BufferSize;
      Status = EFI_SUCCESS;
    }
    break;
    
  case EfiOpenMemoryBuffer:
    CopyMem (Buffer, File->Buffer + File->CurrentPosition, *BufferSize);
    File->CurrentPosition += *BufferSize;
    Status = EFI_SUCCESS;
    break;

  case EfiOpenFileSystem:
    Status = File->FsFileHandle->Read (File->FsFileHandle, BufferSize, Buffer);
    File->CurrentPosition += *BufferSize;
    break;

  case EfiOpenBlockIo:
    Status = gBS->HandleProtocol(File->EfiHandle, &gEfiDiskIoProtocolGuid, (VOID **)&DiskIo);
    if (!EFI_ERROR(Status)) {
      Status = DiskIo->ReadDisk(DiskIo, File->FsBlockIoMedia.MediaId, File->DiskOffset + File->CurrentPosition, *BufferSize, Buffer);
    }
    File->CurrentPosition += *BufferSize;
    break;
  
  case EfiOpenTftp:
    // Cache the file if it hasn't been cached yet.
    if (File->IsBufferValid == FALSE) {
      Status = CacheTftpFile (File);
      if (EFI_ERROR (Status)) {
        return Status;
      }
    }

    // Copy out the requested data
    CopyMem (Buffer, File->Buffer + File->CurrentPosition, *BufferSize);
    File->CurrentPosition += *BufferSize;

    Status = EFI_SUCCESS;
    break;
    
  default:
    return EFI_INVALID_PARAMETER;
  };

  return Status;
}


/**
  Read the entire file into a buffer. This routine allocates the buffer and
  returns it to the user full of the read data. 

  This is very useful for load flie where it's hard to know how big the buffer
  must be.

  @param  Stream      Open File Handle
  @param  Buffer      Pointer to buffer to return. 
  @param  BufferSize  Pointer to Size of buffer return..


  @return EFI_SUCCESS           Stream is not an Open File
  @return EFI_END_OF_FILE       Tried to read past the end of the file
  @return EFI_INVALID_PARAMETER Stream is not an open file handle
  @return EFI_BUFFER_TOO_SMALL  Buffer is not big enough to do the read
  @return "other"               Error returned from device read

**/
EFI_STATUS
EfiReadAllocatePool (
  IN  EFI_OPEN_FILE     *File,
  OUT VOID              **Buffer,
  OUT UINTN             *BufferSize
  )
{
  if (!FileHandleValid (File)) {
    return EFI_INVALID_PARAMETER;
  }

  // Loadfile defers file size determination on Open so use tell to find it
  EfiTell (File, NULL);

  *BufferSize = File->Size;
  *Buffer = AllocatePool (*BufferSize);
  if (*Buffer == NULL) {
    return EFI_NOT_FOUND;
  }

  return EfiRead (File, *Buffer, BufferSize);
}


/**
  Write data back to the file. For TFTP case you must write the entire file. 

  @param  Stream      Open File Handle
  @param  Buffer      Pointer to buffer to return. 
  @param  BufferSize  Pointer to Size of buffer return..


  @return EFI_SUCCESS           Stream is not an Open File
  @return EFI_END_OF_FILE       Tried to read past the end of the file
  @return EFI_INVALID_PARAMETER Stream is not an open file handle
  @return EFI_BUFFER_TOO_SMALL  Buffer is not big enough to do the read
  @return "other"               Error returned from device write

**/
EFI_STATUS
EfiWrite (
  IN  EFI_OPEN_FILE   *File,
  OUT VOID            *Buffer,
  OUT UINTN           *BufferSize
  )
{
  EFI_STATUS              Status;
  EFI_FV_WRITE_FILE_DATA  FileData;
  EFI_DISK_IO_PROTOCOL    *DiskIo;  

  if (!FileHandleValid (File)) {
    return EFI_INVALID_PARAMETER;
  }

  switch (File->Type) {
  case EfiOpenMemoryBuffer:
    if ((File->CurrentPosition + *BufferSize) > File->MaxPosition) {
      return EFI_END_OF_FILE;
    }

    CopyMem (File->Buffer + File->CurrentPosition, Buffer, *BufferSize);
    File->CurrentPosition += *BufferSize;
    Status = EFI_SUCCESS;

  case EfiOpenLoadFile:
    // LoadFile device is read only be definition
    Status = EFI_UNSUPPORTED;
  
  case EfiOpenFirmwareVolume:
    if (File->FvSectionType != EFI_SECTION_ALL) {
      // Writes not support to a specific section. You have to update entire file
      return EFI_UNSUPPORTED;
    }

    FileData.NameGuid       = &(File->FvNameGuid);
    FileData.Type           = File->FvType;
    FileData.FileAttributes = File->FvAttributes;
    FileData.Buffer         = Buffer;
    FileData.BufferSize     = (UINT32)*BufferSize;
    Status = File->Fv->WriteFile (File->Fv, 1, EFI_FV_UNRELIABLE_WRITE, &FileData);
    break;
  
  case EfiOpenFileSystem:
    Status = File->FsFileHandle->Write (File->FsFileHandle, BufferSize, Buffer);
    File->CurrentPosition += *BufferSize;
    break;

  case EfiOpenBlockIo:
    if ((File->CurrentPosition + *BufferSize) > File->MaxPosition) {
      return EFI_END_OF_FILE;
    }

    Status = gBS->HandleProtocol (File->EfiHandle, &gEfiDiskIoProtocolGuid, (VOID **)&DiskIo);
    if (!EFI_ERROR(Status)) {
      Status = DiskIo->WriteDisk (DiskIo, File->FsBlockIoMedia.MediaId, File->DiskOffset + File->CurrentPosition, *BufferSize, Buffer);
    }
    File->CurrentPosition += *BufferSize;
    break;

  case EfiOpenTftp:
    // Cache the file if it hasn't been cached yet.
    if (File->IsBufferValid == FALSE) {
      Status = CacheTftpFile(File);
      if (EFI_ERROR(Status)) {
        return Status;
      }
    }

    // Don't overwrite the buffer
    if ((File->CurrentPosition + *BufferSize) > File->MaxPosition) {
      UINT8 *TempBuffer;

      TempBuffer = File->Buffer;

      File->Buffer = AllocatePool ((UINTN)(File->CurrentPosition + *BufferSize));
      if (File->Buffer == NULL) {
        return EFI_OUT_OF_RESOURCES;
      }

      CopyMem (File->Buffer, TempBuffer, File->Size);

      FreePool (TempBuffer);

      File->Size = (UINTN)(File->CurrentPosition + *BufferSize);
      File->MaxPosition = (UINT64)File->Size;
    }

    // Copy in the requested data
    CopyMem (File->Buffer + File->CurrentPosition, Buffer, *BufferSize);
    File->CurrentPosition += *BufferSize;

    // Mark the file dirty
    File->IsDirty = TRUE;

    Status = EFI_SUCCESS;
    break;

  default:
    Status = EFI_INVALID_PARAMETER;
  };

  return Status;
}


/**
  Given Cwd expand Path to remove .. and replace them with real 
  directory names.
  
  @param  Cwd     Current Working Directory
  @param  Path    Path to expand

  @return NULL     Cwd or Path are not valid
  @return 'other'  Path with .. expanded

**/
CHAR8 *
ExpandPath (
  IN CHAR8    *Cwd,
  IN CHAR8    *Path
  )
{
  CHAR8   *NewPath;
  CHAR8   *Work, *Start, *End;
  UINTN   StrLen;
  UINTN   i;
  
  if (Cwd == NULL || Path == NULL) {
    return NULL;
  }
  
  StrLen = AsciiStrSize (Cwd);
  if (StrLen <= 2) {
    // Smallest valid path is 1 char and a null
    return NULL;
  }

  StrLen = AsciiStrSize (Path);
  NewPath = AllocatePool (AsciiStrSize (Cwd) + StrLen + 1);
  if (NewPath == NULL) {
    return NULL;
  }
  AsciiStrCpy (NewPath, Cwd);
  
  End = Path + StrLen;
  for (Start = Path ;;) {
    Work = AsciiStrStr (Start, "..") ;
    if (Work == NULL) {
      // Remaining part of Path contains no more ..
      break;
    } 
 
    // append path prior to .. 
    AsciiStrnCat (NewPath, Start, Work - Start);
    StrLen = AsciiStrLen (NewPath);
    for (i = StrLen; i >= 0; i--) {
      if (NewPath[i] == ':') {
        // too many ..
        return NULL;
      }
      if (NewPath[i] == '/' || NewPath[i] == '\\') {
        if ((i > 0) && (NewPath[i-1] == ':')) {
          // leave the / before a :
          NewPath[i+1] = '\0';
        } else {
          // replace / will Null to remove trailing file/dir reference
          NewPath[i] = '\0';
        }
        break;
      }
    }
    
    Start = Work + 3;
  } 
  
  // Handle the path that remains after the ..
  AsciiStrnCat (NewPath, Start, End - Start);
  
  return NewPath;
}


/**
  Set the Curent Working Directory (CWD). If a call is made to EfiOpen () and 
  the path does not contain a device name, The CWD is prepended to the path.
  
  @param  Cwd     Current Working Directory to set


  @return EFI_SUCCESS           CWD is set
  @return EFI_INVALID_PARAMETER Cwd is not a valid device:path

**/
EFI_STATUS
EfiSetCwd (
  IN  CHAR8   *Cwd
  ) 
{
  EFI_OPEN_FILE *File;
  UINTN         Len;
  CHAR8         *Path;
  
  if (Cwd == NULL) {
    return EFI_INVALID_PARAMETER;
  }
  
  if (AsciiStrCmp (Cwd, ".") == 0) {
    // cd . is a no-op
    return EFI_SUCCESS;
  }
  
  Path = Cwd;
  if (AsciiStrStr (Cwd, "..") != NULL) {
    if (gCwd == NULL) {
      // no parent 
      return EFI_SUCCESS;
    }
    
    Len = AsciiStrLen (gCwd);
    if ((gCwd[Len-2] == ':') && ((gCwd[Len-1] == '/') || (gCwd[Len-1] == '\\'))) {
      // parent is device so nothing to do
      return EFI_SUCCESS;
    }
    
    // Expand .. in Cwd, given we know current working directory
    Path = ExpandPath (gCwd, Cwd);
    if (Path == NULL) {
      return EFI_NOT_FOUND;
    }
  }
  
  File = EfiOpen (Path, EFI_FILE_MODE_READ, 0);
  if (File == NULL) {
    return EFI_INVALID_PARAMETER;
  }
    
  if (gCwd != NULL) {
    FreePool (gCwd);
  }
  
  // Use the info returned from EfiOpen as it can add in CWD if needed. So Cwd could be
  // relative to the current gCwd or not.
  gCwd = AllocatePool (AsciiStrSize (File->DeviceName) + AsciiStrSize (File->FileName) + 10);
  if (gCwd == NULL) {
    return EFI_INVALID_PARAMETER;
  }
  AsciiStrCpy (gCwd, File->DeviceName);
  if (File->FileName == NULL) {
    AsciiStrCat (gCwd, ":\\");
  } else {
    AsciiStrCat (gCwd, ":");
    AsciiStrCat (gCwd, File->FileName);
  }
  
  EfiClose (File);
  if (Path != Cwd) {
    FreePool (Path);
  }
  return EFI_SUCCESS;
}


/**
  Set the Curent Working Directory (CWD). If a call is made to EfiOpen () and 
  the path does not contain a device name, The CWD is prepended to the path.
  The CWD buffer is only valid until a new call is made to EfiSetCwd(). After
  a call to EfiSetCwd() it is not legal to use the pointer returned by 
  this funciton.
  
  @param  Cwd     Current Working Directory 


  @return ""      No CWD set
  @return 'other' Returns buffer that contains CWD.
  
**/
CHAR8 *
EfiGetCwd (
  VOID
  )
{
  if (gCwd == NULL) {
    return "";
  }
  return gCwd;
}


