1 /** @file
2  Section Extraction DXE Driver
3 
4 Copyright (c) 2013 - 2014, Intel Corporation. All rights reserved.<BR>
5 This program and the accompanying materials
6 are licensed and made available under the terms and conditions of the BSD License
7 which accompanies this distribution.  The full text of the license may be found at
8 http://opensource.org/licenses/bsd-license.php
9 
10 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
11 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
12 
13 **/
14 
15 #include <PiDxe.h>
16 #include <Protocol/GuidedSectionExtraction.h>
17 #include <Library/DebugLib.h>
18 #include <Library/ExtractGuidedSectionLib.h>
19 #include <Library/MemoryAllocationLib.h>
20 #include <Library/BaseMemoryLib.h>
21 #include <Library/UefiBootServicesTableLib.h>
22 
23 /**
24   The ExtractSection() function processes the input section and
25   allocates a buffer from the pool in which it returns the section
26   contents. If the section being extracted contains
27   authentication information (the section's
28   GuidedSectionHeader.Attributes field has the
29   EFI_GUIDED_SECTION_AUTH_STATUS_VALID bit set), the values
30   returned in AuthenticationStatus must reflect the results of
31   the authentication operation. Depending on the algorithm and
32   size of the encapsulated data, the time that is required to do
33   a full authentication may be prohibitively long for some
34   classes of systems. To indicate this, use
35   EFI_SECURITY_POLICY_PROTOCOL_GUID, which may be published by
36   the security policy driver (see the Platform Initialization
37   Driver Execution Environment Core Interface Specification for
38   more details and the GUID definition). If the
39   EFI_SECURITY_POLICY_PROTOCOL_GUID exists in the handle
40   database, then, if possible, full authentication should be
41   skipped and the section contents simply returned in the
42   OutputBuffer. In this case, the
43   EFI_AUTH_STATUS_PLATFORM_OVERRIDE bit AuthenticationStatus
44   must be set on return. ExtractSection() is callable only from
45   TPL_NOTIFY and below. Behavior of ExtractSection() at any
46   EFI_TPL above TPL_NOTIFY is undefined. Type EFI_TPL is
47   defined in RaiseTPL() in the UEFI 2.0 specification.
48 
49 
50   @param This         Indicates the
51                       EFI_GUIDED_SECTION_EXTRACTION_PROTOCOL instance.
52   @param InputSection Buffer containing the input GUIDed section
53                       to be processed. OutputBuffer OutputBuffer
54                       is allocated from boot services pool
55                       memory and contains the new section
56                       stream. The caller is responsible for
57                       freeing this buffer.
58   @param OutputBuffer *OutputBuffer is allocated from boot services
59                       pool memory and contains the new section stream.
60                       The caller is responsible for freeing this buffer.
61   @param OutputSize   A pointer to a caller-allocated UINTN in
62                       which the size of OutputBuffer allocation
63                       is stored. If the function returns
64                       anything other than EFI_SUCCESS, the value
65                       of OutputSize is undefined.
66 
67   @param AuthenticationStatus A pointer to a caller-allocated
68                               UINT32 that indicates the
69                               authentication status of the
70                               output buffer. If the input
71                               section's
72                               GuidedSectionHeader.Attributes
73                               field has the
74                               EFI_GUIDED_SECTION_AUTH_STATUS_VAL
75                               bit as clear, AuthenticationStatus
76                               must return zero. Both local bits
77                               (19:16) and aggregate bits (3:0)
78                               in AuthenticationStatus are
79                               returned by ExtractSection().
80                               These bits reflect the status of
81                               the extraction operation. The bit
82                               pattern in both regions must be
83                               the same, as the local and
84                               aggregate authentication statuses
85                               have equivalent meaning at this
86                               level. If the function returns
87                               anything other than EFI_SUCCESS,
88                               the value of AuthenticationStatus
89                               is undefined.
90 
91 
92   @retval EFI_SUCCESS          The InputSection was successfully
93                                processed and the section contents were
94                                returned.
95 
96   @retval EFI_OUT_OF_RESOURCES The system has insufficient
97                                resources to process the
98                                request.
99 
100   @retval EFI_INVALID_PARAMETER The GUID in InputSection does
101                                 not match this instance of the
102                                 GUIDed Section Extraction
103                                 Protocol.
104 
105 **/
106 EFI_STATUS
107 EFIAPI
108 CustomGuidedSectionExtract (
109   IN CONST  EFI_GUIDED_SECTION_EXTRACTION_PROTOCOL *This,
110   IN CONST  VOID                                   *InputSection,
111   OUT       VOID                                   **OutputBuffer,
112   OUT       UINTN                                  *OutputSize,
113   OUT       UINT32                                 *AuthenticationStatus
114   );
115 
116 //
117 // Module global for the Section Extraction Protocol handle
118 //
119 EFI_HANDLE mSectionExtractionHandle = NULL;
120 
121 //
122 // Module global for the Section Extraction Protocol instance
123 //
124 EFI_GUIDED_SECTION_EXTRACTION_PROTOCOL mCustomGuidedSectionExtractionProtocol = {
125   CustomGuidedSectionExtract
126 };
127 
128 /**
129   The ExtractSection() function processes the input section and
130   allocates a buffer from the pool in which it returns the section
131   contents. If the section being extracted contains
132   authentication information (the section's
133   GuidedSectionHeader.Attributes field has the
134   EFI_GUIDED_SECTION_AUTH_STATUS_VALID bit set), the values
135   returned in AuthenticationStatus must reflect the results of
136   the authentication operation. Depending on the algorithm and
137   size of the encapsulated data, the time that is required to do
138   a full authentication may be prohibitively long for some
139   classes of systems. To indicate this, use
140   EFI_SECURITY_POLICY_PROTOCOL_GUID, which may be published by
141   the security policy driver (see the Platform Initialization
142   Driver Execution Environment Core Interface Specification for
143   more details and the GUID definition). If the
144   EFI_SECURITY_POLICY_PROTOCOL_GUID exists in the handle
145   database, then, if possible, full authentication should be
146   skipped and the section contents simply returned in the
147   OutputBuffer. In this case, the
148   EFI_AUTH_STATUS_PLATFORM_OVERRIDE bit AuthenticationStatus
149   must be set on return. ExtractSection() is callable only from
150   TPL_NOTIFY and below. Behavior of ExtractSection() at any
151   EFI_TPL above TPL_NOTIFY is undefined. Type EFI_TPL is
152   defined in RaiseTPL() in the UEFI 2.0 specification.
153 
154 
155   @param This         Indicates the
156                       EFI_GUIDED_SECTION_EXTRACTION_PROTOCOL instance.
157   @param InputSection Buffer containing the input GUIDed section
158                       to be processed. OutputBuffer OutputBuffer
159                       is allocated from boot services pool
160                       memory and contains the new section
161                       stream. The caller is responsible for
162                       freeing this buffer.
163   @param OutputBuffer *OutputBuffer is allocated from boot services
164                       pool memory and contains the new section stream.
165                       The caller is responsible for freeing this buffer.
166   @param OutputSize   A pointer to a caller-allocated UINTN in
167                       which the size of OutputBuffer allocation
168                       is stored. If the function returns
169                       anything other than EFI_SUCCESS, the value
170                       of OutputSize is undefined.
171 
172   @param AuthenticationStatus A pointer to a caller-allocated
173                               UINT32 that indicates the
174                               authentication status of the
175                               output buffer. If the input
176                               section's
177                               GuidedSectionHeader.Attributes
178                               field has the
179                               EFI_GUIDED_SECTION_AUTH_STATUS_VAL
180                               bit as clear, AuthenticationStatus
181                               must return zero. Both local bits
182                               (19:16) and aggregate bits (3:0)
183                               in AuthenticationStatus are
184                               returned by ExtractSection().
185                               These bits reflect the status of
186                               the extraction operation. The bit
187                               pattern in both regions must be
188                               the same, as the local and
189                               aggregate authentication statuses
190                               have equivalent meaning at this
191                               level. If the function returns
192                               anything other than EFI_SUCCESS,
193                               the value of AuthenticationStatus
194                               is undefined.
195 
196 
197   @retval EFI_SUCCESS          The InputSection was successfully
198                                processed and the section contents were
199                                returned.
200 
201   @retval EFI_OUT_OF_RESOURCES The system has insufficient
202                                resources to process the
203                                request.
204 
205   @retval EFI_INVALID_PARAMETER The GUID in InputSection does
206                                 not match this instance of the
207                                 GUIDed Section Extraction
208                                 Protocol.
209 
210 **/
211 EFI_STATUS
212 EFIAPI
CustomGuidedSectionExtract(IN CONST EFI_GUIDED_SECTION_EXTRACTION_PROTOCOL * This,IN CONST VOID * InputSection,OUT VOID ** OutputBuffer,OUT UINTN * OutputSize,OUT UINT32 * AuthenticationStatus)213 CustomGuidedSectionExtract (
214   IN CONST  EFI_GUIDED_SECTION_EXTRACTION_PROTOCOL *This,
215   IN CONST  VOID                                   *InputSection,
216   OUT       VOID                                   **OutputBuffer,
217   OUT       UINTN                                  *OutputSize,
218   OUT       UINT32                                 *AuthenticationStatus
219   )
220 {
221   EFI_STATUS      Status;
222   VOID            *ScratchBuffer;
223   VOID            *AllocatedOutputBuffer;
224   UINT32          OutputBufferSize;
225   UINT32          ScratchBufferSize;
226   UINT16          SectionAttribute;
227 
228   //
229   // Init local variable
230   //
231   ScratchBuffer         = NULL;
232   AllocatedOutputBuffer = NULL;
233 
234   //
235   // Call GetInfo to get the size and attribute of input guided section data.
236   //
237   Status = ExtractGuidedSectionGetInfo (
238              InputSection,
239              &OutputBufferSize,
240              &ScratchBufferSize,
241              &SectionAttribute
242              );
243 
244   if (EFI_ERROR (Status)) {
245     DEBUG ((DEBUG_ERROR, "GetInfo from guided section Failed - %r\n", Status));
246     return Status;
247   }
248 
249   if (ScratchBufferSize > 0) {
250     //
251     // Allocate scratch buffer
252     //
253     ScratchBuffer = AllocatePool (ScratchBufferSize);
254     if (ScratchBuffer == NULL) {
255       return EFI_OUT_OF_RESOURCES;
256     }
257   }
258 
259   if (OutputBufferSize > 0) {
260     //
261     // Allocate output buffer
262     //
263     AllocatedOutputBuffer = AllocatePool (OutputBufferSize);
264     if (AllocatedOutputBuffer == NULL) {
265       FreePool (ScratchBuffer);
266       return EFI_OUT_OF_RESOURCES;
267     }
268     *OutputBuffer = AllocatedOutputBuffer;
269   }
270 
271   //
272   // Call decode function to extract raw data from the guided section.
273   //
274   Status = ExtractGuidedSectionDecode (
275              InputSection,
276              OutputBuffer,
277              ScratchBuffer,
278              AuthenticationStatus
279              );
280   if (EFI_ERROR (Status)) {
281     //
282     // Decode failed
283     //
284     if (AllocatedOutputBuffer != NULL) {
285       FreePool (AllocatedOutputBuffer);
286     }
287     if (ScratchBuffer != NULL) {
288       FreePool (ScratchBuffer);
289     }
290     DEBUG ((DEBUG_ERROR, "Extract guided section Failed - %r\n", Status));
291     return Status;
292   }
293 
294   if (*OutputBuffer != AllocatedOutputBuffer) {
295     //
296     // OutputBuffer was returned as a different value,
297     // so copy section contents to the allocated memory buffer.
298     //
299     CopyMem (AllocatedOutputBuffer, *OutputBuffer, OutputBufferSize);
300     *OutputBuffer = AllocatedOutputBuffer;
301   }
302 
303   //
304   // Set real size of output buffer.
305   //
306   *OutputSize = (UINTN) OutputBufferSize;
307 
308   //
309   // Free unused scratch buffer.
310   //
311   if (ScratchBuffer != NULL) {
312     FreePool (ScratchBuffer);
313   }
314 
315   return EFI_SUCCESS;
316 }
317 
318 /**
319   Main entry for the Section Extraction DXE module.
320 
321   This routine registers the Section Extraction Protocols that have been registered
322   with the Section Extraction Library.
323 
324   @param[in] ImageHandle    The firmware allocated handle for the EFI image.
325   @param[in] SystemTable    A pointer to the EFI System Table.
326 
327   @retval EFI_SUCCESS       The entry point is executed successfully.
328   @retval other             Some error occurs when executing this entry point.
329 
330 **/
331 EFI_STATUS
332 EFIAPI
SectionExtractionDxeEntry(IN EFI_HANDLE ImageHandle,IN EFI_SYSTEM_TABLE * SystemTable)333 SectionExtractionDxeEntry (
334   IN EFI_HANDLE        ImageHandle,
335   IN EFI_SYSTEM_TABLE  *SystemTable
336   )
337 {
338   EFI_STATUS  Status;
339   EFI_GUID    *ExtractHandlerGuidTable;
340   UINTN       ExtractHandlerNumber;
341 
342   //
343   // Get custom extract guided section method guid list
344   //
345   ExtractHandlerNumber = ExtractGuidedSectionGetGuidList (&ExtractHandlerGuidTable);
346 
347   //
348   // Install custom guided extraction protocol
349   //
350   while (ExtractHandlerNumber-- > 0) {
351     Status = gBS->InstallMultipleProtocolInterfaces (
352                     &mSectionExtractionHandle,
353                     &ExtractHandlerGuidTable [ExtractHandlerNumber], &mCustomGuidedSectionExtractionProtocol,
354                     NULL
355                     );
356     ASSERT_EFI_ERROR (Status);
357   }
358 
359   return EFI_SUCCESS;
360 }
361