]> git.proxmox.com Git - mirror_edk2.git/blobdiff - IntelFrameworkModulePkg/Universal/FirmwareVolume/FwVolDxe/FwVol.c
IntelFrameworkModulePkg FwVolDxe: Get FV auth status propagated from PEI
[mirror_edk2.git] / IntelFrameworkModulePkg / Universal / FirmwareVolume / FwVolDxe / FwVol.c
index f453d5ec0a1a3914a24c381d994d1348eb162895..91fcd472124444d121561a5bea742ad88c80b7fc 100644 (file)
@@ -4,7 +4,7 @@
   Layers on top of Firmware Block protocol to produce a file abstraction\r
   of FV based files.\r
 \r
-  Copyright (c) 2006 - 2010, Intel Corporation. All rights reserved.<BR>\r
+  Copyright (c) 2006 - 2017, Intel Corporation. All rights reserved.<BR>\r
 \r
   This program and the accompanying materials\r
   are licensed and made available under the terms and conditions\r
@@ -34,6 +34,8 @@
   @retval EFI_SUCCESS           Successfully read volume header to the allocated\r
                                 buffer.\r
   @retval EFI_ACCESS_DENIED     Read status of FV is not enabled.\r
+  @retval EFI_INVALID_PARAMETER The FV Header signature is not as expected or\r
+                                the file system could not be understood.\r
 **/\r
 EFI_STATUS\r
 GetFwVolHeader (\r
@@ -90,6 +92,22 @@ GetFwVolHeader (
                     );\r
   }\r
 \r
