Update CustomDecompress library to support algorithm guid and Update DxeIpl and DxeCore to support custom decompress guid section parse.

git-svn-id: https://edk2.svn.sourceforge.net/svnroot/edk2/trunk/edk2@3573 6f19259b-4bc3-4df7-8a09-765794883524
This commit is contained in:
lgao4 2007-08-08 10:17:57 +00:00
parent c76af11785
commit d8c79a815f
11 changed files with 755 additions and 400 deletions

View File

@ -0,0 +1,30 @@
/*++
Copyright (c) 2006 - 2007, Intel Corporation
All rights reserved. This program and the accompanying materials
are licensed and made available under the terms and conditions of the BSD License
which accompanies this distribution. The full text of the license may be found at
http://opensource.org/licenses/bsd-license.php
THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
Module Name:
CustomDecompress.h
Abstract:
Custom decompress Guid definitions
--*/
#ifndef __EFI_CUSTOM_DECOMPRESS_GUID_H__
#define __EFI_CUSTOM_DECOMPRESS_GUID_H__
#define TINAO_CUSTOM_DECOMPRESS_GUID \
{ 0xA31280AD, 0x481E, 0x41B6, { 0x95, 0xE8, 0x12, 0x7F, 0x4C, 0x98, 0x47, 0x79 } }
extern GUID gTianoCustomDecompressGuid;
#endif // #ifndef _EFI_CAPSULE_VENDOR_GUID_H_

View File

@ -34,6 +34,7 @@
gEfiPciHotplugDeviceGuid = { 0x0B280816, 0x52E7, 0x4E51, { 0xAA, 0x57, 0x11, 0xBD, 0x41, 0xCB, 0xEF, 0xC3 }}
gEfiIntelFrameworkModulePkgTokenSpaceGuid = { 0xD3705011, 0xBC19, 0x4af7, { 0xBE, 0x16, 0xF6, 0x80, 0x30, 0x37, 0x8C, 0x15 }}
gTianoCustomDecompressGuid = { 0xA31280AD, 0x481E, 0x41B6, { 0x95, 0xE8, 0x12, 0x7F, 0x4C, 0x98, 0x47, 0x79 }}
[Protocols.common]
gEfiPciHotPlugRequestProtocolGuid = { 0x19CB87AB, 0x2CB9, 0x4665, { 0x83, 0x60, 0xDD, 0xCF, 0x60, 0x54, 0xF7, 0x9D }}

View File

