+++ /dev/null
-/** @file\r
-*\r
-* Copyright (c) 2011-2014, 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
-*\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
-\r
-// Extract the FilePath from the Device Path\r
-CHAR16*\r
-BdsExtractFilePathFromDevicePath (\r
- IN CONST CHAR16 *StrDevicePath,\r
- IN UINTN NumberDevicePathNode\r
- )\r
-{\r
- UINTN Node;\r
- CHAR16 *Str;\r
-\r
- Str = (CHAR16*)StrDevicePath;\r
- Node = 0;\r
- while ((Str != NULL) && (*Str != L'\0') && (Node < NumberDevicePathNode)) {\r
- if ((*Str == L'/') || (*Str == L'\\')) {\r
- Node++;\r
- }\r
- Str++;\r
- }\r
-\r
- if (*Str == L'\0') {\r
- return NULL;\r
- } else {\r
- return Str;\r
- }\r
-}\r
-\r
-BOOLEAN\r
-BdsIsRemovableUsb (\r
- IN EFI_DEVICE_PATH* DevicePath\r
- )\r
-{\r
- return ((DevicePathType (DevicePath) == MESSAGING_DEVICE_PATH) &&\r
- ((DevicePathSubType (DevicePath) == MSG_USB_CLASS_DP) ||\r
- (DevicePathSubType (DevicePath) == MSG_USB_WWID_DP)));\r
-}\r
-\r
-EFI_STATUS\r
-BdsGetDeviceUsb (\r
- IN EFI_DEVICE_PATH* RemovableDevicePath,\r
- OUT EFI_HANDLE* DeviceHandle,\r
- OUT EFI_DEVICE_PATH** NewDevicePath\r
- )\r
-{\r
- EFI_STATUS Status;\r
- UINTN Index;\r
- UINTN UsbIoHandleCount;\r
- EFI_HANDLE *UsbIoBuffer;\r
- EFI_DEVICE_PATH* UsbIoDevicePath;\r
- EFI_DEVICE_PATH* TmpDevicePath;\r
- USB_WWID_DEVICE_PATH* WwidDevicePath1;\r
- USB_WWID_DEVICE_PATH* WwidDevicePath2;\r
- USB_CLASS_DEVICE_PATH* UsbClassDevicePath1;\r
- USB_CLASS_DEVICE_PATH* UsbClassDevicePath2;\r
-\r
- // Get all the UsbIo handles\r
- UsbIoHandleCount = 0;\r
- Status = gBS->LocateHandleBuffer (ByProtocol, &gEfiUsbIoProtocolGuid, NULL, &UsbIoHandleCount, &UsbIoBuffer);\r
- if (EFI_ERROR (Status) || (UsbIoHandleCount == 0)) {\r
- return Status;\r
- }\r
-\r
- // Check if one of the handles matches the USB description\r
- for (Index = 0; Index < UsbIoHandleCount; Index++) {\r
- Status = gBS->HandleProtocol (UsbIoBuffer[Index], &gEfiDevicePathProtocolGuid, (VOID **) &UsbIoDevicePath);\r
- if (!EFI_ERROR (Status)) {\r
- TmpDevicePath = UsbIoDevicePath;\r
- while (!IsDevicePathEnd (TmpDevicePath)) {\r
- // Check if the Device Path node is a USB Removable device Path node\r
- if (BdsIsRemovableUsb (TmpDevicePath)) {\r
- if (TmpDevicePath->SubType == MSG_USB_WWID_DP) {\r
- WwidDevicePath1 = (USB_WWID_DEVICE_PATH*)RemovableDevicePath;\r
- WwidDevicePath2 = (USB_WWID_DEVICE_PATH*)TmpDevicePath;\r
- if ((WwidDevicePath1->VendorId == WwidDevicePath2->VendorId) &&\r
- (WwidDevicePath1->ProductId == WwidDevicePath2->ProductId) &&\r
- (CompareMem (WwidDevicePath1+1, WwidDevicePath2+1, DevicePathNodeLength(WwidDevicePath1)-sizeof (USB_WWID_DEVICE_PATH)) == 0))\r
- {\r
- *DeviceHandle = UsbIoBuffer[Index];\r
- // Add the additional original Device Path Nodes (eg: FilePath Device Path Node) to the new Device Path\r
- *NewDevicePath = AppendDevicePath (UsbIoDevicePath, NextDevicePathNode (RemovableDevicePath));\r
- return EFI_SUCCESS;\r
- }\r
- } else {\r
- UsbClassDevicePath1 = (USB_CLASS_DEVICE_PATH*)RemovableDevicePath;\r
- UsbClassDevicePath2 = (USB_CLASS_DEVICE_PATH*)TmpDevicePath;\r
- if ((UsbClassDevicePath1->VendorId != 0xFFFF) && (UsbClassDevicePath1->VendorId == UsbClassDevicePath2->VendorId) &&\r
- (UsbClassDevicePath1->ProductId != 0xFFFF) && (UsbClassDevicePath1->ProductId == UsbClassDevicePath2->ProductId) &&\r
- (UsbClassDevicePath1->DeviceClass != 0xFF) && (UsbClassDevicePath1->DeviceClass == UsbClassDevicePath2->DeviceClass) &&\r
- (UsbClassDevicePath1->DeviceSubClass != 0xFF) && (UsbClassDevicePath1->DeviceSubClass == UsbClassDevicePath2->DeviceSubClass) &&\r
- (UsbClassDevicePath1->DeviceProtocol != 0xFF) && (UsbClassDevicePath1->DeviceProtocol == UsbClassDevicePath2->DeviceProtocol))\r
- {\r
- *DeviceHandle = UsbIoBuffer[Index];\r
- // Add the additional original Device Path Nodes (eg: FilePath Device Path Node) to the new Device Path\r
- *NewDevicePath = AppendDevicePath (UsbIoDevicePath, NextDevicePathNode (RemovableDevicePath));\r
- return EFI_SUCCESS;\r
- }\r
- }\r
- }\r
- TmpDevicePath = NextDevicePathNode (TmpDevicePath);\r
- }\r
-\r
- }\r
- }\r
-\r
- return EFI_NOT_FOUND;\r
-}\r
-\r
-BOOLEAN\r
-BdsIsRemovableHd (\r
- IN EFI_DEVICE_PATH* DevicePath\r
- )\r
-{\r
- return IS_DEVICE_PATH_NODE (DevicePath, MEDIA_DEVICE_PATH, MEDIA_HARDDRIVE_DP);\r
-}\r
-\r
-EFI_STATUS\r
-BdsGetDeviceHd (\r
- IN EFI_DEVICE_PATH* RemovableDevicePath,\r
- OUT EFI_HANDLE* DeviceHandle,\r
- OUT EFI_DEVICE_PATH** NewDevicePath\r
- )\r
-{\r
- EFI_STATUS Status;\r
- UINTN Index;\r
- UINTN PartitionHandleCount;\r
- EFI_HANDLE *PartitionBuffer;\r
- EFI_DEVICE_PATH* PartitionDevicePath;\r
- EFI_DEVICE_PATH* TmpDevicePath;\r
- HARDDRIVE_DEVICE_PATH* HardDriveDevicePath1;\r
- HARDDRIVE_DEVICE_PATH* HardDriveDevicePath2;\r
-\r
- // Get all the DiskIo handles\r
- PartitionHandleCount = 0;\r
- Status = gBS->LocateHandleBuffer (ByProtocol, &gEfiDiskIoProtocolGuid, NULL, &PartitionHandleCount, &PartitionBuffer);\r
- if (EFI_ERROR (Status) || (PartitionHandleCount == 0)) {\r
- return Status;\r
- }\r
-\r
- // Check if one of the handles matches the Hard Disk Description\r
- for (Index = 0; Index < PartitionHandleCount; Index++) {\r
- Status = gBS->HandleProtocol (PartitionBuffer[Index], &gEfiDevicePathProtocolGuid, (VOID **) &PartitionDevicePath);\r
- if (!EFI_ERROR (Status)) {\r
- TmpDevicePath = PartitionDevicePath;\r
- while (!IsDevicePathEnd (TmpDevicePath)) {\r
- // Check if the Device Path node is a HD Removable device Path node\r
- if (BdsIsRemovableHd (TmpDevicePath)) {\r
- HardDriveDevicePath1 = (HARDDRIVE_DEVICE_PATH*)RemovableDevicePath;\r
- HardDriveDevicePath2 = (HARDDRIVE_DEVICE_PATH*)TmpDevicePath;\r
- if ((HardDriveDevicePath1->SignatureType == HardDriveDevicePath2->SignatureType) &&\r
- (CompareGuid ((EFI_GUID *)HardDriveDevicePath1->Signature, (EFI_GUID *)HardDriveDevicePath2->Signature) == TRUE) &&\r
- (HardDriveDevicePath1->PartitionNumber == HardDriveDevicePath2->PartitionNumber))\r
- {\r
- *DeviceHandle = PartitionBuffer[Index];\r
- // Add the additional original Device Path Nodes (eg: FilePath Device Path Node) to the new Device Path\r
- *NewDevicePath = AppendDevicePath (PartitionDevicePath, NextDevicePathNode (RemovableDevicePath));\r
- return EFI_SUCCESS;\r
- }\r
- }\r
- TmpDevicePath = NextDevicePathNode (TmpDevicePath);\r
- }\r
-\r
- }\r
- }\r
-\r
- return EFI_NOT_FOUND;\r
-}\r
-\r
-/*BOOLEAN\r
-BdsIsRemovableCdrom (\r
- IN EFI_DEVICE_PATH* DevicePath\r
- )\r
-{\r
- return IS_DEVICE_PATH_NODE (DevicePath, MEDIA_DEVICE_PATH, MEDIA_CDROM_DP);\r
-}\r
-\r
-EFI_STATUS\r
-BdsGetDeviceCdrom (\r
- IN EFI_DEVICE_PATH* RemovableDevicePath,\r
- OUT EFI_HANDLE* DeviceHandle,\r
- OUT EFI_DEVICE_PATH** DevicePath\r
- )\r
-{\r
- ASSERT(0);\r
- return EFI_UNSUPPORTED;\r
-}*/\r
-\r
-typedef BOOLEAN\r
-(*BDS_IS_REMOVABLE) (\r
- IN EFI_DEVICE_PATH* DevicePath\r
- );\r
-\r
-typedef EFI_STATUS\r
-(*BDS_GET_DEVICE) (\r
- IN EFI_DEVICE_PATH* RemovableDevicePath,\r
- OUT EFI_HANDLE* DeviceHandle,\r
- OUT EFI_DEVICE_PATH** DevicePath\r
- );\r
-\r
-typedef struct {\r
- BDS_IS_REMOVABLE IsRemovable;\r
- BDS_GET_DEVICE GetDevice;\r
-} BDS_REMOVABLE_DEVICE_SUPPORT;\r
-\r
-BDS_REMOVABLE_DEVICE_SUPPORT RemovableDeviceSupport[] = {\r
- { BdsIsRemovableUsb, BdsGetDeviceUsb },\r
- { BdsIsRemovableHd, BdsGetDeviceHd },\r
- //{ BdsIsRemovableCdrom, BdsGetDeviceCdrom }\r
-};\r
-\r
-STATIC\r
-BOOLEAN\r
-IsRemovableDevice (\r
- IN EFI_DEVICE_PATH* DevicePath\r
- )\r
-{\r
- UINTN Index;\r
- EFI_DEVICE_PATH* TmpDevicePath;\r
-\r
- TmpDevicePath = DevicePath;\r
- while (!IsDevicePathEnd (TmpDevicePath)) {\r
- for (Index = 0; Index < sizeof (RemovableDeviceSupport) / sizeof (BDS_REMOVABLE_DEVICE_SUPPORT); Index++) {\r
- if (RemovableDeviceSupport[Index].IsRemovable (TmpDevicePath)) {\r
- return TRUE;\r
- }\r
- }\r
- TmpDevicePath = NextDevicePathNode (TmpDevicePath);\r
- }\r
-\r
- return FALSE;\r
-}\r
-\r
-STATIC\r
-EFI_STATUS\r
-TryRemovableDevice (\r
- IN EFI_DEVICE_PATH* DevicePath,\r
- OUT EFI_HANDLE* DeviceHandle,\r
- OUT EFI_DEVICE_PATH** NewDevicePath\r
- )\r
-{\r
- EFI_STATUS Status;\r
- UINTN Index;\r
- EFI_DEVICE_PATH* TmpDevicePath;\r
- BDS_REMOVABLE_DEVICE_SUPPORT* RemovableDevice;\r
- EFI_DEVICE_PATH* RemovableDevicePath;\r
- BOOLEAN RemovableFound;\r
-\r
- RemovableDevice = NULL;\r
- RemovableDevicePath = NULL;\r
- RemovableFound = FALSE;\r
- TmpDevicePath = DevicePath;\r
-\r
- while (!IsDevicePathEnd (TmpDevicePath) && !RemovableFound) {\r
- for (Index = 0; Index < sizeof (RemovableDeviceSupport) / sizeof (BDS_REMOVABLE_DEVICE_SUPPORT); Index++) {\r
- RemovableDevice = &RemovableDeviceSupport[Index];\r
- if (RemovableDevice->IsRemovable (TmpDevicePath)) {\r
- RemovableDevicePath = TmpDevicePath;\r
- RemovableFound = TRUE;\r
- break;\r
- }\r
- }\r
- TmpDevicePath = NextDevicePathNode (TmpDevicePath);\r
- }\r
-\r
- if (!RemovableFound) {\r
- return EFI_NOT_FOUND;\r
- }\r
-\r
- // Search into the current started drivers\r
- Status = RemovableDevice->GetDevice (RemovableDevicePath, DeviceHandle, NewDevicePath);\r
- if (Status == EFI_NOT_FOUND) {\r
- // Connect all the drivers\r
- BdsConnectAllDrivers ();\r
-\r
- // Search again into all the drivers\r
- Status = RemovableDevice->GetDevice (RemovableDevicePath, DeviceHandle, NewDevicePath);\r
- }\r
-\r
- return Status;\r
-}\r
-\r
-STATIC\r
-EFI_STATUS\r
-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)) {\r
- return EFI_INVALID_PARAMETER;\r
- }\r
-\r
- PreviousHandle = NULL;\r
- do {\r
- 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
- 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
- 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;\r
- Status = gBS->LocateDevicePath (&gEfiDevicePathProtocolGuid, &Remaining, Handle);\r
- if (!EFI_ERROR (Status)) {\r
- Status = gBS->ConnectController (*Handle, NULL, Remaining, FALSE);\r
- if (EFI_ERROR (Status)) {\r
- // If the last node is a Memory Map Device Path just return EFI_SUCCESS.\r
- if ((Remaining->Type == HARDWARE_DEVICE_PATH) && (Remaining->SubType == HW_MEMMAP_DP)) {\r
- Status = EFI_SUCCESS;\r
- }\r
- }\r
- }\r
- } else if (!IsDevicePathEnd (Remaining) && !IsRemovableDevice (Remaining)) {\r
-\r
- /*// If the remaining Device Path is a FilePath or MemoryMap then we consider the Device Path has been loaded correctly\r
- if ((Remaining->Type == MEDIA_DEVICE_PATH) && (Remaining->SubType == MEDIA_FILEPATH_DP)) {\r
- Status = EFI_SUCCESS;\r
- } else if ((Remaining->Type == HARDWARE_DEVICE_PATH) && (Remaining->SubType == HW_MEMMAP_DP)) {\r
- Status = EFI_SUCCESS;\r
- }*/\r
-\r
- //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);\r
- if (!EFI_ERROR (Status)) {\r
- Status = BdsConnectAndUpdateDevicePath (&NewDevicePath, Handle, RemainingDevicePath);\r
- *DevicePath = NewDevicePath;\r
- return Status;\r
- }\r
- }\r
-\r
- if (RemainingDevicePath) {\r
- *RemainingDevicePath = Remaining;\r
- }\r
-\r
- return Status;\r
-}\r
-\r
-/**\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\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
- IN EFI_HANDLE Handle,\r
- IN EFI_DEVICE_PATH *RemainingDevicePath\r
- )\r
-{\r
- EFI_STATUS Status;\r
- EFI_SIMPLE_FILE_SYSTEM_PROTOCOL *FsProtocol;\r
-\r
- Status = gBS->HandleProtocol (Handle, &gEfiSimpleFileSystemProtocolGuid, (VOID **)&FsProtocol);\r
-\r
- return (!EFI_ERROR (Status) && IS_DEVICE_PATH_NODE (RemainingDevicePath, MEDIA_DEVICE_PATH, MEDIA_FILEPATH_DP));\r
-}\r
-\r
-EFI_STATUS\r
-BdsFileSystemLoadImage (\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
- )\r
-{\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->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
-\r
- // Try to Open the volume and get root directory\r
- Status = FsProtocol->OpenVolume (FsProtocol, &Fs);\r
- if (EFI_ERROR (Status)) {\r
- goto CLOSE_PROTOCOL;\r
- }\r
-\r
- Status = Fs->Open (Fs, &File, FilePathDevicePath->PathName, EFI_FILE_MODE_READ, 0);\r
- if (EFI_ERROR (Status)) {\r
- goto CLOSE_PROTOCOL;\r
- }\r
-\r
- Size = 0;\r
- File->GetInfo (File, &gEfiFileInfoGuid, &Size, NULL);\r
- FileInfo = AllocatePool (Size);\r
- Status = File->GetInfo (File, &gEfiFileInfoGuid, &Size, FileInfo);\r
- if (EFI_ERROR (Status)) {\r
- goto CLOSE_FILE;\r
- }\r
-\r
- // Get the file size\r
- Size = FileInfo->FileSize;\r
- if (ImageSize) {\r
- *ImageSize = Size;\r
- }\r
- FreePool (FileInfo);\r
-\r
- Status = gBS->AllocatePages (Type, EfiBootServicesCode, EFI_SIZE_TO_PAGES(Size), Image);\r
- // Try to allocate in any pages if failed to allocate memory at the defined location\r
- if ((Status == EFI_OUT_OF_RESOURCES) && (Type != AllocateAnyPages)) {\r
- Status = gBS->AllocatePages (AllocateAnyPages, EfiBootServicesCode, EFI_SIZE_TO_PAGES(Size), Image);\r
- }\r
- if (!EFI_ERROR (Status)) {\r
- 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
-BOOLEAN\r
-BdsMemoryMapSupport (\r
- IN EFI_DEVICE_PATH *DevicePath,\r
- IN EFI_HANDLE Handle,\r
- IN EFI_DEVICE_PATH *RemainingDevicePath\r
- )\r
-{\r
- return IS_DEVICE_PATH_NODE (DevicePath, HARDWARE_DEVICE_PATH, HW_MEMMAP_DP) ||\r
- IS_DEVICE_PATH_NODE (RemainingDevicePath, HARDWARE_DEVICE_PATH, HW_MEMMAP_DP);\r
-}\r
-\r
-EFI_STATUS\r
-BdsMemoryMapLoadImage (\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
- )\r
-{\r
- EFI_STATUS Status;\r
- MEMMAP_DEVICE_PATH* MemMapPathDevicePath;\r
- UINTN Size;\r
-\r
- 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
- }\r
-\r
- Size = MemMapPathDevicePath->EndingAddress - MemMapPathDevicePath->StartingAddress;\r
- if (Size == 0) {\r
- return EFI_INVALID_PARAMETER;\r
- }\r
-\r
- Status = gBS->AllocatePages (Type, EfiBootServicesCode, EFI_SIZE_TO_PAGES(Size), Image);\r
- // Try to allocate in any pages if failed to allocate memory at the defined location\r
- if ((Status == EFI_OUT_OF_RESOURCES) && (Type != AllocateAnyPages)) {\r
- Status = gBS->AllocatePages (AllocateAnyPages, EfiBootServicesCode, EFI_SIZE_TO_PAGES(Size), Image);\r
- }\r
- if (!EFI_ERROR (Status)) {\r
- CopyMem ((VOID*)(UINTN)(*Image), (CONST VOID*)(UINTN)MemMapPathDevicePath->StartingAddress, Size);\r
-\r
- if (ImageSize != NULL) {\r
- *ImageSize = Size;\r
- }\r
- }\r
-\r
- return Status;\r
-}\r
-\r
-BOOLEAN\r
-BdsFirmwareVolumeSupport (\r
- IN EFI_DEVICE_PATH *DevicePath,\r
- IN EFI_HANDLE Handle,\r
- IN EFI_DEVICE_PATH *RemainingDevicePath\r
- )\r
-{\r
- return IS_DEVICE_PATH_NODE (RemainingDevicePath, MEDIA_DEVICE_PATH, MEDIA_PIWG_FW_FILE_DP);\r
-}\r
-\r
-EFI_STATUS\r
-BdsFirmwareVolumeLoadImage (\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
- )\r
-{\r
- EFI_STATUS Status;\r
- EFI_FIRMWARE_VOLUME2_PROTOCOL *FwVol;\r
- EFI_GUID *FvNameGuid;\r
- EFI_SECTION_TYPE SectionType;\r
- EFI_FV_FILETYPE FvType;\r
- EFI_FV_FILE_ATTRIBUTES Attrib;\r
- UINT32 AuthenticationStatus;\r
- VOID* ImageBuffer;\r
-\r
- ASSERT (IS_DEVICE_PATH_NODE (RemainingDevicePath, MEDIA_DEVICE_PATH, MEDIA_PIWG_FW_FILE_DP));\r
-\r
- Status = gBS->HandleProtocol (Handle, &gEfiFirmwareVolume2ProtocolGuid, (VOID **)&FwVol);\r
- if (EFI_ERROR (Status)) {\r
- return Status;\r
- }\r
-\r
- FvNameGuid = EfiGetNameGuidFromFwVolDevicePathNode ((CONST MEDIA_FW_VOL_FILEPATH_DEVICE_PATH *)RemainingDevicePath);\r
- if (FvNameGuid == NULL) {\r
- Status = EFI_INVALID_PARAMETER;\r
- }\r
-\r
- SectionType = EFI_SECTION_PE32;\r
- AuthenticationStatus = 0;\r
- //Note: ReadSection at the opposite of ReadFile does not allow to pass ImageBuffer == NULL to get the size of the file.\r
- ImageBuffer = NULL;\r
- Status = FwVol->ReadSection (\r
- FwVol,\r
- FvNameGuid,\r
- SectionType,\r
- 0,\r
- &ImageBuffer,\r
- ImageSize,\r
- &AuthenticationStatus\r
- );\r
- if (!EFI_ERROR (Status)) {\r
-#if 0\r
- // In case the buffer has some address requirements, we must copy the buffer to a buffer following the requirements\r
- if (Type != AllocateAnyPages) {\r
- Status = gBS->AllocatePages (Type, EfiBootServicesCode, EFI_SIZE_TO_PAGES(*ImageSize),Image);\r
- if (!EFI_ERROR (Status)) {\r
- CopyMem ((VOID*)(UINTN)(*Image), ImageBuffer, *ImageSize);\r
- FreePool (ImageBuffer);\r
- }\r
- }\r
-#else\r
- // We must copy the buffer into a page allocations. Otherwise, the caller could call gBS->FreePages() on the pool allocation\r
- Status = gBS->AllocatePages (Type, EfiBootServicesCode, EFI_SIZE_TO_PAGES(*ImageSize), Image);\r
- // Try to allocate in any pages if failed to allocate memory at the defined location\r
- if ((Status == EFI_OUT_OF_RESOURCES) && (Type != AllocateAnyPages)) {\r
- Status = gBS->AllocatePages (AllocateAnyPages, EfiBootServicesCode, EFI_SIZE_TO_PAGES(*ImageSize), Image);\r
- }\r
- if (!EFI_ERROR (Status)) {\r
- CopyMem ((VOID*)(UINTN)(*Image), ImageBuffer, *ImageSize);\r
- FreePool (ImageBuffer);\r
- }\r
-#endif\r
- } else {\r
- // Try a raw file, since a PE32 SECTION does not exist\r
- Status = FwVol->ReadFile (\r
- FwVol,\r
- FvNameGuid,\r
- NULL,\r
- ImageSize,\r
- &FvType,\r
- &Attrib,\r
- &AuthenticationStatus\r
- );\r
- if (!EFI_ERROR (Status)) {\r
- Status = gBS->AllocatePages (Type, EfiBootServicesCode, EFI_SIZE_TO_PAGES(*ImageSize), Image);\r
- // Try to allocate in any pages if failed to allocate memory at the defined location\r
- if ((Status == EFI_OUT_OF_RESOURCES) && (Type != AllocateAnyPages)) {\r
- Status = gBS->AllocatePages (AllocateAnyPages, EfiBootServicesCode, EFI_SIZE_TO_PAGES(*ImageSize), Image);\r
- }\r
- if (!EFI_ERROR (Status)) {\r
- Status = FwVol->ReadFile (\r
- FwVol,\r
- FvNameGuid,\r
- (VOID**)Image,\r
- ImageSize,\r
- &FvType,\r
- &Attrib,\r
- &AuthenticationStatus\r
- );\r
- }\r
- }\r
- }\r
- return Status;\r
-}\r
-\r
-BOOLEAN\r
-BdsPxeSupport (\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_PXE_BASE_CODE_PROTOCOL* PxeBcProtocol;\r
-\r
- if (!IsDevicePathEnd (RemainingDevicePath)) {\r
- return FALSE;\r
- }\r
-\r
- Status = gBS->HandleProtocol (Handle, &gEfiPxeBaseCodeProtocolGuid, (VOID **)&PxeBcProtocol);\r
- if (EFI_ERROR (Status)) {\r
- return FALSE;\r
- } else {\r
- return TRUE;\r
- }\r
-}\r
-\r
-EFI_STATUS\r
-BdsPxeLoadImage (\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
- )\r
-{\r
- EFI_STATUS Status;\r
- EFI_LOAD_FILE_PROTOCOL *LoadFileProtocol;\r
- UINTN BufferSize;\r
- EFI_PXE_BASE_CODE_PROTOCOL *Pxe;\r
-\r
- // Get Load File Protocol attached to the PXE protocol\r
- Status = gBS->HandleProtocol (Handle, &gEfiLoadFileProtocolGuid, (VOID **)&LoadFileProtocol);\r
- if (EFI_ERROR (Status)) {\r
- return Status;\r
- }\r
-\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, RemainingDevicePath, TRUE, &BufferSize, (VOID*)(UINTN)(*Image));\r
- if (!EFI_ERROR (Status) && (ImageSize != NULL)) {\r
- *ImageSize = BufferSize;\r
- }\r
- }\r
-\r
- if (Status == EFI_ALREADY_STARTED) {\r
- Status = gBS->LocateProtocol (&gEfiPxeBaseCodeProtocolGuid, NULL, (VOID **)&Pxe);\r
- if (!EFI_ERROR(Status)) {\r
- // If PXE is already started, we stop it\r
- Pxe->Stop (Pxe);\r
- // And we try again\r
- return BdsPxeLoadImage (DevicePath, Handle, RemainingDevicePath, Type, Image, ImageSize);\r
- }\r
- }\r
- return Status;\r
-}\r
-\r
-BOOLEAN\r
-BdsTftpSupport (\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_DEVICE_PATH *NextDevicePath;\r
- VOID *Interface;\r
-\r
- // Validate the Remaining Device Path\r
- if (IsDevicePathEnd (RemainingDevicePath)) {\r
- return FALSE;\r
- }\r
- if (!IS_DEVICE_PATH_NODE (RemainingDevicePath, MESSAGING_DEVICE_PATH, MSG_IPv4_DP) &&\r
- !IS_DEVICE_PATH_NODE (RemainingDevicePath, MESSAGING_DEVICE_PATH, MSG_IPv6_DP)) {\r
- return FALSE;\r
- }\r
- NextDevicePath = NextDevicePathNode (RemainingDevicePath);\r
- if (IsDevicePathEnd (NextDevicePath)) {\r
- return FALSE;\r
- }\r
- if (!IS_DEVICE_PATH_NODE (NextDevicePath, MEDIA_DEVICE_PATH, MEDIA_FILEPATH_DP)) {\r
- return FALSE;\r
- }\r
-\r
- Status = gBS->HandleProtocol (\r
- Handle, &gEfiDevicePathProtocolGuid,\r
- &Interface\r
- );\r
- if (EFI_ERROR (Status)) {\r
- return FALSE;\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 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_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
- IPv4DevicePathNode = (IPv4_DEVICE_PATH*)RemainingDevicePath;\r
-\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
- //\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
- 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
-\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 (&Mtftp4CfgData.ServerIp , &IPv4DevicePathNode->RemoteIpAddress, sizeof (EFI_IPv4_ADDRESS));\r
-\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
-\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
-\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
- if (EFI_ERROR (Status)) {\r
- *Image = 0;\r
- Print (L"Failed to download the file - Error=%r\n", Status);\r
- }\r
-\r
- return Status;\r
-}\r
-\r
-BDS_FILE_LOADER FileLoaders[] = {\r
- { BdsFileSystemSupport, BdsFileSystemLoadImage },\r
- { BdsFirmwareVolumeSupport, BdsFirmwareVolumeLoadImage },\r
- //{ BdsLoadFileSupport, BdsLoadFileLoadImage },\r
- { BdsMemoryMapSupport, BdsMemoryMapLoadImage },\r
- { BdsPxeSupport, BdsPxeLoadImage },\r
- { BdsTftpSupport, BdsTftpLoadImage },\r
- { NULL, NULL }\r
-};\r
-\r
-EFI_STATUS\r
-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
- )\r
-{\r
- EFI_STATUS Status;\r
- EFI_HANDLE Handle;\r
- EFI_DEVICE_PATH *RemainingDevicePath;\r
- BDS_FILE_LOADER* FileLoader;\r
-\r
- 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)) {\r
- return FileLoader->LoadImage (DevicePath, Handle, RemainingDevicePath, Type, Image, FileSize);\r
- }\r
- FileLoader++;\r
- }\r
-\r
- return EFI_UNSUPPORTED;\r
-}\r
-\r
-EFI_STATUS\r
-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
- @param ParentImageHandle Handle of the calling image\r
- @param DevicePath Location of the EFI Application\r
-\r
- @retval EFI_SUCCESS All drivers have been connected\r
- @retval EFI_NOT_FOUND The Linux kernel Device Path has not been found\r
- @retval EFI_OUT_OF_RESOURCES There is not enough resource memory to store the matching results.\r
-\r
-**/\r
-EFI_STATUS\r
-BdsStartEfiApplication (\r
- IN EFI_HANDLE ParentImageHandle,\r
- IN EFI_DEVICE_PATH_PROTOCOL *DevicePath,\r
- IN UINTN LoadOptionsSize,\r
- IN VOID* LoadOptions\r
- )\r
-{\r
- EFI_STATUS Status;\r
- EFI_HANDLE ImageHandle;\r
- EFI_PHYSICAL_ADDRESS BinaryBuffer;\r
- UINTN BinarySize;\r
- EFI_LOADED_IMAGE_PROTOCOL* LoadedImage;\r
-\r
- // Find the nearest supported file loader\r
- Status = BdsLoadImageAndUpdateDevicePath (&DevicePath, AllocateAnyPages, &BinaryBuffer, &BinarySize);\r
- if (EFI_ERROR (Status)) {\r
- return Status;\r
- }\r
-\r
- // Load the image from the Buffer with Boot Services function\r
- Status = gBS->LoadImage (TRUE, ParentImageHandle, DevicePath, (VOID*)(UINTN)BinaryBuffer, BinarySize, &ImageHandle);\r
- if (EFI_ERROR (Status)) {\r
- return Status;\r
- }\r
-\r
- // Passed LoadOptions to the EFI Application\r
- if (LoadOptionsSize != 0) {\r
- Status = gBS->HandleProtocol (ImageHandle, &gEfiLoadedImageProtocolGuid, (VOID **) &LoadedImage);\r
- if (EFI_ERROR (Status)) {\r
- return Status;\r
- }\r
-\r
- LoadedImage->LoadOptionsSize = LoadOptionsSize;\r
- LoadedImage->LoadOptions = LoadOptions;\r
- }\r
-\r
- // Before calling the image, enable the Watchdog Timer for the 5 Minute period\r
- gBS->SetWatchdogTimer (5 * 60, 0x0000, 0x00, NULL);\r
- // Start the image\r
- Status = gBS->StartImage (ImageHandle, NULL, NULL);\r
- // Clear the Watchdog Timer after the image returns\r
- gBS->SetWatchdogTimer (0x0000, 0x0000, 0x0000, NULL);\r
-\r
- return Status;\r
-}\r
+++ /dev/null
-/** @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
-*\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
-EFI_STATUS\r
-BootOptionParseLoadOption (\r
- IN EFI_LOAD_OPTION *EfiLoadOption,\r
- IN UINTN EfiLoadOptionSize,\r
- IN OUT BDS_LOAD_OPTION **BdsLoadOption\r
- )\r
-{\r
- BDS_LOAD_OPTION *LoadOption;\r
- UINTN DescriptionLength;\r
- UINTN EfiLoadOptionPtr;\r
-\r
- if (EfiLoadOption == NULL) {\r
- return EFI_INVALID_PARAMETER;\r
- }\r
-\r
- if (EfiLoadOptionSize < sizeof(UINT32) + sizeof(UINT16) + sizeof(CHAR16) + sizeof(EFI_DEVICE_PATH_PROTOCOL)) {\r
- return EFI_BAD_BUFFER_SIZE;\r
- }\r
-\r
- if (*BdsLoadOption == NULL) {\r
- LoadOption = (BDS_LOAD_OPTION*)AllocateZeroPool (sizeof(BDS_LOAD_OPTION));\r
- if (LoadOption == NULL) {\r
- return EFI_OUT_OF_RESOURCES;\r
- }\r
- } else {\r
- LoadOption = *BdsLoadOption;\r
- }\r
-\r
- EfiLoadOptionPtr = (UINTN)EfiLoadOption;\r
- LoadOption->LoadOption = EfiLoadOption;\r
- LoadOption->LoadOptionSize = EfiLoadOptionSize;\r
-\r
- LoadOption->Attributes = *(UINT32*)EfiLoadOptionPtr;\r
- LoadOption->FilePathListLength = *(UINT16*)(EfiLoadOptionPtr + sizeof(UINT32));\r
- LoadOption->Description = (CHAR16*)(EfiLoadOptionPtr + sizeof(UINT32) + sizeof(UINT16));\r
- DescriptionLength = StrSize (LoadOption->Description);\r
- LoadOption->FilePathList = (EFI_DEVICE_PATH_PROTOCOL*)(EfiLoadOptionPtr + sizeof(UINT32) + sizeof(UINT16) + DescriptionLength);\r
-\r
- // If ((End of EfiLoadOptiony - Start of EfiLoadOption) == EfiLoadOptionSize) then No Optional Data\r
- if ((UINTN)((UINTN)LoadOption->FilePathList + LoadOption->FilePathListLength - EfiLoadOptionPtr) == EfiLoadOptionSize) {\r
- LoadOption->OptionalData = NULL;\r
- LoadOption->OptionalDataSize = 0;\r
- } else {\r
- LoadOption->OptionalData = (VOID*)((UINTN)(LoadOption->FilePathList) + LoadOption->FilePathListLength);\r
- LoadOption->OptionalDataSize = EfiLoadOptionSize - ((UINTN)LoadOption->OptionalData - EfiLoadOptionPtr);\r
- }\r
-\r
- if (*BdsLoadOption == NULL) {\r
- *BdsLoadOption = LoadOption;\r
- }\r
-\r
- return EFI_SUCCESS;\r
-}\r
-\r
-EFI_STATUS\r
-BootOptionFromLoadOptionVariable (\r
- IN CHAR16* BootVariableName,\r
- OUT BDS_LOAD_OPTION** BdsLoadOption\r
- )\r
-{\r
- EFI_STATUS Status;\r
- EFI_LOAD_OPTION *EfiLoadOption;\r
- UINTN EfiLoadOptionSize;\r
-\r
- Status = GetGlobalEnvironmentVariable (BootVariableName, NULL, &EfiLoadOptionSize, (VOID**)&EfiLoadOption);\r
- if (!EFI_ERROR(Status)) {\r
- *BdsLoadOption = NULL;\r
- Status = BootOptionParseLoadOption (EfiLoadOption, EfiLoadOptionSize, BdsLoadOption);\r
- }\r
-\r
- return Status;\r
-}\r
-\r
-EFI_STATUS\r
-BootOptionFromLoadOptionIndex (\r
- IN UINT16 LoadOptionIndex,\r
- OUT BDS_LOAD_OPTION **BdsLoadOption\r
- )\r
-{\r
- CHAR16 BootVariableName[9];\r
- EFI_STATUS Status;\r
-\r
- UnicodeSPrint (BootVariableName, 9 * sizeof(CHAR16), L"Boot%04X", LoadOptionIndex);\r
-\r
- Status = BootOptionFromLoadOptionVariable (BootVariableName, BdsLoadOption);\r
- if (!EFI_ERROR(Status)) {\r
- (*BdsLoadOption)->LoadOptionIndex = LoadOptionIndex;\r
- }\r
-\r
- return Status;\r
-}\r
-\r
-EFI_STATUS\r
-BootOptionToLoadOptionVariable (\r
- IN BDS_LOAD_OPTION* BdsLoadOption\r
- )\r
-{\r
- EFI_STATUS Status;\r
- UINTN DescriptionSize;\r
- //UINT16 FilePathListLength;\r
- EFI_DEVICE_PATH_PROTOCOL* DevicePathNode;\r
- UINTN NodeLength;\r
- UINT8* EfiLoadOptionPtr;\r
- VOID* OldLoadOption;\r
- CHAR16 BootVariableName[9];\r
- UINTN BootOrderSize;\r
- UINT16* BootOrder;\r
-\r
- // If we are overwriting an existent Boot Option then we have to free previously allocated memory\r
- if (BdsLoadOption->LoadOptionSize > 0) {\r
- OldLoadOption = BdsLoadOption->LoadOption;\r
- } else {\r
- OldLoadOption = NULL;\r
-\r
- // If this function is called at the creation of the Boot Device entry (not at the update) the\r
- // BootOption->LoadOptionSize must be zero then we get a new BootIndex for this entry\r
- BdsLoadOption->LoadOptionIndex = BootOptionAllocateBootIndex ();\r
-\r
- //TODO: Add to the the Boot Entry List\r
- }\r
-\r
- DescriptionSize = StrSize(BdsLoadOption->Description);\r
-\r
- // Ensure the FilePathListLength information is correct\r
- ASSERT (GetDevicePathSize (BdsLoadOption->FilePathList) == BdsLoadOption->FilePathListLength);\r
-\r
- // Allocate the memory for the EFI Load Option\r
- BdsLoadOption->LoadOptionSize = sizeof(UINT32) + sizeof(UINT16) + DescriptionSize + BdsLoadOption->FilePathListLength + BdsLoadOption->OptionalDataSize;\r
-\r
- BdsLoadOption->LoadOption = (EFI_LOAD_OPTION *)AllocateZeroPool (BdsLoadOption->LoadOptionSize);\r
- if (BdsLoadOption->LoadOption == NULL) {\r
- return EFI_OUT_OF_RESOURCES;\r
- }\r
-\r
- EfiLoadOptionPtr = (UINT8 *) BdsLoadOption->LoadOption;\r
-\r
- //\r
- // Populate the EFI Load Option and BDS Boot Option structures\r
- //\r
-\r
- // Attributes fields\r
- *(UINT32*)EfiLoadOptionPtr = BdsLoadOption->Attributes;\r
- EfiLoadOptionPtr += sizeof(UINT32);\r
-\r
- // FilePath List fields\r
- *(UINT16*)EfiLoadOptionPtr = BdsLoadOption->FilePathListLength;\r
- EfiLoadOptionPtr += sizeof(UINT16);\r
-\r
- // Boot description fields\r
- CopyMem (EfiLoadOptionPtr, BdsLoadOption->Description, DescriptionSize);\r
- EfiLoadOptionPtr += DescriptionSize;\r
-\r
- // File path fields\r
- DevicePathNode = BdsLoadOption->FilePathList;\r
- while (!IsDevicePathEndType (DevicePathNode)) {\r
- NodeLength = DevicePathNodeLength(DevicePathNode);\r
- CopyMem (EfiLoadOptionPtr, DevicePathNode, NodeLength);\r
- EfiLoadOptionPtr += NodeLength;\r
- DevicePathNode = NextDevicePathNode (DevicePathNode);\r
- }\r
-\r
- // Set the End Device Path Type\r
- SetDevicePathEndNode (EfiLoadOptionPtr);\r
- EfiLoadOptionPtr += sizeof(EFI_DEVICE_PATH);\r
-\r
- // Fill the Optional Data\r
- if (BdsLoadOption->OptionalDataSize > 0) {\r
- CopyMem (EfiLoadOptionPtr, BdsLoadOption->OptionalData, BdsLoadOption->OptionalDataSize);\r
- }\r
-\r
- // Case where the fields have been updated\r
- if (OldLoadOption) {\r
- // Now, the old data has been copied to the new allocated packed structure, we need to update the pointers of BdsLoadOption\r
- BootOptionParseLoadOption (BdsLoadOption->LoadOption, BdsLoadOption->LoadOptionSize, &BdsLoadOption);\r
- // Free the old packed structure\r
- FreePool (OldLoadOption);\r
- }\r
-\r
- // Create/Update Boot#### environment variable\r
- UnicodeSPrint (BootVariableName, 9 * sizeof(CHAR16), L"Boot%04X", BdsLoadOption->LoadOptionIndex);\r
- Status = gRT->SetVariable (\r
- BootVariableName,\r
- &gEfiGlobalVariableGuid,\r
- EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS,\r
- BdsLoadOption->LoadOptionSize,\r
- BdsLoadOption->LoadOption\r
- );\r
-\r
- // When it is a new entry we must add the entry to the BootOrder\r
- if (OldLoadOption == NULL) {\r
- // Add the new Boot Index to the list\r
- Status = GetGlobalEnvironmentVariable (L"BootOrder", NULL, &BootOrderSize, (VOID**)&BootOrder);\r
- if (!EFI_ERROR(Status)) {\r
- BootOrder = ReallocatePool (BootOrderSize, BootOrderSize + sizeof(UINT16), BootOrder);\r
- // Add the new index at the end\r
- BootOrder[BootOrderSize / sizeof(UINT16)] = BdsLoadOption->LoadOptionIndex;\r
- BootOrderSize += sizeof(UINT16);\r
- } else {\r
- // BootOrder does not exist. Create it\r
- BootOrderSize = sizeof(UINT16);\r
- BootOrder = &(BdsLoadOption->LoadOptionIndex);\r
- }\r
-\r
- // Update (or Create) the BootOrder environment variable\r
- gRT->SetVariable (\r
- L"BootOrder",\r
- &gEfiGlobalVariableGuid,\r
- EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS,\r
- BootOrderSize,\r
- BootOrder\r
- );\r
- DEBUG((EFI_D_ERROR,"Create %s\n",BootVariableName));\r
-\r
- // Free memory allocated by GetGlobalEnvironmentVariable\r
- if (!EFI_ERROR(Status)) {\r
- FreePool (BootOrder);\r
- }\r
- } else {\r
- DEBUG((EFI_D_ERROR,"Update %s\n",BootVariableName));\r
- }\r
-\r
- return EFI_SUCCESS;\r
-}\r
-\r
-UINT16\r
-BootOptionAllocateBootIndex (\r
- VOID\r
- )\r
-{\r
- EFI_STATUS Status;\r
- UINTN Index;\r
- UINT32 BootIndex;\r
- UINT16 *BootOrder;\r
- UINTN BootOrderSize;\r
- BOOLEAN Found;\r
-\r
- // Get the Boot Option Order from the environment variable\r
- Status = GetGlobalEnvironmentVariable (L"BootOrder", NULL, &BootOrderSize, (VOID**)&BootOrder);\r
- if (!EFI_ERROR(Status)) {\r
- for (BootIndex = 0; BootIndex <= 0xFFFF; BootIndex++) {\r
- Found = FALSE;\r
- for (Index = 0; Index < BootOrderSize / sizeof (UINT16); Index++) {\r
- if (BootOrder[Index] == BootIndex) {\r
- Found = TRUE;\r
- break;\r
- }\r
- }\r
- if (!Found) {\r
- return BootIndex;\r
- }\r
- }\r
- FreePool (BootOrder);\r
- }\r
- // Return the first index\r
- return 0;\r
-}\r