2019-09-03 11:58:42 +02:00
|
|
|
/** @file
|
|
|
|
Section Extraction DXE Driver
|
|
|
|
|
|
|
|
Copyright (c) 2013 - 2018, Intel Corporation. All rights reserved.<BR>
|
|
|
|
SPDX-License-Identifier: BSD-2-Clause-Patent
|
|
|
|
|
|
|
|
**/
|
|
|
|
|
|
|
|
#include <PiDxe.h>
|
|
|
|
#include <Protocol/GuidedSectionExtraction.h>
|
|
|
|
#include <Library/DebugLib.h>
|
|
|
|
#include <Library/ExtractGuidedSectionLib.h>
|
|
|
|
#include <Library/MemoryAllocationLib.h>
|
|
|
|
#include <Library/BaseMemoryLib.h>
|
|
|
|
#include <Library/UefiBootServicesTableLib.h>
|
|
|
|
|
|
|
|
/**
|
|
|
|
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 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
|
|
|
|
EFIAPI
|
|
|
|
CustomGuidedSectionExtract (
|
|
|
|
IN CONST EFI_GUIDED_SECTION_EXTRACTION_PROTOCOL *This,
|
|
|
|
IN CONST VOID *InputSection,
|
|
|
|
OUT VOID **OutputBuffer,
|
|
|
|
OUT UINTN *OutputSize,
|
|
|
|
OUT UINT32 *AuthenticationStatus
|
|
|
|
);
|
|
|
|
|
|
|
|
//
|
|
|
|
// Module global for the Section Extraction Protocol handle
|
|
|
|
//
|
|
|
|
EFI_HANDLE mSectionExtractionHandle = NULL;
|
|
|
|
|
|
|
|
//
|
|
|
|
// Module global for the Section Extraction Protocol instance
|
|
|
|
//
|
|
|
|
EFI_GUIDED_SECTION_EXTRACTION_PROTOCOL mCustomGuidedSectionExtractionProtocol = {
|
|
|
|
CustomGuidedSectionExtract
|
|
|
|
};
|
|
|
|
|
|
|
|
/**
|
|
|
|
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 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
|
|
|
|
EFIAPI
|
|
|
|
CustomGuidedSectionExtract (
|
|
|
|
IN CONST EFI_GUIDED_SECTION_EXTRACTION_PROTOCOL *This,
|
|
|
|
IN CONST VOID *InputSection,
|
|
|
|
OUT VOID **OutputBuffer,
|
|
|
|
OUT UINTN *OutputSize,
|
|
|
|
OUT UINT32 *AuthenticationStatus
|
|
|
|
)
|
|
|
|
{
|
|
|
|
EFI_STATUS Status;
|
|
|
|
VOID *ScratchBuffer;
|
|
|
|
VOID *AllocatedOutputBuffer;
|
|
|
|
UINT32 OutputBufferSize;
|
|
|
|
UINT32 ScratchBufferSize;
|
|
|
|
UINT16 SectionAttribute;
|
|
|
|
|
|
|
|
//
|
|
|
|
// Init local variable
|
|
|
|
//
|
|
|
|
ScratchBuffer = NULL;
|
|
|
|
AllocatedOutputBuffer = NULL;
|
|
|
|
|
|
|
|
//
|
|
|
|
// Call GetInfo to get the size and attribute of input guided section data.
|
|
|
|
//
|
|
|
|
Status = ExtractGuidedSectionGetInfo (
|
|
|
|
InputSection,
|
|
|
|
&OutputBufferSize,
|
|
|
|
&ScratchBufferSize,
|
|
|
|
&SectionAttribute
|
|
|
|
);
|
|
|
|
|
2020-04-23 11:08:10 +02:00
|
|
|
if (EFI_ERROR(Status)) {
|
2019-09-03 11:58:42 +02:00
|
|
|
DEBUG ((DEBUG_ERROR, "GetInfo from guided section Failed - %r\n", Status));
|
|
|
|
return Status;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (ScratchBufferSize > 0) {
|
|
|
|
//
|
|
|
|
// Allocate scratch buffer
|
|
|
|
//
|
|
|
|
ScratchBuffer = AllocatePool (ScratchBufferSize);
|
|
|
|
if (ScratchBuffer == NULL) {
|
|
|
|
return EFI_OUT_OF_RESOURCES;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (OutputBufferSize > 0) {
|
|
|
|
//
|
|
|
|
// Allocate output buffer
|
|
|
|
//
|
|
|
|
AllocatedOutputBuffer = AllocatePool (OutputBufferSize);
|
|
|
|
if (AllocatedOutputBuffer == NULL) {
|
2020-04-23 11:08:10 +02:00
|
|
|
FreePool(ScratchBuffer);
|
2019-09-03 11:58:42 +02:00
|
|
|
return EFI_OUT_OF_RESOURCES;
|
|
|
|
}
|
|
|
|
*OutputBuffer = AllocatedOutputBuffer;
|
|
|
|
}
|
|
|
|
|
|
|
|
//
|
|
|
|
// Call decode function to extract raw data from the guided section.
|
|
|
|
//
|
|
|
|
Status = ExtractGuidedSectionDecode (
|
|
|
|
InputSection,
|
|
|
|
OutputBuffer,
|
|
|
|
ScratchBuffer,
|
|
|
|
AuthenticationStatus
|
|
|
|
);
|
2020-04-23 11:08:10 +02:00
|
|
|
if (EFI_ERROR(Status)) {
|
2019-09-03 11:58:42 +02:00
|
|
|
//
|
|
|
|
// Decode failed
|
|
|
|
//
|
|
|
|
if (AllocatedOutputBuffer != NULL) {
|
2020-04-23 11:08:10 +02:00
|
|
|
FreePool(AllocatedOutputBuffer);
|
2019-09-03 11:58:42 +02:00
|
|
|
}
|
|
|
|
if (ScratchBuffer != NULL) {
|
2020-04-23 11:08:10 +02:00
|
|
|
FreePool(ScratchBuffer);
|
2019-09-03 11:58:42 +02:00
|
|
|
}
|
|
|
|
DEBUG ((DEBUG_ERROR, "Extract guided section Failed - %r\n", Status));
|
|
|
|
return Status;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (*OutputBuffer != AllocatedOutputBuffer) {
|
|
|
|
//
|
|
|
|
// OutputBuffer was returned as a different value,
|
|
|
|
// so copy section contents to the allocated memory buffer.
|
|
|
|
//
|
|
|
|
CopyMem (AllocatedOutputBuffer, *OutputBuffer, OutputBufferSize);
|
|
|
|
*OutputBuffer = AllocatedOutputBuffer;
|
|
|
|
}
|
|
|
|
|
|
|
|
//
|
|
|
|
// Set real size of output buffer.
|
|
|
|
//
|
|
|
|
*OutputSize = (UINTN) OutputBufferSize;
|
|
|
|
|
|
|
|
//
|
|
|
|
// Free unused scratch buffer.
|
|
|
|
//
|
|
|
|
if (ScratchBuffer != NULL) {
|
2020-04-23 11:08:10 +02:00
|
|
|
FreePool(ScratchBuffer);
|
2019-09-03 11:58:42 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
return EFI_SUCCESS;
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
Main entry for the Section Extraction DXE module.
|
|
|
|
|
|
|
|
This routine registers the Section Extraction Protocols that have been registered
|
|
|
|
with the Section Extraction Library.
|
|
|
|
|
|
|
|
@param[in] ImageHandle The firmware allocated handle for the EFI image.
|
|
|
|
@param[in] SystemTable A pointer to the EFI System Table.
|
|
|
|
|
|
|
|
@retval EFI_SUCCESS The entry point is executed successfully.
|
|
|
|
@retval other Some error occurs when executing this entry point.
|
|
|
|
|
|
|
|
**/
|
|
|
|
EFI_STATUS
|
|
|
|
EFIAPI
|
|
|
|
SectionExtractionDxeEntry (
|
|
|
|
IN EFI_HANDLE ImageHandle,
|
|
|
|
IN EFI_SYSTEM_TABLE *SystemTable
|
|
|
|
)
|
|
|
|
{
|
|
|
|
EFI_STATUS Status;
|
|
|
|
EFI_GUID *ExtractHandlerGuidTable;
|
|
|
|
UINTN ExtractHandlerNumber;
|
|
|
|
|
|
|
|
//
|
|
|
|
// Get custom extract guided section method guid list
|
|
|
|
//
|
|
|
|
ExtractHandlerNumber = ExtractGuidedSectionGetGuidList (&ExtractHandlerGuidTable);
|
|
|
|
|
|
|
|
//
|
|
|
|
// Install custom guided extraction protocol
|
|
|
|
//
|
|
|
|
while (ExtractHandlerNumber-- > 0) {
|
|
|
|
Status = gBS->InstallMultipleProtocolInterfaces (
|
|
|
|
&mSectionExtractionHandle,
|
|
|
|
&ExtractHandlerGuidTable [ExtractHandlerNumber], &mCustomGuidedSectionExtractionProtocol,
|
|
|
|
NULL
|
|
|
|
);
|
2020-04-23 11:08:10 +02:00
|
|
|
ASSERT_EFI_ERROR(Status);
|
2019-09-03 11:58:42 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
return EFI_SUCCESS;
|
|
|
|
}
|