X-Git-Url: https://git.proxmox.com/?p=mirror_edk2.git;a=blobdiff_plain;f=ArmPlatformPkg%2FBds%2FBootOptionSupport.c;h=3eab0da83bfd5aea535238d0eb3173bca95089aa;hp=fb383b6f2468beb405991784c058fc5b7fbabdf3;hb=152286cea508549928b776e8a2ca62e089bc6790;hpb=11c20f4e06d252feaa65aa5e526686baf015762d diff --git a/ArmPlatformPkg/Bds/BootOptionSupport.c b/ArmPlatformPkg/Bds/BootOptionSupport.c index fb383b6f24..3eab0da83b 100644 --- a/ArmPlatformPkg/Bds/BootOptionSupport.c +++ b/ArmPlatformPkg/Bds/BootOptionSupport.c @@ -1,6 +1,6 @@ /** @file * -* Copyright (c) 2011, ARM Limited. All rights reserved. +* Copyright (c) 2011-2014, ARM Limited. All rights reserved. * * This program and the accompanying materials * are licensed and made available under the terms and conditions of the BSD License @@ -33,23 +33,20 @@ BdsLoadOptionFileSystemList ( EFI_STATUS BdsLoadOptionFileSystemCreateDevicePath ( - IN BDS_SUPPORTED_DEVICE* BdsLoadOption, - OUT EFI_DEVICE_PATH_PROTOCOL **DevicePathNode, - OUT ARM_BDS_LOADER_TYPE *BootType, - OUT UINT32 *Attributes + IN CHAR16* FileName, + OUT EFI_DEVICE_PATH_PROTOCOL **DevicePathNodes ); EFI_STATUS BdsLoadOptionFileSystemUpdateDevicePath ( - IN EFI_DEVICE_PATH *OldDevicePath, - OUT EFI_DEVICE_PATH_PROTOCOL** NewDevicePath, - OUT ARM_BDS_LOADER_TYPE *BootType, - OUT UINT32 *Attributes + IN EFI_DEVICE_PATH *OldDevicePath, + IN CHAR16* FileName, + OUT EFI_DEVICE_PATH_PROTOCOL **NewDevicePath ); BOOLEAN BdsLoadOptionFileSystemIsSupported ( - IN BDS_LOAD_OPTION* BdsLoadOption + IN EFI_DEVICE_PATH *DevicePath ); EFI_STATUS @@ -59,23 +56,20 @@ BdsLoadOptionMemMapList ( EFI_STATUS BdsLoadOptionMemMapCreateDevicePath ( - IN BDS_SUPPORTED_DEVICE* BdsLoadOption, - OUT EFI_DEVICE_PATH_PROTOCOL **DevicePathNode, - OUT ARM_BDS_LOADER_TYPE *BootType, - OUT UINT32 *Attributes + IN CHAR16* FileName, + OUT EFI_DEVICE_PATH_PROTOCOL **DevicePathNodes ); EFI_STATUS BdsLoadOptionMemMapUpdateDevicePath ( - IN EFI_DEVICE_PATH *OldDevicePath, - OUT EFI_DEVICE_PATH_PROTOCOL** NewDevicePath, - OUT ARM_BDS_LOADER_TYPE *BootType, - OUT UINT32 *Attributes + IN EFI_DEVICE_PATH *OldDevicePath, + IN CHAR16* FileName, + OUT EFI_DEVICE_PATH_PROTOCOL **NewDevicePath ); BOOLEAN BdsLoadOptionMemMapIsSupported ( - IN BDS_LOAD_OPTION* BdsLoadOption + IN EFI_DEVICE_PATH *DevicePath ); EFI_STATUS @@ -85,23 +79,20 @@ BdsLoadOptionPxeList ( EFI_STATUS BdsLoadOptionPxeCreateDevicePath ( - IN BDS_SUPPORTED_DEVICE* BdsLoadOption, - OUT EFI_DEVICE_PATH_PROTOCOL **DevicePathNode, - OUT ARM_BDS_LOADER_TYPE *BootType, - OUT UINT32 *Attributes + IN CHAR16* FileName, + OUT EFI_DEVICE_PATH_PROTOCOL **DevicePathNodes ); EFI_STATUS BdsLoadOptionPxeUpdateDevicePath ( - IN EFI_DEVICE_PATH *OldDevicePath, - OUT EFI_DEVICE_PATH_PROTOCOL** NewDevicePath, - OUT ARM_BDS_LOADER_TYPE *BootType, - OUT UINT32 *Attributes + IN EFI_DEVICE_PATH *OldDevicePath, + IN CHAR16* FileName, + OUT EFI_DEVICE_PATH_PROTOCOL **NewDevicePath ); BOOLEAN BdsLoadOptionPxeIsSupported ( - IN BDS_LOAD_OPTION* BdsLoadOption + IN EFI_DEVICE_PATH *DevicePath ); EFI_STATUS @@ -111,23 +102,20 @@ BdsLoadOptionTftpList ( EFI_STATUS BdsLoadOptionTftpCreateDevicePath ( - IN BDS_SUPPORTED_DEVICE* BdsLoadOption, - OUT EFI_DEVICE_PATH_PROTOCOL **DevicePathNode, - OUT ARM_BDS_LOADER_TYPE *BootType, - OUT UINT32 *Attributes + IN CHAR16* FileName, + OUT EFI_DEVICE_PATH_PROTOCOL **DevicePathNodes ); EFI_STATUS BdsLoadOptionTftpUpdateDevicePath ( - IN EFI_DEVICE_PATH *OldDevicePath, - OUT EFI_DEVICE_PATH_PROTOCOL** NewDevicePath, - OUT ARM_BDS_LOADER_TYPE *BootType, - OUT UINT32 *Attributes + IN EFI_DEVICE_PATH *OldDevicePath, + IN CHAR16* FileName, + OUT EFI_DEVICE_PATH_PROTOCOL **NewDevicePath ); BOOLEAN BdsLoadOptionTftpIsSupported ( - IN BDS_LOAD_OPTION* BdsLoadOption + IN EFI_DEVICE_PATH *DevicePath ); BDS_LOAD_OPTION_SUPPORT BdsLoadOptionSupportList[] = { @@ -136,28 +124,32 @@ BDS_LOAD_OPTION_SUPPORT BdsLoadOptionSupportList[] = { BdsLoadOptionFileSystemList, BdsLoadOptionFileSystemIsSupported, BdsLoadOptionFileSystemCreateDevicePath, - BdsLoadOptionFileSystemUpdateDevicePath + BdsLoadOptionFileSystemUpdateDevicePath, + TRUE }, { BDS_DEVICE_MEMMAP, BdsLoadOptionMemMapList, BdsLoadOptionMemMapIsSupported, BdsLoadOptionMemMapCreateDevicePath, - BdsLoadOptionMemMapUpdateDevicePath + BdsLoadOptionMemMapUpdateDevicePath, + TRUE }, { BDS_DEVICE_PXE, BdsLoadOptionPxeList, BdsLoadOptionPxeIsSupported, BdsLoadOptionPxeCreateDevicePath, - BdsLoadOptionPxeUpdateDevicePath + BdsLoadOptionPxeUpdateDevicePath, + FALSE }, { BDS_DEVICE_TFTP, BdsLoadOptionTftpList, BdsLoadOptionTftpIsSupported, BdsLoadOptionTftpCreateDevicePath, - BdsLoadOptionTftpUpdateDevicePath + BdsLoadOptionTftpUpdateDevicePath, + TRUE } }; @@ -201,15 +193,15 @@ BootDeviceListSupportedFree ( EFI_STATUS BootDeviceGetDeviceSupport ( - IN BDS_LOAD_OPTION *BootOption, - OUT BDS_LOAD_OPTION_SUPPORT** DeviceSupport + IN EFI_DEVICE_PATH *DevicePath, + OUT BDS_LOAD_OPTION_SUPPORT **DeviceSupport ) { UINTN Index; // Find which supported device is the most appropriate for (Index = 0; Index < BDS_DEVICE_MAX; Index++) { - if (BdsLoadOptionSupportList[Index].IsSupported (BootOption)) { + if (BdsLoadOptionSupportList[Index].IsSupported (DevicePath)) { *DeviceSupport = &BdsLoadOptionSupportList[Index]; return EFI_SUCCESS; } @@ -218,18 +210,44 @@ BootDeviceGetDeviceSupport ( return EFI_UNSUPPORTED; } -STATIC EFI_STATUS BootDeviceGetType ( - IN CHAR16* FileName, + IN EFI_DEVICE_PATH* DevicePath, OUT ARM_BDS_LOADER_TYPE *BootType, OUT UINT32 *Attributes ) { - EFI_STATUS Status; - BOOLEAN IsEfiApp; - BOOLEAN IsBootLoader; - BOOLEAN HasFDTSupport; + EFI_STATUS Status; + BOOLEAN IsEfiApp; + BOOLEAN IsBootLoader; + BOOLEAN HasFDTSupport; + CHAR16* FileName; + EFI_DEVICE_PATH* PrevDevicePathNode; + EFI_DEVICE_PATH* DevicePathNode; + EFI_PHYSICAL_ADDRESS Image; + UINTN FileSize; + EFI_IMAGE_DOS_HEADER* DosHeader; + UINTN PeCoffHeaderOffset; + EFI_IMAGE_NT_HEADERS32* NtHeader; + + // + // Check if the last node of the device path is a FilePath node + // + PrevDevicePathNode = NULL; + DevicePathNode = DevicePath; + while ((DevicePathNode != NULL) && !IsDevicePathEnd (DevicePathNode)) { + PrevDevicePathNode = DevicePathNode; + DevicePathNode = NextDevicePathNode (DevicePathNode); + } + + if ((PrevDevicePathNode != NULL) && + (PrevDevicePathNode->Type == MEDIA_DEVICE_PATH) && + (PrevDevicePathNode->SubType == MEDIA_FILEPATH_DP)) + { + FileName = ((FILEPATH_DEVICE_PATH*)PrevDevicePathNode)->PathName; + } else { + FileName = NULL; + } if (FileName == NULL) { Print(L"Is an EFI Application? "); @@ -240,7 +258,41 @@ BootDeviceGetType ( } else if (HasFilePathEfiExtension(FileName)) { IsEfiApp = TRUE; } else { - IsEfiApp = FALSE; + // Check if the file exist + Status = BdsLoadImage (DevicePath, AllocateAnyPages, &Image, &FileSize); + if (!EFI_ERROR (Status)) { + + DosHeader = (EFI_IMAGE_DOS_HEADER *)(UINTN) Image; + if (DosHeader->e_magic == EFI_IMAGE_DOS_SIGNATURE) { + // + // DOS image header is present, + // so read the PE header after the DOS image header. + // + PeCoffHeaderOffset = DosHeader->e_lfanew; + } else { + PeCoffHeaderOffset = 0; + } + + // + // Check PE/COFF image. + // + NtHeader = (EFI_IMAGE_NT_HEADERS32 *)(UINTN) (Image + PeCoffHeaderOffset); + if (NtHeader->Signature != EFI_IMAGE_NT_SIGNATURE) { + IsEfiApp = FALSE; + } else { + IsEfiApp = TRUE; + } + + // Free memory + gBS->FreePages (Image, EFI_SIZE_TO_PAGES(FileSize)); + } else { + // If we did not manage to open it then ask for the type + Print(L"Is an EFI Application? "); + Status = GetHIInputBoolean (&IsEfiApp); + if (EFI_ERROR(Status)) { + return EFI_ABORTED; + } + } } if (IsEfiApp) { @@ -327,10 +379,8 @@ BdsLoadOptionFileSystemList ( EFI_STATUS BdsLoadOptionFileSystemCreateDevicePath ( - IN BDS_SUPPORTED_DEVICE* BdsLoadOption, - OUT EFI_DEVICE_PATH_PROTOCOL **DevicePathNode, - OUT ARM_BDS_LOADER_TYPE *BootType, - OUT UINT32 *Attributes + IN CHAR16* FileName, + OUT EFI_DEVICE_PATH_PROTOCOL **DevicePathNodes ) { EFI_STATUS Status; @@ -338,6 +388,7 @@ BdsLoadOptionFileSystemCreateDevicePath ( CHAR16 BootFilePath[BOOT_DEVICE_FILEPATH_MAX]; UINTN BootFilePathSize; + Print(L"File path of the %s: ", FileName); Status = GetHIInputStr (BootFilePath, BOOT_DEVICE_FILEPATH_MAX); if (EFI_ERROR(Status)) { return EFI_ABORTED; @@ -345,36 +396,27 @@ BdsLoadOptionFileSystemCreateDevicePath ( BootFilePathSize = StrSize (BootFilePath); if (BootFilePathSize == 2) { - *DevicePathNode = NULL; + *DevicePathNodes = NULL; return EFI_NOT_FOUND; } // Create the FilePath Device Path node - FilePathDevicePath = (FILEPATH_DEVICE_PATH*)AllocatePool(SIZE_OF_FILEPATH_DEVICE_PATH + BootFilePathSize); + FilePathDevicePath = (FILEPATH_DEVICE_PATH*)AllocatePool(SIZE_OF_FILEPATH_DEVICE_PATH + BootFilePathSize + END_DEVICE_PATH_LENGTH); FilePathDevicePath->Header.Type = MEDIA_DEVICE_PATH; FilePathDevicePath->Header.SubType = MEDIA_FILEPATH_DP; SetDevicePathNodeLength (FilePathDevicePath, SIZE_OF_FILEPATH_DEVICE_PATH + BootFilePathSize); CopyMem (FilePathDevicePath->PathName, BootFilePath, BootFilePathSize); - - if (BootType != NULL || Attributes != NULL) { - Status = BootDeviceGetType (FilePathDevicePath->PathName, BootType, Attributes); - } - - if (EFI_ERROR(Status)) { - FreePool (FilePathDevicePath); - } else { - *DevicePathNode = (EFI_DEVICE_PATH_PROTOCOL*)FilePathDevicePath; - } + SetDevicePathEndNode ((VOID*)((UINTN)FilePathDevicePath + SIZE_OF_FILEPATH_DEVICE_PATH + BootFilePathSize)); + *DevicePathNodes = (EFI_DEVICE_PATH_PROTOCOL*)FilePathDevicePath; return Status; } EFI_STATUS BdsLoadOptionFileSystemUpdateDevicePath ( - IN EFI_DEVICE_PATH *OldDevicePath, - OUT EFI_DEVICE_PATH_PROTOCOL** NewDevicePath, - OUT ARM_BDS_LOADER_TYPE *BootType, - OUT UINT32 *Attributes + IN EFI_DEVICE_PATH *OldDevicePath, + IN CHAR16* FileName, + OUT EFI_DEVICE_PATH_PROTOCOL **NewDevicePath ) { EFI_STATUS Status; @@ -384,10 +426,11 @@ BdsLoadOptionFileSystemUpdateDevicePath ( FILEPATH_DEVICE_PATH* FilePathDevicePath; EFI_DEVICE_PATH* DevicePath; - DevicePath = DuplicateDevicePath(OldDevicePath); + DevicePath = DuplicateDevicePath (OldDevicePath); EndingDevicePath = (FILEPATH_DEVICE_PATH*)GetLastDevicePathNode (DevicePath); + Print(L"File path of the %s: ", FileName); StrnCpy (BootFilePath, EndingDevicePath->PathName, BOOT_DEVICE_FILEPATH_MAX); Status = EditHIInputStr (BootFilePath, BOOT_DEVICE_FILEPATH_MAX); if (EFI_ERROR(Status)) { @@ -412,21 +455,17 @@ BdsLoadOptionFileSystemUpdateDevicePath ( *NewDevicePath = AppendDevicePathNode (DevicePath, (CONST EFI_DEVICE_PATH_PROTOCOL *)FilePathDevicePath); FreePool(DevicePath); - if (BootType != NULL || Attributes != NULL) { - return BootDeviceGetType (FilePathDevicePath->PathName, BootType, Attributes); - } - return EFI_SUCCESS; } BOOLEAN BdsLoadOptionFileSystemIsSupported ( - IN BDS_LOAD_OPTION* BdsLoadOption + IN EFI_DEVICE_PATH *DevicePath ) { EFI_DEVICE_PATH* DevicePathNode; - DevicePathNode = GetLastDevicePathNode (BdsLoadOption->FilePathList); + DevicePathNode = GetLastDevicePathNode (DevicePath); return IS_DEVICE_PATH_NODE(DevicePathNode,MEDIA_DEVICE_PATH,MEDIA_FILEPATH_DP); } @@ -525,53 +564,48 @@ BdsLoadOptionMemMapList ( EFI_STATUS BdsLoadOptionMemMapCreateDevicePath ( - IN BDS_SUPPORTED_DEVICE* BdsLoadOption, - OUT EFI_DEVICE_PATH_PROTOCOL **DevicePathNode, - OUT ARM_BDS_LOADER_TYPE *BootType, - OUT UINT32 *Attributes + IN CHAR16* FileName, + OUT EFI_DEVICE_PATH_PROTOCOL **DevicePathNodes ) { - EFI_STATUS Status; - MEMMAP_DEVICE_PATH* MemMapDevicePath; - CHAR16 StrStartingAddress[BOOT_DEVICE_ADDRESS_MAX]; - CHAR16 StrEndingAddress[BOOT_DEVICE_ADDRESS_MAX]; + EFI_STATUS Status; + MEMMAP_DEVICE_PATH *MemMapDevicePath; + CHAR16 StrStartingAddress[BOOT_DEVICE_ADDRESS_MAX]; + CHAR16 StrEndingAddress[BOOT_DEVICE_ADDRESS_MAX]; - Print(L"Starting Address of the binary: "); - Status = GetHIInputStr (StrStartingAddress,BOOT_DEVICE_ADDRESS_MAX); + Print(L"Starting Address of the %s: ", FileName); + Status = GetHIInputStr (StrStartingAddress, BOOT_DEVICE_ADDRESS_MAX); if (EFI_ERROR(Status)) { return EFI_ABORTED; } - Print(L"Ending Address of the binary: "); - Status = GetHIInputStr (StrEndingAddress,BOOT_DEVICE_ADDRESS_MAX); + Print(L"Ending Address of the %s: ", FileName); + Status = GetHIInputStr (StrEndingAddress, BOOT_DEVICE_ADDRESS_MAX); if (EFI_ERROR(Status)) { return EFI_ABORTED; } // Create the MemMap Device Path Node - MemMapDevicePath = (MEMMAP_DEVICE_PATH*)AllocatePool (sizeof(MEMMAP_DEVICE_PATH)); + MemMapDevicePath = (MEMMAP_DEVICE_PATH*)AllocatePool (sizeof(MEMMAP_DEVICE_PATH) + END_DEVICE_PATH_LENGTH); MemMapDevicePath->Header.Type = HARDWARE_DEVICE_PATH; MemMapDevicePath->Header.SubType = HW_MEMMAP_DP; + SetDevicePathNodeLength (MemMapDevicePath, sizeof(MEMMAP_DEVICE_PATH)); MemMapDevicePath->MemoryType = EfiBootServicesData; MemMapDevicePath->StartingAddress = StrHexToUint64 (StrStartingAddress); MemMapDevicePath->EndingAddress = StrHexToUint64 (StrEndingAddress); - Status = BootDeviceGetType (NULL, BootType, Attributes); - if (EFI_ERROR(Status)) { - FreePool (MemMapDevicePath); - } else { - *DevicePathNode = (EFI_DEVICE_PATH_PROTOCOL*)MemMapDevicePath; - } + // Set a Device Path End Node after the Memory Map Device Path Node + SetDevicePathEndNode (MemMapDevicePath + 1); + *DevicePathNodes = (EFI_DEVICE_PATH_PROTOCOL*)MemMapDevicePath; return Status; } EFI_STATUS BdsLoadOptionMemMapUpdateDevicePath ( - IN EFI_DEVICE_PATH *OldDevicePath, - OUT EFI_DEVICE_PATH_PROTOCOL** NewDevicePath, - OUT ARM_BDS_LOADER_TYPE *BootType, - OUT UINT32 *Attributes + IN EFI_DEVICE_PATH *OldDevicePath, + IN CHAR16* FileName, + OUT EFI_DEVICE_PATH_PROTOCOL **NewDevicePath ) { EFI_STATUS Status; @@ -583,14 +617,14 @@ BdsLoadOptionMemMapUpdateDevicePath ( DevicePath = DuplicateDevicePath (OldDevicePath); EndingDevicePath = (MEMMAP_DEVICE_PATH*)GetLastDevicePathNode (DevicePath); - Print(L"Starting Address of the binary: "); + Print(L"Starting Address of the %s: ", FileName); UnicodeSPrint (StrStartingAddress, BOOT_DEVICE_ADDRESS_MAX, L"0x%X", (UINTN)EndingDevicePath->StartingAddress); Status = EditHIInputStr (StrStartingAddress, BOOT_DEVICE_ADDRESS_MAX); if (EFI_ERROR(Status)) { return EFI_ABORTED; } - Print(L"Ending Address of the binary: "); + Print(L"Ending Address of the %s: ", FileName); UnicodeSPrint (StrEndingAddress, BOOT_DEVICE_ADDRESS_MAX, L"0x%X", (UINTN)EndingDevicePath->EndingAddress); Status = EditHIInputStr (StrEndingAddress, BOOT_DEVICE_ADDRESS_MAX); if (EFI_ERROR(Status)) { @@ -600,7 +634,6 @@ BdsLoadOptionMemMapUpdateDevicePath ( EndingDevicePath->StartingAddress = StrHexToUint64 (StrStartingAddress); EndingDevicePath->EndingAddress = StrHexToUint64 (StrEndingAddress); - Status = BootDeviceGetType (NULL, BootType, Attributes); if (EFI_ERROR(Status)) { FreePool(DevicePath); } else { @@ -612,12 +645,12 @@ BdsLoadOptionMemMapUpdateDevicePath ( BOOLEAN BdsLoadOptionMemMapIsSupported ( - IN BDS_LOAD_OPTION* BdsLoadOption + IN EFI_DEVICE_PATH *DevicePath ) { EFI_DEVICE_PATH* DevicePathNode; - DevicePathNode = GetLastDevicePathNode (BdsLoadOption->FilePathList); + DevicePathNode = GetLastDevicePathNode (DevicePath); return IS_DEVICE_PATH_NODE(DevicePathNode,HARDWARE_DEVICE_PATH,HW_MEMMAP_DP); } @@ -672,33 +705,50 @@ BdsLoadOptionPxeList ( EFI_STATUS BdsLoadOptionPxeCreateDevicePath ( - IN BDS_SUPPORTED_DEVICE* BdsLoadOption, - OUT EFI_DEVICE_PATH_PROTOCOL **DevicePathNode, - OUT ARM_BDS_LOADER_TYPE *BootType, - OUT UINT32 *Attributes + IN CHAR16* FileName, + OUT EFI_DEVICE_PATH_PROTOCOL **DevicePathNodes ) { - *DevicePathNode = (EFI_DEVICE_PATH_PROTOCOL *) AllocatePool (END_DEVICE_PATH_LENGTH); - SetDevicePathEndNode (*DevicePathNode); - *BootType = BDS_LOADER_EFI_APPLICATION; + *DevicePathNodes = (EFI_DEVICE_PATH_PROTOCOL *) AllocatePool (END_DEVICE_PATH_LENGTH); + SetDevicePathEndNode (*DevicePathNodes); + return EFI_SUCCESS; } +/** + Update the parameters of a Pxe boot option + + @param[in] OldDevicePath Current complete device path of the Pxe boot option. + This has to be a valid complete Pxe boot option path. + @param[in] FileName Description of the file the path is asked for + @param[out] NewDevicePath Pointer to the new complete device path. + + @retval EFI_SUCCESS Update completed + @retval EFI_OUT_OF_RESOURCES Fail to perform the update due to lack of resource +**/ EFI_STATUS BdsLoadOptionPxeUpdateDevicePath ( - IN EFI_DEVICE_PATH *OldDevicePath, - OUT EFI_DEVICE_PATH_PROTOCOL** NewDevicePath, - OUT ARM_BDS_LOADER_TYPE *BootType, - OUT UINT32 *Attributes + IN EFI_DEVICE_PATH *OldDevicePath, + IN CHAR16* FileName, + OUT EFI_DEVICE_PATH_PROTOCOL **NewDevicePath ) { - ASSERT (0); - return EFI_SUCCESS; + // + // Make a copy of the complete device path that is made of : + // the device path of the device supporting the Pxe base code protocol + // followed by an end node. + // + *NewDevicePath = DuplicateDevicePath (OldDevicePath); + if (*NewDevicePath == NULL) { + return EFI_OUT_OF_RESOURCES; + } else { + return EFI_SUCCESS; + } } BOOLEAN BdsLoadOptionPxeIsSupported ( - IN BDS_LOAD_OPTION* BdsLoadOption + IN EFI_DEVICE_PATH *DevicePath ) { EFI_STATUS Status; @@ -706,7 +756,7 @@ BdsLoadOptionPxeIsSupported ( EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath; EFI_PXE_BASE_CODE_PROTOCOL *PxeBcProtocol; - Status = BdsConnectDevicePath (BdsLoadOption->FilePathList, &Handle, &RemainingDevicePath); + Status = BdsConnectDevicePath (DevicePath, &Handle, &RemainingDevicePath); if (EFI_ERROR(Status)) { return FALSE; } @@ -759,7 +809,7 @@ BdsLoadOptionTftpList ( Status = GenerateDeviceDescriptionName (HandleBuffer[Index], DeviceDescription); ASSERT_EFI_ERROR (Status); } - UnicodeSPrint (SupportedDevice->Description,BOOT_DEVICE_DESCRIPTION_MAX,L"TFP on %s",DeviceDescription); + UnicodeSPrint (SupportedDevice->Description,BOOT_DEVICE_DESCRIPTION_MAX,L"TFTP on %s",DeviceDescription); SupportedDevice->DevicePathProtocol = DevicePathProtocol; SupportedDevice->Support = &BdsLoadOptionSupportList[BDS_DEVICE_TFTP]; @@ -773,10 +823,8 @@ BdsLoadOptionTftpList ( EFI_STATUS BdsLoadOptionTftpCreateDevicePath ( - IN BDS_SUPPORTED_DEVICE* BdsLoadOption, - OUT EFI_DEVICE_PATH_PROTOCOL **DevicePathNode, - OUT ARM_BDS_LOADER_TYPE *BootType, - OUT UINT32 *Attributes + IN CHAR16* FileName, + OUT EFI_DEVICE_PATH_PROTOCOL **DevicePathNodes ) { EFI_STATUS Status; @@ -808,7 +856,7 @@ BdsLoadOptionTftpCreateDevicePath ( return EFI_ABORTED; } - Print(L"File path of the EFI Application or the kernel : "); + Print(L"File path of the %s : ", FileName); Status = GetHIInputStr (BootFilePath, BOOT_DEVICE_FILEPATH_MAX); if (EFI_ERROR(Status)) { return EFI_ABORTED; @@ -820,7 +868,7 @@ BdsLoadOptionTftpCreateDevicePath ( } // Allocate the memory for the IPv4 + File Path Device Path Nodes - IPv4DevicePathNode = (IPv4_DEVICE_PATH*)AllocatePool(sizeof(IPv4_DEVICE_PATH) + SIZE_OF_FILEPATH_DEVICE_PATH + BootFilePathSize); + IPv4DevicePathNode = (IPv4_DEVICE_PATH*)AllocatePool(sizeof(IPv4_DEVICE_PATH) + SIZE_OF_FILEPATH_DEVICE_PATH + BootFilePathSize + END_DEVICE_PATH_LENGTH); // Create the IPv4 Device Path IPv4DevicePathNode->Header.Type = MESSAGING_DEVICE_PATH; @@ -840,31 +888,196 @@ BdsLoadOptionTftpCreateDevicePath ( SetDevicePathNodeLength (FilePathDevicePath, SIZE_OF_FILEPATH_DEVICE_PATH + BootFilePathSize); CopyMem (FilePathDevicePath->PathName, BootFilePath, BootFilePathSize); - Status = BootDeviceGetType (NULL, BootType, Attributes); - if (EFI_ERROR(Status)) { - FreePool (IPv4DevicePathNode); - } else { - *DevicePathNode = (EFI_DEVICE_PATH_PROTOCOL*)IPv4DevicePathNode; - } + // Set the End Device Path Node + SetDevicePathEndNode ((VOID*)((UINTN)FilePathDevicePath + SIZE_OF_FILEPATH_DEVICE_PATH + BootFilePathSize)); + *DevicePathNodes = (EFI_DEVICE_PATH_PROTOCOL*)IPv4DevicePathNode; return Status; } +/** + Update the parameters of a TFTP boot option + + The function asks sequentially to update the IPv4 parameters as well as the boot file path, + providing the previously set value if any. + + @param[in] OldDevicePath Current complete device path of the Tftp boot option. + This has to be a valid complete Tftp boot option path. + By complete, we mean that it is not only the Tftp + specific end part built by the + "BdsLoadOptionTftpCreateDevicePath()" function. + This path is handled as read only. + @param[in] FileName Description of the file the path is asked for + @param[out] NewDevicePath Pointer to the new complete device path. + + @retval EFI_SUCCESS Update completed + @retval EFI_ABORTED Update aborted by the user + @retval EFI_OUT_OF_RESOURCES Fail to perform the update due to lack of resource +**/ EFI_STATUS BdsLoadOptionTftpUpdateDevicePath ( - IN EFI_DEVICE_PATH *OldDevicePath, - OUT EFI_DEVICE_PATH_PROTOCOL** NewDevicePath, - OUT ARM_BDS_LOADER_TYPE *BootType, - OUT UINT32 *Attributes + IN EFI_DEVICE_PATH *OldDevicePath, + IN CHAR16 *FileName, + OUT EFI_DEVICE_PATH_PROTOCOL **NewDevicePath ) { - ASSERT (0); - return EFI_SUCCESS; + EFI_STATUS Status; + EFI_DEVICE_PATH *DevicePath; + EFI_DEVICE_PATH *DevicePathNode; + UINT8 *Ipv4NodePtr; + IPv4_DEVICE_PATH Ipv4Node; + BOOLEAN IsDHCP; + EFI_IP_ADDRESS OldIp; + EFI_IP_ADDRESS LocalIp; + EFI_IP_ADDRESS RemoteIp; + UINT8 *FileNodePtr; + CHAR16 BootFilePath[BOOT_DEVICE_FILEPATH_MAX]; + UINTN PathSize; + UINTN BootFilePathSize; + FILEPATH_DEVICE_PATH *NewFilePathNode; + + Ipv4NodePtr = NULL; + + // + // Make a copy of the complete device path that is made of : + // the device path of the device that support the Simple Network protocol + // followed by an IPv4 node (type IPv4_DEVICE_PATH), + // followed by a file path node (type FILEPATH_DEVICE_PATH) and ended up + // by an end node. The IPv6 case is not handled yet. + // + + DevicePath = DuplicateDevicePath (OldDevicePath); + if (DevicePath == NULL) { + Status = EFI_OUT_OF_RESOURCES; + goto ErrorExit; + } + + // + // Because of the check done by "BdsLoadOptionTftpIsSupported()" prior to the + // call to this function, we know that the device path ends with an IPv4 node + // followed by a file path node and finally an end node. To get the address of + // the last IPv4 node, we loop over the whole device path, noting down the + // address of each encountered IPv4 node. + // + + for (DevicePathNode = DevicePath; + !IsDevicePathEnd (DevicePathNode); + DevicePathNode = NextDevicePathNode (DevicePathNode)) + { + if (IS_DEVICE_PATH_NODE (DevicePathNode, MESSAGING_DEVICE_PATH, MSG_IPv4_DP)) { + Ipv4NodePtr = (UINT8*)DevicePathNode; + } + } + + // Copy for alignment of the IPv4 node data + CopyMem (&Ipv4Node, Ipv4NodePtr, sizeof (IPv4_DEVICE_PATH)); + + Print (L"Get the IP address from DHCP: "); + Status = GetHIInputBoolean (&IsDHCP); + if (EFI_ERROR (Status)) { + goto ErrorExit; + } + + if (!IsDHCP) { + Print (L"Local static IP address: "); + if (Ipv4Node.StaticIpAddress) { + // Copy local IPv4 address into IPv4 or IPv6 union + CopyMem (&OldIp.v4, &Ipv4Node.LocalIpAddress, sizeof (EFI_IPv4_ADDRESS)); + + Status = EditHIInputIP (&OldIp, &LocalIp); + } else { + Status = GetHIInputIP (&LocalIp); + } + if (EFI_ERROR (Status)) { + goto ErrorExit; + } + } + + Print (L"TFTP server IP address: "); + // Copy remote IPv4 address into IPv4 or IPv6 union + CopyMem (&OldIp.v4, &Ipv4Node.RemoteIpAddress, sizeof (EFI_IPv4_ADDRESS)); + + Status = EditHIInputIP (&OldIp, &RemoteIp); + if (EFI_ERROR (Status)) { + goto ErrorExit; + } + + // Get the path of the boot file and its size in number of bytes + FileNodePtr = Ipv4NodePtr + sizeof (IPv4_DEVICE_PATH); + BootFilePathSize = DevicePathNodeLength (FileNodePtr) - SIZE_OF_FILEPATH_DEVICE_PATH; + + // + // Ask for update of the boot file path + // + do { + // Copy for 2-byte alignment of the Unicode string + CopyMem ( + BootFilePath, FileNodePtr + SIZE_OF_FILEPATH_DEVICE_PATH, + MIN (BootFilePathSize, BOOT_DEVICE_FILEPATH_MAX) + ); + BootFilePath[BOOT_DEVICE_FILEPATH_MAX - 1] = L'\0'; + + Print (L"File path of the %s: ", FileName); + Status = EditHIInputStr (BootFilePath, BOOT_DEVICE_FILEPATH_MAX); + if (EFI_ERROR (Status)) { + goto ErrorExit; + } + PathSize = StrSize (BootFilePath); + if (PathSize > 2) { + break; + } + // Empty string, give the user another try + Print (L"Empty string - Invalid path\n"); + } while (PathSize <= 2) ; + + // + // Update the IPv4 node. IPv6 case not handled yet. + // + if (IsDHCP == TRUE) { + Ipv4Node.StaticIpAddress = FALSE; + } else { + Ipv4Node.StaticIpAddress = TRUE; + } + CopyMem (&Ipv4Node.LocalIpAddress, &LocalIp.v4, sizeof (EFI_IPv4_ADDRESS)); + CopyMem (&Ipv4Node.RemoteIpAddress, &RemoteIp.v4, sizeof (EFI_IPv4_ADDRESS)); + CopyMem (Ipv4NodePtr, &Ipv4Node, sizeof (IPv4_DEVICE_PATH)); + + // + // Create the new file path node + // + NewFilePathNode = (FILEPATH_DEVICE_PATH*)AllocatePool ( + SIZE_OF_FILEPATH_DEVICE_PATH + + PathSize + ); + NewFilePathNode->Header.Type = MEDIA_DEVICE_PATH; + NewFilePathNode->Header.SubType = MEDIA_FILEPATH_DP; + SetDevicePathNodeLength ( + NewFilePathNode, + SIZE_OF_FILEPATH_DEVICE_PATH + PathSize + ); + CopyMem (NewFilePathNode->PathName, BootFilePath, PathSize); + + // + // Generate the new Device Path by replacing the file path node at address + // "FileNodePtr" by the new one "NewFilePathNode" and return its address. + // + SetDevicePathEndNode (FileNodePtr); + *NewDevicePath = AppendDevicePathNode ( + DevicePath, + (CONST EFI_DEVICE_PATH_PROTOCOL*)NewFilePathNode + ); + +ErrorExit: + if (DevicePath != NULL) { + FreePool (DevicePath) ; + } + + return Status; } BOOLEAN BdsLoadOptionTftpIsSupported ( - IN BDS_LOAD_OPTION* BdsLoadOption + IN EFI_DEVICE_PATH *DevicePath ) { EFI_STATUS Status; @@ -873,7 +1086,7 @@ BdsLoadOptionTftpIsSupported ( EFI_DEVICE_PATH *NextDevicePath; EFI_PXE_BASE_CODE_PROTOCOL *PxeBcProtocol; - Status = BdsConnectDevicePath (BdsLoadOption->FilePathList, &Handle, &RemainingDevicePath); + Status = BdsConnectDevicePath (DevicePath, &Handle, &RemainingDevicePath); if (EFI_ERROR(Status)) { return FALSE; }