@ -12,6 +12,7 @@ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
**/
#include <Guid/CustomDecompress.h>
#include "BaseUefiTianoCustomDecompressLibInternals.h"
VOID
@ -775,6 +776,7 @@ Returns:
RETURN_STATUS
EFIAPI
CustomDecompressGetInfo (
IN CONST GUID *DecompressGuid,
IN CONST VOID *Source,
IN UINT32 SourceSize,
OUT UINT32 *DestinationSize,
@ -787,7 +789,7 @@ Routine Description:
The internal implementation of *_DECOMPRESS_PROTOCOL.GetInfo().
Arguments:
DecompressGuid The guid matches this decompress method.
Source - The source buffer containing the compressed data.
SourceSize - The size of source buffer
DestinationSize - The size of destination buffer.
@ -797,15 +799,21 @@ Returns:
RETURN_SUCCESS - The size of destination buffer and the size of scratch buffer are successull retrieved.
RETURN_INVALID_PARAMETER - The source data is corrupted
RETURN_UNSUPPORTED - Decompress method is not supported.
--*/
{
return UefiDecompressGetInfo (Source, SourceSize, DestinationSize, ScratchSize);
if (CompareGuid (DecompressGuid, &gTianoCustomDecompressGuid)) {
return UefiDecompressGetInfo (Source, SourceSize, DestinationSize, ScratchSize);
} else {
return RETURN_UNSUPPORTED;
}
}
RETURN_STATUS
EFIAPI
CustomDecompress (
IN CONST GUID *DecompressGuid,
IN CONST VOID *Source,
IN OUT VOID *Destination,
IN OUT VOID *Scratch
@ -817,7 +825,7 @@ Routine Description:
The internal implementation of *_DECOMPRESS_PROTOCOL.Decompress().
Arguments:
DecompressGuid The guid matches this decompress method.
Source - The source buffer containing the compressed data.
Destination - The destination buffer to store the decompressed data
Scratch - The buffer used internally by the decompress routine. This buffer is needed to store intermediate data.
@ -826,8 +834,50 @@ Returns:
RETURN_SUCCESS - Decompression is successfull
RETURN_INVALID_PARAMETER - The source data is corrupted
RETURN_UNSUPPORTED - Decompress method is not supported.
--*/
{
return UefiTianoDecompress (Source, Destination, Scratch, 2);
if (CompareGuid (DecompressGuid, &gTianoCustomDecompressGuid)) {
return UefiTianoDecompress (Source, Destination, Scratch, 2);
} else {
return RETURN_UNSUPPORTED;
}
}
/**
Get decompress method guid list.
@param[in, out] AlgorithmGuidTable The decompress method guid list.
@param[in, out] NumberOfAlgorithms The number of decompress methods.
@retval RETURN_SUCCESS Get all algorithmes list successfully.
@retval RETURN_INVALID_PARAMETER Input paramter error.
@retval RETURN_OUT_OF_RESOURCES Source is not enough.
**/
RETURN_STATUS
EFIAPI
CustomDecompressGetAlgorithms (
IN OUT GUID **AlgorithmGuidTable,
IN OUT UINTN *NumberOfAlgorithms
)
{
if (NumberOfAlgorithms == NULL) {
return RETURN_INVALID_PARAMETER;
}
if (*NumberOfAlgorithms < 1) {
*NumberOfAlgorithms = 1;
return RETURN_OUT_OF_RESOURCES;
}
if (AlgorithmGuidTable == NULL) {
return RETURN_INVALID_PARAMETER;
}
AlgorithmGuidTable [0] = &gTianoCustomDecompressGuid;
*NumberOfAlgorithms = 1;
return RETURN_SUCCESS;
}

View File

@ -24,7 +24,6 @@
EDK_RELEASE_VERSION = 0x00020000
EFI_SPECIFICATION_VERSION = 0x00020000
#
# The following information is for reference only and not required by the build tools.
#
@ -38,8 +37,12 @@
[Packages]
MdePkg/MdePkg.dec
IntelFrameworkModulePkg/IntelFrameworkModulePkg.dec
[LibraryClasses]
BaseMemoryLib
DebugLib
[Guids]
gTianoCustomDecompressGuid

View File

@ -79,6 +79,7 @@
CacheMaintenanceLib
PeCoffLoaderLib
UefiDecompressLib
CustomDecompressLib
PerformanceLib
HobLib
BaseLib

View File

@ -212,7 +212,15 @@ IsValidSectionStream (
IN VOID *SectionStream,
IN UINTN SectionStreamLength
);
EFI_STATUS
CustomDecompressExtractSection (
IN CONST EFI_GUIDED_SECTION_EXTRACTION_PROTOCOL *This,
IN CONST VOID *InputSection,
OUT VOID **OutputBuffer,
OUT UINTN *OutputSize,
OUT UINT32 *AuthenticationStatus
);
//
// Module globals
//
@ -226,6 +234,9 @@ EFI_SECTION_EXTRACTION_PROTOCOL mSectionExtraction = {
CloseSectionStream
};
EFI_GUIDED_SECTION_EXTRACTION_PROTOCOL mCustomDecompressExtraction = {
CustomDecompressExtractSection
};
EFI_STATUS
EFIAPI
@ -250,6 +261,8 @@ Returns:
--*/
{
EFI_STATUS Status;
EFI_GUID **DecompressGuidList;
UINT32 DecompressMethodNumber;
//
// Install SEP to a new handle
@ -262,6 +275,34 @@ Returns:
);
ASSERT_EFI_ERROR (Status);
//
// Get custom decompress method guid list
//
DecompressGuidList = NULL;
DecompressMethodNumber = 0;
Status = CustomDecompressGetAlgorithms (DecompressGuidList, &DecompressMethodNumber);
if (Status == EFI_OUT_OF_RESOURCES) {
DecompressGuidList = (EFI_GUID **) CoreAllocateBootServicesPool (DecompressMethodNumber * sizeof (EFI_GUID *));
ASSERT (DecompressGuidList != NULL);
Status = CustomDecompressGetAlgorithms (DecompressGuidList, &DecompressMethodNumber);
}
ASSERT_EFI_ERROR(Status);
//
// Install custom decompress guided extraction protocol
//
while (DecompressMethodNumber-- > 0) {
Status = CoreInstallProtocolInterface (
&mSectionExtractionHandle,
DecompressGuidList [DecompressMethodNumber],
EFI_NATIVE_INTERFACE,
&mCustomDecompressExtraction
);
ASSERT_EFI_ERROR (Status);
}
CoreFreePool (DecompressGuidList);
return Status;
}
@ -742,7 +783,7 @@ Returns:
EFI_COMMON_SECTION_HEADER *SectionHeader;
EFI_COMPRESSION_SECTION *CompressionHeader;
EFI_GUID_DEFINED_SECTION *GuidedHeader;
EFI_TIANO_DECOMPRESS_PROTOCOL *Decompress;
EFI_DECOMPRESS_PROTOCOL *Decompress;
EFI_GUIDED_SECTION_EXTRACTION_PROTOCOL *GuidedExtraction;
VOID *NewStreamBuffer;
VOID *ScratchBuffer;
@ -1339,3 +1380,168 @@ Returns:
ASSERT (FALSE);
return FALSE;
}
/**
The ExtractSection() function processes the input section and
allocates a buffer from the pool in which it returns the section
contents. If the section being extracted contains
authentication information (the section's
GuidedSectionHeader.Attributes field has the
EFI_GUIDED_SECTION_AUTH_STATUS_VALID bit set), the values
returned in AuthenticationStatus must reflect the results of
the authentication operation. Depending on the algorithm and
size of the encapsulated data, the time that is required to do
a full authentication may be prohibitively long for some
classes of systems. To indicate this, use
EFI_SECURITY_POLICY_PROTOCOL_GUID, which may be published by
the security policy driver (see the Platform Initialization
Driver Execution Environment Core Interface Specification for
more details and the GUID definition). If the
EFI_SECURITY_POLICY_PROTOCOL_GUID exists in the handle
database, then, if possible, full authentication should be
skipped and the section contents simply returned in the
OutputBuffer. In this case, the
EFI_AUTH_STATUS_PLATFORM_OVERRIDE bit AuthenticationStatus
must be set on return. ExtractSection() is callable only from
TPL_NOTIFY and below. Behavior of ExtractSection() at any
EFI_TPL above TPL_NOTIFY is undefined. Type EFI_TPL is
defined in RaiseTPL() in the UEFI 2.0 specification.
@param This Indicates the
EFI_GUIDED_SECTION_EXTRACTION_PROTOCOL instance.
@param InputSection Buffer containing the input GUIDed section
to be processed. OutputBuffer OutputBuffer
is allocated from boot services pool
memory and contains the new section
stream. The caller is responsible for
freeing this buffer.
@param OutputSize A pointer to a caller-allocated UINTN in
which the size of OutputBuffer allocation
is stored. If the function returns
anything other than EFI_SUCCESS, the value
of OutputSize is undefined.
@param AuthenticationStatus A pointer to a caller-allocated
UINT32 that indicates the
authentication status of the
output buffer. If the input
section's
GuidedSectionHeader.Attributes
field has the
EFI_GUIDED_SECTION_AUTH_STATUS_VAL
bit as clear, AuthenticationStatus
must return zero. Both local bits
(19:16) and aggregate bits (3:0)
in AuthenticationStatus are
returned by ExtractSection().
These bits reflect the status of
the extraction operation. The bit
pattern in both regions must be
the same, as the local and
aggregate authentication statuses
have equivalent meaning at this
level. If the function returns
anything other than EFI_SUCCESS,
the value of AuthenticationStatus
is undefined.
@retval EFI_SUCCESS The InputSection was successfully
processed and the section contents were
returned.
@retval EFI_OUT_OF_RESOURCES The system has insufficient
resources to process the
request.
@retval EFI_INVALID_PARAMETER The GUID in InputSection does
not match this instance of the
GUIDed Section Extraction
Protocol.
**/
EFI_STATUS
CustomDecompressExtractSection (
IN CONST EFI_GUIDED_SECTION_EXTRACTION_PROTOCOL *This,
IN CONST VOID *InputSection,
OUT VOID **OutputBuffer,
OUT UINTN *OutputSize,
OUT UINT32 *AuthenticationStatus
)
{
EFI_STATUS Status;
UINT8 *ScratchBuffer;
UINT32 ScratchSize;
UINT32 SectionLength;
//
// Set authentic value to zero.
//
*AuthenticationStatus = 0;
//
// Calculate Section data Size
//
SectionLength = *(UINT32 *) (((EFI_COMMON_SECTION_HEADER *) InputSection)->Size) & 0x00ffffff;
//
// Get compressed data information
//
Status = CustomDecompressGetInfo (
(GUID *) ((UINT8 *) InputSection + sizeof (EFI_COMMON_SECTION_HEADER)),
(UINT8 *) InputSection + sizeof (EFI_GUID_DEFINED_SECTION),
SectionLength - sizeof (EFI_GUID_DEFINED_SECTION),
OutputSize,
&ScratchSize
);
if (EFI_ERROR (Status)) {
//
// GetInfo failed
//
DEBUG ((EFI_D_ERROR, "Extract guided section Failed - %r\n", Status));
return Status;
}
//
// Allocate scratch buffer
//
ScratchBuffer = CoreAllocateBootServicesPool (ScratchSize);
if (ScratchBuffer == NULL) {
return EFI_OUT_OF_RESOURCES;
}
//
// Allocate destination buffer
//
*OutputBuffer = CoreAllocateBootServicesPool (*OutputSize);
if (*OutputBuffer == NULL) {
CoreFreePool (ScratchBuffer);
return EFI_OUT_OF_RESOURCES;
}
//
// Call decompress function
//
Status = CustomDecompress (
(GUID *) ((UINT8 *) InputSection + sizeof (EFI_COMMON_SECTION_HEADER)),
(UINT8 *) InputSection + sizeof (EFI_GUID_DEFINED_SECTION),
*OutputBuffer,
ScratchBuffer
);
if (EFI_ERROR (Status)) {
//
// Decompress failed
//
CoreFreePool (ScratchBuffer);
CoreFreePool (*OutputBuffer);
DEBUG ((EFI_D_ERROR, "Extract guided section Failed - %r\n", Status));
return Status;
}
//
// Free unused scratch buffer.
//
CoreFreePool (ScratchBuffer);
return EFI_SUCCESS;
}

