]> git.proxmox.com Git - mirror_edk2.git/blobdiff - ArmPkg/Library/BdsLib/BdsAppLoader.c
ArmPkg/BdsLib: Increase fallback tftp buffer size
[mirror_edk2.git] / ArmPkg / Library / BdsLib / BdsAppLoader.c
index 1cc4fddbeacb87740e21694c33fc62f6bf57a58f..1f208f8dd796c3c3f01a842cf736258d5fa6cbdb 100644 (file)
 /** @file\r
 *\r
-*  Copyright (c) 2011, ARM Limited. All rights reserved.\r
-*  \r
-*  This program and the accompanying materials                          \r
-*  are licensed and made available under the terms and conditions of the BSD License         \r
-*  which accompanies this distribution.  The full text of the license may be found at        \r
-*  http://opensource.org/licenses/bsd-license.php                                            \r
+*  Copyright (c) 2011-2015, ARM Limited. All rights reserved.\r
 *\r
-*  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,                     \r
-*  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.             \r
+*  This program and the accompanying materials\r
+*  are licensed and made available under the terms and conditions of the BSD License\r
+*  which accompanies this distribution.  The full text of the license may be found at\r
+*  http://opensource.org/licenses/bsd-license.php\r
+*\r
+*  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
+*  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
 *\r
 **/\r
 \r
 #include "BdsInternal.h"\r
 \r
+/**\r
+  Locate an EFI application in a the Firmware Volumes by its Name\r
+\r
+  @param  EfiAppGuid            Guid of the EFI Application into the Firmware Volume\r
+  @param  DevicePath            EFI Device Path of the EFI application\r
+\r
+  @return EFI_SUCCESS           The function completed successfully.\r
+  @return EFI_NOT_FOUND         The protocol could not be located.\r
+  @return EFI_OUT_OF_RESOURCES  There are not enough resources to find the protocol.\r
+\r
+**/\r
 EFI_STATUS\r
-BdsLoadPeCoff (\r
- IN  BDS_FILE     *EfiAppFile\r
- )\r
+LocateEfiApplicationInFvByName (\r
+  IN  CONST CHAR16*             EfiAppName,\r
+  OUT EFI_DEVICE_PATH           **DevicePath\r
+  )\r
 {\r
-    EFI_STATUS                          Status;\r
-    EFI_HANDLE                          ImageHandle;\r
-    MEDIA_FW_VOL_FILEPATH_DEVICE_PATH   NewNode;\r
-    EFI_DEVICE_PATH_PROTOCOL            *DevicePath;\r
-\r
-    // Only support loading from FV right now\r
-    ASSERT(EfiAppFile->Type == BDS_FILETYPE_FV);\r
-\r
-    // Generate the Device Path for the file\r
-    DevicePath = DuplicateDevicePath(EfiAppFile->DevicePath);\r
-    EfiInitializeFwVolDevicepathNode (&NewNode, &(EfiAppFile->File.Fv.Guid));\r
-    DevicePath = AppendDevicePathNode (DevicePath, (EFI_DEVICE_PATH_PROTOCOL *)&NewNode);\r
-\r
-    Status = gBS->LoadImage (TRUE, gImageHandle, DevicePath, NULL, 0, &ImageHandle);\r
-    if (!EFI_ERROR (Status)) {\r
-        Status = gBS->StartImage (ImageHandle, NULL, NULL);\r
-    }\r
-  \r
+  VOID                          *Key;\r
+  EFI_STATUS                    Status, FileStatus;\r
+  EFI_GUID                      NameGuid;\r
+  EFI_FV_FILETYPE               FileType;\r
+  EFI_FV_FILE_ATTRIBUTES        Attributes;\r
+  UINTN                         Size;\r
+  UINTN                         UiStringLen;\r
+  CHAR16                        *UiSection;\r
+  UINT32                        Authentication;\r
+  EFI_DEVICE_PATH               *FvDevicePath;\r
+  MEDIA_FW_VOL_FILEPATH_DEVICE_PATH    FileDevicePath;\r
+  EFI_HANDLE                    *HandleBuffer;\r
+  UINTN                         NumberOfHandles;\r
+  UINTN                         Index;\r
+  EFI_FIRMWARE_VOLUME2_PROTOCOL *FvInstance;\r
+\r
+  ASSERT (DevicePath != NULL);\r
+\r
+  // Length of FilePath\r
+  UiStringLen = StrLen (EfiAppName);\r
+\r
+  // Locate all the Firmware Volume protocols.\r
+  Status = gBS->LocateHandleBuffer (\r
+                   ByProtocol,\r
+                   &gEfiFirmwareVolume2ProtocolGuid,\r
+                   NULL,\r
+                   &NumberOfHandles,\r
+                   &HandleBuffer\r
+                   );\r
+  if (EFI_ERROR (Status)) {\r
     return Status;\r
-}\r
+  }\r
 \r
