1 /** @file
2   LZMA Decompress GUIDed Section Extraction Library, which produces LZMA custom
3   decompression algorithm with the converter for the different arch code.
4   It wraps Lzma decompress interfaces to GUIDed Section Extraction interfaces
5   and registers them into GUIDed handler table.
6 
7   Copyright (c) 2012, Intel Corporation. All rights reserved.<BR>
8   This program and the accompanying materials
9   are licensed and made available under the terms and conditions of the BSD License
10   which accompanies this distribution.  The full text of the license may be found at
11   http://opensource.org/licenses/bsd-license.php
12 
13   THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
14   WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
15 
16 **/
17 
18 #include "LzmaDecompressLibInternal.h"
19 #include "Sdk/C/Bra.h"
20 
21 /**
22   Examines a GUIDed section and returns the size of the decoded buffer and the
23   size of an scratch buffer required to actually decode the data in a GUIDed section.
24 
25   Examines a GUIDed section specified by InputSection.
26   If GUID for InputSection does not match the GUID that this handler supports,
27   then RETURN_UNSUPPORTED is returned.
28   If the required information can not be retrieved from InputSection,
29   then RETURN_INVALID_PARAMETER is returned.
30   If the GUID of InputSection does match the GUID that this handler supports,
31   then the size required to hold the decoded buffer is returned in OututBufferSize,
32   the size of an optional scratch buffer is returned in ScratchSize, and the Attributes field
33   from EFI_GUID_DEFINED_SECTION header of InputSection is returned in SectionAttribute.
34 
35   If InputSection is NULL, then ASSERT().
36   If OutputBufferSize is NULL, then ASSERT().
37   If ScratchBufferSize is NULL, then ASSERT().
38   If SectionAttribute is NULL, then ASSERT().
39 
40 
41   @param[in]  InputSection       A pointer to a GUIDed section of an FFS formatted file.
42   @param[out] OutputBufferSize   A pointer to the size, in bytes, of an output buffer required
43                                  if the buffer specified by InputSection were decoded.
44   @param[out] ScratchBufferSize  A pointer to the size, in bytes, required as scratch space
45                                  if the buffer specified by InputSection were decoded.
46   @param[out] SectionAttribute   A pointer to the attributes of the GUIDed section. See the Attributes
47                                  field of EFI_GUID_DEFINED_SECTION in the PI Specification.
48 
49   @retval  RETURN_SUCCESS            The information about InputSection was returned.
50   @retval  RETURN_UNSUPPORTED        The section specified by InputSection does not match the GUID this handler supports.
51   @retval  RETURN_INVALID_PARAMETER  The information can not be retrieved from the section specified by InputSection.
52 
53 **/
54 RETURN_STATUS
55 EFIAPI
LzmaArchGuidedSectionGetInfo(IN CONST VOID * InputSection,OUT UINT32 * OutputBufferSize,OUT UINT32 * ScratchBufferSize,OUT UINT16 * SectionAttribute)56 LzmaArchGuidedSectionGetInfo (
57   IN  CONST VOID  *InputSection,
58   OUT UINT32      *OutputBufferSize,
59   OUT UINT32      *ScratchBufferSize,
60   OUT UINT16      *SectionAttribute
61   )
62 {
63   ASSERT (InputSection != NULL);
64   ASSERT (OutputBufferSize != NULL);
65   ASSERT (ScratchBufferSize != NULL);
66   ASSERT (SectionAttribute != NULL);
67 
68   if (IS_SECTION2 (InputSection)) {
69     if (!CompareGuid (
70         &gLzmaF86CustomDecompressGuid,
71         &(((EFI_GUID_DEFINED_SECTION2 *) InputSection)->SectionDefinitionGuid))) {
72       return RETURN_INVALID_PARAMETER;
73     }
74 
75     *SectionAttribute = ((EFI_GUID_DEFINED_SECTION2 *) InputSection)->Attributes;
76 
77     return LzmaUefiDecompressGetInfo (
78              (UINT8 *) InputSection + ((EFI_GUID_DEFINED_SECTION2 *) InputSection)->DataOffset,
79              SECTION2_SIZE (InputSection) - ((EFI_GUID_DEFINED_SECTION2 *) InputSection)->DataOffset,
80              OutputBufferSize,
81              ScratchBufferSize
82              );
83   } else {
84     if (!CompareGuid (
85         &gLzmaF86CustomDecompressGuid,
86         &(((EFI_GUID_DEFINED_SECTION *) InputSection)->SectionDefinitionGuid))) {
87       return RETURN_INVALID_PARAMETER;
88     }
89 
90     *SectionAttribute = ((EFI_GUID_DEFINED_SECTION *) InputSection)->Attributes;
91 
92     return LzmaUefiDecompressGetInfo (
93              (UINT8 *) InputSection + ((EFI_GUID_DEFINED_SECTION *) InputSection)->DataOffset,
94              SECTION_SIZE (InputSection) - ((EFI_GUID_DEFINED_SECTION *) InputSection)->DataOffset,
95              OutputBufferSize,
96              ScratchBufferSize
97              );
98   }
99 }
100 
101 /**
102   Decompress a LZAM compressed GUIDed section into a caller allocated output buffer.
103 
104   Decodes the GUIDed section specified by InputSection.
105   If GUID for InputSection does not match the GUID that this handler supports, then RETURN_UNSUPPORTED is returned.
106   If the data in InputSection can not be decoded, then RETURN_INVALID_PARAMETER is returned.
107   If the GUID of InputSection does match the GUID that this handler supports, then InputSection
108   is decoded into the buffer specified by OutputBuffer and the authentication status of this
109   decode operation is returned in AuthenticationStatus.  If the decoded buffer is identical to the
110   data in InputSection, then OutputBuffer is set to point at the data in InputSection.  Otherwise,
111   the decoded data will be placed in caller allocated buffer specified by OutputBuffer.
112 
113   If InputSection is NULL, then ASSERT().
114   If OutputBuffer is NULL, then ASSERT().
115   If ScratchBuffer is NULL and this decode operation requires a scratch buffer, then ASSERT().
116   If AuthenticationStatus is NULL, then ASSERT().
117 
118 
119   @param[in]  InputSection  A pointer to a GUIDed section of an FFS formatted file.
120   @param[out] OutputBuffer  A pointer to a buffer that contains the result of a decode operation.
121   @param[out] ScratchBuffer A caller allocated buffer that may be required by this function
122                             as a scratch buffer to perform the decode operation.
123   @param[out] AuthenticationStatus
124                             A pointer to the authentication status of the decoded output buffer.
125                             See the definition of authentication status in the EFI_PEI_GUIDED_SECTION_EXTRACTION_PPI
126                             section of the PI Specification. EFI_AUTH_STATUS_PLATFORM_OVERRIDE must
127                             never be set by this handler.
128 
129   @retval  RETURN_SUCCESS            The buffer specified by InputSection was decoded.
130   @retval  RETURN_UNSUPPORTED        The section specified by InputSection does not match the GUID this handler supports.
131   @retval  RETURN_INVALID_PARAMETER  The section specified by InputSection can not be decoded.
132 
133 **/
134 RETURN_STATUS
135 EFIAPI
LzmaArchGuidedSectionExtraction(IN CONST VOID * InputSection,OUT VOID ** OutputBuffer,OUT VOID * ScratchBuffer,OPTIONAL OUT UINT32 * AuthenticationStatus)136 LzmaArchGuidedSectionExtraction (
137   IN CONST  VOID    *InputSection,
138   OUT       VOID    **OutputBuffer,
139   OUT       VOID    *ScratchBuffer,        OPTIONAL
140   OUT       UINT32  *AuthenticationStatus
141   )
142 {
143   EFI_GUID          *InputGuid;
144   VOID              *Source;
145   UINTN             SourceSize;
146   EFI_STATUS        Status;
147   UINT32            X86State;
148   UINT32            OutputBufferSize;
149   UINT32            ScratchBufferSize;
150 
151   ASSERT (OutputBuffer != NULL);
152   ASSERT (InputSection != NULL);
153 
154   if (IS_SECTION2 (InputSection)) {
155     InputGuid  = &(((EFI_GUID_DEFINED_SECTION2 *) InputSection)->SectionDefinitionGuid);
156     Source     = (UINT8 *) InputSection + ((EFI_GUID_DEFINED_SECTION2 *) InputSection)->DataOffset;
157     SourceSize = SECTION2_SIZE (InputSection) - ((EFI_GUID_DEFINED_SECTION2 *) InputSection)->DataOffset;
158   } else {
159     InputGuid  = &(((EFI_GUID_DEFINED_SECTION *) InputSection)->SectionDefinitionGuid);
160     Source     = (UINT8 *) InputSection + ((EFI_GUID_DEFINED_SECTION *) InputSection)->DataOffset;
161     SourceSize = SECTION_SIZE (InputSection) - ((EFI_GUID_DEFINED_SECTION *) InputSection)->DataOffset;
162   }
163 
164   if (!CompareGuid (&gLzmaF86CustomDecompressGuid, InputGuid)) {
165     return RETURN_INVALID_PARAMETER;
166   }
167 
168   //
169   // Authentication is set to Zero, which may be ignored.
170   //
171   *AuthenticationStatus = 0;
172 
173   Status = LzmaUefiDecompress (
174            Source,
175            SourceSize,
176            *OutputBuffer,
177            ScratchBuffer
178            );
179 
180   //
181   // After decompress, the data need to be converted to the raw data.
182   //
183   if (!EFI_ERROR (Status)) {
184     Status = LzmaUefiDecompressGetInfo (
185              Source,
186              (UINT32) SourceSize,
187              &OutputBufferSize,
188              &ScratchBufferSize
189              );
190 
191     if (!EFI_ERROR (Status)) {
192       x86_Convert_Init(X86State);
193       x86_Convert(*OutputBuffer, OutputBufferSize, 0, &X86State, 0);
194     }
195   }
196 
197   return Status;
198 }
199 
200 
201 /**
202   Register LzmaArchDecompress and LzmaArchDecompressGetInfo handlers with LzmaF86CustomDecompressGuid.
203 
204   @retval  RETURN_SUCCESS            Register successfully.
205   @retval  RETURN_OUT_OF_RESOURCES   No enough memory to store this handler.
206 **/
207 EFI_STATUS
208 EFIAPI
LzmaArchDecompressLibConstructor()209 LzmaArchDecompressLibConstructor (
210   )
211 {
212   return ExtractGuidedSectionRegisterHandlers (
213           &gLzmaF86CustomDecompressGuid,
214           LzmaArchGuidedSectionGetInfo,
215           LzmaArchGuidedSectionExtraction
216           );
217 }
218 
219