]> git.proxmox.com Git - mirror_edk2.git/blobdiff - ArmPkg/Library/BdsLib/BdsFilePath.c
ArmPkg: Move IS_DEVICE_PATH_NODE for sharing
[mirror_edk2.git] / ArmPkg / Library / BdsLib / BdsFilePath.c
index 90be9c1e117895282f106a47abb2dd21d80012c1..41557bb91816e7df488298e72e44994090b2af6b 100644 (file)
@@ -1,25 +1,62 @@
 /** @file\r
 *\r
-*  Copyright (c) 2011-2013, ARM Limited. All rights reserved.\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
+*  Copyright (c) 2011-2014, ARM Limited. All rights reserved.\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
+*  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
 **/\r
 \r
 #include "BdsInternal.h"\r
 \r
+#include <Library/NetLib.h>\r
+\r
+#include <Protocol/Bds.h>\r
 #include <Protocol/UsbIo.h>\r
 #include <Protocol/DiskIo.h>\r
 #include <Protocol/LoadedImage.h>\r
 #include <Protocol/SimpleNetwork.h>\r
+#include <Protocol/Dhcp4.h>\r
+#include <Protocol/Mtftp4.h>\r
+\r
+/* Type and defines to set up the DHCP4 options */\r
+\r
+typedef struct {\r
+  EFI_DHCP4_PACKET_OPTION Head;\r
+  UINT8                   Route;\r
+} DHCP4_OPTION;\r
+\r
+#define DHCP_TAG_PARA_LIST  55\r
+#define DHCP_TAG_NETMASK     1\r
+#define DHCP_TAG_ROUTER      3\r
+\r
+/*\r
+   Constant strings and define related to the message indicating the amount of\r
+   progress in the dowloading of a TFTP file.\r
+*/\r
+\r
+// Frame for the progression slider\r
+STATIC CONST CHAR16 mTftpProgressFrame[] = L"[                                        ]";\r
+\r
+// Number of steps in the progression slider\r
+#define TFTP_PROGRESS_SLIDER_STEPS  ((sizeof (mTftpProgressFrame) / sizeof (CHAR16)) - 3)\r
+\r
+// Size in number of characters plus one (final zero) of the message to\r
+// indicate the progress of a tftp download. The format is "[(progress slider:\r
+// 40 characters)] (nb of KBytes downloaded so far: 7 characters) Kb". There\r
+// are thus the number of characters in mTftpProgressFrame[] plus 11 characters\r
+// (2 // spaces, "Kb" and seven characters for the number of KBytes).\r
+#define TFTP_PROGRESS_MESSAGE_SIZE  ((sizeof (mTftpProgressFrame) / sizeof (CHAR16)) + 12)\r
+\r
+// String to delete the tftp progress message to be able to update it :\r
+// (TFTP_PROGRESS_MESSAGE_SIZE-1) '\b'\r
+STATIC CONST CHAR16 mTftpProgressDelete[] = L"\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b";\r
 \r
-#define IS_DEVICE_PATH_NODE(node,type,subtype) (((node)->Type == (type)) && ((node)->SubType == (subtype)))\r
 \r
 // Extract the FilePath from the Device Path\r
 CHAR16*\r
@@ -300,44 +337,57 @@ TryRemovableDevice (
   return Status;\r
 }\r
 \r
-STATIC
+STATIC\r
 EFI_STATUS\r
