X-Git-Url: https://git.proxmox.com/?p=mirror_edk2.git;a=blobdiff_plain;f=Nt32Pkg%2FLibrary%2FEdkGenericBdsLib%2FBdsBoot.c;fp=Nt32Pkg%2FLibrary%2FEdkGenericBdsLib%2FBdsBoot.c;h=cc6adcd78e3c93548672c6c1c853455b37e90ee7;hp=2e241ed6b94dc1cba11301c2640ea9931b83ba0e;hb=76bb6efe953468e0e1fbab52f5e53dba93f99092;hpb=26096d369d88f4101847b32e8b59dde43f6fe47c diff --git a/Nt32Pkg/Library/EdkGenericBdsLib/BdsBoot.c b/Nt32Pkg/Library/EdkGenericBdsLib/BdsBoot.c index 2e241ed6b9..cc6adcd78e 100644 --- a/Nt32Pkg/Library/EdkGenericBdsLib/BdsBoot.c +++ b/Nt32Pkg/Library/EdkGenericBdsLib/BdsBoot.c @@ -122,6 +122,7 @@ Returns: EFI_LOADED_IMAGE_PROTOCOL *ImageInfo; EFI_BLOCK_IO_PROTOCOL *BlkIo; VOID *Buffer; + LIST_ENTRY TempBootLists; // // Record the performance data for End of BDS @@ -178,6 +179,23 @@ Returns: // return BdsLibDoLegacyBoot (Option); } + + // + // If the boot option point to Internal FV shell, make sure it is valid + // + Status = UpdateFvFileDevicePath (&DevicePath, &gEfiShellFileGuid); + if (!EFI_ERROR(Status)) { + if (Option->DevicePath != NULL) { + FreePool (Option->DevicePath); + } + Option->DevicePath = AllocateZeroPool (GetDevicePathSize (DevicePath)); + CopyMem (Option->DevicePath, DevicePath, GetDevicePathSize (DevicePath)); + // + // Update the shell boot option + // + InitializeListHead (&TempBootLists); + BdsLibRegisterNewOption (&TempBootLists, DevicePath, L"EFI Internal Shell", L"BootOrder"); + } DEBUG ((EFI_D_INFO | EFI_D_LOAD, "Booting EFI 1.1 way %S\n", Option->Description)); @@ -1090,3 +1108,203 @@ Returns: } } + +EFI_STATUS +EFIAPI +UpdateFvFileDevicePath ( + IN OUT EFI_DEVICE_PATH_PROTOCOL **DevicePath, + IN EFI_GUID *FileGuid + ) +/*++ + +Routine Description: + According to a file guild, check a Fv file device path is valid. If it is invalid, + try to return the valid device path. + FV address maybe changes for memory layout adjust from time to time, use this funciton + could promise the Fv file device path is right. + +Arguments: + DevicePath - on input, the Fv file device path need to check + on output, the updated valid Fv file device path + + FileGuid - the Fv file guild + +Returns: + EFI_INVALID_PARAMETER - the input DevicePath or FileGuid is invalid parameter + EFI_UNSUPPORTED - the input DevicePath does not contain Fv file guild at all + EFI_ALREADY_STARTED - the input DevicePath has pointed to Fv file, it is valid + EFI_SUCCESS - has successfully updated the invalid DevicePath, and return the updated + device path in DevicePath + +--*/ +{ + EFI_DEVICE_PATH_PROTOCOL *TempDevicePath; + EFI_DEVICE_PATH_PROTOCOL *LastDeviceNode; + EFI_STATUS Status; + EFI_GUID *GuidPoint; + UINTN Index; + UINTN FvHandleCount; + EFI_HANDLE *FvHandleBuffer; + EFI_FV_FILETYPE Type; + UINTN Size; + EFI_FV_FILE_ATTRIBUTES Attributes; + UINT32 AuthenticationStatus; + BOOLEAN FindFvFile; + EFI_LOADED_IMAGE_PROTOCOL *LoadedImage; + EFI_FIRMWARE_VOLUME2_PROTOCOL *Fv; + MEDIA_FW_VOL_FILEPATH_DEVICE_PATH FvFileNode; + EFI_HANDLE FoundFvHandle; + EFI_DEVICE_PATH_PROTOCOL *NewDevicePath; + + if ((DevicePath == NULL) || (*DevicePath == NULL)) { + return EFI_INVALID_PARAMETER; + } + if (FileGuid == NULL) { + return EFI_INVALID_PARAMETER; + } + // + // Check whether the device path point to the default the input Fv file + // + TempDevicePath = *DevicePath; + LastDeviceNode = TempDevicePath; + while (!EfiIsDevicePathEnd (TempDevicePath)) { + LastDeviceNode = TempDevicePath; + TempDevicePath = EfiNextDevicePathNode (TempDevicePath); + } + + GuidPoint = EfiGetNameGuidFromFwVolDevicePathNode ((CONST MEDIA_FW_VOL_FILEPATH_DEVICE_PATH *)LastDeviceNode); + + if (GuidPoint == NULL) { + // + // if this option does not points to a Fv file, just return EFI_UNSUPPORTED + // + return EFI_UNSUPPORTED; + } + + if (!CompareGuid (GuidPoint, FileGuid)) { + // + // If the Fv file is not the input file guid, just return EFI_UNSUPPORTED + // + return EFI_UNSUPPORTED; + } + + // + // Check whether the input Fv file device path is valid + // + TempDevicePath = *DevicePath; + FoundFvHandle = NULL; + Status = gBS->LocateDevicePath ( + &gEfiFirmwareVolume2ProtocolGuid, + &TempDevicePath, + &FoundFvHandle + ); + if (!EFI_ERROR (Status)) { + Status = gBS->HandleProtocol ( + FoundFvHandle, + &gEfiFirmwareVolume2ProtocolGuid, + (VOID **) &Fv + ); + if (!EFI_ERROR (Status)) { + // + // Set FV ReadFile Buffer as NULL, only need to check whether input Fv file exist there + // + Status = Fv->ReadFile ( + Fv, + FileGuid, + NULL, + &Size, + &Type, + &Attributes, + &AuthenticationStatus + ); + if (!EFI_ERROR (Status)) { + return EFI_ALREADY_STARTED; + } + } + } + + // + // Look for the input wanted FV file in current FV + // First, try to look for in Bds own FV. Bds and input wanted FV file usually are in the same FV + // + FindFvFile = FALSE; + FoundFvHandle = NULL; + Status = gBS->HandleProtocol ( + mBdsImageHandle, + &gEfiLoadedImageProtocolGuid, + &LoadedImage + ); + if (!EFI_ERROR (Status)) { + Status = gBS->HandleProtocol ( + LoadedImage->DeviceHandle, + &gEfiFirmwareVolume2ProtocolGuid, + (VOID **) &Fv + ); + if (!EFI_ERROR (Status)) { + Status = Fv->ReadFile ( + Fv, + FileGuid, + NULL, + &Size, + &Type, + &Attributes, + &AuthenticationStatus + ); + if (!EFI_ERROR (Status)) { + FindFvFile = TRUE; + FoundFvHandle = LoadedImage->DeviceHandle; + } + } + } + // + // Second, if fail to find, try to enumerate all FV + // + if (!FindFvFile) { + gBS->LocateHandleBuffer ( + ByProtocol, + &gEfiFirmwareVolume2ProtocolGuid, + NULL, + &FvHandleCount, + &FvHandleBuffer + ); + for (Index = 0; Index < FvHandleCount; Index++) { + gBS->HandleProtocol ( + FvHandleBuffer[Index], + &gEfiFirmwareVolume2ProtocolGuid, + (VOID **) &Fv + ); + + Status = Fv->ReadFile ( + Fv, + FileGuid, + NULL, + &Size, + &Type, + &Attributes, + &AuthenticationStatus + ); + if (EFI_ERROR (Status)) { + // + // Skip if input Fv file not in the FV + // + continue; + } + FindFvFile = TRUE; + FoundFvHandle = FvHandleBuffer[Index]; + break; + } + } + + if (FindFvFile) { + // + // Build the shell device path + // + NewDevicePath = DevicePathFromHandle (FoundFvHandle); + EfiInitializeFwVolDevicepathNode (&FvFileNode, FileGuid); + NewDevicePath = AppendDevicePathNode (NewDevicePath, (EFI_DEVICE_PATH_PROTOCOL *) &FvFileNode); + *DevicePath = NewDevicePath; + return EFI_SUCCESS; + } + + return EFI_NOT_FOUND; +}