Merge EDK tracker 892 to EDK II.
authorlgao4 <lgao4@de2fecce-e211-0410-80a6-f3fac2684e05>
Mon, 15 Oct 2007 02:41:00 +0000 (02:41 +0000)
committerlgao4 <lgao4@de2fecce-e211-0410-80a6-f3fac2684e05>
Mon, 15 Oct 2007 02:41:00 +0000 (02:41 +0000)
892 Internal Shell sometimes can't boot when boot option is not enumerated

git-svn-id: https://edk2.tianocore.org/svn/edk2/trunk@4112 de2fecce-e211-0410-80a6-f3fac2684e05

edk2/Nt32Pkg/Library/EdkGenericBdsLib/BdsBoot.c
edk2/Nt32Pkg/Library/EdkGenericBdsLib/EdkGenericBdsLibInternal.h

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