]> git.proxmox.com Git - mirror_edk2.git/blobdiff - MdeModulePkg/Library/DxeCapsuleLibFmp/DxeCapsuleProcessLib.c
MdeModulePkg: Add Capsule On Disk APIs into CapsuleLib.
[mirror_edk2.git] / MdeModulePkg / Library / DxeCapsuleLibFmp / DxeCapsuleProcessLib.c
index 5e2d2b87a8d0831f1520ccb6c4886c488438c125..2cecc87385b3605b27bac1b610b78b15403a5de8 100644 (file)
@@ -9,7 +9,7 @@
   ProcessCapsules(), ProcessTheseCapsules() will receive untrusted\r
   input and do basic validation.\r
 \r
-  Copyright (c) 2016 - 2018, Intel Corporation. All rights reserved.<BR>\r
+  Copyright (c) 2016 - 2019, Intel Corporation. All rights reserved.<BR>\r
   SPDX-License-Identifier: BSD-2-Clause-Patent\r
 \r
 **/\r
@@ -92,10 +92,41 @@ IsValidCapsuleHeader (
   IN UINT64              CapsuleSize\r
   );\r
 \r
+/**\r
+  Return if this capsule is a capsule name capsule, based upon CapsuleHeader.\r
+\r
+  @param[in] CapsuleHeader A pointer to EFI_CAPSULE_HEADER\r
+\r
+  @retval TRUE  It is a capsule name capsule.\r
+  @retval FALSE It is not a capsule name capsule.\r
+**/\r
+BOOLEAN\r
+IsCapsuleNameCapsule (\r
+  IN EFI_CAPSULE_HEADER         *CapsuleHeader\r
+  );\r
+\r
+/**\r
+  Check the integrity of the capsule name capsule.\r
+  If the capsule is vaild, return the physical address of each capsule name string.\r
+\r
+  @param[in]  CapsuleHeader   Pointer to the capsule header of a capsule name capsule.\r
+  @param[out] CapsuleNameNum  Number of capsule name.\r
+\r
+  @retval NULL                Capsule name capsule is not valid.\r
+  @retval CapsuleNameBuf      Array of capsule name physical address.\r
+\r
+**/\r
+EFI_PHYSICAL_ADDRESS *\r
+ValidateCapsuleNameCapsuleIntegrity (\r
+  IN  EFI_CAPSULE_HEADER            *CapsuleHeader,\r
+  OUT UINTN                         *CapsuleNameNum\r
+  );\r
+\r
 extern BOOLEAN                   mDxeCapsuleLibEndOfDxe;\r
 BOOLEAN                          mNeedReset = FALSE;\r
 \r
 VOID                        **mCapsulePtr;\r
+CHAR16                      **mCapsuleNamePtr;\r
 EFI_STATUS                  *mCapsuleStatusArray;\r
 UINT32                      mCapsuleTotalNumber;\r
 \r
@@ -116,6 +147,7 @@ EFI_STATUS
 EFIAPI\r
 ProcessThisCapsuleImage (\r
   IN EFI_CAPSULE_HEADER  *CapsuleHeader,\r
+  IN CHAR16              *CapFileName,  OPTIONAL\r
   OUT BOOLEAN            *ResetRequired OPTIONAL\r
   );\r
 \r
