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**/
54RETURN_STATUS
55EFIAPI
56LzmaArchGuidedSectionGetInfo (
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**/
134RETURN_STATUS
135EFIAPI
136LzmaArchGuidedSectionExtraction (
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**/
207EFI_STATUS
208EFIAPI
209LzmaArchDecompressLibConstructor (
210  )
211{
212  return ExtractGuidedSectionRegisterHandlers (
213          &gLzmaF86CustomDecompressGuid,
214          LzmaArchGuidedSectionGetInfo,
215          LzmaArchGuidedSectionExtraction
216          );
217}
218
219