-EFI_STATUS BdsLoadApplicationFromPath(\r
-    IN  CHAR16* EfiAppPath\r
-) {\r
-    EFI_STATUS Status;\r
-    BDS_FILE   EfiAppFile;\r
-\r
-    // Need to connect every drivers to ensure no dependencies are missing for the application\r
-    Status = BdsConnectAllDrivers();\r
-    if (EFI_ERROR(Status)) {\r
-        DEBUG ((EFI_D_ERROR, "FAIL to connect all drivers\n"));\r
-        return Status;\r
-    }\r
+  *DevicePath = NULL;\r
 \r
-    // Locate the application from a device path\r
-    Status = BdsLoadFilePath(EfiAppPath, &EfiAppFile);\r
-    if (EFI_ERROR(Status)) {\r
-        DEBUG ((EFI_D_ERROR, "ERROR: Do not find EFI application %s\n",EfiAppPath));\r
-        return Status;\r
+  // Looking for FV with ACPI storage file\r
+  for (Index = 0; Index < NumberOfHandles; Index++) {\r
+    //\r
+    // Get the protocol on this handle\r
+    // This should not fail because of LocateHandleBuffer\r
+    //\r
+    Status = gBS->HandleProtocol (\r
+                     HandleBuffer[Index],\r
+                     &gEfiFirmwareVolume2ProtocolGuid,\r
+                     (VOID**) &FvInstance\r
+                     );\r
+    if (EFI_ERROR (Status)) {\r
+      goto FREE_HANDLE_BUFFER;\r
     }\r
 \r
-    // Start the application\r
-    Status = BdsLoadPeCoff(&EfiAppFile);\r
+    // Allocate Key\r
+    Key = AllocatePool (FvInstance->KeySize);\r
+    ASSERT (Key != NULL);\r
+    ZeroMem (Key, FvInstance->KeySize);\r
 \r
-    return Status;\r
+    do {\r
+      // Search in all files\r
+      FileType = EFI_FV_FILETYPE_ALL;\r
+\r
+      Status = FvInstance->GetNextFile (FvInstance, Key, &FileType, &NameGuid, &Attributes, &Size);\r
+      if (!EFI_ERROR (Status)) {\r
+        UiSection = NULL;\r
+        FileStatus = FvInstance->ReadSection (\r
+                      FvInstance,\r
+                      &NameGuid,\r
+                      EFI_SECTION_USER_INTERFACE,\r
+                      0,\r
+                      (VOID **)&UiSection,\r
+                      &Size,\r
+                      &Authentication\r
+                      );\r
+        if (!EFI_ERROR (FileStatus)) {\r
+          if (StrnCmp (EfiAppName, UiSection, UiStringLen) == 0) {\r
+            //\r
+            // We found a UiString match.\r
+            //\r
+            Status = gBS->HandleProtocol (HandleBuffer[Index], &gEfiDevicePathProtocolGuid, (VOID **)&FvDevicePath);\r
+\r
+            // Generate the Device Path for the file\r
+            EfiInitializeFwVolDevicepathNode (&FileDevicePath, &NameGuid);\r
+            *DevicePath = AppendDevicePathNode (FvDevicePath, (EFI_DEVICE_PATH_PROTOCOL *)&FileDevicePath);\r
+            ASSERT (*DevicePath != NULL);\r
+\r
+            FreePool (Key);\r
+            FreePool (UiSection);\r
+            FreePool (HandleBuffer);\r
+            return FileStatus;\r
+          }\r
+          FreePool (UiSection);\r
+        }\r
+      }\r
+    } while (!EFI_ERROR (Status));\r
+\r
+    FreePool (Key);\r
+  }\r
+\r
+FREE_HANDLE_BUFFER:\r
+  FreePool (HandleBuffer);\r
+  return EFI_NOT_FOUND;\r
 }\r
 \r
-EFI_STATUS BdsLoadApplication(\r
-    IN  CHAR16* EfiApp\r
-) {\r
-    EFI_STATUS                      Status;\r
-    UINTN                           NoHandles, HandleIndex;\r
-    EFI_HANDLE                      *Handles;\r
-    BDS_FILE                        EfiAppFile;\r
-\r
-    // Need to connect every drivers to ensure no dependencies are missing for the application\r
-    Status = BdsConnectAllDrivers();\r
-    if (EFI_ERROR(Status)) {\r
-        DEBUG ((EFI_D_ERROR, "FAIL to connect all drivers\n"));\r
-        return Status;\r
-    }\r
+/**\r
+  Locate an EFI application in a the Firmware Volumes by its GUID\r
+\r
+  @param  EfiAppGuid            Guid of the EFI Application into the Firmware Volume\r
+  @param  DevicePath            EFI Device Path of the EFI application\r
+\r
+  @return EFI_SUCCESS           The function completed successfully.\r
+  @return EFI_NOT_FOUND         The protocol could not be located.\r
+  @return EFI_OUT_OF_RESOURCES  There are not enough resources to find the protocol.\r
+\r
+**/\r
+EFI_STATUS\r
+LocateEfiApplicationInFvByGuid (\r
+  IN  CONST EFI_GUID            *EfiAppGuid,\r
+  OUT EFI_DEVICE_PATH           **DevicePath\r
+  )\r
+{\r
+  EFI_STATUS                    Status;\r
+  EFI_DEVICE_PATH               *FvDevicePath;\r
+  EFI_HANDLE                    *HandleBuffer;\r
+  UINTN                         NumberOfHandles;\r
+  UINTN                         Index;\r
+  EFI_FIRMWARE_VOLUME2_PROTOCOL *FvInstance;\r
+  EFI_FV_FILE_ATTRIBUTES        Attributes;\r
+  UINT32                        AuthenticationStatus;\r
+  EFI_FV_FILETYPE               Type;\r
+  UINTN                         Size;\r
+  CHAR16                        *UiSection;\r
+  MEDIA_FW_VOL_FILEPATH_DEVICE_PATH FvFileDevicePath;\r
+\r
+  ASSERT (DevicePath != NULL);\r
 \r
-    // Search the application in any Firmware Volume\r
-    Status = gBS->LocateHandleBuffer (ByProtocol, &gEfiFirmwareVolume2ProtocolGuid, NULL, &NoHandles, &Handles);\r
-    if (EFI_ERROR (Status) || (NoHandles == 0)) {\r
-        DEBUG ((EFI_D_ERROR, "FAIL to find Firmware Volume\n"));\r
-        return Status;\r
+  // Locate all the Firmware Volume protocols.\r
+  Status = gBS->LocateHandleBuffer (\r
+                   ByProtocol,\r
+                   &gEfiFirmwareVolume2ProtocolGuid,\r
+                   NULL,\r
+                   &NumberOfHandles,\r
+                   &HandleBuffer\r
+                   );\r
+  if (EFI_ERROR (Status)) {\r
+    return Status;\r
+  }\r
+\r
+  *DevicePath = NULL;\r
+\r
+  // Looking for FV with ACPI storage file\r
+  for (Index = 0; Index < NumberOfHandles; Index++) {\r
+    //\r
+    // Get the protocol on this handle\r
+    // This should not fail because of LocateHandleBuffer\r
+    //\r
+    Status = gBS->HandleProtocol (\r
+                     HandleBuffer[Index],\r
+                     &gEfiFirmwareVolume2ProtocolGuid,\r
+                     (VOID**) &FvInstance\r
+                     );\r
+    if (EFI_ERROR (Status)) {\r
+      goto FREE_HANDLE_BUFFER;\r
     }\r
 \r
-    // Search in all Firmware Volume for the EFI Application\r
-    for (HandleIndex = 0; HandleIndex < NoHandles; HandleIndex++) {\r
-        Status = BdsLoadFileFromFirmwareVolume(Handles[HandleIndex],EfiApp,EFI_FV_FILETYPE_APPLICATION,&EfiAppFile);\r
-        if (!EFI_ERROR (Status)) {\r
-            // Start the application\r
-            Status = BdsLoadPeCoff(&EfiAppFile);\r
-            return Status;\r
-        }\r
+    Status = FvInstance->ReadFile (\r
+                  FvInstance,\r
+                  EfiAppGuid,\r
+                  NULL,\r
+                  &Size,\r
+                  &Type,\r
+                  &Attributes,\r
+                  &AuthenticationStatus\r
+                  );\r
+    if (EFI_ERROR (Status)) {\r
+      //\r
+      // Skip if no EFI application file in the FV\r
+      //\r
+      continue;\r
+    } else {\r
+      UiSection = NULL;\r
+      Status = FvInstance->ReadSection (\r
+                    FvInstance,\r
+                    EfiAppGuid,\r
+                    EFI_SECTION_USER_INTERFACE,\r
+                    0,\r
+                    (VOID **)&UiSection,\r
+                    &Size,\r
+                    &AuthenticationStatus\r
+                    );\r
+      if (!EFI_ERROR (Status)) {\r
+        //\r
+        // Create the EFI Device Path for the application using the Filename of the application\r
+        //\r
+        *DevicePath = FileDevicePath (HandleBuffer[Index], UiSection);\r
+      } else {\r
+        Status = gBS->HandleProtocol (HandleBuffer[Index], &gEfiDevicePathProtocolGuid, (VOID**)&FvDevicePath);\r
+        ASSERT_EFI_ERROR (Status);\r
+\r
+        //\r
+        // Create the EFI Device Path for the application using the EFI GUID of the application\r
+        //\r
+        EfiInitializeFwVolDevicepathNode (&FvFileDevicePath, EfiAppGuid);\r
+\r
+        *DevicePath = AppendDevicePathNode (FvDevicePath, (EFI_DEVICE_PATH_PROTOCOL *)&FvFileDevicePath);\r
+        ASSERT (*DevicePath != NULL);\r
+      }\r
+      break;\r
     }\r
+  }\r
 \r
-    return Status;\r
+FREE_HANDLE_BUFFER:\r
+  //\r
+  // Free any allocated buffers\r
+  //\r
+  FreePool (HandleBuffer);\r
+\r
+  if (*DevicePath == NULL) {\r
+    return EFI_NOT_FOUND;\r
+  } else {\r
+    return EFI_SUCCESS;\r
+  }\r
 }\r