]> git.proxmox.com Git - mirror_edk2.git/blobdiff - MdeModulePkg/Universal/CapsulePei/Common/CapsuleCoalesce.c
MdeModulePkg CapsulePei: Validate capsule integrity by memory resource hob
[mirror_edk2.git] / MdeModulePkg / Universal / CapsulePei / Common / CapsuleCoalesce.c
index 006d9006369c280182a7e56c461d0ae944466351..9e8315eb97c62c7d87aca443424f8eb097c9855f 100644 (file)
@@ -59,20 +59,6 @@ FindFreeMem (
   UINTN                             DataSize\r
   );\r
 \r
-/**\r
-  Check the integrity of the capsule descriptors.\r
-\r
-  @param BlockList    Pointer to the capsule descriptors\r
-\r
-  @retval NULL           BlockList is not valid.\r
-  @retval LastBlockDesc  Last one Block in BlockList\r
-\r
-**/\r
-EFI_CAPSULE_BLOCK_DESCRIPTOR *\r
-ValidateCapsuleIntegrity (\r
-  IN EFI_CAPSULE_BLOCK_DESCRIPTOR    *BlockList\r
-  );\r
-\r
 /**\r
   The capsule block descriptors may be fragmented and spread all over memory.\r
   To simplify the coalescing of capsule blocks, first coalesce all the\r
@@ -247,10 +233,69 @@ FindFreeMem (
   return MemBase;\r
 }\r
 \r
+/**\r
+  Validate capsule by MemoryResource.\r
+\r
+  @param MemoryResource  Pointer to the buffer of memory resource descriptor.\r
+  @param Address         Address to be validated.\r
+  @param Size            Size to be validated.\r
+\r
+  @retval TRUE  No memory resource descriptor reported in HOB list before capsule Coalesce,\r
+                or it is valid in one MemoryResource.\r
+          FALSE It is not in any MemoryResource.\r
+\r
+**/\r
+BOOLEAN\r
+ValidateCapsuleByMemoryResource (\r
+  IN MEMORY_RESOURCE_DESCRIPTOR     *MemoryResource,\r
+  IN EFI_PHYSICAL_ADDRESS           Address,\r
+  IN UINT64                         Size\r
+  )\r
+{\r
+  UINTN             Index;\r
+\r
+  //\r
+  // Sanity Check\r
+  //\r
+  if (Size > MAX_ADDRESS) {\r
+    DEBUG ((EFI_D_ERROR, "ERROR: Size(0x%lx) > MAX_ADDRESS\n", Size));\r
+    return FALSE;\r
+  }\r
+\r
+  //\r
+  // Sanity Check\r
+  //\r
+  if (Address > (MAX_ADDRESS - Size)) {\r
+    DEBUG ((EFI_D_ERROR, "ERROR: Address(0x%lx) > (MAX_ADDRESS - Size(0x%lx))\n", Address, Size));\r
+    return FALSE;\r
+  }\r
+\r
+  if (MemoryResource == NULL) {\r
+    //\r
+    // No memory resource descriptor reported in HOB list before capsule Coalesce.\r
+    //\r
+    return TRUE;\r
+  }\r
+\r
+  for (Index = 0; MemoryResource[Index].ResourceLength != 0; Index++) {\r
+    if ((Address >= MemoryResource[Index].PhysicalStart) &&\r
+        ((Address + Size) <= (MemoryResource[Index].PhysicalStart + MemoryResource[Index].ResourceLength))) {\r
+      DEBUG ((EFI_D_INFO, "Address(0x%lx) Size(0x%lx) in MemoryResource[0x%x] - Start(0x%lx) Length(0x%lx)\n",\r
+                          Address, Size,\r
+                          Index, MemoryResource[Index].PhysicalStart, MemoryResource[Index].ResourceLength));\r
+      return TRUE;\r
+    }\r
+  }\r
+\r
+  DEBUG ((EFI_D_ERROR, "ERROR: Address(0x%lx) Size(0x%lx) not in any MemoryResource\n", Address, Size));\r
+  return FALSE;\r
+}\r
+\r
 /**\r
   Check the integrity of the capsule descriptors.\r
 \r
-  @param BlockList    Pointer to the capsule descriptors\r
+  @param BlockList       Pointer to the capsule descriptors\r
+  @param MemoryResource  Pointer to the buffer of memory resource descriptor.\r
 \r
   @retval NULL           BlockList is not valid.\r
   @retval LastBlockDesc  Last one Block in BlockList\r
@@ -258,7 +303,8 @@ FindFreeMem (
 **/\r
 EFI_CAPSULE_BLOCK_DESCRIPTOR *\r
 ValidateCapsuleIntegrity (\r
-  IN EFI_CAPSULE_BLOCK_DESCRIPTOR    *BlockList\r
+  IN EFI_CAPSULE_BLOCK_DESCRIPTOR    *BlockList,\r
+  IN MEMORY_RESOURCE_DESCRIPTOR      *MemoryResource\r
   )\r
 {\r
   EFI_CAPSULE_HEADER             *CapsuleHeader;\r
@@ -274,14 +320,19 @@ ValidateCapsuleIntegrity (
   //   * The first capsule header guid\r
   //   * The first capsule header flag\r
   //   * The first capsule header HeaderSize\r
-  //   * Length > MAX_ADDRESS\r
-  //   * ContinuationPointer > MAX_ADDRESS\r
-  //   * DataBlock + Length > MAX_ADDRESS\r
+  //   * Below check will be done in ValidateCapsuleByMemoryResource()\r
+  //     Length > MAX_ADDRESS \r
+  //     Ptr + sizeof (EFI_CAPSULE_BLOCK_DESCRIPTOR) > MAX_ADDRESS\r
+  //     DataBlock + Length > MAX_ADDRESS\r
   //\r
   CapsuleSize  = 0;\r
   CapsuleCount = 0;\r
   Ptr = BlockList;\r
 \r
+  if (!ValidateCapsuleByMemoryResource (MemoryResource, (EFI_PHYSICAL_ADDRESS) (UINTN) Ptr, sizeof (EFI_CAPSULE_BLOCK_DESCRIPTOR))) {\r
+    return NULL;\r
+  }\r
+\r
   DEBUG ((EFI_D_INFO, "Ptr - 0x%x\n", Ptr));\r
   DEBUG ((EFI_D_INFO, "Ptr->Length - 0x%x\n", Ptr->Length));\r
   DEBUG ((EFI_D_INFO, "Ptr->Union - 0x%x\n", Ptr->Union.ContinuationPointer));\r
@@ -293,36 +344,21 @@ ValidateCapsuleIntegrity (
       DEBUG ((EFI_D_ERROR, "ERROR: BlockList address failed alignment check\n"));\r
       return NULL;\r
     }\r
-    //\r
-    // Sanity Check\r
-    //\r
-    if (Ptr->Length > MAX_ADDRESS) {\r
-      DEBUG ((EFI_D_ERROR, "ERROR: Ptr->Length(0x%lx) > MAX_ADDRESS\n", Ptr->Length));\r
-      return NULL;\r
-    }\r
 \r
     if (Ptr->Length == 0) {\r
-      //\r
-      // Sanity Check\r
-      //\r
-      if (Ptr->Union.ContinuationPointer > MAX_ADDRESS) {\r
-        DEBUG ((EFI_D_ERROR, "ERROR: Ptr->Union.ContinuationPointer(0x%lx) > MAX_ADDRESS\n", Ptr->Union.ContinuationPointer));\r
-        return NULL;\r
-      }\r
       //\r
       // Descriptor points to another list of block descriptors somewhere\r
       // else.\r
       //\r
       Ptr = (EFI_CAPSULE_BLOCK_DESCRIPTOR  *) (UINTN) Ptr->Union.ContinuationPointer;\r
+      if (!ValidateCapsuleByMemoryResource (MemoryResource, (EFI_PHYSICAL_ADDRESS) (UINTN) Ptr, sizeof (EFI_CAPSULE_BLOCK_DESCRIPTOR))) {\r
+        return NULL;\r
+      }\r
       DEBUG ((EFI_D_INFO, "Ptr(C) - 0x%x\n", Ptr));\r
       DEBUG ((EFI_D_INFO, "Ptr->Length - 0x%x\n", Ptr->Length));\r
       DEBUG ((EFI_D_INFO, "Ptr->Union - 0x%x\n", Ptr->Union.ContinuationPointer));\r
     } else {\r
-      //\r
-      // Sanity Check\r
-      //\r
-      if (Ptr->Union.DataBlock > (MAX_ADDRESS - (UINTN)Ptr->Length)) {\r
-        DEBUG ((EFI_D_ERROR, "ERROR: Ptr->Union.DataBlock(0x%lx) > (MAX_ADDRESS - (UINTN)Ptr->Length(0x%lx))\n", Ptr->Union.DataBlock, Ptr->Length));\r
+      if (!ValidateCapsuleByMemoryResource (MemoryResource, Ptr->Union.DataBlock, Ptr->Length)) {\r
         return NULL;\r
       }\r
 \r
@@ -370,6 +406,9 @@ ValidateCapsuleIntegrity (
       // Move to next BLOCK descriptor\r
       //\r
       Ptr++;\r
+      if (!ValidateCapsuleByMemoryResource (MemoryResource, (EFI_PHYSICAL_ADDRESS) (UINTN) Ptr, sizeof (EFI_CAPSULE_BLOCK_DESCRIPTOR))) {\r
+        return NULL;\r
+      }\r
       DEBUG ((EFI_D_INFO, "Ptr(B) - 0x%x\n", Ptr));\r
       DEBUG ((EFI_D_INFO, "Ptr->Length - 0x%x\n", Ptr->Length));\r
       DEBUG ((EFI_D_INFO, "Ptr->Union - 0x%x\n", Ptr->Union.ContinuationPointer));\r
@@ -816,6 +855,7 @@ CapsuleTestPatternPreCoalesce (
   Get capsule descriptors from variable CapsuleUpdateData, CapsuleUpdateData1, CapsuleUpdateData2...\r
 \r
   @param BlockListBuffer            Pointer to the buffer of capsule descriptors variables\r
+  @param MemoryResource             Pointer to the buffer of memory resource descriptor.\r
   @param BlockDescriptorList        Pointer to the capsule descriptors list\r
 \r
   @retval EFI_SUCCESS               a valid capsule is present\r
@@ -824,6 +864,7 @@ CapsuleTestPatternPreCoalesce (
 EFI_STATUS\r
 BuildCapsuleDescriptors (\r
   IN  EFI_PHYSICAL_ADDRESS            *BlockListBuffer,\r
+  IN  MEMORY_RESOURCE_DESCRIPTOR      *MemoryResource,\r
   OUT EFI_CAPSULE_BLOCK_DESCRIPTOR    **BlockDescriptorList \r
   )\r
 {\r
@@ -844,7 +885,7 @@ BuildCapsuleDescriptors (
     // Test integrity of descriptors.\r
     //\r
     if (BlockListBuffer[Index] < MAX_ADDRESS) {\r
-      TempBlock = ValidateCapsuleIntegrity ((EFI_CAPSULE_BLOCK_DESCRIPTOR *)(UINTN)BlockListBuffer[Index]);\r
+      TempBlock = ValidateCapsuleIntegrity ((EFI_CAPSULE_BLOCK_DESCRIPTOR *)(UINTN)BlockListBuffer[Index], MemoryResource);\r
       if (TempBlock != NULL) {\r
         if (LastBlock == NULL) {\r
           LastBlock = TempBlock;\r
@@ -928,7 +969,8 @@ CapsuleImageBase-->+---------------------------+
   coalesce capsule data into memory.\r
 \r
   @param PeiServices        General purpose services available to every PEIM.\r
-  @param BlockListBuffer    Point to the buffer of Capsule Descriptor Variables.\r
+  @param BlockListBuffer    Pointer to the buffer of Capsule Descriptor Variables.\r
+  @param MemoryResource     Pointer to the buffer of memory resource descriptor.\r
   @param MemoryBase         Pointer to the base of a block of memory that we can walk\r
                             all over while trying to coalesce our buffers.\r
                             On output, this variable will hold the base address of\r
@@ -950,6 +992,7 @@ EFIAPI
 CapsuleDataCoalesce (\r
   IN EFI_PEI_SERVICES                **PeiServices,\r
   IN EFI_PHYSICAL_ADDRESS            *BlockListBuffer,\r
+  IN MEMORY_RESOURCE_DESCRIPTOR      *MemoryResource,\r
   IN OUT VOID                        **MemoryBase,\r
   IN OUT UINTN                       *MemorySize\r
   )\r
@@ -994,7 +1037,7 @@ CapsuleDataCoalesce (
   //\r
   // Build capsule descriptors list\r
   //\r
-  Status = BuildCapsuleDescriptors (BlockListBuffer, &BlockList);\r
+  Status = BuildCapsuleDescriptors (BlockListBuffer, MemoryResource, &BlockList);\r
   if (EFI_ERROR (Status)) {\r
     return Status;\r
   }\r