summaryrefslogtreecommitdiff
path: root/IntelFrameworkModulePkg/Library/LzmaCustomDecompressLib
diff options
context:
space:
mode:
authorlgao4 <lgao4@6f19259b-4bc3-4df7-8a09-765794883524>2012-03-19 07:13:29 +0000
committerlgao4 <lgao4@6f19259b-4bc3-4df7-8a09-765794883524>2012-03-19 07:13:29 +0000
commit5aab2d509403352d97809649eaad26f7f44e170c (patch)
tree5af358c8ed2eb171a648ab0070ace9229b6e8c09 /IntelFrameworkModulePkg/Library/LzmaCustomDecompressLib
parent16d2c32c4dff7fd8b0ee19e3ba908c0121f6636e (diff)
downloadedk2-platforms-5aab2d509403352d97809649eaad26f7f44e170c.tar.xz
Add LzmaArchCustomDecompressLib library instance, which supports for X86 (IA32/X64) optimized decompression. It can provide the improved compression for IA32 and X64 architecture code.
Signed-off-by: lgao4 Reviewed-by: jljusten git-svn-id: https://edk2.svn.sourceforge.net/svnroot/edk2/trunk/edk2@13111 6f19259b-4bc3-4df7-8a09-765794883524
Diffstat (limited to 'IntelFrameworkModulePkg/Library/LzmaCustomDecompressLib')
-rw-r--r--IntelFrameworkModulePkg/Library/LzmaCustomDecompressLib/F86GuidedSectionExtraction.c218
-rw-r--r--IntelFrameworkModulePkg/Library/LzmaCustomDecompressLib/LzmaArchCustomDecompressLib.inf66
-rw-r--r--IntelFrameworkModulePkg/Library/LzmaCustomDecompressLib/Sdk/C/Bra.h60
-rw-r--r--IntelFrameworkModulePkg/Library/LzmaCustomDecompressLib/Sdk/C/Bra86.c85
4 files changed, 429 insertions, 0 deletions
diff --git a/IntelFrameworkModulePkg/Library/LzmaCustomDecompressLib/F86GuidedSectionExtraction.c b/IntelFrameworkModulePkg/Library/LzmaCustomDecompressLib/F86GuidedSectionExtraction.c
new file mode 100644
index 0000000000..4f870a119b
--- /dev/null
+++ b/IntelFrameworkModulePkg/Library/LzmaCustomDecompressLib/F86GuidedSectionExtraction.c
@@ -0,0 +1,218 @@
+/** @file
+ LZMA Decompress GUIDed Section Extraction Library, which produces LZMA custom
+ decompression algorithm with the converter for the different arch code.
+ It wraps Lzma decompress interfaces to GUIDed Section Extraction interfaces
+ and registers them into GUIDed handler table.
+
+ Copyright (c) 2012, Intel Corporation. All rights reserved.<BR>
+ 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.
+
+**/
+
+#include "LzmaDecompressLibInternal.h"
+#include "Sdk/C/Bra.h"
+
+/**
+ Examines a GUIDed section and returns the size of the decoded buffer and the
+ size of an scratch buffer required to actually decode the data in a GUIDed section.
+
+ Examines a GUIDed section specified by InputSection.
+ If GUID for InputSection does not match the GUID that this handler supports,
+ then RETURN_UNSUPPORTED is returned.
+ If the required information can not be retrieved from InputSection,
+ then RETURN_INVALID_PARAMETER is returned.
+ If the GUID of InputSection does match the GUID that this handler supports,
+ then the size required to hold the decoded buffer is returned in OututBufferSize,
+ the size of an optional scratch buffer is returned in ScratchSize, and the Attributes field
+ from EFI_GUID_DEFINED_SECTION header of InputSection is returned in SectionAttribute.
+
+ If InputSection is NULL, then ASSERT().
+ If OutputBufferSize is NULL, then ASSERT().
+ If ScratchBufferSize is NULL, then ASSERT().
+ If SectionAttribute is NULL, then ASSERT().
+
+
+ @param[in] InputSection A pointer to a GUIDed section of an FFS formatted file.
+ @param[out] OutputBufferSize A pointer to the size, in bytes, of an output buffer required
+ if the buffer specified by InputSection were decoded.
+ @param[out] ScratchBufferSize A pointer to the size, in bytes, required as scratch space
+ if the buffer specified by InputSection were decoded.
+ @param[out] SectionAttribute A pointer to the attributes of the GUIDed section. See the Attributes
+ field of EFI_GUID_DEFINED_SECTION in the PI Specification.
+
+ @retval RETURN_SUCCESS The information about InputSection was returned.
+ @retval RETURN_UNSUPPORTED The section specified by InputSection does not match the GUID this handler supports.
+ @retval RETURN_INVALID_PARAMETER The information can not be retrieved from the section specified by InputSection.
+
+**/
+RETURN_STATUS
+EFIAPI
+LzmaArchGuidedSectionGetInfo (
+ IN CONST VOID *InputSection,
+ OUT UINT32 *OutputBufferSize,
+ OUT UINT32 *ScratchBufferSize,
+ OUT UINT16 *SectionAttribute
+ )
+{
+ ASSERT (InputSection != NULL);
+ ASSERT (OutputBufferSize != NULL);
+ ASSERT (ScratchBufferSize != NULL);
+ ASSERT (SectionAttribute != NULL);
+
+ if (IS_SECTION2 (InputSection)) {
+ if (!CompareGuid (
+ &gLzmaF86CustomDecompressGuid,
+ &(((EFI_GUID_DEFINED_SECTION2 *) InputSection)->SectionDefinitionGuid))) {
+ return RETURN_INVALID_PARAMETER;
+ }
+
+ *SectionAttribute = ((EFI_GUID_DEFINED_SECTION2 *) InputSection)->Attributes;
+
+ return LzmaUefiDecompressGetInfo (
+ (UINT8 *) InputSection + ((EFI_GUID_DEFINED_SECTION2 *) InputSection)->DataOffset,
+ SECTION2_SIZE (InputSection) - ((EFI_GUID_DEFINED_SECTION2 *) InputSection)->DataOffset,
+ OutputBufferSize,
+ ScratchBufferSize
+ );
+ } else {
+ if (!CompareGuid (
+ &gLzmaF86CustomDecompressGuid,
+ &(((EFI_GUID_DEFINED_SECTION *) InputSection)->SectionDefinitionGuid))) {
+ return RETURN_INVALID_PARAMETER;
+ }
+
+ *SectionAttribute = ((EFI_GUID_DEFINED_SECTION *) InputSection)->Attributes;
+
+ return LzmaUefiDecompressGetInfo (
+ (UINT8 *) InputSection + ((EFI_GUID_DEFINED_SECTION *) InputSection)->DataOffset,
+ SECTION_SIZE (InputSection) - ((EFI_GUID_DEFINED_SECTION *) InputSection)->DataOffset,
+ OutputBufferSize,
+ ScratchBufferSize
+ );
+ }
+}
+
+/**
+ Decompress a LZAM compressed GUIDed section into a caller allocated output buffer.
+
+ Decodes the GUIDed section specified by InputSection.
+ If GUID for InputSection does not match the GUID that this handler supports, then RETURN_UNSUPPORTED is returned.
+ If the data in InputSection can not be decoded, then RETURN_INVALID_PARAMETER is returned.
+ If the GUID of InputSection does match the GUID that this handler supports, then InputSection
+ is decoded into the buffer specified by OutputBuffer and the authentication status of this
+ decode operation is returned in AuthenticationStatus. If the decoded buffer is identical to the
+ data in InputSection, then OutputBuffer is set to point at the data in InputSection. Otherwise,
+ the decoded data will be placed in caller allocated buffer specified by OutputBuffer.
+
+ If InputSection is NULL, then ASSERT().
+ If OutputBuffer is NULL, then ASSERT().
+ If ScratchBuffer is NULL and this decode operation requires a scratch buffer, then ASSERT().
+ If AuthenticationStatus is NULL, then ASSERT().
+
+
+ @param[in] InputSection A pointer to a GUIDed section of an FFS formatted file.
+ @param[out] OutputBuffer A pointer to a buffer that contains the result of a decode operation.
+ @param[out] ScratchBuffer A caller allocated buffer that may be required by this function
+ as a scratch buffer to perform the decode operation.
+ @param[out] AuthenticationStatus
+ A pointer to the authentication status of the decoded output buffer.
+ See the definition of authentication status in the EFI_PEI_GUIDED_SECTION_EXTRACTION_PPI
+ section of the PI Specification. EFI_AUTH_STATUS_PLATFORM_OVERRIDE must
+ never be set by this handler.
+
+ @retval RETURN_SUCCESS The buffer specified by InputSection was decoded.
+ @retval RETURN_UNSUPPORTED The section specified by InputSection does not match the GUID this handler supports.
+ @retval RETURN_INVALID_PARAMETER The section specified by InputSection can not be decoded.
+
+**/
+RETURN_STATUS
+EFIAPI
+LzmaArchGuidedSectionExtraction (
+ IN CONST VOID *InputSection,
+ OUT VOID **OutputBuffer,
+ OUT VOID *ScratchBuffer, OPTIONAL
+ OUT UINT32 *AuthenticationStatus
+ )
+{
+ EFI_GUID *InputGuid;
+ VOID *Source;
+ UINTN SourceSize;
+ EFI_STATUS Status;
+ UINT32 X86State;
+ UINT32 OutputBufferSize;
+ UINT32 ScratchBufferSize;
+
+ ASSERT (OutputBuffer != NULL);
+ ASSERT (InputSection != NULL);
+
+ if (IS_SECTION2 (InputSection)) {
+ InputGuid = &(((EFI_GUID_DEFINED_SECTION2 *) InputSection)->SectionDefinitionGuid);
+ Source = (UINT8 *) InputSection + ((EFI_GUID_DEFINED_SECTION2 *) InputSection)->DataOffset;
+ SourceSize = SECTION2_SIZE (InputSection) - ((EFI_GUID_DEFINED_SECTION2 *) InputSection)->DataOffset;
+ } else {
+ InputGuid = &(((EFI_GUID_DEFINED_SECTION *) InputSection)->SectionDefinitionGuid);
+ Source = (UINT8 *) InputSection + ((EFI_GUID_DEFINED_SECTION *) InputSection)->DataOffset;
+ SourceSize = SECTION_SIZE (InputSection) - ((EFI_GUID_DEFINED_SECTION *) InputSection)->DataOffset;
+ }
+
+ if (!CompareGuid (&gLzmaF86CustomDecompressGuid, InputGuid)) {
+ return RETURN_INVALID_PARAMETER;
+ }
+
+ //
+ // Authentication is set to Zero, which may be ignored.
+ //
+ *AuthenticationStatus = 0;
+
+ Status = LzmaUefiDecompress (
+ Source,
+ SourceSize,
+ *OutputBuffer,
+ ScratchBuffer
+ );
+
+ //
+ // After decompress, the data need to be converted to the raw data.
+ //
+ if (!EFI_ERROR (Status)) {
+ Status = LzmaUefiDecompressGetInfo (
+ Source,
+ SourceSize,
+ &OutputBufferSize,
+ &ScratchBufferSize
+ );
+
+ if (!EFI_ERROR (Status)) {
+ x86_Convert_Init(X86State);
+ x86_Convert(*OutputBuffer, OutputBufferSize, 0, &X86State, 0);
+ }
+ }
+
+ return Status;
+}
+
+
+/**
+ Register LzmaArchDecompress and LzmaArchDecompressGetInfo handlers with LzmaF86CustomDecompressGuid.
+
+ @retval RETURN_SUCCESS Register successfully.
+ @retval RETURN_OUT_OF_RESOURCES No enough memory to store this handler.
+**/
+EFI_STATUS
+EFIAPI
+LzmaArchDecompressLibConstructor (
+ )
+{
+ return ExtractGuidedSectionRegisterHandlers (
+ &gLzmaF86CustomDecompressGuid,
+ LzmaArchGuidedSectionGetInfo,
+ LzmaArchGuidedSectionExtraction
+ );
+}
+
diff --git a/IntelFrameworkModulePkg/Library/LzmaCustomDecompressLib/LzmaArchCustomDecompressLib.inf b/IntelFrameworkModulePkg/Library/LzmaCustomDecompressLib/LzmaArchCustomDecompressLib.inf
new file mode 100644
index 0000000000..9dda21186b
--- /dev/null
+++ b/IntelFrameworkModulePkg/Library/LzmaCustomDecompressLib/LzmaArchCustomDecompressLib.inf
@@ -0,0 +1,66 @@
+## @file
+# LzmaArchCustomDecompressLib produces LZMA custom decompression algorithm
+# with the converter for the different arch code.
+#
+# It is based on the LZMA SDK 4.65.
+# LZMA SDK 4.65 was placed in the public domain on 2009-02-03.
+# It was released on the http://www.7-zip.org/sdk.html website.
+#
+# Copyright (c) 2012, Intel Corporation. All rights reserved.<BR>
+#
+# 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.
+#
+#
+##
+
+[Defines]
+ INF_VERSION = 0x00010005
+ BASE_NAME = LzmaArchDecompressLib
+ FILE_GUID = A853C1D2-E003-4cc4-9DD1-8824AD79FE48
+ MODULE_TYPE = BASE
+ VERSION_STRING = 1.0
+ LIBRARY_CLASS = NULL
+ CONSTRUCTOR = LzmaArchDecompressLibConstructor
+
+#
+# The following information is for reference only and not required by the build tools.
+#
+# VALID_ARCHITECTURES = IA32 X64
+#
+
+[Sources]
+ LzmaDecompress.c
+ Sdk/C/Bra.h
+ Sdk/C/LzFind.c
+ Sdk/C/LzmaDec.c
+ Sdk/C/7zVersion.h
+ Sdk/C/CpuArch.h
+ Sdk/C/LzFind.h
+ Sdk/C/LzHash.h
+ Sdk/C/LzmaDec.h
+ Sdk/C/Types.h
+ UefiLzma.h
+ LzmaDecompressLibInternal.h
+
+[Sources.Ia32, Sources.X64]
+ Sdk/C/Bra86.c
+ F86GuidedSectionExtraction.c
+
+[Packages]
+ MdePkg/MdePkg.dec
+ IntelFrameworkModulePkg/IntelFrameworkModulePkg.dec
+
+[Guids.Ia32, Guids.X64]
+ gLzmaF86CustomDecompressGuid ## PRODUCED ## GUID specifies LZMA custom decompress algorithm with converter for x86 code.
+
+[LibraryClasses]
+ BaseLib
+ DebugLib
+ BaseMemoryLib
+ ExtractGuidedSectionLib
+
diff --git a/IntelFrameworkModulePkg/Library/LzmaCustomDecompressLib/Sdk/C/Bra.h b/IntelFrameworkModulePkg/Library/LzmaCustomDecompressLib/Sdk/C/Bra.h
new file mode 100644
index 0000000000..b9018eb991
--- /dev/null
+++ b/IntelFrameworkModulePkg/Library/LzmaCustomDecompressLib/Sdk/C/Bra.h
@@ -0,0 +1,60 @@
+/* Bra.h -- Branch converters for executables
+2008-10-04 : Igor Pavlov : Public domain */
+
+#ifndef __BRA_H
+#define __BRA_H
+
+#include "Types.h"
+
+/*
+These functions convert relative addresses to absolute addresses
+in CALL instructions to increase the compression ratio.
+
+ In:
+ data - data buffer
+ size - size of data
+ ip - current virtual Instruction Pinter (IP) value
+ state - state variable for x86 converter
+ encoding - 0 (for decoding), 1 (for encoding)
+
+ Out:
+ state - state variable for x86 converter
+
+ Returns:
+ The number of processed bytes. If you call these functions with multiple calls,
+ you must start next call with first byte after block of processed bytes.
+
+ Type Endian Alignment LookAhead
+
+ x86 little 1 4
+ ARMT little 2 2
+ ARM little 4 0
+ PPC big 4 0
+ SPARC big 4 0
+ IA64 little 16 0
+
+ size must be >= Alignment + LookAhead, if it's not last block.
+ If (size < Alignment + LookAhead), converter returns 0.
+
+ Example:
+
+ UInt32 ip = 0;
+ for ()
+ {
+ ; size must be >= Alignment + LookAhead, if it's not last block
+ SizeT processed = Convert(data, size, ip, 1);
+ data += processed;
+ size -= processed;
+ ip += processed;
+ }
+*/
+
+#define x86_Convert_Init(state) { state = 0; }
+SizeT x86_Convert(Byte *data, SizeT size, UInt32 ip, UInt32 *state, int encoding);
+SizeT ARM_Convert(Byte *data, SizeT size, UInt32 ip, int encoding);
+SizeT ARMT_Convert(Byte *data, SizeT size, UInt32 ip, int encoding);
+SizeT PPC_Convert(Byte *data, SizeT size, UInt32 ip, int encoding);
+SizeT SPARC_Convert(Byte *data, SizeT size, UInt32 ip, int encoding);
+SizeT IA64_Convert(Byte *data, SizeT size, UInt32 ip, int encoding);
+
+#endif
diff --git a/IntelFrameworkModulePkg/Library/LzmaCustomDecompressLib/Sdk/C/Bra86.c b/IntelFrameworkModulePkg/Library/LzmaCustomDecompressLib/Sdk/C/Bra86.c
new file mode 100644
index 0000000000..93566cb212
--- /dev/null
+++ b/IntelFrameworkModulePkg/Library/LzmaCustomDecompressLib/Sdk/C/Bra86.c
@@ -0,0 +1,85 @@
+/* Bra86.c -- Converter for x86 code (BCJ)
+2008-10-04 : Igor Pavlov : Public domain */
+
+#include "Bra.h"
+
+#define Test86MSByte(b) ((b) == 0 || (b) == 0xFF)
+
+const Byte kMaskToAllowedStatus[8] = {1, 1, 1, 0, 1, 0, 0, 0};
+const Byte kMaskToBitNumber[8] = {0, 1, 2, 2, 3, 3, 3, 3};
+
+SizeT x86_Convert(Byte *data, SizeT size, UInt32 ip, UInt32 *state, int encoding)
+{
+ SizeT bufferPos = 0, prevPosT;
+ UInt32 prevMask = *state & 0x7;
+ if (size < 5)
+ return 0;
+ ip += 5;
+ prevPosT = (SizeT)0 - 1;
+
+ for (;;)
+ {
+ Byte *p = data + bufferPos;
+ Byte *limit = data + size - 4;
+ for (; p < limit; p++)
+ if ((*p & 0xFE) == 0xE8)
+ break;
+ bufferPos = (SizeT)(p - data);
+ if (p >= limit)
+ break;
+ prevPosT = bufferPos - prevPosT;
+ if (prevPosT > 3)
+ prevMask = 0;
+ else
+ {
+ prevMask = (prevMask << ((int)prevPosT - 1)) & 0x7;
+ if (prevMask != 0)
+ {
+ Byte b = p[4 - kMaskToBitNumber[prevMask]];
+ if (!kMaskToAllowedStatus[prevMask] || Test86MSByte(b))
+ {
+ prevPosT = bufferPos;
+ prevMask = ((prevMask << 1) & 0x7) | 1;
+ bufferPos++;
+ continue;
+ }
+ }
+ }
+ prevPosT = bufferPos;
+
+ if (Test86MSByte(p[4]))
+ {
+ UInt32 src = ((UInt32)p[4] << 24) | ((UInt32)p[3] << 16) | ((UInt32)p[2] << 8) | ((UInt32)p[1]);
+ UInt32 dest;
+ for (;;)
+ {
+ Byte b;
+ int index;
+ if (encoding)
+ dest = (ip + (UInt32)bufferPos) + src;
+ else
+ dest = src - (ip + (UInt32)bufferPos);
+ if (prevMask == 0)
+ break;
+ index = kMaskToBitNumber[prevMask] * 8;
+ b = (Byte)(dest >> (24 - index));
+ if (!Test86MSByte(b))
+ break;
+ src = dest ^ ((1 << (32 - index)) - 1);
+ }
+ p[4] = (Byte)(~(((dest >> 24) & 1) - 1));
+ p[3] = (Byte)(dest >> 16);
+ p[2] = (Byte)(dest >> 8);
+ p[1] = (Byte)dest;
+ bufferPos += 5;
+ }
+ else
+ {
+ prevMask = ((prevMask << 1) & 0x7) | 1;
+ bufferPos++;
+ }
+ }
+ prevPosT = bufferPos - prevPosT;
+ *state = ((prevPosT > 3) ? 0 : ((prevMask << ((int)prevPosT - 1)) & 0x7));
+ return bufferPos;
+}