View File

@ -1,47 +0,0 @@
/*++
Copyright (c) 2006, Intel Corporation
All rights reserved. This program and the accompanying materials
are licensed and made available under the terms and conditions of the BSD License
which accompanies this distribution. The full text of the license may be found at
http://opensource.org/licenses/bsd-license.php
THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
Module Name:
DecompressLibraryHob.h
Abstract:
Declaration of HOB that is used to pass decompressor library functions from PEI to DXE
--*/
#ifndef __DECOMPRESS_LIBRARY_H__
#define __DECOMPRESS_LIBRARY_H__
typedef
RETURN_STATUS
(EFIAPI *DECOMPRESS_LIBRARY_GET_INFO) (
IN CONST VOID *Source,
IN UINT32 SourceSize,
OUT UINT32 *DestinationSize,
OUT UINT32 *ScratchSize
);
typedef
RETURN_STATUS
(EFIAPI *DECOMPRESS_LIBRARY_DECOMPRESS) (
IN CONST VOID *Source,
IN OUT VOID *Destination,
IN OUT VOID *Scratch
);
typedef struct {
DECOMPRESS_LIBRARY_GET_INFO GetInfo;
DECOMPRESS_LIBRARY_DECOMPRESS Decompress;
} DECOMPRESS_LIBRARY;
#endif

View File

