1e29caef253e1cffe2a94ec40a549e5771eb28b80Jiewen Yao/** @file
2e29caef253e1cffe2a94ec40a549e5771eb28b80Jiewen Yao  EDKII System Capsule library.
3e29caef253e1cffe2a94ec40a549e5771eb28b80Jiewen Yao
4e29caef253e1cffe2a94ec40a549e5771eb28b80Jiewen Yao  EDKII System Capsule library instance.
5e29caef253e1cffe2a94ec40a549e5771eb28b80Jiewen Yao
6e29caef253e1cffe2a94ec40a549e5771eb28b80Jiewen Yao  CapsuleAuthenticateSystemFirmware(), ExtractAuthenticatedImage() will receive
7e29caef253e1cffe2a94ec40a549e5771eb28b80Jiewen Yao  untrusted input and do basic validation.
8e29caef253e1cffe2a94ec40a549e5771eb28b80Jiewen Yao
9e29caef253e1cffe2a94ec40a549e5771eb28b80Jiewen Yao  Copyright (c) 2016, Intel Corporation. All rights reserved.<BR>
10e29caef253e1cffe2a94ec40a549e5771eb28b80Jiewen Yao  This program and the accompanying materials
11e29caef253e1cffe2a94ec40a549e5771eb28b80Jiewen Yao  are licensed and made available under the terms and conditions of the BSD License
12e29caef253e1cffe2a94ec40a549e5771eb28b80Jiewen Yao  which accompanies this distribution.  The full text of the license may be found at
13e29caef253e1cffe2a94ec40a549e5771eb28b80Jiewen Yao  http://opensource.org/licenses/bsd-license.php
14e29caef253e1cffe2a94ec40a549e5771eb28b80Jiewen Yao
15e29caef253e1cffe2a94ec40a549e5771eb28b80Jiewen Yao  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
16e29caef253e1cffe2a94ec40a549e5771eb28b80Jiewen Yao  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
17e29caef253e1cffe2a94ec40a549e5771eb28b80Jiewen Yao
18e29caef253e1cffe2a94ec40a549e5771eb28b80Jiewen Yao**/
19e29caef253e1cffe2a94ec40a549e5771eb28b80Jiewen Yao
20e29caef253e1cffe2a94ec40a549e5771eb28b80Jiewen Yao#include <PiDxe.h>
21e29caef253e1cffe2a94ec40a549e5771eb28b80Jiewen Yao
22e29caef253e1cffe2a94ec40a549e5771eb28b80Jiewen Yao#include <Guid/SystemResourceTable.h>
23e29caef253e1cffe2a94ec40a549e5771eb28b80Jiewen Yao#include <Guid/FirmwareContentsSigned.h>
24e29caef253e1cffe2a94ec40a549e5771eb28b80Jiewen Yao#include <Guid/WinCertificate.h>
25e29caef253e1cffe2a94ec40a549e5771eb28b80Jiewen Yao#include <Guid/EdkiiSystemFmpCapsule.h>
26e29caef253e1cffe2a94ec40a549e5771eb28b80Jiewen Yao#include <Guid/WinCertificate.h>
27e29caef253e1cffe2a94ec40a549e5771eb28b80Jiewen Yao#include <Guid/ImageAuthentication.h>
28e29caef253e1cffe2a94ec40a549e5771eb28b80Jiewen Yao
29e29caef253e1cffe2a94ec40a549e5771eb28b80Jiewen Yao#include <Library/BaseLib.h>
30e29caef253e1cffe2a94ec40a549e5771eb28b80Jiewen Yao#include <Library/BaseMemoryLib.h>
31e29caef253e1cffe2a94ec40a549e5771eb28b80Jiewen Yao#include <Library/DebugLib.h>
32e29caef253e1cffe2a94ec40a549e5771eb28b80Jiewen Yao#include <Library/MemoryAllocationLib.h>
33e29caef253e1cffe2a94ec40a549e5771eb28b80Jiewen Yao#include <Library/EdkiiSystemCapsuleLib.h>
34e29caef253e1cffe2a94ec40a549e5771eb28b80Jiewen Yao#include <Library/FmpAuthenticationLib.h>
35e29caef253e1cffe2a94ec40a549e5771eb28b80Jiewen Yao
36e29caef253e1cffe2a94ec40a549e5771eb28b80Jiewen Yao#include <Protocol/FirmwareManagement.h>
37e29caef253e1cffe2a94ec40a549e5771eb28b80Jiewen Yao
38e29caef253e1cffe2a94ec40a549e5771eb28b80Jiewen YaoEDKII_SYSTEM_FIRMWARE_IMAGE_DESCRIPTOR   *mImageFmpInfo;
39e29caef253e1cffe2a94ec40a549e5771eb28b80Jiewen YaoUINTN                                    mImageFmpInfoSize;
40e29caef253e1cffe2a94ec40a549e5771eb28b80Jiewen YaoEFI_GUID                                 mEdkiiSystemFirmwareFileGuid;
41e29caef253e1cffe2a94ec40a549e5771eb28b80Jiewen Yao
42e29caef253e1cffe2a94ec40a549e5771eb28b80Jiewen Yao/**
43e29caef253e1cffe2a94ec40a549e5771eb28b80Jiewen Yao  Check if a block of buffer is erased.
44e29caef253e1cffe2a94ec40a549e5771eb28b80Jiewen Yao
45e29caef253e1cffe2a94ec40a549e5771eb28b80Jiewen Yao  @param[in] ErasePolarity  Erase polarity attribute of the firmware volume
46e29caef253e1cffe2a94ec40a549e5771eb28b80Jiewen Yao  @param[in] InBuffer       The buffer to be checked
47e29caef253e1cffe2a94ec40a549e5771eb28b80Jiewen Yao  @param[in] BufferSize     Size of the buffer in bytes
48e29caef253e1cffe2a94ec40a549e5771eb28b80Jiewen Yao
49e29caef253e1cffe2a94ec40a549e5771eb28b80Jiewen Yao  @retval    TRUE           The block of buffer is erased
50e29caef253e1cffe2a94ec40a549e5771eb28b80Jiewen Yao  @retval    FALSE          The block of buffer is not erased
51e29caef253e1cffe2a94ec40a549e5771eb28b80Jiewen Yao**/
52e29caef253e1cffe2a94ec40a549e5771eb28b80Jiewen YaoBOOLEAN
53e29caef253e1cffe2a94ec40a549e5771eb28b80Jiewen YaoIsBufferErased (
54e29caef253e1cffe2a94ec40a549e5771eb28b80Jiewen Yao  IN UINT8    ErasePolarity,
55e29caef253e1cffe2a94ec40a549e5771eb28b80Jiewen Yao  IN VOID     *InBuffer,
56e29caef253e1cffe2a94ec40a549e5771eb28b80Jiewen Yao  IN UINTN    BufferSize
57e29caef253e1cffe2a94ec40a549e5771eb28b80Jiewen Yao  )
58e29caef253e1cffe2a94ec40a549e5771eb28b80Jiewen Yao{
59e29caef253e1cffe2a94ec40a549e5771eb28b80Jiewen Yao  UINTN   Count;
60e29caef253e1cffe2a94ec40a549e5771eb28b80Jiewen Yao  UINT8   EraseByte;
61e29caef253e1cffe2a94ec40a549e5771eb28b80Jiewen Yao  UINT8   *Buffer;
62e29caef253e1cffe2a94ec40a549e5771eb28b80Jiewen Yao
63e29caef253e1cffe2a94ec40a549e5771eb28b80Jiewen Yao  if(ErasePolarity == 1) {
64e29caef253e1cffe2a94ec40a549e5771eb28b80Jiewen Yao    EraseByte = 0xFF;
65e29caef253e1cffe2a94ec40a549e5771eb28b80Jiewen Yao  } else {
66e29caef253e1cffe2a94ec40a549e5771eb28b80Jiewen Yao    EraseByte = 0;
67e29caef253e1cffe2a94ec40a549e5771eb28b80Jiewen Yao  }
68e29caef253e1cffe2a94ec40a549e5771eb28b80Jiewen Yao
69e29caef253e1cffe2a94ec40a549e5771eb28b80Jiewen Yao  Buffer = InBuffer;
70e29caef253e1cffe2a94ec40a549e5771eb28b80Jiewen Yao  for (Count = 0; Count < BufferSize; Count++) {
71e29caef253e1cffe2a94ec40a549e5771eb28b80Jiewen Yao    if (Buffer[Count] != EraseByte) {
72e29caef253e1cffe2a94ec40a549e5771eb28b80Jiewen Yao      return FALSE;
73e29caef253e1cffe2a94ec40a549e5771eb28b80Jiewen Yao    }
74e29caef253e1cffe2a94ec40a549e5771eb28b80Jiewen Yao  }
75e29caef253e1cffe2a94ec40a549e5771eb28b80Jiewen Yao
76e29caef253e1cffe2a94ec40a549e5771eb28b80Jiewen Yao  return TRUE;
77e29caef253e1cffe2a94ec40a549e5771eb28b80Jiewen Yao}
78e29caef253e1cffe2a94ec40a549e5771eb28b80Jiewen Yao
79e29caef253e1cffe2a94ec40a549e5771eb28b80Jiewen Yao/**
80e29caef253e1cffe2a94ec40a549e5771eb28b80Jiewen Yao  Get Section buffer pointer by SectionType and SectionInstance.
81e29caef253e1cffe2a94ec40a549e5771eb28b80Jiewen Yao
82e29caef253e1cffe2a94ec40a549e5771eb28b80Jiewen Yao  @param[in]   SectionBuffer     The buffer of section
83e29caef253e1cffe2a94ec40a549e5771eb28b80Jiewen Yao  @param[in]   SectionBufferSize The size of SectionBuffer in bytes
84e29caef253e1cffe2a94ec40a549e5771eb28b80Jiewen Yao  @param[in]   SectionType       The SectionType of Section to be found
85e29caef253e1cffe2a94ec40a549e5771eb28b80Jiewen Yao  @param[in]   SectionInstance   The Instance of Section to be found
86e29caef253e1cffe2a94ec40a549e5771eb28b80Jiewen Yao  @param[out]  OutSectionBuffer  The section found, including SECTION_HEADER
87e29caef253e1cffe2a94ec40a549e5771eb28b80Jiewen Yao  @param[out]  OutSectionSize    The size of section found, including SECTION_HEADER
88e29caef253e1cffe2a94ec40a549e5771eb28b80Jiewen Yao
89e29caef253e1cffe2a94ec40a549e5771eb28b80Jiewen Yao  @retval TRUE  The FFS buffer is found.
90e29caef253e1cffe2a94ec40a549e5771eb28b80Jiewen Yao  @retval FALSE The FFS buffer is not found.
91e29caef253e1cffe2a94ec40a549e5771eb28b80Jiewen Yao**/
92e29caef253e1cffe2a94ec40a549e5771eb28b80Jiewen YaoBOOLEAN
93e29caef253e1cffe2a94ec40a549e5771eb28b80Jiewen YaoGetSectionByType (
94e29caef253e1cffe2a94ec40a549e5771eb28b80Jiewen Yao  IN VOID                  *SectionBuffer,
95e29caef253e1cffe2a94ec40a549e5771eb28b80Jiewen Yao  IN UINT32                SectionBufferSize,
96e29caef253e1cffe2a94ec40a549e5771eb28b80Jiewen Yao  IN EFI_SECTION_TYPE      SectionType,
97e29caef253e1cffe2a94ec40a549e5771eb28b80Jiewen Yao  IN UINTN                 SectionInstance,
98e29caef253e1cffe2a94ec40a549e5771eb28b80Jiewen Yao  OUT VOID                 **OutSectionBuffer,
99e29caef253e1cffe2a94ec40a549e5771eb28b80Jiewen Yao  OUT UINTN                *OutSectionSize
100e29caef253e1cffe2a94ec40a549e5771eb28b80Jiewen Yao  )
101e29caef253e1cffe2a94ec40a549e5771eb28b80Jiewen Yao{
102e29caef253e1cffe2a94ec40a549e5771eb28b80Jiewen Yao  EFI_COMMON_SECTION_HEADER             *SectionHeader;
103e29caef253e1cffe2a94ec40a549e5771eb28b80Jiewen Yao  UINTN                                 SectionSize;
104e29caef253e1cffe2a94ec40a549e5771eb28b80Jiewen Yao  UINTN                                 Instance;
105e29caef253e1cffe2a94ec40a549e5771eb28b80Jiewen Yao
106e29caef253e1cffe2a94ec40a549e5771eb28b80Jiewen Yao  DEBUG ((DEBUG_INFO, "GetSectionByType - Buffer: 0x%08x - 0x%08x\n", SectionBuffer, SectionBufferSize));
107e29caef253e1cffe2a94ec40a549e5771eb28b80Jiewen Yao
108e29caef253e1cffe2a94ec40a549e5771eb28b80Jiewen Yao  //
109e29caef253e1cffe2a94ec40a549e5771eb28b80Jiewen Yao  // Find Section
110e29caef253e1cffe2a94ec40a549e5771eb28b80Jiewen Yao  //
111e29caef253e1cffe2a94ec40a549e5771eb28b80Jiewen Yao  SectionHeader = SectionBuffer;
112e29caef253e1cffe2a94ec40a549e5771eb28b80Jiewen Yao
113e29caef253e1cffe2a94ec40a549e5771eb28b80Jiewen Yao  Instance = 0;
114e29caef253e1cffe2a94ec40a549e5771eb28b80Jiewen Yao  while ((UINTN)SectionHeader < (UINTN)SectionBuffer + SectionBufferSize) {
115e29caef253e1cffe2a94ec40a549e5771eb28b80Jiewen Yao    DEBUG ((DEBUG_INFO, "GetSectionByType - Section: 0x%08x\n", SectionHeader));
116e29caef253e1cffe2a94ec40a549e5771eb28b80Jiewen Yao    if (IS_SECTION2(SectionHeader)) {
117e29caef253e1cffe2a94ec40a549e5771eb28b80Jiewen Yao      SectionSize = SECTION2_SIZE(SectionHeader);
118e29caef253e1cffe2a94ec40a549e5771eb28b80Jiewen Yao    } else {
119e29caef253e1cffe2a94ec40a549e5771eb28b80Jiewen Yao      SectionSize = SECTION_SIZE(SectionHeader);
120e29caef253e1cffe2a94ec40a549e5771eb28b80Jiewen Yao    }
121e29caef253e1cffe2a94ec40a549e5771eb28b80Jiewen Yao
122e29caef253e1cffe2a94ec40a549e5771eb28b80Jiewen Yao    if (SectionHeader->Type == SectionType) {
123e29caef253e1cffe2a94ec40a549e5771eb28b80Jiewen Yao      if (Instance == SectionInstance) {
124e29caef253e1cffe2a94ec40a549e5771eb28b80Jiewen Yao        *OutSectionBuffer = (UINT8 *)SectionHeader;
125e29caef253e1cffe2a94ec40a549e5771eb28b80Jiewen Yao        *OutSectionSize = SectionSize;
126e29caef253e1cffe2a94ec40a549e5771eb28b80Jiewen Yao        DEBUG((DEBUG_INFO, "GetSectionByType - 0x%x - 0x%x\n", *OutSectionBuffer, *OutSectionSize));
127e29caef253e1cffe2a94ec40a549e5771eb28b80Jiewen Yao        return TRUE;
128e29caef253e1cffe2a94ec40a549e5771eb28b80Jiewen Yao      } else {
129e29caef253e1cffe2a94ec40a549e5771eb28b80Jiewen Yao        DEBUG((DEBUG_INFO, "GetSectionByType - find section instance %x\n", Instance));
130e29caef253e1cffe2a94ec40a549e5771eb28b80Jiewen Yao        Instance++;
131e29caef253e1cffe2a94ec40a549e5771eb28b80Jiewen Yao      }
132e29caef253e1cffe2a94ec40a549e5771eb28b80Jiewen Yao    } else {
133e29caef253e1cffe2a94ec40a549e5771eb28b80Jiewen Yao      //
134e29caef253e1cffe2a94ec40a549e5771eb28b80Jiewen Yao      // Skip other section type
135e29caef253e1cffe2a94ec40a549e5771eb28b80Jiewen Yao      //
136e29caef253e1cffe2a94ec40a549e5771eb28b80Jiewen Yao      DEBUG ((DEBUG_INFO, "GetSectionByType - other section type 0x%x\n", SectionHeader->Type));
137e29caef253e1cffe2a94ec40a549e5771eb28b80Jiewen Yao    }
138e29caef253e1cffe2a94ec40a549e5771eb28b80Jiewen Yao
139e29caef253e1cffe2a94ec40a549e5771eb28b80Jiewen Yao    //
140e29caef253e1cffe2a94ec40a549e5771eb28b80Jiewen Yao    // Next Section
141e29caef253e1cffe2a94ec40a549e5771eb28b80Jiewen Yao    //
142e29caef253e1cffe2a94ec40a549e5771eb28b80Jiewen Yao    SectionHeader = (EFI_COMMON_SECTION_HEADER *)((UINTN)SectionHeader + ALIGN_VALUE(SectionSize, 4));
143e29caef253e1cffe2a94ec40a549e5771eb28b80Jiewen Yao  }
144e29caef253e1cffe2a94ec40a549e5771eb28b80Jiewen Yao
145e29caef253e1cffe2a94ec40a549e5771eb28b80Jiewen Yao  return FALSE;
146e29caef253e1cffe2a94ec40a549e5771eb28b80Jiewen Yao}
147e29caef253e1cffe2a94ec40a549e5771eb28b80Jiewen Yao
148e29caef253e1cffe2a94ec40a549e5771eb28b80Jiewen Yao/**
149e29caef253e1cffe2a94ec40a549e5771eb28b80Jiewen Yao  Get FFS buffer pointer by FileName GUID and FileType.
150e29caef253e1cffe2a94ec40a549e5771eb28b80Jiewen Yao
151e29caef253e1cffe2a94ec40a549e5771eb28b80Jiewen Yao  @param[in]   FdStart          The System Firmware FD image
152e29caef253e1cffe2a94ec40a549e5771eb28b80Jiewen Yao  @param[in]   FdSize           The size of System Firmware FD image
153e29caef253e1cffe2a94ec40a549e5771eb28b80Jiewen Yao  @param[in]   FileName         The FileName GUID of FFS to be found
154e29caef253e1cffe2a94ec40a549e5771eb28b80Jiewen Yao  @param[in]   Type             The FileType of FFS to be found
155e29caef253e1cffe2a94ec40a549e5771eb28b80Jiewen Yao  @param[out]  OutFfsBuffer     The FFS buffer found, including FFS_FILE_HEADER
156e29caef253e1cffe2a94ec40a549e5771eb28b80Jiewen Yao  @param[out]  OutFfsBufferSize The size of FFS buffer found, including FFS_FILE_HEADER
157e29caef253e1cffe2a94ec40a549e5771eb28b80Jiewen Yao
158e29caef253e1cffe2a94ec40a549e5771eb28b80Jiewen Yao  @retval TRUE  The FFS buffer is found.
159e29caef253e1cffe2a94ec40a549e5771eb28b80Jiewen Yao  @retval FALSE The FFS buffer is not found.
160e29caef253e1cffe2a94ec40a549e5771eb28b80Jiewen Yao**/
161e29caef253e1cffe2a94ec40a549e5771eb28b80Jiewen YaoBOOLEAN
162e29caef253e1cffe2a94ec40a549e5771eb28b80Jiewen YaoGetFfsByName (
163e29caef253e1cffe2a94ec40a549e5771eb28b80Jiewen Yao  IN VOID                  *FdStart,
164e29caef253e1cffe2a94ec40a549e5771eb28b80Jiewen Yao  IN UINTN                 FdSize,
165e29caef253e1cffe2a94ec40a549e5771eb28b80Jiewen Yao  IN EFI_GUID              *FileName,
166e29caef253e1cffe2a94ec40a549e5771eb28b80Jiewen Yao  IN EFI_FV_FILETYPE       Type,
167e29caef253e1cffe2a94ec40a549e5771eb28b80Jiewen Yao  OUT VOID                 **OutFfsBuffer,
168e29caef253e1cffe2a94ec40a549e5771eb28b80Jiewen Yao  OUT UINTN                *OutFfsBufferSize
169e29caef253e1cffe2a94ec40a549e5771eb28b80Jiewen Yao  )
170e29caef253e1cffe2a94ec40a549e5771eb28b80Jiewen Yao{
171e29caef253e1cffe2a94ec40a549e5771eb28b80Jiewen Yao  UINTN                                     FvSize;
172e29caef253e1cffe2a94ec40a549e5771eb28b80Jiewen Yao  EFI_FIRMWARE_VOLUME_HEADER                *FvHeader;
173e29caef253e1cffe2a94ec40a549e5771eb28b80Jiewen Yao  EFI_FIRMWARE_VOLUME_EXT_HEADER            *FvExtHeader;
174e29caef253e1cffe2a94ec40a549e5771eb28b80Jiewen Yao  EFI_FFS_FILE_HEADER                       *FfsHeader;
175e29caef253e1cffe2a94ec40a549e5771eb28b80Jiewen Yao  UINT32                                    FfsSize;
176e29caef253e1cffe2a94ec40a549e5771eb28b80Jiewen Yao  UINTN                                     TestLength;
177e29caef253e1cffe2a94ec40a549e5771eb28b80Jiewen Yao  BOOLEAN                                   FvFound;
178e29caef253e1cffe2a94ec40a549e5771eb28b80Jiewen Yao
179e29caef253e1cffe2a94ec40a549e5771eb28b80Jiewen Yao  DEBUG ((DEBUG_INFO, "GetFfsByName - FV: 0x%08x - 0x%08x\n", (UINTN)FdStart, (UINTN)FdSize));
180e29caef253e1cffe2a94ec40a549e5771eb28b80Jiewen Yao
181e29caef253e1cffe2a94ec40a549e5771eb28b80Jiewen Yao  FvFound = FALSE;
182e29caef253e1cffe2a94ec40a549e5771eb28b80Jiewen Yao  FvHeader = (EFI_FIRMWARE_VOLUME_HEADER *)FdStart;
183e29caef253e1cffe2a94ec40a549e5771eb28b80Jiewen Yao  while ((UINTN)FvHeader < (UINTN)FdStart + FdSize - 1) {
184e29caef253e1cffe2a94ec40a549e5771eb28b80Jiewen Yao    FvSize = (UINTN)FdStart + FdSize - (UINTN)FvHeader;
185e29caef253e1cffe2a94ec40a549e5771eb28b80Jiewen Yao
186e29caef253e1cffe2a94ec40a549e5771eb28b80Jiewen Yao    if (FvHeader->Signature != EFI_FVH_SIGNATURE) {
187e29caef253e1cffe2a94ec40a549e5771eb28b80Jiewen Yao      FvHeader = (EFI_FIRMWARE_VOLUME_HEADER *)((UINTN)FvHeader + SIZE_4KB);
188e29caef253e1cffe2a94ec40a549e5771eb28b80Jiewen Yao      continue;
189e29caef253e1cffe2a94ec40a549e5771eb28b80Jiewen Yao    }
190e29caef253e1cffe2a94ec40a549e5771eb28b80Jiewen Yao    DEBUG((DEBUG_ERROR, "checking FV....0x%08x - 0x%x\n", FvHeader, FvHeader->FvLength));
191e29caef253e1cffe2a94ec40a549e5771eb28b80Jiewen Yao    FvFound = TRUE;
192e29caef253e1cffe2a94ec40a549e5771eb28b80Jiewen Yao    if (FvHeader->FvLength > FvSize) {
193e29caef253e1cffe2a94ec40a549e5771eb28b80Jiewen Yao      DEBUG((DEBUG_ERROR, "GetFfsByName - FvSize: 0x%08x, MaxSize - 0x%08x\n", (UINTN)FvHeader->FvLength, (UINTN)FvSize));
194e29caef253e1cffe2a94ec40a549e5771eb28b80Jiewen Yao      return FALSE;
195e29caef253e1cffe2a94ec40a549e5771eb28b80Jiewen Yao    }
196e29caef253e1cffe2a94ec40a549e5771eb28b80Jiewen Yao    FvSize = (UINTN)FvHeader->FvLength;
197e29caef253e1cffe2a94ec40a549e5771eb28b80Jiewen Yao
198e29caef253e1cffe2a94ec40a549e5771eb28b80Jiewen Yao    //
199e29caef253e1cffe2a94ec40a549e5771eb28b80Jiewen Yao    // Find FFS
200e29caef253e1cffe2a94ec40a549e5771eb28b80Jiewen Yao    //
201e29caef253e1cffe2a94ec40a549e5771eb28b80Jiewen Yao    if (FvHeader->ExtHeaderOffset != 0) {
202e29caef253e1cffe2a94ec40a549e5771eb28b80Jiewen Yao      FvExtHeader = (EFI_FIRMWARE_VOLUME_EXT_HEADER *)((UINT8 *)FvHeader + FvHeader->ExtHeaderOffset);
203e29caef253e1cffe2a94ec40a549e5771eb28b80Jiewen Yao      FfsHeader = (EFI_FFS_FILE_HEADER *)((UINT8 *)FvExtHeader + FvExtHeader->ExtHeaderSize);
204e29caef253e1cffe2a94ec40a549e5771eb28b80Jiewen Yao    } else {
205e29caef253e1cffe2a94ec40a549e5771eb28b80Jiewen Yao      FfsHeader = (EFI_FFS_FILE_HEADER *)((UINT8 *)FvHeader + FvHeader->HeaderLength);
206e29caef253e1cffe2a94ec40a549e5771eb28b80Jiewen Yao    }
207e29caef253e1cffe2a94ec40a549e5771eb28b80Jiewen Yao    FfsHeader = (EFI_FFS_FILE_HEADER *)((UINTN)FvHeader + ALIGN_VALUE((UINTN)FfsHeader - (UINTN)FvHeader, 8));
208e29caef253e1cffe2a94ec40a549e5771eb28b80Jiewen Yao
209e29caef253e1cffe2a94ec40a549e5771eb28b80Jiewen Yao    while ((UINTN)FfsHeader < (UINTN)FvHeader + FvSize - 1) {
210e29caef253e1cffe2a94ec40a549e5771eb28b80Jiewen Yao      DEBUG((DEBUG_INFO, "GetFfsByName - FFS: 0x%08x\n", FfsHeader));
211e29caef253e1cffe2a94ec40a549e5771eb28b80Jiewen Yao      TestLength = (UINTN)((UINTN)FvHeader + FvSize - (UINTN)FfsHeader);
212e29caef253e1cffe2a94ec40a549e5771eb28b80Jiewen Yao      if (TestLength > sizeof(EFI_FFS_FILE_HEADER)) {
213e29caef253e1cffe2a94ec40a549e5771eb28b80Jiewen Yao        TestLength = sizeof(EFI_FFS_FILE_HEADER);
214e29caef253e1cffe2a94ec40a549e5771eb28b80Jiewen Yao      }
215e29caef253e1cffe2a94ec40a549e5771eb28b80Jiewen Yao      if (IsBufferErased(1, FfsHeader, TestLength)) {
216e29caef253e1cffe2a94ec40a549e5771eb28b80Jiewen Yao        break;
217e29caef253e1cffe2a94ec40a549e5771eb28b80Jiewen Yao      }
218e29caef253e1cffe2a94ec40a549e5771eb28b80Jiewen Yao
219e29caef253e1cffe2a94ec40a549e5771eb28b80Jiewen Yao      if (IS_FFS_FILE2(FfsHeader)) {
220e29caef253e1cffe2a94ec40a549e5771eb28b80Jiewen Yao        FfsSize = FFS_FILE2_SIZE(FfsHeader);
221e29caef253e1cffe2a94ec40a549e5771eb28b80Jiewen Yao      } else {
222e29caef253e1cffe2a94ec40a549e5771eb28b80Jiewen Yao        FfsSize = FFS_FILE_SIZE(FfsHeader);
223e29caef253e1cffe2a94ec40a549e5771eb28b80Jiewen Yao      }
224e29caef253e1cffe2a94ec40a549e5771eb28b80Jiewen Yao
225e29caef253e1cffe2a94ec40a549e5771eb28b80Jiewen Yao      if (CompareGuid(FileName, &FfsHeader->Name) &&
226e29caef253e1cffe2a94ec40a549e5771eb28b80Jiewen Yao          ((Type == EFI_FV_FILETYPE_ALL) || (FfsHeader->Type == Type))) {
227e29caef253e1cffe2a94ec40a549e5771eb28b80Jiewen Yao        //
228e29caef253e1cffe2a94ec40a549e5771eb28b80Jiewen Yao        // Check section
229e29caef253e1cffe2a94ec40a549e5771eb28b80Jiewen Yao        //
230e29caef253e1cffe2a94ec40a549e5771eb28b80Jiewen Yao        *OutFfsBuffer = FfsHeader;
231e29caef253e1cffe2a94ec40a549e5771eb28b80Jiewen Yao        *OutFfsBufferSize = FfsSize;
232e29caef253e1cffe2a94ec40a549e5771eb28b80Jiewen Yao        return TRUE;
233e29caef253e1cffe2a94ec40a549e5771eb28b80Jiewen Yao      } else {
234e29caef253e1cffe2a94ec40a549e5771eb28b80Jiewen Yao        //
235e29caef253e1cffe2a94ec40a549e5771eb28b80Jiewen Yao        // Any other type is not allowed
236e29caef253e1cffe2a94ec40a549e5771eb28b80Jiewen Yao        //
237e29caef253e1cffe2a94ec40a549e5771eb28b80Jiewen Yao        DEBUG((DEBUG_INFO, "GetFfsByName - other FFS type 0x%x, name %g\n", FfsHeader->Type, &FfsHeader->Name));
238e29caef253e1cffe2a94ec40a549e5771eb28b80Jiewen Yao      }
239e29caef253e1cffe2a94ec40a549e5771eb28b80Jiewen Yao
240e29caef253e1cffe2a94ec40a549e5771eb28b80Jiewen Yao      //
241e29caef253e1cffe2a94ec40a549e5771eb28b80Jiewen Yao      // Next File
242e29caef253e1cffe2a94ec40a549e5771eb28b80Jiewen Yao      //
243e29caef253e1cffe2a94ec40a549e5771eb28b80Jiewen Yao      FfsHeader = (EFI_FFS_FILE_HEADER *)((UINTN)FfsHeader + ALIGN_VALUE(FfsSize, 8));
244e29caef253e1cffe2a94ec40a549e5771eb28b80Jiewen Yao    }
245e29caef253e1cffe2a94ec40a549e5771eb28b80Jiewen Yao
246e29caef253e1cffe2a94ec40a549e5771eb28b80Jiewen Yao    //
247e29caef253e1cffe2a94ec40a549e5771eb28b80Jiewen Yao    // Next FV
248e29caef253e1cffe2a94ec40a549e5771eb28b80Jiewen Yao    //
249e29caef253e1cffe2a94ec40a549e5771eb28b80Jiewen Yao    FvHeader = (VOID *)(UINTN)((UINTN)FvHeader + FvHeader->FvLength);
250e29caef253e1cffe2a94ec40a549e5771eb28b80Jiewen Yao    DEBUG((DEBUG_ERROR, "Next FV....0x%08x - 0x%x\n", FvHeader, FvHeader->FvLength));
251e29caef253e1cffe2a94ec40a549e5771eb28b80Jiewen Yao  }
252e29caef253e1cffe2a94ec40a549e5771eb28b80Jiewen Yao
253e29caef253e1cffe2a94ec40a549e5771eb28b80Jiewen Yao  if (!FvFound) {
254e29caef253e1cffe2a94ec40a549e5771eb28b80Jiewen Yao    DEBUG((DEBUG_ERROR, "GetFfsByName - NO FV Found\n"));
255e29caef253e1cffe2a94ec40a549e5771eb28b80Jiewen Yao  }
256e29caef253e1cffe2a94ec40a549e5771eb28b80Jiewen Yao  return FALSE;
257e29caef253e1cffe2a94ec40a549e5771eb28b80Jiewen Yao}
258e29caef253e1cffe2a94ec40a549e5771eb28b80Jiewen Yao
259e29caef253e1cffe2a94ec40a549e5771eb28b80Jiewen Yao/**
260e29caef253e1cffe2a94ec40a549e5771eb28b80Jiewen Yao  Extract the driver FV from an authenticated image.
261e29caef253e1cffe2a94ec40a549e5771eb28b80Jiewen Yao
262e29caef253e1cffe2a94ec40a549e5771eb28b80Jiewen Yao  @param[in]  AuthenticatedImage      The authenticated capsule image.
263e29caef253e1cffe2a94ec40a549e5771eb28b80Jiewen Yao  @param[in]  AuthenticatedImageSize  The size of the authenticated capsule image in bytes.
264e29caef253e1cffe2a94ec40a549e5771eb28b80Jiewen Yao  @param[out] DriverFvImage           The driver FV image.
265e29caef253e1cffe2a94ec40a549e5771eb28b80Jiewen Yao  @param[out] DriverFvImageSize       The size of the driver FV image in bytes.
266e29caef253e1cffe2a94ec40a549e5771eb28b80Jiewen Yao
267e29caef253e1cffe2a94ec40a549e5771eb28b80Jiewen Yao  @retval TRUE  The driver Fv is extracted.
268e29caef253e1cffe2a94ec40a549e5771eb28b80Jiewen Yao  @retval FALSE The driver Fv is not extracted.
269e29caef253e1cffe2a94ec40a549e5771eb28b80Jiewen Yao**/
270e29caef253e1cffe2a94ec40a549e5771eb28b80Jiewen YaoBOOLEAN
271e29caef253e1cffe2a94ec40a549e5771eb28b80Jiewen YaoEFIAPI
272e29caef253e1cffe2a94ec40a549e5771eb28b80Jiewen YaoExtractDriverFvImage (
273e29caef253e1cffe2a94ec40a549e5771eb28b80Jiewen Yao  IN VOID                         *AuthenticatedImage,
274e29caef253e1cffe2a94ec40a549e5771eb28b80Jiewen Yao  IN UINTN                        AuthenticatedImageSize,
275e29caef253e1cffe2a94ec40a549e5771eb28b80Jiewen Yao  OUT VOID                        **DriverFvImage,
276e29caef253e1cffe2a94ec40a549e5771eb28b80Jiewen Yao  OUT UINTN                       *DriverFvImageSize
277e29caef253e1cffe2a94ec40a549e5771eb28b80Jiewen Yao  )
278e29caef253e1cffe2a94ec40a549e5771eb28b80Jiewen Yao{
279e29caef253e1cffe2a94ec40a549e5771eb28b80Jiewen Yao  BOOLEAN     Result;
280e29caef253e1cffe2a94ec40a549e5771eb28b80Jiewen Yao  UINT32      FileHeaderSize;
281e29caef253e1cffe2a94ec40a549e5771eb28b80Jiewen Yao
282e29caef253e1cffe2a94ec40a549e5771eb28b80Jiewen Yao  *DriverFvImage = NULL;
283e29caef253e1cffe2a94ec40a549e5771eb28b80Jiewen Yao  *DriverFvImageSize = 0;
284e29caef253e1cffe2a94ec40a549e5771eb28b80Jiewen Yao
285e29caef253e1cffe2a94ec40a549e5771eb28b80Jiewen Yao  Result = GetFfsByName(AuthenticatedImage, AuthenticatedImageSize, &gEdkiiSystemFmpCapsuleDriverFvFileGuid, EFI_FV_FILETYPE_RAW, DriverFvImage, DriverFvImageSize);
286e29caef253e1cffe2a94ec40a549e5771eb28b80Jiewen Yao  if (!Result) {
287e29caef253e1cffe2a94ec40a549e5771eb28b80Jiewen Yao    return FALSE;
288e29caef253e1cffe2a94ec40a549e5771eb28b80Jiewen Yao  }
289e29caef253e1cffe2a94ec40a549e5771eb28b80Jiewen Yao
290e29caef253e1cffe2a94ec40a549e5771eb28b80Jiewen Yao  if (IS_FFS_FILE2(*DriverFvImage)) {
291e29caef253e1cffe2a94ec40a549e5771eb28b80Jiewen Yao    FileHeaderSize = sizeof(EFI_FFS_FILE_HEADER2);
292e29caef253e1cffe2a94ec40a549e5771eb28b80Jiewen Yao  } else {
293e29caef253e1cffe2a94ec40a549e5771eb28b80Jiewen Yao    FileHeaderSize = sizeof(EFI_FFS_FILE_HEADER);
294e29caef253e1cffe2a94ec40a549e5771eb28b80Jiewen Yao  }
295e29caef253e1cffe2a94ec40a549e5771eb28b80Jiewen Yao  *DriverFvImage = (UINT8 *)*DriverFvImage + FileHeaderSize;
296e29caef253e1cffe2a94ec40a549e5771eb28b80Jiewen Yao  *DriverFvImageSize = *DriverFvImageSize - FileHeaderSize;
297e29caef253e1cffe2a94ec40a549e5771eb28b80Jiewen Yao
298e29caef253e1cffe2a94ec40a549e5771eb28b80Jiewen Yao  return Result;
299e29caef253e1cffe2a94ec40a549e5771eb28b80Jiewen Yao}
300e29caef253e1cffe2a94ec40a549e5771eb28b80Jiewen Yao
301e29caef253e1cffe2a94ec40a549e5771eb28b80Jiewen Yao/**
302e29caef253e1cffe2a94ec40a549e5771eb28b80Jiewen Yao  Extract the config image from an authenticated image.
303e29caef253e1cffe2a94ec40a549e5771eb28b80Jiewen Yao
304e29caef253e1cffe2a94ec40a549e5771eb28b80Jiewen Yao  @param[in]  AuthenticatedImage      The authenticated capsule image.
305e29caef253e1cffe2a94ec40a549e5771eb28b80Jiewen Yao  @param[in]  AuthenticatedImageSize  The size of the authenticated capsule image in bytes.
306e29caef253e1cffe2a94ec40a549e5771eb28b80Jiewen Yao  @param[out] ConfigImage             The config image.
307e29caef253e1cffe2a94ec40a549e5771eb28b80Jiewen Yao  @param[out] ConfigImageSize         The size of the config image in bytes.
308e29caef253e1cffe2a94ec40a549e5771eb28b80Jiewen Yao
309e29caef253e1cffe2a94ec40a549e5771eb28b80Jiewen Yao  @retval TRUE  The config image is extracted.
310e29caef253e1cffe2a94ec40a549e5771eb28b80Jiewen Yao  @retval FALSE The config image is not extracted.
311e29caef253e1cffe2a94ec40a549e5771eb28b80Jiewen Yao**/
312e29caef253e1cffe2a94ec40a549e5771eb28b80Jiewen YaoBOOLEAN
313e29caef253e1cffe2a94ec40a549e5771eb28b80Jiewen YaoEFIAPI
314e29caef253e1cffe2a94ec40a549e5771eb28b80Jiewen YaoExtractConfigImage (
315e29caef253e1cffe2a94ec40a549e5771eb28b80Jiewen Yao  IN VOID                         *AuthenticatedImage,
316e29caef253e1cffe2a94ec40a549e5771eb28b80Jiewen Yao  IN UINTN                        AuthenticatedImageSize,
317e29caef253e1cffe2a94ec40a549e5771eb28b80Jiewen Yao  OUT VOID                        **ConfigImage,
318e29caef253e1cffe2a94ec40a549e5771eb28b80Jiewen Yao  OUT UINTN                       *ConfigImageSize
319e29caef253e1cffe2a94ec40a549e5771eb28b80Jiewen Yao  )
320e29caef253e1cffe2a94ec40a549e5771eb28b80Jiewen Yao{
321e29caef253e1cffe2a94ec40a549e5771eb28b80Jiewen Yao  BOOLEAN     Result;
322e29caef253e1cffe2a94ec40a549e5771eb28b80Jiewen Yao  UINT32      FileHeaderSize;
323e29caef253e1cffe2a94ec40a549e5771eb28b80Jiewen Yao
324e29caef253e1cffe2a94ec40a549e5771eb28b80Jiewen Yao  *ConfigImage = NULL;
325e29caef253e1cffe2a94ec40a549e5771eb28b80Jiewen Yao  *ConfigImageSize = 0;
326e29caef253e1cffe2a94ec40a549e5771eb28b80Jiewen Yao
327e29caef253e1cffe2a94ec40a549e5771eb28b80Jiewen Yao  Result = GetFfsByName(AuthenticatedImage, AuthenticatedImageSize, &gEdkiiSystemFmpCapsuleConfigFileGuid, EFI_FV_FILETYPE_RAW, ConfigImage, ConfigImageSize);
328e29caef253e1cffe2a94ec40a549e5771eb28b80Jiewen Yao  if (!Result) {
329e29caef253e1cffe2a94ec40a549e5771eb28b80Jiewen Yao    return FALSE;
330e29caef253e1cffe2a94ec40a549e5771eb28b80Jiewen Yao  }
331e29caef253e1cffe2a94ec40a549e5771eb28b80Jiewen Yao
332e29caef253e1cffe2a94ec40a549e5771eb28b80Jiewen Yao  if (IS_FFS_FILE2(*ConfigImage)) {
333e29caef253e1cffe2a94ec40a549e5771eb28b80Jiewen Yao    FileHeaderSize = sizeof(EFI_FFS_FILE_HEADER2);
334e29caef253e1cffe2a94ec40a549e5771eb28b80Jiewen Yao  } else {
335e29caef253e1cffe2a94ec40a549e5771eb28b80Jiewen Yao    FileHeaderSize = sizeof(EFI_FFS_FILE_HEADER);
336e29caef253e1cffe2a94ec40a549e5771eb28b80Jiewen Yao  }
337e29caef253e1cffe2a94ec40a549e5771eb28b80Jiewen Yao  *ConfigImage = (UINT8 *)*ConfigImage + FileHeaderSize;
338e29caef253e1cffe2a94ec40a549e5771eb28b80Jiewen Yao  *ConfigImageSize = *ConfigImageSize - FileHeaderSize;
339e29caef253e1cffe2a94ec40a549e5771eb28b80Jiewen Yao
340e29caef253e1cffe2a94ec40a549e5771eb28b80Jiewen Yao  return Result;
341e29caef253e1cffe2a94ec40a549e5771eb28b80Jiewen Yao}
342e29caef253e1cffe2a94ec40a549e5771eb28b80Jiewen Yao
343e29caef253e1cffe2a94ec40a549e5771eb28b80Jiewen Yao/**
344e29caef253e1cffe2a94ec40a549e5771eb28b80Jiewen Yao  Extract the authenticated image from an FMP capsule image.
345e29caef253e1cffe2a94ec40a549e5771eb28b80Jiewen Yao
346e29caef253e1cffe2a94ec40a549e5771eb28b80Jiewen Yao  Caution: This function may receive untrusted input.
347e29caef253e1cffe2a94ec40a549e5771eb28b80Jiewen Yao
348e29caef253e1cffe2a94ec40a549e5771eb28b80Jiewen Yao  @param[in]  Image                   The FMP capsule image, including EFI_FIRMWARE_IMAGE_AUTHENTICATION.
349e29caef253e1cffe2a94ec40a549e5771eb28b80Jiewen Yao  @param[in]  ImageSize               The size of FMP capsule image in bytes.
350e29caef253e1cffe2a94ec40a549e5771eb28b80Jiewen Yao  @param[out] LastAttemptStatus       The last attempt status, which will be recorded in ESRT and FMP EFI_FIRMWARE_IMAGE_DESCRIPTOR.
351e29caef253e1cffe2a94ec40a549e5771eb28b80Jiewen Yao  @param[out] AuthenticatedImage      The authenticated capsule image, excluding EFI_FIRMWARE_IMAGE_AUTHENTICATION.
352e29caef253e1cffe2a94ec40a549e5771eb28b80Jiewen Yao  @param[out] AuthenticatedImageSize  The size of the authenticated capsule image in bytes.
353e29caef253e1cffe2a94ec40a549e5771eb28b80Jiewen Yao
354e29caef253e1cffe2a94ec40a549e5771eb28b80Jiewen Yao  @retval TRUE  The authenticated image is extracted.
355e29caef253e1cffe2a94ec40a549e5771eb28b80Jiewen Yao  @retval FALSE The authenticated image is not extracted.
356e29caef253e1cffe2a94ec40a549e5771eb28b80Jiewen Yao**/
357e29caef253e1cffe2a94ec40a549e5771eb28b80Jiewen YaoBOOLEAN
358e29caef253e1cffe2a94ec40a549e5771eb28b80Jiewen YaoEFIAPI
359e29caef253e1cffe2a94ec40a549e5771eb28b80Jiewen YaoExtractAuthenticatedImage (
360e29caef253e1cffe2a94ec40a549e5771eb28b80Jiewen Yao  IN VOID                         *Image,
361e29caef253e1cffe2a94ec40a549e5771eb28b80Jiewen Yao  IN UINTN                        ImageSize,
362e29caef253e1cffe2a94ec40a549e5771eb28b80Jiewen Yao  OUT UINT32                      *LastAttemptStatus,
363e29caef253e1cffe2a94ec40a549e5771eb28b80Jiewen Yao  OUT VOID                        **AuthenticatedImage,
364e29caef253e1cffe2a94ec40a549e5771eb28b80Jiewen Yao  OUT UINTN                       *AuthenticatedImageSize
365e29caef253e1cffe2a94ec40a549e5771eb28b80Jiewen Yao  )
366e29caef253e1cffe2a94ec40a549e5771eb28b80Jiewen Yao{
367e29caef253e1cffe2a94ec40a549e5771eb28b80Jiewen Yao  EFI_FIRMWARE_IMAGE_AUTHENTICATION         *ImageAuth;
368e29caef253e1cffe2a94ec40a549e5771eb28b80Jiewen Yao  EFI_STATUS                                Status;
369e29caef253e1cffe2a94ec40a549e5771eb28b80Jiewen Yao  GUID                                      *CertType;
370e29caef253e1cffe2a94ec40a549e5771eb28b80Jiewen Yao  VOID                                      *PublicKeyData;
371e29caef253e1cffe2a94ec40a549e5771eb28b80Jiewen Yao  UINTN                                     PublicKeyDataLength;
372e29caef253e1cffe2a94ec40a549e5771eb28b80Jiewen Yao
373e29caef253e1cffe2a94ec40a549e5771eb28b80Jiewen Yao  DEBUG((DEBUG_INFO, "ExtractAuthenticatedImage - Image: 0x%08x - 0x%08x\n", (UINTN)Image, (UINTN)ImageSize));
374e29caef253e1cffe2a94ec40a549e5771eb28b80Jiewen Yao
375e29caef253e1cffe2a94ec40a549e5771eb28b80Jiewen Yao  *LastAttemptStatus = LAST_ATTEMPT_STATUS_ERROR_INVALID_FORMAT;
376e29caef253e1cffe2a94ec40a549e5771eb28b80Jiewen Yao  if ((Image == NULL) || (ImageSize == 0)) {
377e29caef253e1cffe2a94ec40a549e5771eb28b80Jiewen Yao    return FALSE;
378e29caef253e1cffe2a94ec40a549e5771eb28b80Jiewen Yao  }
379e29caef253e1cffe2a94ec40a549e5771eb28b80Jiewen Yao
380e29caef253e1cffe2a94ec40a549e5771eb28b80Jiewen Yao  ImageAuth = (EFI_FIRMWARE_IMAGE_AUTHENTICATION *)Image;
381e29caef253e1cffe2a94ec40a549e5771eb28b80Jiewen Yao  if (ImageSize < sizeof(EFI_FIRMWARE_IMAGE_AUTHENTICATION)) {
382e29caef253e1cffe2a94ec40a549e5771eb28b80Jiewen Yao    DEBUG((DEBUG_ERROR, "ExtractAuthenticatedImage - ImageSize too small\n"));
383e29caef253e1cffe2a94ec40a549e5771eb28b80Jiewen Yao    return FALSE;
384e29caef253e1cffe2a94ec40a549e5771eb28b80Jiewen Yao  }
385e29caef253e1cffe2a94ec40a549e5771eb28b80Jiewen Yao  if (ImageAuth->AuthInfo.Hdr.dwLength <= OFFSET_OF(WIN_CERTIFICATE_UEFI_GUID, CertData)) {
386e29caef253e1cffe2a94ec40a549e5771eb28b80Jiewen Yao    DEBUG((DEBUG_ERROR, "ExtractAuthenticatedImage - dwLength too small\n"));
387e29caef253e1cffe2a94ec40a549e5771eb28b80Jiewen Yao    return FALSE;
388e29caef253e1cffe2a94ec40a549e5771eb28b80Jiewen Yao  }
389e29caef253e1cffe2a94ec40a549e5771eb28b80Jiewen Yao  if (ImageAuth->AuthInfo.Hdr.dwLength > MAX_UINTN - sizeof(UINT64)) {
390e29caef253e1cffe2a94ec40a549e5771eb28b80Jiewen Yao    DEBUG((DEBUG_ERROR, "ExtractAuthenticatedImage - dwLength too big\n"));
391e29caef253e1cffe2a94ec40a549e5771eb28b80Jiewen Yao    return FALSE;
392e29caef253e1cffe2a94ec40a549e5771eb28b80Jiewen Yao  }
393e29caef253e1cffe2a94ec40a549e5771eb28b80Jiewen Yao  if (ImageSize <= sizeof(ImageAuth->MonotonicCount) + ImageAuth->AuthInfo.Hdr.dwLength) {
394e29caef253e1cffe2a94ec40a549e5771eb28b80Jiewen Yao    DEBUG((DEBUG_ERROR, "ExtractAuthenticatedImage - ImageSize too small\n"));
395e29caef253e1cffe2a94ec40a549e5771eb28b80Jiewen Yao    return FALSE;
396e29caef253e1cffe2a94ec40a549e5771eb28b80Jiewen Yao  }
397e29caef253e1cffe2a94ec40a549e5771eb28b80Jiewen Yao  if (ImageAuth->AuthInfo.Hdr.wRevision != 0x0200) {
398e29caef253e1cffe2a94ec40a549e5771eb28b80Jiewen Yao    DEBUG((DEBUG_ERROR, "ExtractAuthenticatedImage - wRevision: 0x%02x, expect - 0x%02x\n", (UINTN)ImageAuth->AuthInfo.Hdr.wRevision, (UINTN)0x0200));
399e29caef253e1cffe2a94ec40a549e5771eb28b80Jiewen Yao    return FALSE;
400e29caef253e1cffe2a94ec40a549e5771eb28b80Jiewen Yao  }
401e29caef253e1cffe2a94ec40a549e5771eb28b80Jiewen Yao  if (ImageAuth->AuthInfo.Hdr.wCertificateType != WIN_CERT_TYPE_EFI_GUID) {
402e29caef253e1cffe2a94ec40a549e5771eb28b80Jiewen Yao    DEBUG((DEBUG_ERROR, "ExtractAuthenticatedImage - wCertificateType: 0x%02x, expect - 0x%02x\n", (UINTN)ImageAuth->AuthInfo.Hdr.wCertificateType, (UINTN)WIN_CERT_TYPE_EFI_GUID));
403e29caef253e1cffe2a94ec40a549e5771eb28b80Jiewen Yao    return FALSE;
404e29caef253e1cffe2a94ec40a549e5771eb28b80Jiewen Yao  }
405e29caef253e1cffe2a94ec40a549e5771eb28b80Jiewen Yao
406e29caef253e1cffe2a94ec40a549e5771eb28b80Jiewen Yao  CertType = &ImageAuth->AuthInfo.CertType;
407e29caef253e1cffe2a94ec40a549e5771eb28b80Jiewen Yao  DEBUG((DEBUG_INFO, "ExtractAuthenticatedImage - CertType: %g\n", CertType));
408e29caef253e1cffe2a94ec40a549e5771eb28b80Jiewen Yao
409e29caef253e1cffe2a94ec40a549e5771eb28b80Jiewen Yao  if (CompareGuid(&gEfiCertPkcs7Guid, CertType)) {
410e29caef253e1cffe2a94ec40a549e5771eb28b80Jiewen Yao    PublicKeyData   = PcdGetPtr(PcdPkcs7CertBuffer);
411e29caef253e1cffe2a94ec40a549e5771eb28b80Jiewen Yao    PublicKeyDataLength = PcdGetSize(PcdPkcs7CertBuffer);
412e29caef253e1cffe2a94ec40a549e5771eb28b80Jiewen Yao  } else if (CompareGuid(&gEfiCertTypeRsa2048Sha256Guid, CertType)) {
413e29caef253e1cffe2a94ec40a549e5771eb28b80Jiewen Yao    PublicKeyData = PcdGetPtr(PcdRsa2048Sha256PublicKeyBuffer);
414e29caef253e1cffe2a94ec40a549e5771eb28b80Jiewen Yao    PublicKeyDataLength = PcdGetSize(PcdRsa2048Sha256PublicKeyBuffer);
415e29caef253e1cffe2a94ec40a549e5771eb28b80Jiewen Yao  } else {
416e29caef253e1cffe2a94ec40a549e5771eb28b80Jiewen Yao    return FALSE;
417e29caef253e1cffe2a94ec40a549e5771eb28b80Jiewen Yao  }
4187e6e4f96069464ed6ee0669e181abe7cb6801223Jiewen Yao  ASSERT (PublicKeyData != NULL);
4197e6e4f96069464ed6ee0669e181abe7cb6801223Jiewen Yao  ASSERT (PublicKeyDataLength != 0);
420e29caef253e1cffe2a94ec40a549e5771eb28b80Jiewen Yao
421e29caef253e1cffe2a94ec40a549e5771eb28b80Jiewen Yao  Status = AuthenticateFmpImage(
422e29caef253e1cffe2a94ec40a549e5771eb28b80Jiewen Yao             ImageAuth,
423e29caef253e1cffe2a94ec40a549e5771eb28b80Jiewen Yao             ImageSize,
424e29caef253e1cffe2a94ec40a549e5771eb28b80Jiewen Yao             PublicKeyData,
425e29caef253e1cffe2a94ec40a549e5771eb28b80Jiewen Yao             PublicKeyDataLength
426e29caef253e1cffe2a94ec40a549e5771eb28b80Jiewen Yao             );
427e29caef253e1cffe2a94ec40a549e5771eb28b80Jiewen Yao  switch (Status) {
428e29caef253e1cffe2a94ec40a549e5771eb28b80Jiewen Yao  case RETURN_SUCCESS:
429e29caef253e1cffe2a94ec40a549e5771eb28b80Jiewen Yao    *LastAttemptStatus = LAST_ATTEMPT_STATUS_SUCCESS;
430e29caef253e1cffe2a94ec40a549e5771eb28b80Jiewen Yao    break;
431e29caef253e1cffe2a94ec40a549e5771eb28b80Jiewen Yao  case RETURN_SECURITY_VIOLATION:
432e29caef253e1cffe2a94ec40a549e5771eb28b80Jiewen Yao    *LastAttemptStatus = LAST_ATTEMPT_STATUS_ERROR_AUTH_ERROR;
433e29caef253e1cffe2a94ec40a549e5771eb28b80Jiewen Yao    break;
434e29caef253e1cffe2a94ec40a549e5771eb28b80Jiewen Yao  case RETURN_INVALID_PARAMETER:
435e29caef253e1cffe2a94ec40a549e5771eb28b80Jiewen Yao    *LastAttemptStatus = LAST_ATTEMPT_STATUS_ERROR_INVALID_FORMAT;
436e29caef253e1cffe2a94ec40a549e5771eb28b80Jiewen Yao    break;
437e29caef253e1cffe2a94ec40a549e5771eb28b80Jiewen Yao  case RETURN_UNSUPPORTED:
438e29caef253e1cffe2a94ec40a549e5771eb28b80Jiewen Yao    *LastAttemptStatus = LAST_ATTEMPT_STATUS_ERROR_INVALID_FORMAT;
439e29caef253e1cffe2a94ec40a549e5771eb28b80Jiewen Yao    break;
440e29caef253e1cffe2a94ec40a549e5771eb28b80Jiewen Yao  case RETURN_OUT_OF_RESOURCES:
441e29caef253e1cffe2a94ec40a549e5771eb28b80Jiewen Yao    *LastAttemptStatus = LAST_ATTEMPT_STATUS_ERROR_INSUFFICIENT_RESOURCES;
442e29caef253e1cffe2a94ec40a549e5771eb28b80Jiewen Yao    break;
443e29caef253e1cffe2a94ec40a549e5771eb28b80Jiewen Yao  default:
444e29caef253e1cffe2a94ec40a549e5771eb28b80Jiewen Yao    *LastAttemptStatus = LAST_ATTEMPT_STATUS_ERROR_UNSUCCESSFUL;
445e29caef253e1cffe2a94ec40a549e5771eb28b80Jiewen Yao    break;
446e29caef253e1cffe2a94ec40a549e5771eb28b80Jiewen Yao  }
447e29caef253e1cffe2a94ec40a549e5771eb28b80Jiewen Yao  if (EFI_ERROR(Status)) {
448e29caef253e1cffe2a94ec40a549e5771eb28b80Jiewen Yao    return FALSE;
449e29caef253e1cffe2a94ec40a549e5771eb28b80Jiewen Yao  }
450e29caef253e1cffe2a94ec40a549e5771eb28b80Jiewen Yao
451e29caef253e1cffe2a94ec40a549e5771eb28b80Jiewen Yao  if (AuthenticatedImage != NULL) {
452e29caef253e1cffe2a94ec40a549e5771eb28b80Jiewen Yao    *AuthenticatedImage = (UINT8 *)ImageAuth + ImageAuth->AuthInfo.Hdr.dwLength + sizeof(ImageAuth->MonotonicCount);
453e29caef253e1cffe2a94ec40a549e5771eb28b80Jiewen Yao  }
454e29caef253e1cffe2a94ec40a549e5771eb28b80Jiewen Yao  if (AuthenticatedImageSize != NULL) {
455e29caef253e1cffe2a94ec40a549e5771eb28b80Jiewen Yao    *AuthenticatedImageSize = ImageSize - ImageAuth->AuthInfo.Hdr.dwLength - sizeof(ImageAuth->MonotonicCount);
456e29caef253e1cffe2a94ec40a549e5771eb28b80Jiewen Yao  }
457e29caef253e1cffe2a94ec40a549e5771eb28b80Jiewen Yao  return TRUE;
458e29caef253e1cffe2a94ec40a549e5771eb28b80Jiewen Yao}
459e29caef253e1cffe2a94ec40a549e5771eb28b80Jiewen Yao
460e29caef253e1cffe2a94ec40a549e5771eb28b80Jiewen Yao/**
461e29caef253e1cffe2a94ec40a549e5771eb28b80Jiewen Yao  Extract ImageFmpInfo from system firmware.
462e29caef253e1cffe2a94ec40a549e5771eb28b80Jiewen Yao
463e29caef253e1cffe2a94ec40a549e5771eb28b80Jiewen Yao  @param[in]  SystemFirmwareImage     The System Firmware image.
464e29caef253e1cffe2a94ec40a549e5771eb28b80Jiewen Yao  @param[in]  SystemFirmwareImageSize The size of the System Firmware image in bytes.
465e29caef253e1cffe2a94ec40a549e5771eb28b80Jiewen Yao  @param[out] ImageFmpInfo            The ImageFmpInfo.
466e29caef253e1cffe2a94ec40a549e5771eb28b80Jiewen Yao  @param[out] ImageFmpInfoSize        The size of the ImageFmpInfo in bytes.
467e29caef253e1cffe2a94ec40a549e5771eb28b80Jiewen Yao
468e29caef253e1cffe2a94ec40a549e5771eb28b80Jiewen Yao  @retval TRUE  The ImageFmpInfo is extracted.
469e29caef253e1cffe2a94ec40a549e5771eb28b80Jiewen Yao  @retval FALSE The ImageFmpInfo is not extracted.
470e29caef253e1cffe2a94ec40a549e5771eb28b80Jiewen Yao**/
471e29caef253e1cffe2a94ec40a549e5771eb28b80Jiewen YaoBOOLEAN
472e29caef253e1cffe2a94ec40a549e5771eb28b80Jiewen YaoEFIAPI
473e29caef253e1cffe2a94ec40a549e5771eb28b80Jiewen YaoExtractSystemFirmwareImageFmpInfo (
474e29caef253e1cffe2a94ec40a549e5771eb28b80Jiewen Yao  IN VOID                                      *SystemFirmwareImage,
475e29caef253e1cffe2a94ec40a549e5771eb28b80Jiewen Yao  IN UINTN                                     SystemFirmwareImageSize,
476e29caef253e1cffe2a94ec40a549e5771eb28b80Jiewen Yao  OUT EDKII_SYSTEM_FIRMWARE_IMAGE_DESCRIPTOR   **ImageFmpInfo,
477e29caef253e1cffe2a94ec40a549e5771eb28b80Jiewen Yao  OUT UINTN                                    *ImageFmpInfoSize
478e29caef253e1cffe2a94ec40a549e5771eb28b80Jiewen Yao  )
479e29caef253e1cffe2a94ec40a549e5771eb28b80Jiewen Yao{
480e29caef253e1cffe2a94ec40a549e5771eb28b80Jiewen Yao  BOOLEAN     Result;
481e29caef253e1cffe2a94ec40a549e5771eb28b80Jiewen Yao  UINT32      SectionHeaderSize;
482e29caef253e1cffe2a94ec40a549e5771eb28b80Jiewen Yao  UINT32      FileHeaderSize;
483e29caef253e1cffe2a94ec40a549e5771eb28b80Jiewen Yao
484e29caef253e1cffe2a94ec40a549e5771eb28b80Jiewen Yao  *ImageFmpInfo = NULL;
485e29caef253e1cffe2a94ec40a549e5771eb28b80Jiewen Yao  *ImageFmpInfoSize = 0;
486e29caef253e1cffe2a94ec40a549e5771eb28b80Jiewen Yao
487e29caef253e1cffe2a94ec40a549e5771eb28b80Jiewen Yao  Result = GetFfsByName(SystemFirmwareImage, SystemFirmwareImageSize, &gEdkiiSystemFirmwareImageDescriptorFileGuid, EFI_FV_FILETYPE_ALL, (VOID **)ImageFmpInfo, ImageFmpInfoSize);
488e29caef253e1cffe2a94ec40a549e5771eb28b80Jiewen Yao  if (!Result) {
489e29caef253e1cffe2a94ec40a549e5771eb28b80Jiewen Yao    return FALSE;
490e29caef253e1cffe2a94ec40a549e5771eb28b80Jiewen Yao  }
491e29caef253e1cffe2a94ec40a549e5771eb28b80Jiewen Yao  if (IS_FFS_FILE2 (*ImageFmpInfo)) {
492e29caef253e1cffe2a94ec40a549e5771eb28b80Jiewen Yao    FileHeaderSize = sizeof(EFI_FFS_FILE_HEADER2);
493e29caef253e1cffe2a94ec40a549e5771eb28b80Jiewen Yao  } else {
494e29caef253e1cffe2a94ec40a549e5771eb28b80Jiewen Yao    FileHeaderSize = sizeof(EFI_FFS_FILE_HEADER);
495e29caef253e1cffe2a94ec40a549e5771eb28b80Jiewen Yao  }
496e29caef253e1cffe2a94ec40a549e5771eb28b80Jiewen Yao  *ImageFmpInfo = (VOID *)((UINT8 *)*ImageFmpInfo + FileHeaderSize);
497e29caef253e1cffe2a94ec40a549e5771eb28b80Jiewen Yao  *ImageFmpInfoSize = *ImageFmpInfoSize - FileHeaderSize;
498e29caef253e1cffe2a94ec40a549e5771eb28b80Jiewen Yao
499e29caef253e1cffe2a94ec40a549e5771eb28b80Jiewen Yao  Result = GetSectionByType(*ImageFmpInfo, (UINT32)*ImageFmpInfoSize, EFI_SECTION_RAW, 0, (VOID **)ImageFmpInfo, ImageFmpInfoSize);
500e29caef253e1cffe2a94ec40a549e5771eb28b80Jiewen Yao  if (!Result) {
501e29caef253e1cffe2a94ec40a549e5771eb28b80Jiewen Yao    return FALSE;
502e29caef253e1cffe2a94ec40a549e5771eb28b80Jiewen Yao  }
503e29caef253e1cffe2a94ec40a549e5771eb28b80Jiewen Yao  if (IS_SECTION2(*ImageFmpInfo)) {
504e29caef253e1cffe2a94ec40a549e5771eb28b80Jiewen Yao    SectionHeaderSize = sizeof(EFI_RAW_SECTION2);
505e29caef253e1cffe2a94ec40a549e5771eb28b80Jiewen Yao  } else {
506e29caef253e1cffe2a94ec40a549e5771eb28b80Jiewen Yao    SectionHeaderSize = sizeof(EFI_RAW_SECTION);
507e29caef253e1cffe2a94ec40a549e5771eb28b80Jiewen Yao  }
508e29caef253e1cffe2a94ec40a549e5771eb28b80Jiewen Yao  *ImageFmpInfo = (VOID *)((UINT8 *)*ImageFmpInfo + SectionHeaderSize);
509e29caef253e1cffe2a94ec40a549e5771eb28b80Jiewen Yao  *ImageFmpInfoSize = *ImageFmpInfoSize - SectionHeaderSize;
510e29caef253e1cffe2a94ec40a549e5771eb28b80Jiewen Yao
511e29caef253e1cffe2a94ec40a549e5771eb28b80Jiewen Yao  return TRUE;
512e29caef253e1cffe2a94ec40a549e5771eb28b80Jiewen Yao}
513e29caef253e1cffe2a94ec40a549e5771eb28b80Jiewen Yao
514e29caef253e1cffe2a94ec40a549e5771eb28b80Jiewen Yao/**
515e29caef253e1cffe2a94ec40a549e5771eb28b80Jiewen Yao  Extract the System Firmware image from an authenticated image.
516e29caef253e1cffe2a94ec40a549e5771eb28b80Jiewen Yao
517e29caef253e1cffe2a94ec40a549e5771eb28b80Jiewen Yao  @param[in]  AuthenticatedImage      The authenticated capsule image.
518e29caef253e1cffe2a94ec40a549e5771eb28b80Jiewen Yao  @param[in]  AuthenticatedImageSize  The size of the authenticated capsule image in bytes.
519e29caef253e1cffe2a94ec40a549e5771eb28b80Jiewen Yao  @param[out] SystemFirmwareImage     The System Firmware image.
520e29caef253e1cffe2a94ec40a549e5771eb28b80Jiewen Yao  @param[out] SystemFirmwareImageSize The size of the System Firmware image in bytes.
521e29caef253e1cffe2a94ec40a549e5771eb28b80Jiewen Yao
522e29caef253e1cffe2a94ec40a549e5771eb28b80Jiewen Yao  @retval TRUE  The System Firmware image is extracted.
523e29caef253e1cffe2a94ec40a549e5771eb28b80Jiewen Yao  @retval FALSE The System Firmware image is not extracted.
524e29caef253e1cffe2a94ec40a549e5771eb28b80Jiewen Yao**/
525e29caef253e1cffe2a94ec40a549e5771eb28b80Jiewen YaoBOOLEAN
526e29caef253e1cffe2a94ec40a549e5771eb28b80Jiewen YaoEFIAPI
527e29caef253e1cffe2a94ec40a549e5771eb28b80Jiewen YaoExtractSystemFirmwareImage (
528e29caef253e1cffe2a94ec40a549e5771eb28b80Jiewen Yao  IN VOID                         *AuthenticatedImage,
529e29caef253e1cffe2a94ec40a549e5771eb28b80Jiewen Yao  IN UINTN                        AuthenticatedImageSize,
530e29caef253e1cffe2a94ec40a549e5771eb28b80Jiewen Yao  OUT VOID                        **SystemFirmwareImage,
531e29caef253e1cffe2a94ec40a549e5771eb28b80Jiewen Yao  OUT UINTN                       *SystemFirmwareImageSize
532e29caef253e1cffe2a94ec40a549e5771eb28b80Jiewen Yao  )
533e29caef253e1cffe2a94ec40a549e5771eb28b80Jiewen Yao{
534e29caef253e1cffe2a94ec40a549e5771eb28b80Jiewen Yao  BOOLEAN     Result;
535e29caef253e1cffe2a94ec40a549e5771eb28b80Jiewen Yao  UINT32      FileHeaderSize;
536e29caef253e1cffe2a94ec40a549e5771eb28b80Jiewen Yao
537e29caef253e1cffe2a94ec40a549e5771eb28b80Jiewen Yao  *SystemFirmwareImage = NULL;
538e29caef253e1cffe2a94ec40a549e5771eb28b80Jiewen Yao  *SystemFirmwareImageSize = 0;
539e29caef253e1cffe2a94ec40a549e5771eb28b80Jiewen Yao
540e29caef253e1cffe2a94ec40a549e5771eb28b80Jiewen Yao  Result = GetFfsByName(AuthenticatedImage, AuthenticatedImageSize, &mEdkiiSystemFirmwareFileGuid, EFI_FV_FILETYPE_RAW, SystemFirmwareImage, SystemFirmwareImageSize);
541e29caef253e1cffe2a94ec40a549e5771eb28b80Jiewen Yao  if (!Result) {
542e29caef253e1cffe2a94ec40a549e5771eb28b80Jiewen Yao    // no nested FV, just return all data.
543e29caef253e1cffe2a94ec40a549e5771eb28b80Jiewen Yao    *SystemFirmwareImage = AuthenticatedImage;
544e29caef253e1cffe2a94ec40a549e5771eb28b80Jiewen Yao    *SystemFirmwareImageSize = AuthenticatedImageSize;
545e29caef253e1cffe2a94ec40a549e5771eb28b80Jiewen Yao
546e29caef253e1cffe2a94ec40a549e5771eb28b80Jiewen Yao    return TRUE;
547e29caef253e1cffe2a94ec40a549e5771eb28b80Jiewen Yao  }
548e29caef253e1cffe2a94ec40a549e5771eb28b80Jiewen Yao  if (IS_FFS_FILE2 (*SystemFirmwareImage)) {
549e29caef253e1cffe2a94ec40a549e5771eb28b80Jiewen Yao    FileHeaderSize = sizeof(EFI_FFS_FILE_HEADER2);
550e29caef253e1cffe2a94ec40a549e5771eb28b80Jiewen Yao  } else {
551e29caef253e1cffe2a94ec40a549e5771eb28b80Jiewen Yao    FileHeaderSize = sizeof(EFI_FFS_FILE_HEADER);
552e29caef253e1cffe2a94ec40a549e5771eb28b80Jiewen Yao  }
553e29caef253e1cffe2a94ec40a549e5771eb28b80Jiewen Yao  *SystemFirmwareImage = (UINT8 *)*SystemFirmwareImage + FileHeaderSize;
554e29caef253e1cffe2a94ec40a549e5771eb28b80Jiewen Yao  *SystemFirmwareImageSize = *SystemFirmwareImageSize - FileHeaderSize;
555e29caef253e1cffe2a94ec40a549e5771eb28b80Jiewen Yao
556e29caef253e1cffe2a94ec40a549e5771eb28b80Jiewen Yao  return Result;
557e29caef253e1cffe2a94ec40a549e5771eb28b80Jiewen Yao}
558e29caef253e1cffe2a94ec40a549e5771eb28b80Jiewen Yao
559e29caef253e1cffe2a94ec40a549e5771eb28b80Jiewen Yao/**
560e29caef253e1cffe2a94ec40a549e5771eb28b80Jiewen Yao  Authenticated system firmware FMP capsule image.
561e29caef253e1cffe2a94ec40a549e5771eb28b80Jiewen Yao
562e29caef253e1cffe2a94ec40a549e5771eb28b80Jiewen Yao  Caution: This function may receive untrusted input.
563e29caef253e1cffe2a94ec40a549e5771eb28b80Jiewen Yao
564e29caef253e1cffe2a94ec40a549e5771eb28b80Jiewen Yao  @param[in]  Image                   The FMP capsule image, including EFI_FIRMWARE_IMAGE_AUTHENTICATION.
565e29caef253e1cffe2a94ec40a549e5771eb28b80Jiewen Yao  @param[in]  ImageSize               The size of FMP capsule image in bytes.
566e29caef253e1cffe2a94ec40a549e5771eb28b80Jiewen Yao  @param[in]  ForceVersionMatch       TRUE: The version of capsule must be as same as the version of current image.
567e29caef253e1cffe2a94ec40a549e5771eb28b80Jiewen Yao                                      FALSE: The version of capsule must be as same as greater than the lowest
568e29caef253e1cffe2a94ec40a549e5771eb28b80Jiewen Yao                                             supported version of current image.
569e29caef253e1cffe2a94ec40a549e5771eb28b80Jiewen Yao  @param[out] LastAttemptVersion      The last attempt version, which will be recorded in ESRT and FMP EFI_FIRMWARE_IMAGE_DESCRIPTOR.
570e29caef253e1cffe2a94ec40a549e5771eb28b80Jiewen Yao  @param[out] LastAttemptStatus       The last attempt status, which will be recorded in ESRT and FMP EFI_FIRMWARE_IMAGE_DESCRIPTOR.
571e29caef253e1cffe2a94ec40a549e5771eb28b80Jiewen Yao  @param[out] AuthenticatedImage      The authenticated capsule image, excluding EFI_FIRMWARE_IMAGE_AUTHENTICATION.
572e29caef253e1cffe2a94ec40a549e5771eb28b80Jiewen Yao  @param[out] AuthenticatedImageSize  The size of the authenticated capsule image in bytes.
573e29caef253e1cffe2a94ec40a549e5771eb28b80Jiewen Yao
574e29caef253e1cffe2a94ec40a549e5771eb28b80Jiewen Yao  @retval TRUE  Authentication passes and the authenticated image is extracted.
575e29caef253e1cffe2a94ec40a549e5771eb28b80Jiewen Yao  @retval FALSE Authentication fails and the authenticated image is not extracted.
576e29caef253e1cffe2a94ec40a549e5771eb28b80Jiewen Yao**/
577e29caef253e1cffe2a94ec40a549e5771eb28b80Jiewen YaoEFI_STATUS
578e29caef253e1cffe2a94ec40a549e5771eb28b80Jiewen YaoEFIAPI
579e29caef253e1cffe2a94ec40a549e5771eb28b80Jiewen YaoCapsuleAuthenticateSystemFirmware (
580e29caef253e1cffe2a94ec40a549e5771eb28b80Jiewen Yao  IN VOID                         *Image,
581e29caef253e1cffe2a94ec40a549e5771eb28b80Jiewen Yao  IN UINTN                        ImageSize,
582e29caef253e1cffe2a94ec40a549e5771eb28b80Jiewen Yao  IN BOOLEAN                      ForceVersionMatch,
583e29caef253e1cffe2a94ec40a549e5771eb28b80Jiewen Yao  OUT UINT32                      *LastAttemptVersion,
584e29caef253e1cffe2a94ec40a549e5771eb28b80Jiewen Yao  OUT UINT32                      *LastAttemptStatus,
585e29caef253e1cffe2a94ec40a549e5771eb28b80Jiewen Yao  OUT VOID                        **AuthenticatedImage,
586e29caef253e1cffe2a94ec40a549e5771eb28b80Jiewen Yao  OUT UINTN                       *AuthenticatedImageSize
587e29caef253e1cffe2a94ec40a549e5771eb28b80Jiewen Yao  )
588e29caef253e1cffe2a94ec40a549e5771eb28b80Jiewen Yao{
589e29caef253e1cffe2a94ec40a549e5771eb28b80Jiewen Yao  BOOLEAN                                  Result;
590e29caef253e1cffe2a94ec40a549e5771eb28b80Jiewen Yao  EDKII_SYSTEM_FIRMWARE_IMAGE_DESCRIPTOR   *ImageFmpInfo;
591e29caef253e1cffe2a94ec40a549e5771eb28b80Jiewen Yao  UINTN                                    ImageFmpInfoSize;
592e29caef253e1cffe2a94ec40a549e5771eb28b80Jiewen Yao  EDKII_SYSTEM_FIRMWARE_IMAGE_DESCRIPTOR   *CurrentImageFmpInfo;
593e29caef253e1cffe2a94ec40a549e5771eb28b80Jiewen Yao  UINTN                                    CurrentImageFmpInfoSize;
594e29caef253e1cffe2a94ec40a549e5771eb28b80Jiewen Yao  VOID                                     *SystemFirmwareImage;
595e29caef253e1cffe2a94ec40a549e5771eb28b80Jiewen Yao  UINTN                                    SystemFirmwareImageSize;
596e29caef253e1cffe2a94ec40a549e5771eb28b80Jiewen Yao
597e29caef253e1cffe2a94ec40a549e5771eb28b80Jiewen Yao  *LastAttemptVersion = 0;
598e29caef253e1cffe2a94ec40a549e5771eb28b80Jiewen Yao
599e29caef253e1cffe2a94ec40a549e5771eb28b80Jiewen Yao  //
600e29caef253e1cffe2a94ec40a549e5771eb28b80Jiewen Yao  // NOTE: This function need run in an isolated environment.
601e29caef253e1cffe2a94ec40a549e5771eb28b80Jiewen Yao  // Do not touch FMP protocol and its private structure.
602e29caef253e1cffe2a94ec40a549e5771eb28b80Jiewen Yao  //
603e29caef253e1cffe2a94ec40a549e5771eb28b80Jiewen Yao
604e29caef253e1cffe2a94ec40a549e5771eb28b80Jiewen Yao  Result = ExtractAuthenticatedImage((VOID *)Image, ImageSize, LastAttemptStatus, AuthenticatedImage, AuthenticatedImageSize);
605e29caef253e1cffe2a94ec40a549e5771eb28b80Jiewen Yao  if (!Result) {
606e29caef253e1cffe2a94ec40a549e5771eb28b80Jiewen Yao    DEBUG((DEBUG_INFO, "ExtractAuthenticatedImage - fail\n"));
607e29caef253e1cffe2a94ec40a549e5771eb28b80Jiewen Yao    return EFI_SECURITY_VIOLATION;
608e29caef253e1cffe2a94ec40a549e5771eb28b80Jiewen Yao  }
609e29caef253e1cffe2a94ec40a549e5771eb28b80Jiewen Yao
610e29caef253e1cffe2a94ec40a549e5771eb28b80Jiewen Yao  DEBUG((DEBUG_INFO, "AuthenticatedImage - 0x%x - 0x%x\n", *AuthenticatedImage, *AuthenticatedImageSize));
611e29caef253e1cffe2a94ec40a549e5771eb28b80Jiewen Yao
612e29caef253e1cffe2a94ec40a549e5771eb28b80Jiewen Yao  Result = ExtractSystemFirmwareImage(*AuthenticatedImage, *AuthenticatedImageSize, &SystemFirmwareImage, &SystemFirmwareImageSize);
613e29caef253e1cffe2a94ec40a549e5771eb28b80Jiewen Yao  if (!Result) {
614e29caef253e1cffe2a94ec40a549e5771eb28b80Jiewen Yao    *LastAttemptStatus = LAST_ATTEMPT_STATUS_ERROR_INVALID_FORMAT;
615e29caef253e1cffe2a94ec40a549e5771eb28b80Jiewen Yao    DEBUG((DEBUG_INFO, "ExtractSystemFirmwareImage - fail\n"));
616e29caef253e1cffe2a94ec40a549e5771eb28b80Jiewen Yao    return EFI_SECURITY_VIOLATION;
617e29caef253e1cffe2a94ec40a549e5771eb28b80Jiewen Yao  }
618e29caef253e1cffe2a94ec40a549e5771eb28b80Jiewen Yao  DEBUG((DEBUG_INFO, "SystemFirmwareImage - 0x%x - 0x%x\n", SystemFirmwareImage, SystemFirmwareImageSize));
619e29caef253e1cffe2a94ec40a549e5771eb28b80Jiewen Yao
620e29caef253e1cffe2a94ec40a549e5771eb28b80Jiewen Yao  Result = ExtractSystemFirmwareImageFmpInfo(SystemFirmwareImage, SystemFirmwareImageSize, &ImageFmpInfo, &ImageFmpInfoSize);
621e29caef253e1cffe2a94ec40a549e5771eb28b80Jiewen Yao  if (!Result) {
622e29caef253e1cffe2a94ec40a549e5771eb28b80Jiewen Yao    *LastAttemptStatus = LAST_ATTEMPT_STATUS_ERROR_INVALID_FORMAT;
623e29caef253e1cffe2a94ec40a549e5771eb28b80Jiewen Yao    DEBUG((DEBUG_INFO, "ExtractSystemFirmwareImageFmpInfo - fail\n"));
624e29caef253e1cffe2a94ec40a549e5771eb28b80Jiewen Yao    return EFI_SECURITY_VIOLATION;
625e29caef253e1cffe2a94ec40a549e5771eb28b80Jiewen Yao  }
626e29caef253e1cffe2a94ec40a549e5771eb28b80Jiewen Yao
627e29caef253e1cffe2a94ec40a549e5771eb28b80Jiewen Yao  *LastAttemptVersion = ImageFmpInfo->Version;
628e29caef253e1cffe2a94ec40a549e5771eb28b80Jiewen Yao  DEBUG((DEBUG_INFO, "ImageFmpInfo - 0x%x - 0x%x\n", ImageFmpInfo, ImageFmpInfoSize));
629e29caef253e1cffe2a94ec40a549e5771eb28b80Jiewen Yao  DEBUG((DEBUG_INFO, "NewImage Version - 0x%x\n", ImageFmpInfo->Version));
630e29caef253e1cffe2a94ec40a549e5771eb28b80Jiewen Yao  DEBUG((DEBUG_INFO, "NewImage LowestSupportedImageVersion - 0x%x\n", ImageFmpInfo->LowestSupportedImageVersion));
631e29caef253e1cffe2a94ec40a549e5771eb28b80Jiewen Yao
632e29caef253e1cffe2a94ec40a549e5771eb28b80Jiewen Yao  CurrentImageFmpInfo = mImageFmpInfo;
633e29caef253e1cffe2a94ec40a549e5771eb28b80Jiewen Yao  CurrentImageFmpInfoSize = mImageFmpInfoSize;
634e29caef253e1cffe2a94ec40a549e5771eb28b80Jiewen Yao
635e29caef253e1cffe2a94ec40a549e5771eb28b80Jiewen Yao  DEBUG((DEBUG_INFO, "ImageFmpInfo - 0x%x - 0x%x\n", CurrentImageFmpInfo, CurrentImageFmpInfoSize));
636e29caef253e1cffe2a94ec40a549e5771eb28b80Jiewen Yao  DEBUG((DEBUG_INFO, "Current Version - 0x%x\n", CurrentImageFmpInfo->Version));
637e29caef253e1cffe2a94ec40a549e5771eb28b80Jiewen Yao  DEBUG((DEBUG_INFO, "Current LowestSupportedImageVersion - 0x%x\n", CurrentImageFmpInfo->LowestSupportedImageVersion));
638e29caef253e1cffe2a94ec40a549e5771eb28b80Jiewen Yao
639e29caef253e1cffe2a94ec40a549e5771eb28b80Jiewen Yao  if (ForceVersionMatch) {
640e29caef253e1cffe2a94ec40a549e5771eb28b80Jiewen Yao    if (CurrentImageFmpInfo->Version != ImageFmpInfo->Version) {
641e29caef253e1cffe2a94ec40a549e5771eb28b80Jiewen Yao      *LastAttemptStatus = LAST_ATTEMPT_STATUS_ERROR_INCORRECT_VERSION;
642e29caef253e1cffe2a94ec40a549e5771eb28b80Jiewen Yao      DEBUG((DEBUG_INFO, "ForceVersionMatch check - fail\n"));
643e29caef253e1cffe2a94ec40a549e5771eb28b80Jiewen Yao      return EFI_SECURITY_VIOLATION;
644e29caef253e1cffe2a94ec40a549e5771eb28b80Jiewen Yao    }
645e29caef253e1cffe2a94ec40a549e5771eb28b80Jiewen Yao  } else {
646e29caef253e1cffe2a94ec40a549e5771eb28b80Jiewen Yao    if (CurrentImageFmpInfo->Version < ImageFmpInfo->LowestSupportedImageVersion) {
647e29caef253e1cffe2a94ec40a549e5771eb28b80Jiewen Yao      *LastAttemptStatus = LAST_ATTEMPT_STATUS_ERROR_INCORRECT_VERSION;
648e29caef253e1cffe2a94ec40a549e5771eb28b80Jiewen Yao      DEBUG((DEBUG_INFO, "LowestSupportedImageVersion check - fail\n"));
649e29caef253e1cffe2a94ec40a549e5771eb28b80Jiewen Yao      return EFI_SECURITY_VIOLATION;
650e29caef253e1cffe2a94ec40a549e5771eb28b80Jiewen Yao    }
651e29caef253e1cffe2a94ec40a549e5771eb28b80Jiewen Yao  }
652e29caef253e1cffe2a94ec40a549e5771eb28b80Jiewen Yao
653e29caef253e1cffe2a94ec40a549e5771eb28b80Jiewen Yao  *LastAttemptStatus = LAST_ATTEMPT_STATUS_SUCCESS;
654e29caef253e1cffe2a94ec40a549e5771eb28b80Jiewen Yao  return EFI_SUCCESS;
655e29caef253e1cffe2a94ec40a549e5771eb28b80Jiewen Yao}
656e29caef253e1cffe2a94ec40a549e5771eb28b80Jiewen Yao
657e29caef253e1cffe2a94ec40a549e5771eb28b80Jiewen Yao/**
658e29caef253e1cffe2a94ec40a549e5771eb28b80Jiewen Yao  The constructor function.
659e29caef253e1cffe2a94ec40a549e5771eb28b80Jiewen Yao
660e29caef253e1cffe2a94ec40a549e5771eb28b80Jiewen Yao  @retval EFI_SUCCESS   The constructor successfully .
661e29caef253e1cffe2a94ec40a549e5771eb28b80Jiewen Yao**/
662e29caef253e1cffe2a94ec40a549e5771eb28b80Jiewen YaoEFI_STATUS
663e29caef253e1cffe2a94ec40a549e5771eb28b80Jiewen YaoEFIAPI
664e29caef253e1cffe2a94ec40a549e5771eb28b80Jiewen YaoEdkiiSystemCapsuleLibConstructor (
665e29caef253e1cffe2a94ec40a549e5771eb28b80Jiewen Yao  VOID
666e29caef253e1cffe2a94ec40a549e5771eb28b80Jiewen Yao  )
667e29caef253e1cffe2a94ec40a549e5771eb28b80Jiewen Yao{
668e29caef253e1cffe2a94ec40a549e5771eb28b80Jiewen Yao  mImageFmpInfoSize = PcdGetSize(PcdEdkiiSystemFirmwareImageDescriptor);
669e29caef253e1cffe2a94ec40a549e5771eb28b80Jiewen Yao  mImageFmpInfo = AllocateCopyPool (mImageFmpInfoSize, PcdGetPtr(PcdEdkiiSystemFirmwareImageDescriptor));
670e29caef253e1cffe2a94ec40a549e5771eb28b80Jiewen Yao  ASSERT(mImageFmpInfo != NULL);
671e29caef253e1cffe2a94ec40a549e5771eb28b80Jiewen Yao  CopyGuid(&mEdkiiSystemFirmwareFileGuid, PcdGetPtr(PcdEdkiiSystemFirmwareFileGuid));
672e29caef253e1cffe2a94ec40a549e5771eb28b80Jiewen Yao  return EFI_SUCCESS;
673e29caef253e1cffe2a94ec40a549e5771eb28b80Jiewen Yao}
674