• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /** @file
2   Provide generic extract guided section functions.
3 
4   Copyright (c) 2007 - 2011, 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 <PiPei.h>
16 
17 #include <Library/DebugLib.h>
18 #include <Library/PcdLib.h>
19 #include <Library/BaseMemoryLib.h>
20 #include <Library/ExtractGuidedSectionLib.h>
21 
22 #define EXTRACT_HANDLER_INFO_SIGNATURE SIGNATURE_32 ('E', 'G', 'S', 'I')
23 
24 typedef struct {
25   UINT32                                  Signature;
26   UINT32                                  NumberOfExtractHandler;
27   GUID                                    *ExtractHandlerGuidTable;
28   EXTRACT_GUIDED_SECTION_DECODE_HANDLER   *ExtractDecodeHandlerTable;
29   EXTRACT_GUIDED_SECTION_GET_INFO_HANDLER *ExtractGetInfoHandlerTable;
30 } EXTRACT_GUIDED_SECTION_HANDLER_INFO;
31 
32 /**
33   HandlerInfo table address is set by PcdGuidedExtractHandlerTableAddress, which is used to store
34   the registered guid and Handler list. When it is initialized, it will be directly returned.
35   Or, HandlerInfo table will be initialized in this function.
36 
37   @param[in, out]  InfoPointer   The pointer to the handler information structure.
38 
39   @retval  RETURN_SUCCESS            HandlerInfo table can be used to store guid and function tables.
40   @retval  RETURN_OUT_OF_RESOURCES   HandlerInfo table address is not writable.
41 **/
42 RETURN_STATUS
GetExtractGuidedSectionHandlerInfo(IN OUT EXTRACT_GUIDED_SECTION_HANDLER_INFO ** InfoPointer)43 GetExtractGuidedSectionHandlerInfo (
44   IN OUT EXTRACT_GUIDED_SECTION_HANDLER_INFO **InfoPointer
45   )
46 {
47   EXTRACT_GUIDED_SECTION_HANDLER_INFO *HandlerInfo;
48 
49   //
50   // Set the available memory address to handler info.
51   //
52   HandlerInfo = (EXTRACT_GUIDED_SECTION_HANDLER_INFO*)(VOID*)(UINTN) PcdGet64 (PcdGuidedExtractHandlerTableAddress);
53   if (HandlerInfo == NULL) {
54     *InfoPointer = NULL;
55     return EFI_OUT_OF_RESOURCES;
56   }
57 
58   //
59   // First check whether the handler information structure is initialized.
60   //
61   if (HandlerInfo->Signature == EXTRACT_HANDLER_INFO_SIGNATURE) {
62     //
63     // The handler information has been initialized and is returned.
64     //
65     *InfoPointer = HandlerInfo;
66     return RETURN_SUCCESS;
67   }
68 
69   //
70   // Try to initialize the handler information structure
71   //
72   HandlerInfo->Signature = EXTRACT_HANDLER_INFO_SIGNATURE;
73   if (HandlerInfo->Signature != EXTRACT_HANDLER_INFO_SIGNATURE) {
74     //
75     // The handler information structure was not writeable because the memory is not ready.
76     //
77     *InfoPointer = NULL;
78     return RETURN_OUT_OF_RESOURCES;
79   }
80 
81   //
82   // Init HandlerInfo structure
83   //
84   HandlerInfo->NumberOfExtractHandler     = 0;
85   HandlerInfo->ExtractHandlerGuidTable    = (GUID *) (HandlerInfo + 1);
86   HandlerInfo->ExtractDecodeHandlerTable  = (EXTRACT_GUIDED_SECTION_DECODE_HANDLER *) (
87                                               (UINT8 *)HandlerInfo->ExtractHandlerGuidTable +
88                                               PcdGet32 (PcdMaximumGuidedExtractHandler) * sizeof (GUID)
89                                              );
90   HandlerInfo->ExtractGetInfoHandlerTable = (EXTRACT_GUIDED_SECTION_GET_INFO_HANDLER *) (
91                                               (UINT8 *)HandlerInfo->ExtractDecodeHandlerTable +
92                                               PcdGet32 (PcdMaximumGuidedExtractHandler) *
93                                               sizeof (EXTRACT_GUIDED_SECTION_DECODE_HANDLER)
94                                              );
95   *InfoPointer = HandlerInfo;
96   return RETURN_SUCCESS;
97 }
98 
99 /**
100   Retrieve the list GUIDs that have been registered through ExtractGuidedSectionRegisterHandlers().
101 
102   Sets ExtractHandlerGuidTable so it points at a callee allocated array of registered GUIDs.
103   The total number of GUIDs in the array are returned. Since the array of GUIDs is callee allocated
104   and caller must treat this array of GUIDs as read-only data.
105   If ExtractHandlerGuidTable is NULL, then ASSERT().
106 
107   @param[out]  ExtractHandlerGuidTable  A pointer to the array of GUIDs that have been registered through
108                                         ExtractGuidedSectionRegisterHandlers().
109 
110   @return The number of the supported extract guided Handler.
111 
112 **/
113 UINTN
114 EFIAPI
ExtractGuidedSectionGetGuidList(OUT GUID ** ExtractHandlerGuidTable)115 ExtractGuidedSectionGetGuidList (
116   OUT  GUID  **ExtractHandlerGuidTable
117   )
118 {
119   RETURN_STATUS                       Status;
120   EXTRACT_GUIDED_SECTION_HANDLER_INFO *HandlerInfo;
121 
122   ASSERT (ExtractHandlerGuidTable != NULL);
123 
124   //
125   // Get all registered handler information
126   //
127   Status = GetExtractGuidedSectionHandlerInfo (&HandlerInfo);
128   if (RETURN_ERROR (Status)) {
129     *ExtractHandlerGuidTable = NULL;
130     return 0;
131   }
132 
133   //
134   // Get GuidTable and Table Number
135   //
136   ASSERT (HandlerInfo != NULL);
137   *ExtractHandlerGuidTable = HandlerInfo->ExtractHandlerGuidTable;
138   return HandlerInfo->NumberOfExtractHandler;
139 }
140 
141 /**
142   Registers handlers of type EXTRACT_GUIDED_SECTION_GET_INFO_HANDLER and EXTRACT_GUIDED_SECTION_DECODE_HANDLER
143   for a specific GUID section type.
144 
145   Registers the handlers specified by GetInfoHandler and DecodeHandler with the GUID specified by SectionGuid.
146   If the GUID value specified by SectionGuid has already been registered, then return RETURN_ALREADY_STARTED.
147   If there are not enough resources available to register the handlers  then RETURN_OUT_OF_RESOURCES is returned.
148 
149   If SectionGuid is NULL, then ASSERT().
150   If GetInfoHandler is NULL, then ASSERT().
151   If DecodeHandler is NULL, then ASSERT().
152 
153   @param[in]  SectionGuid    A pointer to the GUID associated with the the handlers
154                              of the GUIDed section type being registered.
155   @param[in]  GetInfoHandler The pointer to a function that examines a GUIDed section and returns the
156                              size of the decoded buffer and the size of an optional scratch buffer
157                              required to actually decode the data in a GUIDed section.
158   @param[in]  DecodeHandler  The pointer to a function that decodes a GUIDed section into a caller
159                              allocated output buffer.
160 
161   @retval  RETURN_SUCCESS           The handlers were registered.
162   @retval  RETURN_OUT_OF_RESOURCES  There are not enough resources available to register the handlers.
163 
164 **/
165 RETURN_STATUS
166 EFIAPI
ExtractGuidedSectionRegisterHandlers(IN CONST GUID * SectionGuid,IN EXTRACT_GUIDED_SECTION_GET_INFO_HANDLER GetInfoHandler,IN EXTRACT_GUIDED_SECTION_DECODE_HANDLER DecodeHandler)167 ExtractGuidedSectionRegisterHandlers (
168   IN CONST  GUID                                     *SectionGuid,
169   IN        EXTRACT_GUIDED_SECTION_GET_INFO_HANDLER  GetInfoHandler,
170   IN        EXTRACT_GUIDED_SECTION_DECODE_HANDLER    DecodeHandler
171   )
172 {
173   UINT32                              Index;
174   RETURN_STATUS                       Status;
175   EXTRACT_GUIDED_SECTION_HANDLER_INFO *HandlerInfo;
176 
177   //
178   // Check input parameter
179   //
180   ASSERT (SectionGuid != NULL);
181   ASSERT (GetInfoHandler != NULL);
182   ASSERT (DecodeHandler != NULL);
183 
184   //
185   // Get the registered handler information
186   //
187   Status = GetExtractGuidedSectionHandlerInfo (&HandlerInfo);
188   if (RETURN_ERROR (Status)) {
189     return Status;
190   }
191 
192   //
193   // Search the match registered GetInfo handler for the input guided section.
194   //
195   ASSERT (HandlerInfo != NULL);
196   for (Index = 0; Index < HandlerInfo->NumberOfExtractHandler; Index ++) {
197     if (CompareGuid (HandlerInfo->ExtractHandlerGuidTable + Index, SectionGuid)) {
198       //
199       // If the guided handler has been registered before, only update its handler.
200       //
201       HandlerInfo->ExtractDecodeHandlerTable [Index] = DecodeHandler;
202       HandlerInfo->ExtractGetInfoHandlerTable [Index] = GetInfoHandler;
203       return RETURN_SUCCESS;
204     }
205   }
206 
207   //
208   // Check the global table is enough to contain new Handler.
209   //
210   if (HandlerInfo->NumberOfExtractHandler >= PcdGet32 (PcdMaximumGuidedExtractHandler)) {
211     return RETURN_OUT_OF_RESOURCES;
212   }
213 
214   //
215   // Register new Handler and guid value.
216   //
217   CopyGuid (HandlerInfo->ExtractHandlerGuidTable + HandlerInfo->NumberOfExtractHandler, SectionGuid);
218   HandlerInfo->ExtractDecodeHandlerTable [HandlerInfo->NumberOfExtractHandler] = DecodeHandler;
219   HandlerInfo->ExtractGetInfoHandlerTable [HandlerInfo->NumberOfExtractHandler++] = GetInfoHandler;
220 
221   return RETURN_SUCCESS;
222 }
223 
224 /**
225   Retrieves a GUID from a GUIDed section and uses that GUID to select an associated handler of type
226   EXTRACT_GUIDED_SECTION_GET_INFO_HANDLER that was registered with ExtractGuidedSectionRegisterHandlers().
227   The selected handler is used to retrieve and return the size of the decoded buffer and the size of an
228   optional scratch buffer required to actually decode the data in a GUIDed section.
229 
230   Examines a GUIDed section specified by InputSection.
231   If GUID for InputSection does not match any of the GUIDs registered through ExtractGuidedSectionRegisterHandlers(),
232   then RETURN_UNSUPPORTED is returned.
233   If the GUID of InputSection does match the GUID that this handler supports, then the the associated handler
234   of type EXTRACT_GUIDED_SECTION_GET_INFO_HANDLER that was registered with ExtractGuidedSectionRegisterHandlers()
235   is used to retrieve the OututBufferSize, ScratchSize, and Attributes values. The return status from the handler of
236   type EXTRACT_GUIDED_SECTION_GET_INFO_HANDLER is returned.
237 
238   If InputSection is NULL, then ASSERT().
239   If OutputBufferSize is NULL, then ASSERT().
240   If ScratchBufferSize is NULL, then ASSERT().
241   If SectionAttribute is NULL, then ASSERT().
242 
243   @param[in]  InputSection       A pointer to a GUIDed section of an FFS formatted file.
244   @param[out] OutputBufferSize   A pointer to the size, in bytes, of an output buffer required if the buffer
245                                  specified by InputSection were decoded.
246   @param[out] ScratchBufferSize  A pointer to the size, in bytes, required as scratch space if the buffer specified by
247                                  InputSection were decoded.
248   @param[out] SectionAttribute   A pointer to the attributes of the GUIDed section.  See the Attributes field of
249                                  EFI_GUID_DEFINED_SECTION in the PI Specification.
250 
251   @retval  RETURN_SUCCESS      Successfully retrieved the required information.
252   @retval  RETURN_UNSUPPORTED  The GUID from the section specified by InputSection does not match any of
253                                the GUIDs registered with ExtractGuidedSectionRegisterHandlers().
254   @retval  Others              The return status from the handler associated with the GUID retrieved from
255                                the section specified by InputSection.
256 
257 **/
258 RETURN_STATUS
259 EFIAPI
ExtractGuidedSectionGetInfo(IN CONST VOID * InputSection,OUT UINT32 * OutputBufferSize,OUT UINT32 * ScratchBufferSize,OUT UINT16 * SectionAttribute)260 ExtractGuidedSectionGetInfo (
261   IN  CONST VOID    *InputSection,
262   OUT       UINT32  *OutputBufferSize,
263   OUT       UINT32  *ScratchBufferSize,
264   OUT       UINT16  *SectionAttribute
265   )
266 {
267   UINT32                              Index;
268   RETURN_STATUS                       Status;
269   EXTRACT_GUIDED_SECTION_HANDLER_INFO *HandlerInfo;
270   EFI_GUID                            *SectionDefinitionGuid;
271 
272   //
273   // Check input parameter
274   //
275   ASSERT (InputSection != NULL);
276   ASSERT (OutputBufferSize != NULL);
277   ASSERT (ScratchBufferSize != NULL);
278   ASSERT (SectionAttribute != NULL);
279 
280   //
281   // Get all registered handler information.
282   //
283   Status = GetExtractGuidedSectionHandlerInfo (&HandlerInfo);
284   if (RETURN_ERROR (Status)) {
285     return Status;
286   }
287 
288   if (IS_SECTION2 (InputSection)) {
289     SectionDefinitionGuid = &(((EFI_GUID_DEFINED_SECTION2 *) InputSection)->SectionDefinitionGuid);
290   } else {
291     SectionDefinitionGuid = &(((EFI_GUID_DEFINED_SECTION *) InputSection)->SectionDefinitionGuid);
292   }
293 
294   //
295   // Search the match registered GetInfo handler for the input guided section.
296   //
297   ASSERT (HandlerInfo != NULL);
298   for (Index = 0; Index < HandlerInfo->NumberOfExtractHandler; Index ++) {
299     if (CompareGuid (HandlerInfo->ExtractHandlerGuidTable + Index, SectionDefinitionGuid)) {
300       //
301       // Call the match handler to get information for the input section data.
302       //
303       return HandlerInfo->ExtractGetInfoHandlerTable [Index] (
304                 InputSection,
305                 OutputBufferSize,
306                 ScratchBufferSize,
307                 SectionAttribute
308               );
309     }
310   }
311 
312   //
313   // Not found, the input guided section is not supported.
314   //
315   return RETURN_UNSUPPORTED;
316 }
317 
318 /**
319   Retrieves the GUID from a GUIDed section and uses that GUID to select an associated handler of type
320   EXTRACT_GUIDED_SECTION_DECODE_HANDLER that was registered with ExtractGuidedSectionRegisterHandlers().
321   The selected handler is used to decode the data in a GUIDed section and return the result in a caller
322   allocated output buffer.
323 
324   Decodes the GUIDed section specified by InputSection.
325   If GUID for InputSection does not match any of the GUIDs registered through ExtractGuidedSectionRegisterHandlers(),
326   then RETURN_UNSUPPORTED is returned.
327   If the GUID of InputSection does match the GUID that this handler supports, then the the associated handler
328   of type EXTRACT_GUIDED_SECTION_DECODE_HANDLER that was registered with ExtractGuidedSectionRegisterHandlers()
329   is used to decode InputSection into the buffer specified by OutputBuffer and the authentication status of this
330   decode operation is returned in AuthenticationStatus.  If the decoded buffer is identical to the data in InputSection,
331   then OutputBuffer is set to point at the data in InputSection.  Otherwise, the decoded data will be placed in a caller
332   allocated buffer specified by OutputBuffer.    This function is responsible for computing the  EFI_AUTH_STATUS_PLATFORM_OVERRIDE
333   bit of in AuthenticationStatus.  The return status from the handler of type EXTRACT_GUIDED_SECTION_DECODE_HANDLER is returned.
334 
335   If InputSection is NULL, then ASSERT().
336   If OutputBuffer is NULL, then ASSERT().
337   If ScratchBuffer is NULL and this decode operation requires a scratch buffer, then ASSERT().
338   If AuthenticationStatus is NULL, then ASSERT().
339 
340   @param[in]  InputSection   A pointer to a GUIDed section of an FFS formatted file.
341   @param[out] OutputBuffer   A pointer to a buffer that contains the result of a decode operation.
342   @param[in]  ScratchBuffer  A caller allocated buffer that may be required by this function as a scratch buffer to perform the decode operation.
343   @param[out] AuthenticationStatus
344                              A pointer to the authentication status of the decoded output buffer. See the definition
345                              of authentication status in the EFI_PEI_GUIDED_SECTION_EXTRACTION_PPI section of the PI
346                              Specification.
347 
348   @retval  RETURN_SUCCESS           The buffer specified by InputSection was decoded.
349   @retval  RETURN_UNSUPPORTED       The section specified by InputSection does not match the GUID this handler supports.
350   @retval  RETURN_INVALID_PARAMETER The section specified by InputSection can not be decoded.
351 
352 **/
353 RETURN_STATUS
354 EFIAPI
ExtractGuidedSectionDecode(IN CONST VOID * InputSection,OUT VOID ** OutputBuffer,IN VOID * ScratchBuffer,OPTIONAL OUT UINT32 * AuthenticationStatus)355 ExtractGuidedSectionDecode (
356   IN  CONST VOID    *InputSection,
357   OUT       VOID    **OutputBuffer,
358   IN        VOID    *ScratchBuffer,        OPTIONAL
359   OUT       UINT32  *AuthenticationStatus
360   )
361 {
362   UINT32                              Index;
363   RETURN_STATUS                       Status;
364   EXTRACT_GUIDED_SECTION_HANDLER_INFO *HandlerInfo;
365   EFI_GUID                            *SectionDefinitionGuid;
366 
367   //
368   // Check input parameter
369   //
370   ASSERT (InputSection != NULL);
371   ASSERT (OutputBuffer != NULL);
372   ASSERT (AuthenticationStatus != NULL);
373 
374   //
375   // Get all registered handler information.
376   //
377   Status = GetExtractGuidedSectionHandlerInfo (&HandlerInfo);
378   if (RETURN_ERROR (Status)) {
379     return Status;
380   }
381 
382   if (IS_SECTION2 (InputSection)) {
383     SectionDefinitionGuid = &(((EFI_GUID_DEFINED_SECTION2 *) InputSection)->SectionDefinitionGuid);
384   } else {
385     SectionDefinitionGuid = &(((EFI_GUID_DEFINED_SECTION *) InputSection)->SectionDefinitionGuid);
386   }
387 
388   //
389   // Search the match registered Extract handler for the input guided section.
390   //
391   ASSERT (HandlerInfo != NULL);
392   for (Index = 0; Index < HandlerInfo->NumberOfExtractHandler; Index ++) {
393     if (CompareGuid (HandlerInfo->ExtractHandlerGuidTable + Index, SectionDefinitionGuid)) {
394       //
395       // Call the match handler to extract raw data for the input guided section.
396       //
397       return HandlerInfo->ExtractDecodeHandlerTable [Index] (
398                 InputSection,
399                 OutputBuffer,
400                 ScratchBuffer,
401                 AuthenticationStatus
402               );
403     }
404   }
405 
406   //
407   // Not found, the input guided section is not supported.
408   //
409   return RETURN_UNSUPPORTED;
410 }
411 
412 /**
413   Retrieves handlers of type EXTRACT_GUIDED_SECTION_GET_INFO_HANDLER and
414   EXTRACT_GUIDED_SECTION_DECODE_HANDLER for a specific GUID section type.
415 
416   Retrieves the handlers associated with SectionGuid and returns them in
417   GetInfoHandler and DecodeHandler.
418 
419   If the GUID value specified by SectionGuid has not been registered, then
420   return RETURN_NOT_FOUND.
421 
422   If SectionGuid is NULL, then ASSERT().
423 
424   @param[in]  SectionGuid    A pointer to the GUID associated with the handlersof the GUIDed
425                              section type being retrieved.
426   @param[out] GetInfoHandler Pointer to a function that examines a GUIDed section and returns
427                              the size of the decoded buffer and the size of an optional scratch
428                              buffer required to actually decode the data in a GUIDed section.
429                              This is an optional parameter that may be NULL. If it is NULL, then
430                              the previously registered handler is not returned.
431   @param[out] DecodeHandler  Pointer to a function that decodes a GUIDed section into a caller
432                              allocated output buffer. This is an optional parameter that may be NULL.
433                              If it is NULL, then the previously registered handler is not returned.
434 
435   @retval  RETURN_SUCCESS     The handlers were retrieved.
436   @retval  RETURN_NOT_FOUND   No handlers have been registered with the specified GUID.
437 
438 **/
439 RETURN_STATUS
440 EFIAPI
ExtractGuidedSectionGetHandlers(IN CONST GUID * SectionGuid,OUT EXTRACT_GUIDED_SECTION_GET_INFO_HANDLER * GetInfoHandler,OPTIONAL OUT EXTRACT_GUIDED_SECTION_DECODE_HANDLER * DecodeHandler OPTIONAL)441 ExtractGuidedSectionGetHandlers (
442   IN CONST   GUID                                     *SectionGuid,
443   OUT        EXTRACT_GUIDED_SECTION_GET_INFO_HANDLER  *GetInfoHandler,  OPTIONAL
444   OUT        EXTRACT_GUIDED_SECTION_DECODE_HANDLER    *DecodeHandler    OPTIONAL
445   )
446 {
447   UINT32                              Index;
448   RETURN_STATUS                       Status;
449   EXTRACT_GUIDED_SECTION_HANDLER_INFO *HandlerInfo;
450 
451   //
452   // Check input parameter
453   //
454   ASSERT (SectionGuid != NULL);
455 
456   //
457   // Get the registered handler information
458   //
459   Status = GetExtractGuidedSectionHandlerInfo (&HandlerInfo);
460   if (RETURN_ERROR (Status)) {
461     return Status;
462   }
463 
464   //
465   // Search the match registered GetInfo handler for the input guided section.
466   //
467   ASSERT (HandlerInfo != NULL);
468   for (Index = 0; Index < HandlerInfo->NumberOfExtractHandler; Index ++) {
469     if (CompareGuid (HandlerInfo->ExtractHandlerGuidTable + Index, SectionGuid)) {
470 
471       //
472       // If the guided handler has been registered before, then return the registered handlers.
473       //
474       if (GetInfoHandler != NULL) {
475         *GetInfoHandler = HandlerInfo->ExtractGetInfoHandlerTable[Index];
476       }
477       if (DecodeHandler != NULL) {
478         *DecodeHandler = HandlerInfo->ExtractDecodeHandlerTable[Index];
479       }
480       return RETURN_SUCCESS;
481     }
482   }
483   return RETURN_NOT_FOUND;
484 }
485