@@ -185,6 +217,18 @@ InitCapsulePtr (
 {\r
   EFI_PEI_HOB_POINTERS        HobPointer;\r
   UINTN                       Index;\r
+  UINTN                       Index2;\r
+  UINTN                       Index3;\r
+  UINTN                       CapsuleNameNumber;\r
+  UINTN                       CapsuleNameTotalNumber;\r
+  UINTN                       CapsuleNameCapsuleTotalNumber;\r
+  VOID                        **CapsuleNameCapsulePtr;\r
+  EFI_PHYSICAL_ADDRESS        *CapsuleNameAddress;\r
+\r
+  CapsuleNameNumber             = 0;\r
+  CapsuleNameTotalNumber        = 0;\r
+  CapsuleNameCapsuleTotalNumber = 0;\r
+  CapsuleNameCapsulePtr         = NULL;\r
 \r
   //\r
   // Find all capsule images from hob\r
@@ -194,7 +238,11 @@ InitCapsulePtr (
     if (!IsValidCapsuleHeader((VOID *)(UINTN)HobPointer.Capsule->BaseAddress, HobPointer.Capsule->Length)) {\r
       HobPointer.Header->HobType = EFI_HOB_TYPE_UNUSED; // Mark this hob as invalid\r
     } else {\r
-      mCapsuleTotalNumber++;\r
+      if (IsCapsuleNameCapsule((VOID *)(UINTN)HobPointer.Capsule->BaseAddress)) {\r
+        CapsuleNameCapsuleTotalNumber++;\r
+      } else {\r
+        mCapsuleTotalNumber++;\r
+      }\r
     }\r
     HobPointer.Raw = GET_NEXT_HOB (HobPointer);\r
   }\r
@@ -224,15 +272,68 @@ InitCapsulePtr (
   }\r
   SetMemN (mCapsuleStatusArray, sizeof (EFI_STATUS) * mCapsuleTotalNumber, EFI_NOT_READY);\r
 \r
+  CapsuleNameCapsulePtr =  (VOID **) AllocateZeroPool (sizeof (VOID *) * CapsuleNameCapsuleTotalNumber);\r
+  if (CapsuleNameCapsulePtr == NULL) {\r
+    DEBUG ((DEBUG_ERROR, "Allocate CapsuleNameCapsulePtr fail!\n"));\r
+    FreePool (mCapsulePtr);\r
+    FreePool (mCapsuleStatusArray);\r
+    mCapsulePtr         = NULL;\r
+    mCapsuleStatusArray = NULL;\r
+    mCapsuleTotalNumber = 0;\r
+    return ;\r
+  }\r
+\r
   //\r
   // Find all capsule images from hob\r
   //\r
   HobPointer.Raw = GetHobList ();\r
-  Index = 0;\r
+  Index  = 0;\r
+  Index2 = 0;\r
   while ((HobPointer.Raw = GetNextHob (EFI_HOB_TYPE_UEFI_CAPSULE, HobPointer.Raw)) != NULL) {\r
-    mCapsulePtr [Index++] = (VOID *) (UINTN) HobPointer.Capsule->BaseAddress;\r
+    if (IsCapsuleNameCapsule ((VOID *) (UINTN) HobPointer.Capsule->BaseAddress)) {\r
+      CapsuleNameCapsulePtr [Index2++] = (VOID *) (UINTN) HobPointer.Capsule->BaseAddress;\r
+    } else {\r
+      mCapsulePtr [Index++] = (VOID *) (UINTN) HobPointer.Capsule->BaseAddress;\r
+    }\r
     HobPointer.Raw = GET_NEXT_HOB (HobPointer);\r
   }\r
+\r
+  //\r
+  // Find Capsule On Disk Names\r
+  //\r
+  for (Index = 0; Index < CapsuleNameCapsuleTotalNumber; Index ++) {\r
+    CapsuleNameAddress = ValidateCapsuleNameCapsuleIntegrity (CapsuleNameCapsulePtr[Index], &CapsuleNameNumber);\r
+    if (CapsuleNameAddress != NULL ) {\r
+      CapsuleNameTotalNumber += CapsuleNameNumber;\r
+    }\r
+  }\r
+\r
+  if (CapsuleNameTotalNumber == mCapsuleTotalNumber) {\r
+    mCapsuleNamePtr = (CHAR16 **) AllocateZeroPool (sizeof (CHAR16 *) * mCapsuleTotalNumber);\r
+    if (mCapsuleNamePtr == NULL) {\r
+      DEBUG ((DEBUG_ERROR, "Allocate mCapsuleNamePtr fail!\n"));\r
+      FreePool (mCapsulePtr);\r
+      FreePool (mCapsuleStatusArray);\r
+      FreePool (CapsuleNameCapsulePtr);\r
+      mCapsulePtr         = NULL;\r
+      mCapsuleStatusArray = NULL;\r
+      mCapsuleTotalNumber = 0;\r
+      return ;\r
+    }\r
+\r
+    for (Index = 0, Index3 = 0; Index < CapsuleNameCapsuleTotalNumber; Index ++) {\r
+      CapsuleNameAddress = ValidateCapsuleNameCapsuleIntegrity (CapsuleNameCapsulePtr[Index], &CapsuleNameNumber);\r
+      if (CapsuleNameAddress != NULL ) {\r
+        for (Index2 = 0; Index2 < CapsuleNameNumber; Index2 ++) {\r
+          mCapsuleNamePtr[Index3 ++] = (CHAR16 *)(UINTN) CapsuleNameAddress[Index2];\r
+        }\r
+      }\r
+    }\r
+  } else {\r
+    mCapsuleNamePtr = NULL;\r
+  }\r
+\r
+  FreePool (CapsuleNameCapsulePtr);\r
 }\r
 \r
 /**\r
@@ -396,6 +497,7 @@ ProcessTheseCapsules (
   ESRT_MANAGEMENT_PROTOCOL    *EsrtManagement;\r
   UINT16                      EmbeddedDriverCount;\r
   BOOLEAN                     ResetRequired;\r
+  CHAR16                      *CapsuleName;\r
 \r
   REPORT_STATUS_CODE(EFI_PROGRESS_CODE, (EFI_SOFTWARE | PcdGet32(PcdStatusCodeSubClassCapsule) | PcdGet32(PcdCapsuleStatusCodeProcessCapsulesBegin)));\r
 \r
@@ -408,6 +510,7 @@ ProcessTheseCapsules (
     // We didn't find a hob, so had no errors.\r
     //\r
     DEBUG ((DEBUG_ERROR, "We can not find capsule data in capsule update boot mode.\n"));\r
+    mNeedReset = TRUE;\r
     return EFI_SUCCESS;\r
   }\r
 \r
@@ -430,10 +533,11 @@ ProcessTheseCapsules (
   //\r
   for (Index = 0; Index < mCapsuleTotalNumber; Index++) {\r
     CapsuleHeader = (EFI_CAPSULE_HEADER*) mCapsulePtr [Index];\r
+    CapsuleName = (mCapsuleNamePtr == NULL) ? NULL : mCapsuleNamePtr[Index];\r
     if (CompareGuid (&CapsuleHeader->CapsuleGuid, &gWindowsUxCapsuleGuid)) {\r
       DEBUG ((DEBUG_INFO, "ProcessThisCapsuleImage (Ux) - 0x%x\n", CapsuleHeader));\r
       DEBUG ((DEBUG_INFO, "Display logo capsule is found.\n"));\r
-      Status = ProcessThisCapsuleImage (CapsuleHeader, NULL);\r
+      Status = ProcessThisCapsuleImage (CapsuleHeader, CapsuleName, NULL);\r
       mCapsuleStatusArray [Index] = EFI_SUCCESS;\r
       DEBUG((DEBUG_INFO, "ProcessThisCapsuleImage (Ux) - %r\n", Status));\r
       break;\r
@@ -451,6 +555,7 @@ ProcessTheseCapsules (
       continue;\r
     }\r
     CapsuleHeader = (EFI_CAPSULE_HEADER*) mCapsulePtr [Index];\r
+    CapsuleName = (mCapsuleNamePtr == NULL) ? NULL : mCapsuleNamePtr[Index];\r
     if (!CompareGuid (&CapsuleHeader->CapsuleGuid, &gWindowsUxCapsuleGuid)) {\r
       //\r
       // Call capsule library to process capsule image.\r
@@ -471,7 +576,7 @@ ProcessTheseCapsules (
       if ((!FirstRound) || (EmbeddedDriverCount == 0)) {\r
         DEBUG((DEBUG_INFO, "ProcessThisCapsuleImage - 0x%x\n", CapsuleHeader));\r
         ResetRequired = FALSE;\r
-        Status = ProcessThisCapsuleImage (CapsuleHeader, &ResetRequired);\r
+        Status = ProcessThisCapsuleImage (CapsuleHeader, CapsuleName, &ResetRequired);\r
         mCapsuleStatusArray [Index] = Status;\r
         DEBUG((DEBUG_INFO, "ProcessThisCapsuleImage - %r\n", Status));\r
 \r
@@ -530,7 +635,8 @@ DoResetSystem (
   Caution: This function may receive untrusted input.\r
 \r
   The capsules reported in EFI_HOB_UEFI_CAPSULE are processed.\r
-  If there is no EFI_HOB_UEFI_CAPSULE, this routine does nothing.\r
+  If there is no EFI_HOB_UEFI_CAPSULE, it means error occurs, force reset to\r
+  normal boot path.\r
 \r
   This routine should be called twice in BDS.\r
   1) The first call must be before EndOfDxe. The system capsules is processed.\r