+  //\r
+  // Validate FV Header signature, if not as expected, continue.\r
+  //\r
+  if (TempFvh.Signature != EFI_FVH_SIGNATURE) {\r
+    return EFI_INVALID_PARAMETER;\r
+  }\r
+\r
+  //\r
+  // Check to see that the file system is indeed formatted in a way we can\r
+  // understand it...\r
+  //\r
+  if ((!CompareGuid (&TempFvh.FileSystemGuid, &gEfiFirmwareFileSystem2Guid)) &&\r
+      (!CompareGuid (&TempFvh.FileSystemGuid, &gEfiFirmwareFileSystem3Guid))) {\r
+    return EFI_INVALID_PARAMETER;\r
+  }\r
+\r
   *FwVolHeader = AllocatePool (TempFvh.HeaderLength);\r
   if (*FwVolHeader == NULL) {\r
     return EFI_OUT_OF_RESOURCES;\r
@@ -174,6 +192,142 @@ FreeFvDeviceResource (
   return ;\r
 }\r
 \r
+/**\r
+\r
+  Firmware volume inherits authentication status from the FV image file and section(in another firmware volume)\r
+  where it came from or propagated from PEI-phase.\r
+\r
+  @param  FvDevice              A pointer to the FvDevice.\r
+\r
+**/\r
+VOID\r
+FwVolInheritAuthenticationStatus (\r
+  IN FV_DEVICE  *FvDevice\r
+  )\r
+{\r
+  EFI_STATUS                            Status;\r
+  EFI_FIRMWARE_VOLUME_HEADER            *CachedFvHeader;\r
+  EFI_FIRMWARE_VOLUME_EXT_HEADER        *CachedFvExtHeader;\r
+  EFI_FIRMWARE_VOLUME2_PROTOCOL         *ParentFvProtocol;\r
+  UINTN                                 Key;\r
+  EFI_GUID                              FileNameGuid;\r
+  EFI_FV_FILETYPE                       FileType;\r
+  EFI_FV_FILE_ATTRIBUTES                FileAttributes;\r
+  UINTN                                 FileSize;\r
+  EFI_SECTION_TYPE                      SectionType;\r
+  UINT32                                AuthenticationStatus;\r
+  EFI_FIRMWARE_VOLUME_HEADER            *FvHeader;\r
+  EFI_FIRMWARE_VOLUME_EXT_HEADER        *FvExtHeader;\r
+  UINTN                                 BufferSize;\r
+  EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL    *Fvb;\r
+  EFI_FVB_ATTRIBUTES_2                  FvbAttributes;\r
+  EFI_PHYSICAL_ADDRESS                  BaseAddress;\r
+  EFI_PEI_HOB_POINTERS                  Fv3Hob;\r
+\r
+  if (FvDevice->Fv.ParentHandle != NULL) {\r
+    CachedFvHeader = (EFI_FIRMWARE_VOLUME_HEADER *) (UINTN) FvDevice->CachedFv;\r
+\r
+    //\r
+    // By Parent Handle, find out the FV image file and section(in another firmware volume) where the firmware volume came from\r
+    //\r
+    Status = gBS->HandleProtocol (FvDevice->Fv.ParentHandle, &gEfiFirmwareVolume2ProtocolGuid, (VOID **) &ParentFvProtocol);\r
+    if (!EFI_ERROR (Status) && (ParentFvProtocol != NULL)) {\r
+      Key = 0;\r
+      do {\r
+        FileType = EFI_FV_FILETYPE_FIRMWARE_VOLUME_IMAGE;\r
+        Status = ParentFvProtocol->GetNextFile (\r
+                                     ParentFvProtocol,\r
+                                     &Key,\r
+                                     &FileType,\r
+                                     &FileNameGuid,\r
+                                     &FileAttributes,\r
+                                     &FileSize\r
+                                     );\r
+        if (EFI_ERROR (Status)) {\r
+          return;\r
+        }\r
+\r
+        SectionType = EFI_SECTION_FIRMWARE_VOLUME_IMAGE;\r
+        FvHeader = NULL;\r
+        BufferSize = 0;\r
+        Status = ParentFvProtocol->ReadSection (\r
+                                     ParentFvProtocol,\r
+                                     &FileNameGuid,\r
+                                     SectionType,\r
+                                     0,\r
+                                     (VOID **) &FvHeader,\r
+                                     &BufferSize,\r
+                                     &AuthenticationStatus\r
+                                     );\r
+        if (!EFI_ERROR (Status)) {\r
+          if ((FvHeader->FvLength == CachedFvHeader->FvLength) &&\r
+              (FvHeader->ExtHeaderOffset == CachedFvHeader->ExtHeaderOffset)) {\r
+            if (FvHeader->ExtHeaderOffset != 0) {\r
+              //\r
+              // Both FVs contain extension header, then compare their FV Name GUID\r
+              //\r
+              FvExtHeader = (EFI_FIRMWARE_VOLUME_EXT_HEADER *) ((UINTN) FvHeader + FvHeader->ExtHeaderOffset);\r
+              CachedFvExtHeader = (EFI_FIRMWARE_VOLUME_EXT_HEADER *) ((UINTN) CachedFvHeader + CachedFvHeader->ExtHeaderOffset);\r
+              if (CompareGuid (&FvExtHeader->FvName, &CachedFvExtHeader->FvName)) {\r
+                //\r
+                // Found the FV image section where the firmware volume came from,\r
+                // and then inherit authentication status from it.\r
+                //\r
+                FvDevice->AuthenticationStatus = AuthenticationStatus;\r
+                FreePool ((VOID *) FvHeader);\r
+                return;\r
+              }\r
+            } else {\r
+              //\r
+              // Both FVs don't contain extension header, then compare their whole FV Image.\r
+              //\r
+              if (CompareMem ((VOID *) FvHeader, (VOID *) CachedFvHeader, (UINTN) FvHeader->FvLength) == 0) {\r
+                //\r
+                // Found the FV image section where the firmware volume came from\r
+                // and then inherit authentication status from it.\r
+                //\r
+                FvDevice->AuthenticationStatus = AuthenticationStatus;\r
+                FreePool ((VOID *) FvHeader);\r
+                return;\r
+              }\r
+            }\r
+          }\r
+          FreePool ((VOID *) FvHeader);\r
+        }\r
+      } while (TRUE);\r
+    }\r
+  } else {\r
+    Fvb = FvDevice->Fvb;\r
+\r
+    Status  = Fvb->GetAttributes (Fvb, &FvbAttributes);\r
+    if (EFI_ERROR (Status)) {\r
+      return;\r
+    }\r
+\r
+    if ((FvbAttributes & EFI_FVB2_MEMORY_MAPPED) != 0) {\r
+      //\r
+      // Get volume base address\r
+      //\r
+      Status = Fvb->GetPhysicalAddress (Fvb, &BaseAddress);\r
+      if (EFI_ERROR (Status)) {\r
+        return;\r
+      }\r
+\r
+      //\r
+      // Get the authentication status propagated from PEI-phase to DXE.\r
+      //\r
+      Fv3Hob.Raw = GetHobList ();\r
+      while ((Fv3Hob.Raw = GetNextHob (EFI_HOB_TYPE_FV3, Fv3Hob.Raw)) != NULL) {\r
+        if (Fv3Hob.FirmwareVolume3->BaseAddress == BaseAddress) {\r
+          FvDevice->AuthenticationStatus = Fv3Hob.FirmwareVolume3->AuthenticationStatus;\r
+          return;\r
+        }\r
+        Fv3Hob.Raw = GET_NEXT_HOB (Fv3Hob);\r
+      }\r
+    }\r
+  }\r
+}\r
+\r
 /**\r
   Check if an FV is consistent and allocate cache for it.\r
 \r
@@ -194,6 +348,7 @@ FvCheck (
   EFI_FVB_ATTRIBUTES_2                FvbAttributes;\r
   EFI_FV_BLOCK_MAP_ENTRY              *BlockMap;\r
   EFI_FIRMWARE_VOLUME_HEADER          *FwVolHeader;\r
+  EFI_FIRMWARE_VOLUME_EXT_HEADER      *FwVolExtHeader;\r
   UINT8                               *FwCache;\r
   LBA_ENTRY                           *LbaEntry;\r
   FREE_SPACE_ENTRY                    *FreeSpaceEntry;\r
@@ -206,7 +361,6 @@ FvCheck (
   UINT8                               *FreeStart;\r
   UINTN                               FreeSize;\r
   UINT8                               ErasePolarity;\r
-  UINTN                               FileLength;\r
   EFI_FFS_FILE_STATE                  FileState;\r
   UINT8                               *TopFvAddress;\r
   UINTN                               TestLength;\r
@@ -230,6 +384,8 @@ FvCheck (
   }\r
   ASSERT (FwVolHeader != NULL);\r
 \r
+  FvDevice->IsFfs3Fv = CompareGuid (&FwVolHeader->FileSystemGuid, &gEfiFirmwareFileSystem3Guid);\r
+\r
   //\r
   // Double Check firmware volume header here\r
   //\r
@@ -348,14 +504,23 @@ FvCheck (
   //\r
   // go through the whole FV cache, check the consistence of the FV\r
   //\r
-  Ptr           = (UINT8 *) (UINTN) (FvDevice->CachedFv + FvDevice->FwVolHeader->HeaderLength);\r
-  TopFvAddress  = (UINT8 *) (UINTN) (FvDevice->CachedFv + FvDevice->FwVolHeader->FvLength - 1);\r
+  if (FvDevice->FwVolHeader->ExtHeaderOffset != 0) {\r
+    //\r
+    // Searching for files starts on an 8 byte aligned boundary after the end of the Extended Header if it exists.\r
+    //\r
+    FwVolExtHeader = (EFI_FIRMWARE_VOLUME_EXT_HEADER *) (UINTN) (FvDevice->CachedFv + FvDevice->FwVolHeader->ExtHeaderOffset);\r
+    Ptr = (UINT8 *) FwVolExtHeader + FwVolExtHeader->ExtHeaderSize;\r
+    Ptr = (UINT8 *) ALIGN_POINTER (Ptr, 8);\r
+  } else {\r
+    Ptr = (UINT8 *) (UINTN) (FvDevice->CachedFv + FvDevice->FwVolHeader->HeaderLength);\r
+  }\r
+  TopFvAddress = (UINT8 *) (UINTN) (FvDevice->CachedFv + FvDevice->FwVolHeader->FvLength);\r
 \r
   //\r
   // Build FFS list & Free Space List here\r
   //\r
-  while (Ptr <= TopFvAddress) {\r
-    TestLength = TopFvAddress - Ptr + 1;\r
+  while (Ptr < TopFvAddress) {\r
+    TestLength = TopFvAddress - Ptr;\r
 \r
     if (TestLength > sizeof (EFI_FFS_FILE_HEADER)) {\r
       TestLength = sizeof (EFI_FFS_FILE_HEADER);\r
@@ -369,7 +534,7 @@ FvCheck (
       FreeSize  = 0;\r
 \r
       do {\r
-        TestLength = TopFvAddress - Ptr + 1;\r
+        TestLength = TopFvAddress - Ptr;\r
 \r
         if (TestLength > sizeof (EFI_FFS_FILE_HEADER)) {\r
           TestLength = sizeof (EFI_FFS_FILE_HEADER);\r
@@ -381,7 +546,7 @@ FvCheck (
 \r
         FreeSize += TestLength;\r
         Ptr += TestLength;\r
-      } while (Ptr <= TopFvAddress);\r
+      } while (Ptr < TopFvAddress);\r
 \r
       FreeSpaceEntry = AllocateZeroPool (sizeof (FREE_SPACE_ENTRY));\r
       if (FreeSpaceEntry == NULL) {\r
@@ -397,7 +562,7 @@ FvCheck (
       continue;\r
     }\r
     //\r
-    // double check boundry\r
+    // double check boundary\r
     //\r
     if (TestLength < sizeof (EFI_FFS_FILE_HEADER)) {\r
       break;\r
@@ -412,7 +577,14 @@ FvCheck (
                     (EFI_FFS_FILE_HEADER *) Ptr\r
                     );\r
       if ((FileState == EFI_FILE_HEADER_INVALID) || (FileState == EFI_FILE_HEADER_CONSTRUCTION)) {\r
-        Ptr += sizeof (EFI_FFS_FILE_HEADER);\r
+        if (IS_FFS_FILE2 (Ptr)) {\r
+          if (!FvDevice->IsFfs3Fv) {\r
+            DEBUG ((EFI_D_ERROR, "Found a FFS3 formatted file: %g in a non-FFS3 formatted FV.\n", &((EFI_FFS_FILE_HEADER *) Ptr)->Name));\r
+          }\r
+          Ptr = Ptr + sizeof (EFI_FFS_FILE_HEADER2);\r
+        } else {\r
+          Ptr = Ptr + sizeof (EFI_FFS_FILE_HEADER);\r
+        }\r
 \r
         continue;\r
 \r
@@ -425,8 +597,22 @@ FvCheck (
       }\r
     }\r
 \r
+    if (IS_FFS_FILE2 (Ptr)) {\r
+      ASSERT (FFS_FILE2_SIZE (Ptr) > 0x00FFFFFF);\r
+      if (!FvDevice->IsFfs3Fv) {\r
+        DEBUG ((EFI_D_ERROR, "Found a FFS3 formatted file: %g in a non-FFS3 formatted FV.\n", &((EFI_FFS_FILE_HEADER *) Ptr)->Name));\r
+        Ptr = Ptr + FFS_FILE2_SIZE (Ptr);\r
+        //\r
+        // Adjust Ptr to the next 8-byte aligned boundary.\r
+        //\r
+        while (((UINTN) Ptr & 0x07) != 0) {\r
+          Ptr++;\r
+        }\r
+        continue;\r
+      }\r
+    }\r
+\r
     if (IsValidFFSFile (FvDevice, (EFI_FFS_FILE_HEADER *) Ptr)) {\r
-      FileLength = *(UINT32 *) ((EFI_FFS_FILE_HEADER *) Ptr)->Size & 0x00FFFFFF;\r
       FileState = GetFileState (\r
                     FvDevice->ErasePolarity,\r
                     (EFI_FFS_FILE_HEADER *) Ptr\r
@@ -449,10 +635,14 @@ FvCheck (
         InsertTailList (&FvDevice->FfsFileListHeader, &FfsFileEntry->Link);\r
       }\r
 \r
-      Ptr += FileLength;\r
+      if (IS_FFS_FILE2 (Ptr)) {\r
+        Ptr = Ptr + FFS_FILE2_SIZE (Ptr);\r
+      } else {\r
+        Ptr = Ptr + FFS_FILE_SIZE (Ptr);\r
+      }\r
 \r
       //\r
-      // Adjust Ptr to the next 8-byte aligned boundry.\r
+      // Adjust Ptr to the next 8-byte aligned boundary.\r
       //\r
       while (((UINTN) Ptr & 0x07) != 0) {\r
         Ptr++;\r
@@ -513,9 +703,7 @@ FwVolDriverInit (
   if (EFI_ERROR (Status)) {\r
     return EFI_NOT_FOUND;\r
   }\r
-  //\r
-  // Get FV with gEfiFirmwareFileSystemGuid\r
-  //\r
+\r
   for (Index = 0; Index < HandleCount; Index += 1) {\r
     Status = gBS->HandleProtocol (\r
                     HandleBuffer[Index],\r
@@ -532,17 +720,6 @@ FwVolDriverInit (
       continue;\r
     }\r
     ASSERT (FwVolHeader != NULL);\r
-    //\r
-    // Check to see that the file system is indeed formatted in a way we can\r
-    // understand it...\r
-    //\r
-    if (!CompareGuid (\r
-          &FwVolHeader->FileSystemGuid,\r
-          &gEfiFirmwareFileSystem2Guid\r
-          )) {\r
-      FreePool (FwVolHeader);\r
-      continue;\r
-    }\r
     FreePool (FwVolHeader);\r
 \r
     Reinstall = FALSE;\r
@@ -580,6 +757,7 @@ FwVolDriverInit (
     FvDevice->Fv.KeySize              = KEYSIZE;\r
     FvDevice->Fv.GetInfo              = FvGetVolumeInfo;\r
     FvDevice->Fv.SetInfo              = FvSetVolumeInfo;\r
+    FvDevice->Fv.ParentHandle         = Fvb->ParentHandle;\r
 \r
     Status = FvCheck (FvDevice);\r
     if (EFI_ERROR (Status)) {\r
@@ -590,6 +768,8 @@ FwVolDriverInit (
       continue;\r
     }\r
 \r
+    FwVolInheritAuthenticationStatus (FvDevice);\r
+\r
     if (Reinstall) {\r
       //\r
       // Reinstall an New FV protocol\r