-BdsConnectAndUpdateDevicePath (
-  IN OUT EFI_DEVICE_PATH_PROTOCOL  **DevicePath,
-  OUT    EFI_HANDLE                *Handle,
-  OUT    EFI_DEVICE_PATH_PROTOCOL  **RemainingDevicePath
+BdsConnectAndUpdateDevicePath (\r
+  IN OUT EFI_DEVICE_PATH_PROTOCOL  **DevicePath,\r
+  OUT    EFI_HANDLE                *Handle,\r
+  OUT    EFI_DEVICE_PATH_PROTOCOL  **RemainingDevicePath\r
   )\r
 {\r
   EFI_DEVICE_PATH*            Remaining;\r
   EFI_DEVICE_PATH*            NewDevicePath;\r
   EFI_STATUS                  Status;\r
+  EFI_HANDLE                  PreviousHandle;\r
 \r
-  if ((DevicePath == NULL) || (*DevicePath == NULL) || (Handle == NULL)) {
+  if ((DevicePath == NULL) || (*DevicePath == NULL) || (Handle == NULL)) {\r
     return EFI_INVALID_PARAMETER;\r
   }\r
 \r
+  PreviousHandle = NULL;\r
   do {\r
-    Remaining = *DevicePath;
+    Remaining = *DevicePath;\r
+\r
     // The LocateDevicePath() function locates all devices on DevicePath that support Protocol and returns\r
     // the handle to the device that is closest to DevicePath. On output, the device path pointer is modified\r
     // to point to the remaining part of the device path\r
     Status = gBS->LocateDevicePath (&gEfiDevicePathProtocolGuid, &Remaining, Handle);\r
+\r
     if (!EFI_ERROR (Status)) {\r
-      // Recursive = FALSE: We do not want to start all the device tree\r
-      Status = gBS->ConnectController (*Handle, NULL, Remaining, FALSE);\r
-    }\r
+      if (*Handle == PreviousHandle) {\r
+        //\r
+        // If no forward progress is made try invoking the Dispatcher.\r
+        // A new FV may have been added to the system and new drivers\r
+        // may now be found.\r
+        // Status == EFI_SUCCESS means a driver was dispatched\r
+        // Status == EFI_NOT_FOUND means no new drivers were dispatched\r
+        //\r
+        Status = gDS->Dispatch ();\r
+      }\r
 \r
-    /*// We need to check if RemainingDevicePath does not point on the last node. Otherwise, calling\r
-    // NextDevicePathNode () will return an undetermined Device Path Node\r
-    if (!IsDevicePathEnd (RemainingDevicePath)) {\r
-      RemainingDevicePath = NextDevicePathNode (RemainingDevicePath);\r
-    }*/\r
+      if (!EFI_ERROR (Status)) {\r
+        PreviousHandle = *Handle;\r
+\r
+        // Recursive = FALSE: We do not want to start the whole device tree\r
+        Status = gBS->ConnectController (*Handle, NULL, Remaining, FALSE);\r
+      }\r
+    }\r
   } while (!EFI_ERROR (Status) && !IsDevicePathEnd (Remaining));\r
 \r
   if (!EFI_ERROR (Status)) {\r
     // Now, we have got the whole Device Path connected, call again ConnectController to ensure all the supported Driver\r
     // Binding Protocol are connected (such as DiskIo and SimpleFileSystem)\r
-    Remaining = *DevicePath;
+    Remaining = *DevicePath;\r
     Status = gBS->LocateDevicePath (&gEfiDevicePathProtocolGuid, &Remaining, Handle);\r
     if (!EFI_ERROR (Status)) {\r
       Status = gBS->ConnectController (*Handle, NULL, Remaining, FALSE);\r
@@ -360,11 +410,11 @@ BdsConnectAndUpdateDevicePath (
     //TODO: Should we just return success and leave the caller decide if it is the expected RemainingPath\r
     Status = EFI_SUCCESS;\r
   } else {\r
-    Status = TryRemovableDevice (*DevicePath, Handle, &NewDevicePath);
+    Status = TryRemovableDevice (*DevicePath, Handle, &NewDevicePath);\r
     if (!EFI_ERROR (Status)) {\r
-      Status = BdsConnectAndUpdateDevicePath (&NewDevicePath, Handle, RemainingDevicePath);
-      *DevicePath = NewDevicePath;
-      return Status;
+      Status = BdsConnectAndUpdateDevicePath (&NewDevicePath, Handle, RemainingDevicePath);\r
+      *DevicePath = NewDevicePath;\r
+      return Status;\r
     }\r
   }\r
 \r
@@ -375,28 +425,28 @@ BdsConnectAndUpdateDevicePath (
   return Status;\r
 }\r
 \r
-/**
-  Connect a Device Path and return the handle of the driver that support this DevicePath
-
-  @param  DevicePath            Device Path of the File to connect
-  @param  Handle                Handle of the driver that support this DevicePath
-  @param  RemainingDevicePath   Remaining DevicePath nodes that do not match the driver DevicePath
-
-  @retval EFI_SUCCESS           A driver that matches the Device Path has been found
-  @retval EFI_NOT_FOUND         No handles match the search.
-  @retval EFI_INVALID_PARAMETER DevicePath or Handle is NULL
-
+/**\r
+  Connect a Device Path and return the handle of the driver that support this DevicePath\r
+\r
+  @param  DevicePath            Device Path of the File to connect\r
+  @param  Handle                Handle of the driver that support this DevicePath\r
+  @param  RemainingDevicePath   Remaining DevicePath nodes that do not match the driver DevicePath\r
+\r
+  @retval EFI_SUCCESS           A driver that matches the Device Path has been found\r
+  @retval EFI_NOT_FOUND         No handles match the search.\r
+  @retval EFI_INVALID_PARAMETER DevicePath or Handle is NULL\r
+\r
 **/\r
-EFI_STATUS
-BdsConnectDevicePath (
-  IN  EFI_DEVICE_PATH_PROTOCOL* DevicePath,
-  OUT EFI_HANDLE                *Handle,
-  OUT EFI_DEVICE_PATH_PROTOCOL  **RemainingDevicePath
-  )
-{
-  return BdsConnectAndUpdateDevicePath (&DevicePath, Handle, RemainingDevicePath);
-}
-
+EFI_STATUS\r
+BdsConnectDevicePath (\r
+  IN  EFI_DEVICE_PATH_PROTOCOL* DevicePath,\r
+  OUT EFI_HANDLE                *Handle,\r
+  OUT EFI_DEVICE_PATH_PROTOCOL  **RemainingDevicePath\r
+  )\r
+{\r
+  return BdsConnectAndUpdateDevicePath (&DevicePath, Handle, RemainingDevicePath);\r
+}\r
+\r
 BOOLEAN\r
 BdsFileSystemSupport (\r
   IN EFI_DEVICE_PATH *DevicePath,\r
@@ -414,27 +464,34 @@ BdsFileSystemSupport (
 \r
 EFI_STATUS\r
 BdsFileSystemLoadImage (\r
-  IN     EFI_DEVICE_PATH *DevicePath,\r
-  IN     EFI_HANDLE Handle,\r
-  IN     EFI_DEVICE_PATH *RemainingDevicePath,\r
+  IN OUT EFI_DEVICE_PATH       **DevicePath,\r
+  IN     EFI_HANDLE            Handle,\r
+  IN     EFI_DEVICE_PATH       *RemainingDevicePath,\r
   IN     EFI_ALLOCATE_TYPE     Type,\r
-  IN OUT EFI_PHYSICAL_ADDRESSImage,\r
+  IN OUT EFI_PHYSICAL_ADDRESS  *Image,\r
   OUT    UINTN                 *ImageSize\r
   )\r
 {\r
-  FILEPATH_DEVICE_PATH*             FilePathDevicePath;\r
-  EFI_SIMPLE_FILE_SYSTEM_PROTOCOL     *FsProtocol;\r
-  EFI_FILE_PROTOCOL                   *Fs;\r
-  EFI_STATUS Status;\r
-  EFI_FILE_INFO       *FileInfo;\r
-  EFI_FILE_PROTOCOL   *File;\r
-  UINTN               Size;\r
+  EFI_STATUS                       Status;\r
+  FILEPATH_DEVICE_PATH             *FilePathDevicePath;\r
+  EFI_SIMPLE_FILE_SYSTEM_PROTOCOL  *FsProtocol;\r
+  EFI_FILE_PROTOCOL                *Fs;\r
+  EFI_FILE_INFO                    *FileInfo;\r
+  EFI_FILE_PROTOCOL                *File;\r
+  UINTN                            Size;\r
 \r
   ASSERT (IS_DEVICE_PATH_NODE (RemainingDevicePath, MEDIA_DEVICE_PATH, MEDIA_FILEPATH_DP));\r
 \r
   FilePathDevicePath = (FILEPATH_DEVICE_PATH*)RemainingDevicePath;\r
 \r
-  Status = gBS->HandleProtocol (Handle, &gEfiSimpleFileSystemProtocolGuid, (VOID **)&FsProtocol);\r
+  Status = gBS->OpenProtocol (\r
+                  Handle,\r
+                  &gEfiSimpleFileSystemProtocolGuid,\r
+                  (VOID**)&FsProtocol,\r
+                  gImageHandle,\r
+                  Handle,\r
+                  EFI_OPEN_PROTOCOL_BY_DRIVER\r
+                  );\r
   if (EFI_ERROR (Status)) {\r
     return Status;\r
   }\r
@@ -442,13 +499,12 @@ BdsFileSystemLoadImage (
   // Try to Open the volume and get root directory\r
   Status = FsProtocol->OpenVolume (FsProtocol, &Fs);\r
   if (EFI_ERROR (Status)) {\r
-    return Status;\r
+    goto CLOSE_PROTOCOL;\r
   }\r
 \r
-  File = NULL;\r
   Status = Fs->Open (Fs, &File, FilePathDevicePath->PathName, EFI_FILE_MODE_READ, 0);\r
   if (EFI_ERROR (Status)) {\r
-    return Status;\r
+    goto CLOSE_PROTOCOL;\r
   }\r
 \r
   Size = 0;\r
@@ -456,7 +512,7 @@ BdsFileSystemLoadImage (
   FileInfo = AllocatePool (Size);\r
   Status = File->GetInfo (File, &gEfiFileInfoGuid, &Size, FileInfo);\r
   if (EFI_ERROR (Status)) {\r
-    return Status;\r
+    goto CLOSE_FILE;\r
   }\r
 \r
   // Get the file size\r
@@ -475,6 +531,16 @@ BdsFileSystemLoadImage (
     Status = File->Read (File, &Size, (VOID*)(UINTN)(*Image));\r
   }\r
 \r
+CLOSE_FILE:\r
+  File->Close (File);\r
+\r
+CLOSE_PROTOCOL:\r
+  gBS->CloseProtocol (\r
+         Handle,\r
+         &gEfiSimpleFileSystemProtocolGuid,\r
+         gImageHandle,\r
+         Handle);\r
+\r
   return Status;\r
 }\r
 \r
@@ -491,9 +557,9 @@ BdsMemoryMapSupport (
 \r
 EFI_STATUS\r
 BdsMemoryMapLoadImage (\r
-  IN     EFI_DEVICE_PATH *DevicePath,\r
-  IN     EFI_HANDLE Handle,\r
-  IN     EFI_DEVICE_PATH *RemainingDevicePath,\r
+  IN OUT EFI_DEVICE_PATH       **DevicePath,\r
+  IN     EFI_HANDLE            Handle,\r
+  IN     EFI_DEVICE_PATH       *RemainingDevicePath,\r
   IN     EFI_ALLOCATE_TYPE     Type,\r
   IN OUT EFI_PHYSICAL_ADDRESS* Image,\r
   OUT    UINTN                 *ImageSize\r
@@ -506,8 +572,8 @@ BdsMemoryMapLoadImage (
   if (IS_DEVICE_PATH_NODE (RemainingDevicePath, HARDWARE_DEVICE_PATH, HW_MEMMAP_DP)) {\r
     MemMapPathDevicePath = (MEMMAP_DEVICE_PATH*)RemainingDevicePath;\r
   } else {\r
-    ASSERT (IS_DEVICE_PATH_NODE (DevicePath, HARDWARE_DEVICE_PATH, HW_MEMMAP_DP));\r
-    MemMapPathDevicePath = (MEMMAP_DEVICE_PATH*)DevicePath;\r
+    ASSERT (IS_DEVICE_PATH_NODE (*DevicePath, HARDWARE_DEVICE_PATH, HW_MEMMAP_DP));\r
+    MemMapPathDevicePath = (MEMMAP_DEVICE_PATH*)*DevicePath;\r
   }\r
 \r
   Size = MemMapPathDevicePath->EndingAddress - MemMapPathDevicePath->StartingAddress;\r
@@ -543,9 +609,9 @@ BdsFirmwareVolumeSupport (
 \r
 EFI_STATUS\r
 BdsFirmwareVolumeLoadImage (\r
-  IN     EFI_DEVICE_PATH *DevicePath,\r
-  IN     EFI_HANDLE Handle,\r
-  IN     EFI_DEVICE_PATH *RemainingDevicePath,\r
+  IN OUT EFI_DEVICE_PATH       **DevicePath,\r
+  IN     EFI_HANDLE            Handle,\r
+  IN     EFI_DEVICE_PATH       *RemainingDevicePath,\r
   IN     EFI_ALLOCATE_TYPE     Type,\r
   IN OUT EFI_PHYSICAL_ADDRESS* Image,\r
   OUT    UINTN                 *ImageSize\r
@@ -628,7 +694,7 @@ BdsFirmwareVolumeLoadImage (
         Status = FwVol->ReadFile (\r
                                 FwVol,\r
                                 FvNameGuid,\r
-                                (VOID*)(UINTN)(*Image),\r
+                                (VOID**)Image,\r
                                 ImageSize,\r
                                 &FvType,\r
                                 &Attrib,\r
@@ -664,12 +730,12 @@ BdsPxeSupport (
 \r
 EFI_STATUS\r
 BdsPxeLoadImage (\r
-  IN     EFI_DEVICE_PATH*       DevicePath,\r
-  IN     EFI_HANDLE             Handle,\r
-  IN     EFI_DEVICE_PATH*       RemainingDevicePath,\r
-  IN     EFI_ALLOCATE_TYPE      Type,\r
-  IN OUT EFI_PHYSICAL_ADDRESS   *Image,\r
-  OUT    UINTN                  *ImageSize\r
+  IN OUT EFI_DEVICE_PATH       **DevicePath,\r
+  IN     EFI_HANDLE            Handle,\r
+  IN     EFI_DEVICE_PATH       *RemainingDevicePath,\r
+  IN     EFI_ALLOCATE_TYPE     Type,\r
+  IN OUT EFI_PHYSICAL_ADDRESSImage,\r
+  OUT    UINTN                 *ImageSize\r
   )\r
 {\r
   EFI_STATUS              Status;\r
@@ -683,14 +749,14 @@ BdsPxeLoadImage (
     return Status;\r
   }\r
 \r
-  Status = LoadFileProtocol->LoadFile (LoadFileProtocol, DevicePath, TRUE, &BufferSize, NULL);\r
+  Status = LoadFileProtocol->LoadFile (LoadFileProtocol, RemainingDevicePath, TRUE, &BufferSize, NULL);\r
   if (Status == EFI_BUFFER_TOO_SMALL) {\r
     Status = gBS->AllocatePages (Type, EfiBootServicesCode, EFI_SIZE_TO_PAGES(BufferSize), Image);\r
     if (EFI_ERROR (Status)) {\r
       return Status;\r
     }\r
 \r
-    Status = LoadFileProtocol->LoadFile (LoadFileProtocol, DevicePath, TRUE, &BufferSize, (VOID*)(UINTN)(*Image));\r
+    Status = LoadFileProtocol->LoadFile (LoadFileProtocol, RemainingDevicePath, TRUE, &BufferSize, (VOID*)(UINTN)(*Image));\r
     if (!EFI_ERROR (Status) && (ImageSize != NULL)) {\r
       *ImageSize = BufferSize;\r
     }\r
@@ -710,14 +776,14 @@ BdsPxeLoadImage (
 \r
 BOOLEAN\r
 BdsTftpSupport (\r
-  IN EFI_DEVICE_PATH*           DevicePath,\r
-  IN EFI_HANDLE                 Handle,\r
-  IN EFI_DEVICE_PATH*           RemainingDevicePath\r
+  IN EFI_DEVICE_PATH  *DevicePath,\r
+  IN EFI_HANDLE       Handle,\r
+  IN EFI_DEVICE_PATH  *RemainingDevicePath\r
   )\r
 {\r
-  EFI_STATUS  Status;\r
+  EFI_STATUS       Status;\r
   EFI_DEVICE_PATH  *NextDevicePath;\r
-  EFI_PXE_BASE_CODE_PROTOCOL  *PxeBcProtocol;\r
+  VOID             *Interface;\r
 \r
   // Validate the Remaining Device Path\r
   if (IsDevicePathEnd (RemainingDevicePath)) {\r
@@ -735,139 +801,504 @@ BdsTftpSupport (
     return FALSE;\r
   }\r
 \r
-  Status = gBS->HandleProtocol (Handle, &gEfiPxeBaseCodeProtocolGuid, (VOID **)&PxeBcProtocol);\r
+  Status = gBS->HandleProtocol (\r
+                  Handle, &gEfiDevicePathProtocolGuid,\r
+                  &Interface\r
+                  );\r
   if (EFI_ERROR (Status)) {\r
     return FALSE;\r
-  } else {\r
-    return TRUE;\r
   }\r
+\r
+  //\r
+  // Check that the controller (identified by its handle "Handle") supports the\r
+  // MTFTPv4 Service Binding Protocol. If it does, it means that it supports the\r
+  // EFI MTFTPv4 Protocol needed to download the image through TFTP.\r
+  //\r
+  Status = gBS->HandleProtocol (\r
+                  Handle, &gEfiMtftp4ServiceBindingProtocolGuid,\r
+                  &Interface\r
+                  );\r
+  if (EFI_ERROR (Status)) {\r
+    return FALSE;\r
+  }\r
+\r
+  return TRUE;\r
+}\r
+\r
+/**\r
+  Worker function that get the size in numbers of bytes of a file from a TFTP\r
+  server before to download the file.\r
+\r
+  @param[in]   Mtftp4    MTFTP4 protocol interface\r
+  @param[in]   FilePath  Path of the file, Ascii encoded\r
+  @param[out]  FileSize  Address where to store the file size in number of\r
+                         bytes.\r
+\r
+  @retval  EFI_SUCCESS   The size of the file was returned.\r
+  @retval  !EFI_SUCCESS  The size of the file was not returned.\r
+\r
+**/\r
+STATIC\r
+EFI_STATUS\r
+Mtftp4GetFileSize (\r
+  IN  EFI_MTFTP4_PROTOCOL  *Mtftp4,\r
+  IN  CHAR8                *FilePath,\r
+  OUT UINT64               *FileSize\r
+  )\r
+{\r
+  EFI_STATUS         Status;\r
+  EFI_MTFTP4_OPTION  ReqOpt[1];\r
+  EFI_MTFTP4_PACKET  *Packet;\r
+  UINT32             PktLen;\r
+  EFI_MTFTP4_OPTION  *TableOfOptions;\r
+  EFI_MTFTP4_OPTION  *Option;\r
+  UINT32             OptCnt;\r
+  UINT8              OptBuf[128];\r
+\r
+  ReqOpt[0].OptionStr = (UINT8*)"tsize";\r
+  OptBuf[0] = '0';\r
+  OptBuf[1] = 0;\r
+  ReqOpt[0].ValueStr = OptBuf;\r
+\r
+  Status = Mtftp4->GetInfo (\r
+             Mtftp4,\r
+             NULL,\r
+             (UINT8*)FilePath,\r
+             NULL,\r
+             1,\r
+             ReqOpt,\r
+             &PktLen,\r
+             &Packet\r
+             );\r
+\r
+  if (EFI_ERROR (Status)) {\r
+    goto Error;\r
+  }\r
+\r
+  Status = Mtftp4->ParseOptions (\r
+                     Mtftp4,\r
+                     PktLen,\r
+                     Packet,\r
+                     (UINT32 *) &OptCnt,\r
+                     &TableOfOptions\r
+                     );\r
+  if (EFI_ERROR (Status)) {\r
+    goto Error;\r
+  }\r
+\r
+  Option = TableOfOptions;\r
+  while (OptCnt != 0) {\r
+    if (AsciiStrnCmp ((CHAR8 *)Option->OptionStr, "tsize", 5) == 0) {\r
+      *FileSize = AsciiStrDecimalToUint64 ((CHAR8 *)Option->ValueStr);\r
+      break;\r
+    }\r
+    OptCnt--;\r
+    Option++;\r
+  }\r
+  FreePool (TableOfOptions);\r
+\r
+  if (OptCnt == 0) {\r
+    Status = EFI_UNSUPPORTED;\r
+  }\r
+\r
+Error :\r
+\r
+  return Status;\r
+}\r
+\r
+/**\r
+  Update the progress of a file download\r
+  This procedure is called each time a new TFTP packet is received.\r
+\r
+  @param[in]  This       MTFTP4 protocol interface\r
+  @param[in]  Token      Parameters for the download of the file\r
+  @param[in]  PacketLen  Length of the packet\r
+  @param[in]  Packet     Address of the packet\r
+\r
+  @retval  EFI_SUCCESS  All packets are accepted.\r
+\r
+**/\r
+STATIC\r
+EFI_STATUS\r
+Mtftp4CheckPacket (\r
+  IN EFI_MTFTP4_PROTOCOL  *This,\r
+  IN EFI_MTFTP4_TOKEN     *Token,\r
+  IN UINT16               PacketLen,\r
+  IN EFI_MTFTP4_PACKET    *Packet\r
+  )\r
+{\r
+  BDS_TFTP_CONTEXT  *Context;\r
+  CHAR16            Progress[TFTP_PROGRESS_MESSAGE_SIZE];\r
+  UINT64            NbOfKb;\r
+  UINTN             Index;\r
+  UINTN             LastStep;\r
+  UINTN             Step;\r
+  UINT64            LastNbOf50Kb;\r
+  UINT64            NbOf50Kb;\r
+\r
+  if ((NTOHS (Packet->OpCode)) == EFI_MTFTP4_OPCODE_DATA) {\r
+    Context = (BDS_TFTP_CONTEXT*)Token->Context;\r
+\r
+    if (Context->DownloadedNbOfBytes == 0) {\r
+      if (Context->FileSize > 0) {\r
+        Print (L"%s       0 Kb", mTftpProgressFrame);\r
+      } else {\r
+        Print (L"    0 Kb");\r
+      }\r
+    }\r
+\r
+    //\r
+    // The data is the packet are prepended with two UINT16 :\r
+    // . OpCode = EFI_MTFTP4_OPCODE_DATA\r
+    // . Block  = the number of this block of data\r
+    //\r
+    Context->DownloadedNbOfBytes += PacketLen - sizeof (Packet->OpCode) - sizeof (Packet->Data.Block);\r
+    NbOfKb = Context->DownloadedNbOfBytes / 1024;\r
+\r
+    Progress[0] = L'\0';\r
+    if (Context->FileSize > 0) {\r
+      LastStep  = (Context->LastReportedNbOfBytes * TFTP_PROGRESS_SLIDER_STEPS) / Context->FileSize;\r
+      Step      = (Context->DownloadedNbOfBytes   * TFTP_PROGRESS_SLIDER_STEPS) / Context->FileSize;\r
+      if (Step > LastStep) {\r
+        Print (mTftpProgressDelete);\r
+        CopyMem (Progress, mTftpProgressFrame, sizeof mTftpProgressFrame);\r
+        for (Index = 1; Index < Step; Index++) {\r
+          Progress[Index] = L'=';\r
+        }\r
+        Progress[Step] = L'>';\r
+\r
+        UnicodeSPrint (\r
+          Progress + (sizeof (mTftpProgressFrame) / sizeof (CHAR16)) - 1,\r
+          sizeof (Progress) - sizeof (mTftpProgressFrame),\r
+          L" %7d Kb",\r
+          NbOfKb\r
+          );\r
+        Context->LastReportedNbOfBytes = Context->DownloadedNbOfBytes;\r
+      }\r
+    } else {\r
+      //\r
+      // Case when we do not know the size of the final file.\r
+      // We print the updated size every 50KB of downloaded data\r
+      //\r
+      LastNbOf50Kb = Context->LastReportedNbOfBytes / (50*1024);\r
+      NbOf50Kb     = Context->DownloadedNbOfBytes   / (50*1024);\r
+      if (NbOf50Kb > LastNbOf50Kb) {\r
+        Print (L"\b\b\b\b\b\b\b\b\b\b");\r
+        UnicodeSPrint (Progress, sizeof (Progress), L"%7d Kb", NbOfKb);\r
+        Context->LastReportedNbOfBytes = Context->DownloadedNbOfBytes;\r
+      }\r
+    }\r
+    if (Progress[0] != L'\0') {\r
+      Print (L"%s", Progress);\r
+    }\r
+  }\r
+\r
+  return EFI_SUCCESS;\r
 }\r
 \r
+/**\r
+  Download an image from a TFTP server\r
+\r
+  @param[in]   DevicePath           Device path of the TFTP boot option\r
+  @param[in]   ControllerHandle     Handle of the network controller\r
+  @param[in]   RemainingDevicePath  Device path of the TFTP boot option but\r
+                                    the first node that identifies the network controller\r
+  @param[in]   Type                 Type to allocate memory pages\r
+  @param[out]  Image                Address of the bufer where the image is stored in\r
+                                    case of success\r
+  @param[out]  ImageSize            Size in number of bytes of the i;age in case of\r
+                                    success\r
+\r
+  @retval  EFI_SUCCESS   The image was returned.\r
+  @retval  !EFI_SUCCESS  Something went wrong.\r
+\r
+**/\r
 EFI_STATUS\r
 BdsTftpLoadImage (\r
-  IN     EFI_DEVICE_PATH*       DevicePath,\r
-  IN     EFI_HANDLE             Handle,\r
-  IN     EFI_DEVICE_PATH*       RemainingDevicePath,\r
-  IN     EFI_ALLOCATE_TYPE      Type,\r
-  IN OUT EFI_PHYSICAL_ADDRESS   *Image,\r
-  OUT    UINTN                  *ImageSize\r
+  IN OUT EFI_DEVICE_PATH       **DevicePath,\r
+  IN     EFI_HANDLE            ControllerHandle,\r
+  IN     EFI_DEVICE_PATH       *RemainingDevicePath,\r
+  IN     EFI_ALLOCATE_TYPE     Type,\r
+  IN OUT EFI_PHYSICAL_ADDRESS  *Image,\r
+  OUT    UINTN                 *ImageSize\r
   )\r
 {\r
-  EFI_STATUS                  Status;\r
-  EFI_PXE_BASE_CODE_PROTOCOL  *Pxe;\r
-  UINT64                      TftpBufferSize;\r
-  EFI_IP_ADDRESS              ServerIp;\r
-  IPv4_DEVICE_PATH*           IPv4DevicePathNode;\r
-  FILEPATH_DEVICE_PATH*       FilePathDevicePath;\r
-  EFI_IP_ADDRESS              LocalIp;\r
-  CHAR8*                      AsciiPathName;\r
-  EFI_SIMPLE_NETWORK_PROTOCOL *Snp;\r
+  EFI_STATUS               Status;\r
+  EFI_HANDLE               Dhcp4ChildHandle;\r
+  EFI_DHCP4_PROTOCOL       *Dhcp4;\r
+  BOOLEAN                  Dhcp4ToStop;\r
+  EFI_HANDLE               Mtftp4ChildHandle;\r
+  EFI_MTFTP4_PROTOCOL      *Mtftp4;\r
+  DHCP4_OPTION             ParaList;\r
+  EFI_DHCP4_PACKET_OPTION  *OptionList[2];\r
+  EFI_DHCP4_CONFIG_DATA    Dhcp4CfgData;\r
+  EFI_DHCP4_MODE_DATA      Dhcp4Mode;\r
+  EFI_MTFTP4_CONFIG_DATA   Mtftp4CfgData;\r
+  IPv4_DEVICE_PATH         *IPv4DevicePathNode;\r
+  CHAR16                   *PathName;\r
+  CHAR8                    *AsciiFilePath;\r
+  EFI_MTFTP4_TOKEN         Mtftp4Token;\r
+  UINT64                   FileSize;\r
+  UINT64                   TftpBufferSize;\r
+  BDS_TFTP_CONTEXT         *TftpContext;\r
+  UINTN                    PathNameLen;\r
 \r
   ASSERT(IS_DEVICE_PATH_NODE (RemainingDevicePath, MESSAGING_DEVICE_PATH, MSG_IPv4_DP));\r
-\r
   IPv4DevicePathNode = (IPv4_DEVICE_PATH*)RemainingDevicePath;\r
-  FilePathDevicePath = (FILEPATH_DEVICE_PATH*)(IPv4DevicePathNode + 1);\r
 \r
-  Status = gBS->LocateProtocol (&gEfiPxeBaseCodeProtocolGuid, NULL, (VOID **)&Pxe);\r
-  if (EFI_ERROR (Status)) {\r
-    return Status;\r
+  Dhcp4ChildHandle  = NULL;\r
+  Dhcp4             = NULL;\r
+  Dhcp4ToStop       = FALSE;\r
+  Mtftp4ChildHandle = NULL;\r
+  Mtftp4            = NULL;\r
+  AsciiFilePath     = NULL;\r
+  TftpContext       = NULL;\r
+\r
+  if (!IPv4DevicePathNode->StaticIpAddress) {\r
+    //\r
+    // Using the DHCP4 Service Binding Protocol, create a child handle of the DHCP4 service and\r
+    // install the DHCP4 protocol on it. Then, open the DHCP protocol.\r
+    //\r
+    Status = NetLibCreateServiceChild (\r
+               ControllerHandle,\r
+               gImageHandle,\r
+               &gEfiDhcp4ServiceBindingProtocolGuid,\r
+               &Dhcp4ChildHandle\r
+               );\r
+    if (!EFI_ERROR (Status)) {\r
+      Status = gBS->OpenProtocol (\r
+                      Dhcp4ChildHandle,\r
+                      &gEfiDhcp4ProtocolGuid,\r
+                      (VOID **) &Dhcp4,\r
+                      gImageHandle,\r
+                      ControllerHandle,\r
+                      EFI_OPEN_PROTOCOL_BY_DRIVER\r
+                      );\r
+    }\r
+    if (EFI_ERROR (Status)) {\r
+      Print (L"Unable to open DHCP4 protocol\n");\r
+      goto Error;\r
+    }\r
   }\r
 \r
-  Status = Pxe->Start (Pxe, FALSE);\r
-  if (EFI_ERROR (Status) && (Status != EFI_ALREADY_STARTED)) {\r
-    return Status;\r
+  //\r
+  // Using the MTFTP4 Service Binding Protocol, create a child handle of the MTFTP4 service and\r
+  // install the MTFTP4 protocol on it. Then, open the MTFTP4 protocol.\r
+  //\r
+  Status = NetLibCreateServiceChild (\r
+             ControllerHandle,\r
+             gImageHandle,\r
+             &gEfiMtftp4ServiceBindingProtocolGuid,\r
+             &Mtftp4ChildHandle\r
+             );\r
+  if (!EFI_ERROR (Status)) {\r
+    Status = gBS->OpenProtocol (\r
+                    Mtftp4ChildHandle,\r
+                    &gEfiMtftp4ProtocolGuid,\r
+                    (VOID **) &Mtftp4,\r
+                    gImageHandle,\r
+                    ControllerHandle,\r
+                    EFI_OPEN_PROTOCOL_BY_DRIVER\r
+                    );\r
+  }\r
+  if (EFI_ERROR (Status)) {\r
+    Print (L"Unable to open MTFTP4 protocol\n");\r
+    goto Error;\r
   }\r
 \r
-  do {\r
-    if (!IPv4DevicePathNode->StaticIpAddress) {\r
-      Status = Pxe->Dhcp (Pxe, TRUE);\r
-    } else {\r
-      CopyMem (&LocalIp.v4, &IPv4DevicePathNode->LocalIpAddress, sizeof (EFI_IPv4_ADDRESS));\r
-      Status = Pxe->SetStationIp (Pxe, &LocalIp, NULL);\r
-    }\r
-\r
-    // If an IP Address has already been set and a different static IP address is requested then restart\r
-    // the Network service.\r
-    if (Status == EFI_ALREADY_STARTED) {\r
-      Status = gBS->LocateProtocol (&gEfiSimpleNetworkProtocolGuid, NULL, (VOID **)&Snp);\r
-      if (!EFI_ERROR (Status) && IPv4DevicePathNode->StaticIpAddress &&\r
-          (CompareMem (&Snp->Mode->CurrentAddress, &IPv4DevicePathNode->LocalIpAddress, sizeof(EFI_MAC_ADDRESS)) != 0))\r
-      {\r
-        Pxe->Stop (Pxe);\r
-        Status = Pxe->Start (Pxe, FALSE);\r
-        if (EFI_ERROR(Status)) {\r
-          break;\r
-        }\r
-        // After restarting the PXE protocol, we want to try again with our new IP Address\r
-        Status = EFI_ALREADY_STARTED;\r
+  if (!IPv4DevicePathNode->StaticIpAddress) {\r
+    //\r
+    // Configure the DHCP4, all default settings. It is acceptable for the configuration to\r
+    // fail if the return code is equal to EFI_ACCESS_DENIED which means that the configuration\r
+    // has been done by another instance of the DHCP4 protocol or that the DHCP configuration\r
+    // process has been started but is not completed yet.\r
+    //\r
+    ZeroMem (&Dhcp4CfgData, sizeof (EFI_DHCP4_CONFIG_DATA));\r
+    ParaList.Head.OpCode     = DHCP_TAG_PARA_LIST;\r
+    ParaList.Head.Length     = 2;\r
+    ParaList.Head.Data[0]    = DHCP_TAG_NETMASK;\r
+    ParaList.Route           = DHCP_TAG_ROUTER;\r
+    OptionList[0]            = &ParaList.Head;\r
+    Dhcp4CfgData.OptionCount = 1;\r
+    Dhcp4CfgData.OptionList  = OptionList;\r
+\r
+    Status = Dhcp4->Configure (Dhcp4, &Dhcp4CfgData);\r
+    if (EFI_ERROR (Status)) {\r
+      if (Status != EFI_ACCESS_DENIED) {\r
+        Print (L"Error while configuring the DHCP4 protocol\n");\r
+        goto Error;\r
       }\r
     }\r
-  } while (Status == EFI_ALREADY_STARTED);\r
 \r
-  if (EFI_ERROR(Status)) {\r
-    return Status;\r
+    //\r
+    // Start the DHCP configuration. This may have already been done thus do not leave in error\r
+    // if the return code is EFI_ALREADY_STARTED.\r
+    //\r
+    Status = Dhcp4->Start (Dhcp4, NULL);\r
+    if (EFI_ERROR (Status)) {\r
+      if (Status != EFI_ALREADY_STARTED) {\r
+        Print (L"DHCP configuration failed\n");\r
+        goto Error;\r
+      }\r
+    } else {\r
+      Dhcp4ToStop = TRUE;\r
+    }\r
+\r
+    Status = Dhcp4->GetModeData (Dhcp4, &Dhcp4Mode);\r
+    if (EFI_ERROR (Status)) {\r
+      goto Error;\r
+    }\r
+\r
+    if (Dhcp4Mode.State != Dhcp4Bound) {\r
+      Status = EFI_TIMEOUT;\r
+      Print (L"DHCP configuration failed\n");\r
+      goto Error;\r
+    }\r
+  }\r
+\r
+  //\r
+  // Configure the TFTP4 protocol\r
+  //\r
+\r
+  ZeroMem (&Mtftp4CfgData, sizeof (EFI_MTFTP4_CONFIG_DATA));\r
+  Mtftp4CfgData.UseDefaultSetting = FALSE;\r
+  Mtftp4CfgData.TimeoutValue      = 4;\r
+  Mtftp4CfgData.TryCount          = 6;\r
+\r
+  if (IPv4DevicePathNode->StaticIpAddress) {\r
+    CopyMem (&Mtftp4CfgData.StationIp , &IPv4DevicePathNode->LocalIpAddress, sizeof (EFI_IPv4_ADDRESS));\r
+    CopyMem (&Mtftp4CfgData.SubnetMask, &IPv4DevicePathNode->SubnetMask, sizeof (EFI_IPv4_ADDRESS));\r
+    CopyMem (&Mtftp4CfgData.GatewayIp , &IPv4DevicePathNode->GatewayIpAddress, sizeof (EFI_IPv4_ADDRESS));\r
+  } else {\r
+    CopyMem (&Mtftp4CfgData.StationIp , &Dhcp4Mode.ClientAddress, sizeof (EFI_IPv4_ADDRESS));\r
+    CopyMem (&Mtftp4CfgData.SubnetMask, &Dhcp4Mode.SubnetMask   , sizeof (EFI_IPv4_ADDRESS));\r
+    CopyMem (&Mtftp4CfgData.GatewayIp , &Dhcp4Mode.RouterAddress, sizeof (EFI_IPv4_ADDRESS));\r
   }\r
 \r
-  CopyMem (&ServerIp.v4, &IPv4DevicePathNode->RemoteIpAddress, sizeof (EFI_IPv4_ADDRESS));\r
+  CopyMem (&Mtftp4CfgData.ServerIp  , &IPv4DevicePathNode->RemoteIpAddress, sizeof (EFI_IPv4_ADDRESS));\r
 \r
-  // Convert the Unicode PathName to Ascii\r
-  AsciiPathName = AllocatePool ((StrLen (FilePathDevicePath->PathName) + 1) * sizeof (CHAR8));\r
-  if (AsciiPathName == NULL) {\r
-    return EFI_OUT_OF_RESOURCES;\r
+  Status = Mtftp4->Configure (Mtftp4, &Mtftp4CfgData);\r
+  if (EFI_ERROR (Status)) {\r
+    Print (L"Error while configuring the MTFTP4 protocol\n");\r
+    goto Error;\r
   }\r
-  UnicodeStrToAsciiStr (FilePathDevicePath->PathName, AsciiPathName);\r
 \r
-  Status = Pxe->Mtftp (\r
-                  Pxe,\r
-                  EFI_PXE_BASE_CODE_TFTP_GET_FILE_SIZE,\r
-                  NULL,\r
-                  FALSE,\r
-                  &TftpBufferSize,\r
-                  NULL,\r
-                  &ServerIp,\r
-                  (UINT8*)AsciiPathName,\r
-                  NULL,\r
-                  FALSE\r
-                  );\r
-  if (EFI_ERROR(Status)) {\r
-    if (Status == EFI_TFTP_ERROR) {\r
-      DEBUG((EFI_D_ERROR, "TFTP Error: Fail to get the size of the file\n"));\r
+  // The Device Path might contain multiple FilePath nodes\r
+  PathName      = ConvertDevicePathToText ((EFI_DEVICE_PATH_PROTOCOL*)(IPv4DevicePathNode + 1), FALSE, FALSE);\r
+  PathNameLen   = StrLen (PathName) + 1;\r
+  AsciiFilePath = AllocatePool (PathNameLen);\r
+  UnicodeStrToAsciiStrS (PathName, AsciiFilePath, PathNameLen);\r
+\r
+  //\r
+  // Try to get the size of the file in bytes from the server. If it fails,\r
+  // start with a 8MB buffer to download the file.\r
+  //\r
+  FileSize = 0;\r
+  if (Mtftp4GetFileSize (Mtftp4, AsciiFilePath, &FileSize) == EFI_SUCCESS) {\r
+    TftpBufferSize = FileSize;\r
+  } else {\r
+    TftpBufferSize = SIZE_16MB;\r
+  }\r
+\r
+  TftpContext = AllocatePool (sizeof (BDS_TFTP_CONTEXT));\r
+  if (TftpContext == NULL) {\r
+    Status = EFI_OUT_OF_RESOURCES;\r
+    goto Error;\r
+  }\r
+  TftpContext->FileSize = FileSize;\r
+\r
+  for (; TftpBufferSize <= FixedPcdGet32 (PcdMaxTftpFileSize);\r
+         TftpBufferSize = (TftpBufferSize + SIZE_16MB) & (~(SIZE_16MB-1))) {\r
+    //\r
+    // Allocate a buffer to hold the whole file.\r
+    //\r
+    Status = gBS->AllocatePages (\r
+                    Type,\r
+                    EfiBootServicesCode,\r
+                    EFI_SIZE_TO_PAGES (TftpBufferSize),\r
+                    Image\r
+                    );\r
+    if (EFI_ERROR (Status)) {\r
+      Print (L"Failed to allocate space for image\n");\r
+      goto Error;\r
     }\r
-    goto EXIT;\r
+\r
+    TftpContext->DownloadedNbOfBytes   = 0;\r
+    TftpContext->LastReportedNbOfBytes = 0;\r
+\r
+    ZeroMem (&Mtftp4Token, sizeof (EFI_MTFTP4_TOKEN));\r
+    Mtftp4Token.Filename    = (UINT8*)AsciiFilePath;\r
+    Mtftp4Token.BufferSize  = TftpBufferSize;\r
+    Mtftp4Token.Buffer      = (VOID *)(UINTN)*Image;\r
+    Mtftp4Token.CheckPacket = Mtftp4CheckPacket;\r
+    Mtftp4Token.Context     = (VOID*)TftpContext;\r
+\r
+    Print (L"Downloading the file <%a> from the TFTP server\n", AsciiFilePath);\r
+    Status = Mtftp4->ReadFile (Mtftp4, &Mtftp4Token);\r
+    Print (L"\n");\r
+    if (EFI_ERROR (Status)) {\r
+      gBS->FreePages (*Image, EFI_SIZE_TO_PAGES (TftpBufferSize));\r
+      if (Status == EFI_BUFFER_TOO_SMALL) {\r
+        Print (L"Downloading failed, file larger than expected.\n");\r
+        continue;\r
+      } else {\r
+        goto Error;\r
+      }\r
+    }\r
+\r
+    *ImageSize = Mtftp4Token.BufferSize;\r
+    break;\r
+  }\r
+\r
+Error:\r
+  if (Dhcp4ChildHandle != NULL) {\r
+    if (Dhcp4 != NULL) {\r
+      if (Dhcp4ToStop) {\r
+        Dhcp4->Stop (Dhcp4);\r
+      }\r
+      gBS->CloseProtocol (\r
+             Dhcp4ChildHandle,\r
+             &gEfiDhcp4ProtocolGuid,\r
+             gImageHandle,\r
+             ControllerHandle\r
+            );\r
+    }\r
+    NetLibDestroyServiceChild (\r
+      ControllerHandle,\r
+      gImageHandle,\r
+      &gEfiDhcp4ServiceBindingProtocolGuid,\r
+      Dhcp4ChildHandle\r
+      );\r
+  }\r
+\r
+  if (Mtftp4ChildHandle != NULL) {\r
+    if (Mtftp4 != NULL) {\r
+      if (AsciiFilePath != NULL) {\r
+        FreePool (AsciiFilePath);\r
+      }\r
+      if (TftpContext != NULL) {\r
+        FreePool (TftpContext);\r
+      }\r
+      gBS->CloseProtocol (\r
+             Mtftp4ChildHandle,\r
+             &gEfiMtftp4ProtocolGuid,\r
+             gImageHandle,\r
+             ControllerHandle\r
+            );\r
+    }\r
+    NetLibDestroyServiceChild (\r
+      ControllerHandle,\r
+      gImageHandle,\r
+      &gEfiMtftp4ServiceBindingProtocolGuid,\r
+      Mtftp4ChildHandle\r
+      );\r
   }\r
 \r
-  // Allocate a buffer to hold the whole file.\r
-  Status = gBS->AllocatePages (\r
-                  Type,\r
-                  EfiBootServicesCode,\r
-                  EFI_SIZE_TO_PAGES (TftpBufferSize),\r
-                  Image\r
-                  );\r
-  if (EFI_ERROR (Status)) {\r
-    DEBUG ((EFI_D_ERROR, "Failed to allocate space for kernel image: %r\n", Status));\r
-    goto EXIT;\r
-  }\r
-\r
-  Status = Pxe->Mtftp (\r
-                  Pxe,\r
-                  EFI_PXE_BASE_CODE_TFTP_READ_FILE,\r
-                  (VOID *)(UINTN)*Image,\r
-                  FALSE,\r
-                  &TftpBufferSize,\r
-                  NULL,\r
-                  &ServerIp,\r
-                  (UINT8*)AsciiPathName,\r
-                  NULL,\r
-                  FALSE\r
-                  );\r
   if (EFI_ERROR (Status)) {\r
-    gBS->FreePages (*Image, EFI_SIZE_TO_PAGES (TftpBufferSize));\r
-  } else {\r
-    *ImageSize = (UINTN)TftpBufferSize;\r
+    *Image = 0;\r
+    Print (L"Failed to download the file - Error=%r\n", Status);\r
   }\r
 \r
-EXIT:\r
-  FreePool (AsciiPathName);\r
   return Status;\r
 }\r
 \r
@@ -882,8 +1313,8 @@ BDS_FILE_LOADER FileLoaders[] = {
 };\r
 \r
 EFI_STATUS\r
-BdsLoadImageAndUpdateDevicePath (
-  IN OUT EFI_DEVICE_PATH       **DevicePath,
+BdsLoadImageAndUpdateDevicePath (\r
+  IN OUT EFI_DEVICE_PATH       **DevicePath,\r
   IN     EFI_ALLOCATE_TYPE     Type,\r
   IN OUT EFI_PHYSICAL_ADDRESS* Image,\r
   OUT    UINTN                 *FileSize\r
@@ -894,15 +1325,15 @@ BdsLoadImageAndUpdateDevicePath (
   EFI_DEVICE_PATH *RemainingDevicePath;\r
   BDS_FILE_LOADER*  FileLoader;\r
 \r
-  Status = BdsConnectAndUpdateDevicePath (DevicePath, &Handle, &RemainingDevicePath);
+  Status = BdsConnectAndUpdateDevicePath (DevicePath, &Handle, &RemainingDevicePath);\r
   if (EFI_ERROR (Status)) {\r
     return Status;\r
   }\r
 \r
   FileLoader = FileLoaders;\r
   while (FileLoader->Support != NULL) {\r
-    if (FileLoader->Support (*DevicePath, Handle, RemainingDevicePath)) {
-      return FileLoader->LoadImage (*DevicePath, Handle, RemainingDevicePath, Type, Image, FileSize);
+    if (FileLoader->Support (*DevicePath, Handle, RemainingDevicePath)) {\r
+      return FileLoader->LoadImage (DevicePath, Handle, RemainingDevicePath, Type, Image, FileSize);\r
     }\r
     FileLoader++;\r
   }\r
@@ -911,16 +1342,16 @@ BdsLoadImageAndUpdateDevicePath (
 }\r
 \r
 EFI_STATUS\r
-BdsLoadImage (
-  IN     EFI_DEVICE_PATH       *DevicePath,
-  IN     EFI_ALLOCATE_TYPE     Type,
-  IN OUT EFI_PHYSICAL_ADDRESS* Image,
-  OUT    UINTN                 *FileSize
-  )
-{
-  return BdsLoadImageAndUpdateDevicePath (&DevicePath, Type, Image, FileSize);
-}
-
+BdsLoadImage (\r
+  IN     EFI_DEVICE_PATH       *DevicePath,\r
+  IN     EFI_ALLOCATE_TYPE     Type,\r
+  IN OUT EFI_PHYSICAL_ADDRESS* Image,\r
+  OUT    UINTN                 *FileSize\r
+  )\r
+{\r
+  return BdsLoadImageAndUpdateDevicePath (&DevicePath, Type, Image, FileSize);\r
+}\r
+\r
 /**\r
   Start an EFI Application from a Device Path\r
 \r
@@ -947,7 +1378,7 @@ BdsStartEfiApplication (
   EFI_LOADED_IMAGE_PROTOCOL*   LoadedImage;\r
 \r
   // Find the nearest supported file loader\r
-  Status = BdsLoadImageAndUpdateDevicePath (&DevicePath, AllocateAnyPages, &BinaryBuffer, &BinarySize);
+  Status = BdsLoadImageAndUpdateDevicePath (&DevicePath, AllocateAnyPages, &BinaryBuffer, &BinarySize);\r
   if (EFI_ERROR (Status)) {\r
     return Status;\r
   }\r