@ -59,7 +59,7 @@ extern BOOLEAN gInMemory;
EFI_STATUS
PeiFindFile (
IN UINT8 Type,
IN UINT16 SectionType,
IN EFI_SECTION_TYPE SectionType,
OUT EFI_GUID *FileName,
OUT VOID **Pe32Data
)
@ -124,7 +124,7 @@ HandOffToDxeCore (
EFI_STATUS
PeiProcessFile (
IN UINT16 SectionType,
IN EFI_SECTION_TYPE SectionType,
IN EFI_FFS_FILE_HEADER *FfsFileHeader,
OUT VOID **Pe32Data,
IN EFI_PEI_HOB_POINTERS *OrigHob

View File

@ -21,12 +21,21 @@ Abstract:
--*/
#include "DxeIpl.h"
#include <Ppi/GuidedSectionExtraction.h>
// porting note remove later
#include "DecompressLibrary.h"
#include "FrameworkPei.h"
// end of remove later
EFI_STATUS
CustomDecompressExtractSection (
IN CONST EFI_PEI_GUIDED_SECTION_EXTRACTION_PPI *This,
IN CONST VOID *InputSection,
OUT VOID **OutputBuffer,
OUT UINTN *OutputSize,
OUT UINT32 *AuthenticationStatus
);
BOOLEAN gInMemory = FALSE;
//
@ -41,6 +50,10 @@ static EFI_PEI_FV_FILE_LOADER_PPI mLoadFilePpi = {
DxeIplLoadFile
};
static EFI_PEI_GUIDED_SECTION_EXTRACTION_PPI mCustomDecompressExtractiongPpi = {
CustomDecompressExtractSection
};
static EFI_PEI_PPI_DESCRIPTOR mPpiList[] = {
{
EFI_PEI_PPI_DESCRIPTOR_PPI,
@ -60,16 +73,6 @@ static EFI_PEI_PPI_DESCRIPTOR mPpiSignal = {
NULL
};
GLOBAL_REMOVE_IF_UNREFERENCED DECOMPRESS_LIBRARY gEfiDecompress = {
UefiDecompressGetInfo,
UefiDecompress
};
GLOBAL_REMOVE_IF_UNREFERENCED DECOMPRESS_LIBRARY gCustomDecompress = {
CustomDecompressGetInfo,
CustomDecompress
};
EFI_STATUS
EFIAPI
PeimInitializeDxeIpl (
@ -96,7 +99,10 @@ Returns:
EFI_STATUS Status;
EFI_PEI_PE_COFF_LOADER_PROTOCOL *PeiEfiPeiPeCoffLoader;
EFI_BOOT_MODE BootMode;
EFI_GUID **DecompressGuidList;
UINT32 DecompressMethodNumber;
EFI_PEI_PPI_DESCRIPTOR *GuidPpi;
Status = PeiServicesGetBootMode (&BootMode);
ASSERT_EFI_ERROR (Status);
@ -111,6 +117,35 @@ Returns:
//
Status = ShadowDxeIpl (FfsHeader, PeiEfiPeiPeCoffLoader);
} else {
//
// Get custom decompress method guid list
//
DecompressGuidList = NULL;
DecompressMethodNumber = 0;
Status = CustomDecompressGetAlgorithms (DecompressGuidList, &DecompressMethodNumber);
if (Status == EFI_OUT_OF_RESOURCES) {
DecompressGuidList = (EFI_GUID **) AllocatePages (EFI_SIZE_TO_PAGES (DecompressMethodNumber * sizeof (EFI_GUID *)));
ASSERT (DecompressGuidList != NULL);
Status = CustomDecompressGetAlgorithms (DecompressGuidList, &DecompressMethodNumber);
}
ASSERT_EFI_ERROR(Status);
//
// Install custom decompress extraction guid ppi
//
if (DecompressMethodNumber > 0) {
GuidPpi = NULL;
GuidPpi = (EFI_PEI_PPI_DESCRIPTOR *) AllocatePages (EFI_SIZE_TO_PAGES (DecompressMethodNumber * sizeof (EFI_PEI_PPI_DESCRIPTOR)));
ASSERT (GuidPpi != NULL);
while (DecompressMethodNumber-- > 0) {
GuidPpi->Flags = EFI_PEI_PPI_DESCRIPTOR_PPI | EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST;
GuidPpi->Ppi = &mCustomDecompressExtractiongPpi;
GuidPpi->Guid = DecompressGuidList [DecompressMethodNumber];
Status = PeiServicesInstallPpi (GuidPpi++);
ASSERT_EFI_ERROR(Status);
}
}
//
// Install FvFileLoader and DxeIpl PPIs.
//
@ -205,7 +240,6 @@ Returns:
PeiEfiPeiPeCoffLoader = (EFI_PEI_PE_COFF_LOADER_PROTOCOL *)GetPeCoffLoaderProtocol ();
ASSERT (PeiEfiPeiPeCoffLoader != NULL);
//
// Find the EFI_FV_FILETYPE_FIRMWARE_VOLUME_IMAGE type compressed Firmware Volume file
// The file found will be processed by PeiProcessFile: It will first be decompressed to
@ -252,6 +286,14 @@ Returns:
);
//
// Add HOB for the PE/COFF Loader Protocol
//
BuildGuidDataHob (
&gEfiPeiPeCoffLoaderGuid,
(VOID *)&PeiEfiPeiPeCoffLoader,
sizeof (VOID *)
);
//
// Report Status Code EFI_SW_PEI_PC_HANDOFF_TO_NEXT
//
REPORT_STATUS_CODE (
@ -259,38 +301,6 @@ Returns:
EFI_SOFTWARE_PEI_MODULE | EFI_SW_PEI_CORE_PC_HANDOFF_TO_NEXT
);
if (FeaturePcdGet (PcdDxeIplBuildShareCodeHobs)) {
if (FeaturePcdGet (PcdDxeIplSupportEfiDecompress)) {
//
// Add HOB for the EFI Decompress Protocol
//
BuildGuidDataHob (
&gEfiDecompressProtocolGuid,
(VOID *)&gEfiDecompress,
sizeof (gEfiDecompress)
);
}
if (FeaturePcdGet (PcdDxeIplSupportCustomDecompress)) {
//
// Add HOB for the user customized Decompress Protocol
//
BuildGuidDataHob (
&gEfiCustomizedDecompressProtocolGuid,
(VOID *)&gCustomDecompress,
sizeof (gCustomDecompress)
);
}
//
// Add HOB for the PE/COFF Loader Protocol
//
BuildGuidDataHob (
&gEfiPeiPeCoffLoaderGuid,
(VOID *)&PeiEfiPeiPeCoffLoader,
sizeof (VOID *)
);
}
//
// Transfer control to the DXE Core
// The handoff state is simply a pointer to the HOB list
@ -311,7 +321,7 @@ Returns:
EFI_STATUS
PeiFindFile (
IN UINT8 Type,
IN UINT16 SectionType,
IN EFI_SECTION_TYPE SectionType,
OUT EFI_GUID *FileName,
OUT VOID **Pe32Data
)
@ -609,7 +619,7 @@ Returns:
EFI_STATUS
PeiProcessFile (
IN UINT16 SectionType,
IN EFI_SECTION_TYPE SectionType,
IN EFI_FFS_FILE_HEADER *FfsFileHeader,
OUT VOID **Pe32Data,
IN EFI_PEI_HOB_POINTERS *OrigHob
@ -635,8 +645,6 @@ Returns:
--*/
{
EFI_STATUS Status;
VOID *SectionData;
DECOMPRESS_LIBRARY *DecompressLibrary;
UINT8 *DstBuffer;
UINT8 *ScratchBuffer;
UINT32 DstBufferSize;
@ -649,327 +657,367 @@ Returns:
EFI_COMMON_SECTION_HEADER *Section;
UINTN SectionLength;
UINTN OccupiedSectionLength;
UINT64 FileSize;
UINT32 AuthenticationStatus;
EFI_PEI_SECTION_EXTRACTION_PPI *SectionExtract;
UINT32 BufferSize;
UINT8 *Buffer;
EFI_PEI_SECURITY_PPI *Security;
BOOLEAN StartCrisisRecovery;
EFI_GUID TempGuid;
UINTN FileSize;
EFI_FIRMWARE_VOLUME_HEADER *FvHeader;
EFI_COMPRESSION_SECTION *CompressionSection;
EFI_PEI_GUIDED_SECTION_EXTRACTION_PPI *SectionExtract;
UINT32 AuthenticationStatus;
//
// Initialize local variables.
// First try to find the required section in this ffs file.
//
DecompressLibrary = NULL;
DstBuffer = NULL;
DstBufferSize = 0;
Status = PeiServicesFfsFindSectionData (
EFI_SECTION_COMPRESSION,
SectionType,
FfsFileHeader,
&SectionData
Pe32Data
);
//
// First process the compression section
//
if (!EFI_ERROR (Status)) {
return Status;
}
//
// If not found, the required section may be in guided or compressed section.
// So, search guided or compressed section to process
//
Section = (EFI_COMMON_SECTION_HEADER *) (UINTN) (VOID *) ((UINT8 *) (FfsFileHeader) + (UINTN) sizeof (EFI_FFS_FILE_HEADER));
FileSize = FfsFileHeader->Size[0] & 0xFF;
FileSize += (FfsFileHeader->Size[1] << 8) & 0xFF00;
FileSize += (FfsFileHeader->Size[2] << 16) & 0xFF0000;
FileSize &= 0x00FFFFFF;
OccupiedSectionLength = 0;
do {
//
// Yes, there is a compression section, so extract the contents
// Decompress the image here
// Initialize local variables.
//
Section = (EFI_COMMON_SECTION_HEADER *) (UINTN) (VOID *) ((UINT8 *) (FfsFileHeader) + (UINTN) sizeof (EFI_FFS_FILE_HEADER));
DstBuffer = NULL;
DstBufferSize = 0;
do {
SectionLength = *(UINT32 *) (Section->Size) & 0x00ffffff;
OccupiedSectionLength = GET_OCCUPIED_SIZE (SectionLength, 4);
Section = (EFI_COMMON_SECTION_HEADER *) ((UINT8 *) Section + OccupiedSectionLength);
SectionLength = *(UINT32 *) (Section->Size) & 0x00ffffff;
OccupiedSectionLength = GET_OCCUPIED_SIZE (SectionLength, 4);
//
// Was the DXE Core file encapsulated in a GUID'd section?
//
if (Section->Type == EFI_SECTION_GUID_DEFINED) {
//
// Was the DXE Core file encapsulated in a GUID'd section?
// Set a default authenticatino state
//
if (Section->Type == EFI_SECTION_GUID_DEFINED) {
AuthenticationStatus = 0;
//
// Locate extract guid section ppi
//
Status = PeiServicesLocatePpi (
(EFI_GUID *) (Section + 1),
0,
NULL,
(VOID **)&SectionExtract
);
if (EFI_ERROR (Status)) {
//
// This following code constitutes the addition of the security model
// to the DXE IPL.
// ignore the unknown guid section
//
//
// Set a default authenticatino state
//
AuthenticationStatus = 0;
Status = PeiServicesLocatePpi (
&gEfiPeiSectionExtractionPpiGuid,
0,
NULL,
(VOID **)&SectionExtract
);
if (EFI_ERROR (Status)) {
return Status;
}
//
// Verify Authentication State
//
CopyMem (&TempGuid, Section + 1, sizeof (EFI_GUID));
Status = SectionExtract->PeiGetSection (
GetPeiServicesTablePointer(),
SectionExtract,
(EFI_SECTION_TYPE *) &SectionType,
&TempGuid,
0,
(VOID **) &Buffer,
&BufferSize,
&AuthenticationStatus
);
if (EFI_ERROR (Status)) {
return Status;
}
//
// If not ask the Security PPI, if exists, for disposition
//
//
Status = PeiServicesLocatePpi (
&gEfiPeiSecurityPpiGuid,
0,
NULL,
(VOID **)&Security
);
if (EFI_ERROR (Status)) {
return Status;
}
Status = Security->AuthenticationState (
GetPeiServicesTablePointer(),
(struct _EFI_PEI_SECURITY_PPI *) Security,
AuthenticationStatus,
FfsFileHeader,
&StartCrisisRecovery
);
if (EFI_ERROR (Status)) {
return Status;
}
//
// If there is a security violation, report to caller and have
// the upper-level logic possible engender a crisis recovery
//
if (StartCrisisRecovery) {
return EFI_SECURITY_VIOLATION;
}
continue;
}
//
// Extract the contents from guid section
//
Status = SectionExtract->ExtractSection (
SectionExtract,
(VOID *) Section,
(VOID **) &DstBuffer,
&DstBufferSize,
&AuthenticationStatus
);
if (Section->Type == EFI_SECTION_PE32) {
if (EFI_ERROR (Status)) {
DEBUG ((EFI_D_ERROR, "Extract section content failed - %r\n", Status));
return Status;
}
//
// Todo check AuthenticationStatus and do the verify
//
} else if (Section->Type == EFI_SECTION_COMPRESSION) {
//
// This is a compression set, expand it
//
CompressionSection = (EFI_COMPRESSION_SECTION *) Section;
switch (CompressionSection->CompressionType) {
case EFI_STANDARD_COMPRESSION:
//
// Load EFI standard compression.
// For compressed data, decompress them to dstbuffer.
//
Status = UefiDecompressGetInfo (
(UINT8 *) ((EFI_COMPRESSION_SECTION *) Section + 1),
(UINT32) SectionLength - sizeof (EFI_COMPRESSION_SECTION),
&DstBufferSize,
&ScratchBufferSize
);
if (EFI_ERROR (Status)) {
//
// GetInfo failed
//
DEBUG ((EFI_D_ERROR, "Decompress GetInfo Failed - %r\n", Status));
return EFI_NOT_FOUND;
}
//
// Allocate scratch buffer
//
ScratchBuffer = AllocatePages (EFI_SIZE_TO_PAGES (ScratchBufferSize));
if (ScratchBuffer == NULL) {
return EFI_OUT_OF_RESOURCES;
}
//
// Allocate destination buffer
//
DstBuffer = AllocatePages (EFI_SIZE_TO_PAGES (DstBufferSize));
if (DstBuffer == NULL) {
return EFI_OUT_OF_RESOURCES;
}
//
// Call decompress function
//
Status = UefiDecompress (
(CHAR8 *) ((EFI_COMPRESSION_SECTION *) Section + 1),
DstBuffer,
ScratchBuffer
);
if (EFI_ERROR (Status)) {
//
// Decompress failed
//
DEBUG ((EFI_D_ERROR, "Decompress Failed - %r\n", Status));
return EFI_NOT_FOUND;
}
break;
// porting note the original branch for customized compress is removed, it should be change to use GUID compress
case EFI_NOT_COMPRESSED:
//
// Allocate destination buffer
//
DstBufferSize = CompressionSection->UncompressedLength;
DstBuffer = AllocatePages (EFI_SIZE_TO_PAGES (DstBufferSize));
if (DstBuffer == NULL) {
return EFI_OUT_OF_RESOURCES;
}
//
// stream is not actually compressed, just encapsulated. So just copy it.
//
CopyMem (DstBuffer, CompressionSection + 1, DstBufferSize);
break;
default:
//
// Don't support other unknown compression type.
//
ASSERT_EFI_ERROR (Status);
return EFI_NOT_FOUND;
}
} else {
//
// ignore other type sections
//
continue;
}
//
// Extract contents from guided or compressed sections.
// Loop the decompressed data searching for expected section.
//
CmpSection = (EFI_COMMON_SECTION_HEADER *) DstBuffer;
CmpFileData = (VOID *) DstBuffer;
CmpFileSize = DstBufferSize;
do {
CmpSectionLength = *(UINT32 *) (CmpSection->Size) & 0x00ffffff;
if (CmpSection->Type == SectionType) {
//
// This is what we want
//
*Pe32Data = (VOID *) (Section + 1);
return EFI_SUCCESS;
} else if (Section->Type == EFI_SECTION_COMPRESSION) {
//
// This is a compression set, expand it
//
CompressionSection = (EFI_COMPRESSION_SECTION *) Section;
if (SectionType == EFI_SECTION_FIRMWARE_VOLUME_IMAGE) {
//
// Firmware Volume Image in this Section
// Skip the section header to get FvHeader
//
FvHeader = (EFI_FIRMWARE_VOLUME_HEADER *) (CmpSection + 1);
switch (CompressionSection->CompressionType) {
case EFI_STANDARD_COMPRESSION:
//
// Load EFI standard compression.
//
if (FeaturePcdGet (PcdDxeIplSupportTianoDecompress)) {
DecompressLibrary = &gEfiDecompress;
} else {
ASSERT (FALSE);
return EFI_NOT_FOUND;
}
break;
// porting note the original branch for customized compress is removed, it should be change to use GUID compress
case EFI_NOT_COMPRESSED:
//
// Allocate destination buffer
//
DstBufferSize = CompressionSection->UncompressedLength;
DstBuffer = AllocatePages (EFI_SIZE_TO_PAGES (DstBufferSize));
if (DstBuffer == NULL) {
return EFI_OUT_OF_RESOURCES;
}
//
// stream is not actually compressed, just encapsulated. So just copy it.
//
CopyMem (DstBuffer, CompressionSection + 1, DstBufferSize);
break;
default:
//
// Don't support other unknown compression type.
//
ASSERT_EFI_ERROR (Status);
return EFI_NOT_FOUND;
}
if (CompressionSection->CompressionType != EFI_NOT_COMPRESSED) {
//
// For compressed data, decompress them to dstbuffer.
//
Status = DecompressLibrary->GetInfo (
(UINT8 *) ((EFI_COMPRESSION_SECTION *) Section + 1),
(UINT32) SectionLength - sizeof (EFI_COMPRESSION_SECTION),
&DstBufferSize,
&ScratchBufferSize
);
if (EFI_ERROR (Status)) {
if (FvHeader->Signature == EFI_FVH_SIGNATURE) {
//
// GetInfo failed
// Because FvLength in FvHeader is UINT64 type,
// so FvHeader must meed at least 8 bytes alignment.
// If current FvImage base address doesn't meet its alignment,
// we need to reload this FvImage to another correct memory address.
//
DEBUG ((EFI_D_ERROR, "Decompress GetInfo Failed - %r\n", Status));
return EFI_NOT_FOUND;
}
//
// Allocate scratch buffer
//
ScratchBuffer = AllocatePages (EFI_SIZE_TO_PAGES (ScratchBufferSize));
if (ScratchBuffer == NULL) {
return EFI_OUT_OF_RESOURCES;
}
//
// Allocate destination buffer
//
DstBuffer = AllocatePages (EFI_SIZE_TO_PAGES (DstBufferSize));
if (DstBuffer == NULL) {
return EFI_OUT_OF_RESOURCES;
}
//
// Call decompress function
//
Status = DecompressLibrary->Decompress (
(CHAR8 *) ((EFI_COMPRESSION_SECTION *) Section + 1),
DstBuffer,
ScratchBuffer
);
if (EFI_ERROR (Status)) {
//
// Decompress failed
//
DEBUG ((EFI_D_ERROR, "Decompress Failed - %r\n", Status));
return EFI_NOT_FOUND;
}
}
//
// Decompress successfully.
// Loop the decompressed data searching for expected section.
//
CmpSection = (EFI_COMMON_SECTION_HEADER *) DstBuffer;
CmpFileData = (VOID *) DstBuffer;
CmpFileSize = DstBufferSize;
do {
CmpSectionLength = *(UINT32 *) (CmpSection->Size) & 0x00ffffff;
if (CmpSection->Type == SectionType) {
//
// This is what we want
//
if (SectionType == EFI_SECTION_PE32) {
*Pe32Data = (VOID *) (CmpSection + 1);
return EFI_SUCCESS;
} else if (SectionType == EFI_SECTION_FIRMWARE_VOLUME_IMAGE) {
//
// Firmware Volume Image in this Section
// Skip the section header to get FvHeader
//
FvHeader = (EFI_FIRMWARE_VOLUME_HEADER *) (CmpSection + 1);
if (FvHeader->Signature == EFI_FVH_SIGNATURE) {
//
// Because FvLength in FvHeader is UINT64 type,
// so FvHeader must meed at least 8 bytes alignment.
// If current FvImage base address doesn't meet its alignment,
// we need to reload this FvImage to another correct memory address.
//
if (((UINTN) FvHeader % sizeof (UINT64)) != 0) {
DstBuffer = AllocateAlignedPages (EFI_SIZE_TO_PAGES ((UINTN) CmpSectionLength - sizeof (EFI_COMMON_SECTION_HEADER)), sizeof (UINT64));
if (DstBuffer == NULL) {
return EFI_OUT_OF_RESOURCES;
}
CopyMem (DstBuffer, FvHeader, (UINTN) CmpSectionLength - sizeof (EFI_COMMON_SECTION_HEADER));
FvHeader = (EFI_FIRMWARE_VOLUME_HEADER *) DstBuffer;
}
//
// Build new FvHob for new decompressed Fv image.
//
BuildFvHob ((EFI_PHYSICAL_ADDRESS) (UINTN) FvHeader, FvHeader->FvLength);
//
// Set the original FvHob to unused.
//
if (OrigHob != NULL) {
OrigHob->Header->HobType = EFI_HOB_TYPE_UNUSED;
}
//
// return found FvImage data.
//
*Pe32Data = (VOID *) FvHeader;
return EFI_SUCCESS;
}
if (((UINTN) FvHeader % sizeof (UINT64)) != 0) {
CopyMem (DstBuffer, FvHeader, (UINTN) CmpSectionLength - sizeof (EFI_COMMON_SECTION_HEADER));
FvHeader = (EFI_FIRMWARE_VOLUME_HEADER *) DstBuffer;
}
//
// Build new FvHob for new decompressed Fv image.
//
BuildFvHob ((EFI_PHYSICAL_ADDRESS) (UINTN) FvHeader, FvHeader->FvLength);
//
// Set the original FvHob to unused.
//
if (OrigHob != NULL) {
OrigHob->Header->HobType = EFI_HOB_TYPE_UNUSED;
}
//
// return found FvImage data.
//
*Pe32Data = (VOID *) FvHeader;
return EFI_SUCCESS;
}
OccupiedCmpSectionLength = GET_OCCUPIED_SIZE (CmpSectionLength, 4);
CmpSection = (EFI_COMMON_SECTION_HEADER *) ((UINT8 *) CmpSection + OccupiedCmpSectionLength);
} while (CmpSection->Type != 0 && (UINTN) ((UINT8 *) CmpSection - (UINT8 *) CmpFileData) < CmpFileSize);
} else {
//
// direct return the found section.
//
*Pe32Data = (VOID *) (CmpSection + 1);
return EFI_SUCCESS;
}
}
//
// End of the decompression activity
//
OccupiedCmpSectionLength = GET_OCCUPIED_SIZE (CmpSectionLength, 4);
CmpSection = (EFI_COMMON_SECTION_HEADER *) ((UINT8 *) CmpSection + OccupiedCmpSectionLength);
} while (CmpSection->Type != 0 && (UINTN) ((UINT8 *) CmpSection - (UINT8 *) CmpFileData) < CmpFileSize);
} while (Section->Type != 0 && (UINTN) ((UINT8 *) Section + OccupiedSectionLength - (UINT8 *) FfsFileHeader) < FileSize);
Section = (EFI_COMMON_SECTION_HEADER *) ((UINT8 *) Section + OccupiedSectionLength);
FileSize = FfsFileHeader->Size[0] & 0xFF;
FileSize += (FfsFileHeader->Size[1] << 8) & 0xFF00;
FileSize += (FfsFileHeader->Size[2] << 16) & 0xFF0000;
FileSize &= 0x00FFFFFF;
} while (Section->Type != 0 && (UINTN) ((UINT8 *) Section - (UINT8 *) FfsFileHeader) < FileSize);
//
// search all sections (compression and non compression) in this FFS, don't
// find expected section.
//
return EFI_NOT_FOUND;
} else {
//
// For those FFS that doesn't contain compression section, directly search
// PE or TE section in this FFS.
//
Status = PeiServicesFfsFindSectionData (
EFI_SECTION_PE32,
FfsFileHeader,
&SectionData
);
if (EFI_ERROR (Status)) {
Status = PeiServicesFfsFindSectionData (
EFI_SECTION_TE,
FfsFileHeader,
&SectionData
);
if (EFI_ERROR (Status)) {
return Status;
}
}
}
*Pe32Data = SectionData;
return EFI_SUCCESS;
//
// search all sections (compression and non compression) in this FFS, don't
// find expected section.
//
return EFI_NOT_FOUND;
}
/**
The ExtractSection() function processes the input section and
returns a pointer to the section contents. If the section being
extracted does not require processing (if the section
GuidedSectionHeader.Attributes has the
EFI_GUIDED_SECTION_PROCESSING_REQUIRED field cleared), then
OutputBuffer is just updated to point to the start of the
section's contents. Otherwise, *Buffer must be allocated
from PEI permanent memory.
@param This Indicates the
EFI_PEI_GUIDED_SECTION_EXTRACTION_PPI instance.
Buffer containing the input GUIDed section to be
processed. OutputBuffer OutputBuffer is
allocated from PEI permanent memory and contains
the new section stream.
@param OutputSize A pointer to a caller-allocated
UINTN in which the size of *OutputBuffer
allocation is stored. If the function
returns anything other than EFI_SUCCESS,
the value of OutputSize is undefined.
@param AuthenticationStatus A pointer to a caller-allocated
UINT32 that indicates the
authentication status of the
output buffer. If the input
section's GuidedSectionHeader.
Attributes field has the
EFI_GUIDED_SECTION_AUTH_STATUS_VALID
bit as clear,
AuthenticationStatus must return
zero. These bits reflect the
status of the extraction
operation. If the function
returns anything other than
EFI_SUCCESS, the value of
AuthenticationStatus is
undefined.
@retval EFI_SUCCESS The InputSection was
successfully processed and the
section contents were returned.
@retval EFI_OUT_OF_RESOURCES The system has insufficient
resources to process the request.
@reteval EFI_INVALID_PARAMETER The GUID in InputSection does
not match this instance of the
GUIDed Section Extraction PPI.
**/
EFI_STATUS
CustomDecompressExtractSection (
IN CONST EFI_PEI_GUIDED_SECTION_EXTRACTION_PPI *This,
IN CONST VOID *InputSection,
OUT VOID **OutputBuffer,
OUT UINTN *OutputSize,
OUT UINT32 *AuthenticationStatus
)
{
EFI_STATUS Status;
UINT8 *ScratchBuffer;
UINT32 ScratchSize;
UINT32 SectionLength;
//
// Set authentic value to zero.
//
*AuthenticationStatus = 0;
//
// Calculate Section data Size
//
SectionLength = *(UINT32 *) (((EFI_COMMON_SECTION_HEADER *) InputSection)->Size) & 0x00ffffff;
//
// Get compressed data information
//
Status = CustomDecompressGetInfo (
(GUID *) ((UINT8 *) InputSection + sizeof (EFI_COMMON_SECTION_HEADER)),
(UINT8 *) InputSection + sizeof (EFI_GUID_DEFINED_SECTION),
SectionLength - sizeof (EFI_GUID_DEFINED_SECTION),
OutputSize,
&ScratchSize
);
if (EFI_ERROR (Status)) {
//
// GetInfo failed
//
DEBUG ((EFI_D_ERROR, "Extract guided section Failed - %r\n", Status));
return Status;
}
//
// Allocate scratch buffer
//
ScratchBuffer = AllocatePages (EFI_SIZE_TO_PAGES (ScratchSize));
if (ScratchBuffer == NULL) {
return EFI_OUT_OF_RESOURCES;
}
//
// Allocate destination buffer
//
*OutputBuffer = AllocatePages (EFI_SIZE_TO_PAGES (*OutputSize));
if (*OutputBuffer == NULL) {
return EFI_OUT_OF_RESOURCES;
}
//
// Call decompress function
//
Status = CustomDecompress (
(GUID *) ((UINT8 *) InputSection + sizeof (EFI_COMMON_SECTION_HEADER)),
(UINT8 *) InputSection + sizeof (EFI_GUID_DEFINED_SECTION),
*OutputBuffer,
ScratchBuffer
);
if (EFI_ERROR (Status)) {
//
// Decompress failed
//
DEBUG ((EFI_D_ERROR, "Extract guided section Failed - %r\n", Status));
return Status;
}
return EFI_SUCCESS;
}

View File

@ -16,21 +16,63 @@
#ifndef __CUSTOM_DECPOMPRESS_LIB_H__
#define __CUSTOM_DECPOMPRESS_LIB_H__
/**
Decompress GetInfo fucntion.
@param[in] DecompressGuid The guid matches this decompress method.
@param[in] Source The source buffer containing the compressed data.
@param[in] SourceSize The size of source buffer
@param[out] DestinationSize The size of destination buffer.
@param[out] ScratchSize The size of scratch buffer.
@retval RETURN_SUCCESS The size of destination buffer and the size of scratch buffer are successull retrieved.
@retval RETURN_INVALID_PARAMETER The source data is corrupted
**/
RETURN_STATUS
EFIAPI
CustomDecompressGetInfo (
IN CONST GUID *DecompressGuid,
IN CONST VOID *Source,
IN UINT32 SourceSize,
OUT UINT32 *DestinationSize,
OUT UINT32 *ScratchSize
);
/**
Decompress fucntion.
@param[in] DecompressGuid The guid matches this decompress method.
@param[in] Source The source buffer containing the compressed data.
@param[in] Destination The destination buffer to store the decompressed data
@param[out] Scratch The buffer used internally by the decompress routine. This buffer is needed to store intermediate data.
@retval RETURN_SUCCESS Decompression is successfull
@retval RETURN_INVALID_PARAMETER The source data is corrupted
**/
RETURN_STATUS
EFIAPI
CustomDecompress (
IN CONST VOID *Source,
IN OUT VOID *Destination,
IN OUT VOID *Scratch
IN CONST GUID *DecompressGuid,
IN CONST VOID *Source,
IN OUT VOID *Destination,
IN OUT VOID *Scratch
);
/**
Get decompress method guid list.
@param[in, out] AlgorithmGuidTable The decompress method guid list.
@param[in, out] NumberOfAlgorithms The number of decompress methods.
@retval RETURN_SUCCESS Get all algorithmes list successfully..
**/
RETURN_STATUS
EFIAPI
CustomDecompressGetAlgorithms (
IN OUT GUID **AlgorithmGuidTable,
IN OUT UINTN *NumberOfAlgorithms
);
#endif

View File

@ -31,6 +31,7 @@
RETURN_STATUS
EFIAPI
CustomDecompressGetInfo (
IN CONST GUID *DecompressGuid,
IN CONST VOID *Source,
IN UINT32 SourceSize,
OUT UINT32 *DestinationSize,
@ -56,6 +57,7 @@ CustomDecompressGetInfo (
RETURN_STATUS
EFIAPI
CustomDecompress (
IN const GUID *DecompressGuid,
IN CONST VOID *Source,
IN OUT VOID *Destination,
IN OUT VOID *Scratch
@ -63,3 +65,22 @@ CustomDecompress (
{
return RETURN_UNSUPPORTED;
}
/**
Get decompress method guid list.
@param[in, out] AlgorithmGuidTable The decompress method guid list.
@param[in, out] NumberOfAlgorithms The number of decompress methods.
@retval RETURN_SUCCESS Get all algorithmes list successfully..
**/
RETURN_STATUS
EFIAPI
CustomDecompressGetAlgorithms (
IN OUT GUID **AlgorithmGuidTable,
IN OUT UINTN *NumberOfAlgorithms
)
{
*NumberOfAlgorithms = 0;
return RETURN_SUCCESS;
}