1 /*++
2 
3 Copyright (c) 2006 - 2008, Intel Corporation. All rights reserved.<BR>
4 This program and the accompanying materials
5 are licensed and made available under the terms and conditions of the BSD License
6 which accompanies this distribution.  The full text of the license may be found at
7 http://opensource.org/licenses/bsd-license.php
8 
9 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
10 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
11 
12 Module Name:
13 
14   GetImage.c
15 
16 Abstract:
17 
18   Image data extraction support for common use.
19 
20 --*/
21 
22 #include "Tiano.h"
23 #include "EfiRuntimeLib.h"
24 #include "EfiImageFormat.h"
25 
26 #include EFI_PROTOCOL_CONSUMER (LoadedImage)
27 
28 EFI_STATUS
GetImageFromFv(IN EFI_FIRMWARE_VOLUME_PROTOCOL * Fv,IN EFI_GUID * NameGuid,IN EFI_SECTION_TYPE SectionType,OUT VOID ** Buffer,OUT UINTN * Size)29 GetImageFromFv (
30 #if (PI_SPECIFICATION_VERSION < 0x00010000)
31   IN  EFI_FIRMWARE_VOLUME_PROTOCOL  *Fv,
32 #else
33   IN  EFI_FIRMWARE_VOLUME2_PROTOCOL *Fv,
34 #endif
35   IN  EFI_GUID           *NameGuid,
36   IN  EFI_SECTION_TYPE   SectionType,
37   OUT VOID               **Buffer,
38   OUT UINTN              *Size
39   )
40 {
41   EFI_STATUS                Status;
42   EFI_FV_FILETYPE           FileType;
43   EFI_FV_FILE_ATTRIBUTES    Attributes;
44   UINT32                    AuthenticationStatus;
45 
46   //
47   // Read desired section content in NameGuid file
48   //
49   *Buffer     = NULL;
50   *Size       = 0;
51   Status      = Fv->ReadSection (
52                       Fv,
53                       NameGuid,
54                       SectionType,
55                       0,
56                       Buffer,
57                       Size,
58                       &AuthenticationStatus
59                       );
60 
61   if (EFI_ERROR (Status) && (SectionType == EFI_SECTION_TE)) {
62     //
63     // Try reading PE32 section, since the TE section does not exist
64     //
65     *Buffer = NULL;
66     *Size   = 0;
67     Status  = Fv->ReadSection (
68                     Fv,
69                     NameGuid,
70                     EFI_SECTION_PE32,
71                     0,
72                     Buffer,
73                     Size,
74                     &AuthenticationStatus
75                     );
76   }
77 
78   if (EFI_ERROR (Status) &&
79       ((SectionType == EFI_SECTION_TE) || (SectionType == EFI_SECTION_PE32))) {
80     //
81     // Try reading raw file, since the desired section does not exist
82     //
83     *Buffer = NULL;
84     *Size   = 0;
85     Status  = Fv->ReadFile (
86                     Fv,
87                     NameGuid,
88                     Buffer,
89                     Size,
90                     &FileType,
91                     &Attributes,
92                     &AuthenticationStatus
93                     );
94   }
95 
96   return Status;
97 }
98 
99 EFI_STATUS
GetImage(IN EFI_GUID * NameGuid,IN EFI_SECTION_TYPE SectionType,OUT VOID ** Buffer,OUT UINTN * Size)100 GetImage (
101   IN  EFI_GUID           *NameGuid,
102   IN  EFI_SECTION_TYPE   SectionType,
103   OUT VOID               **Buffer,
104   OUT UINTN              *Size
105   )
106 {
107   return GetImageEx (NULL, NameGuid, SectionType, Buffer, Size, FALSE);
108 }
109 
110 EFI_STATUS
GetImageEx(IN EFI_HANDLE ImageHandle,IN EFI_GUID * NameGuid,IN EFI_SECTION_TYPE SectionType,OUT VOID ** Buffer,OUT UINTN * Size,BOOLEAN WithinImageFv)111 GetImageEx (
112   IN  EFI_HANDLE         ImageHandle,
113   IN  EFI_GUID           *NameGuid,
114   IN  EFI_SECTION_TYPE   SectionType,
115   OUT VOID               **Buffer,
116   OUT UINTN              *Size,
117   BOOLEAN                WithinImageFv
118   )
119 {
120   EFI_STATUS                    Status;
121   EFI_HANDLE                    *HandleBuffer;
122   UINTN                         HandleCount;
123   UINTN                         Index;
124   EFI_LOADED_IMAGE_PROTOCOL     *LoadedImage;
125 #if (PI_SPECIFICATION_VERSION < 0x00010000)
126   EFI_FIRMWARE_VOLUME_PROTOCOL  *ImageFv;
127   EFI_FIRMWARE_VOLUME_PROTOCOL  *Fv;
128 #else
129   EFI_FIRMWARE_VOLUME2_PROTOCOL *ImageFv;
130   EFI_FIRMWARE_VOLUME2_PROTOCOL *Fv;
131 #endif
132 
133   if (ImageHandle == NULL && WithinImageFv) {
134     return EFI_INVALID_PARAMETER;
135   }
136 
137   Status  = EFI_NOT_FOUND;
138   ImageFv = NULL;
139   if (ImageHandle != NULL) {
140     Status = gBS->HandleProtocol (
141                ImageHandle,
142                &gEfiLoadedImageProtocolGuid,
143                (VOID **) &LoadedImage
144                );
145     if (EFI_ERROR (Status)) {
146       return Status;
147     }
148     Status = gBS->HandleProtocol (
149                     LoadedImage->DeviceHandle,
150                   #if (PI_SPECIFICATION_VERSION < 0x00010000)
151                     &gEfiFirmwareVolumeProtocolGuid,
152                   #else
153                     &gEfiFirmwareVolume2ProtocolGuid,
154                   #endif
155                     (VOID **) &ImageFv
156                     );
157     if (!EFI_ERROR (Status)) {
158       Status = GetImageFromFv (ImageFv, NameGuid, SectionType, Buffer, Size);
159     }
160   }
161 
162   if (Status == EFI_SUCCESS || WithinImageFv) {
163     return Status;
164   }
165 
166   Status = gBS->LocateHandleBuffer (
167                   ByProtocol,
168                 #if (PI_SPECIFICATION_VERSION < 0x00010000)
169                   &gEfiFirmwareVolumeProtocolGuid,
170                 #else
171                   &gEfiFirmwareVolume2ProtocolGuid,
172                 #endif
173                   NULL,
174                   &HandleCount,
175                   &HandleBuffer
176                   );
177   if (EFI_ERROR (Status)) {
178     return Status;
179   }
180 
181   //
182   // Find desired image in all Fvs
183   //
184   for (Index = 0; Index < HandleCount; ++Index) {
185     Status = gBS->HandleProtocol (
186                     HandleBuffer[Index],
187                   #if (PI_SPECIFICATION_VERSION < 0x00010000)
188                     &gEfiFirmwareVolumeProtocolGuid,
189                   #else
190                     &gEfiFirmwareVolume2ProtocolGuid,
191                   #endif
192                     (VOID**)&Fv
193                     );
194 
195     if (EFI_ERROR (Status)) {
196       gBS->FreePool(HandleBuffer);
197       return Status;
198     }
199 
200     if (ImageFv != NULL && Fv == ImageFv) {
201       continue;
202     }
203 
204     Status = GetImageFromFv (Fv, NameGuid, SectionType, Buffer, Size);
205 
206     if (!EFI_ERROR (Status)) {
207       break;
208     }
209   }
210   gBS->FreePool(HandleBuffer);
211 
212   //
213   // Not found image
214   //
215   if (Index == HandleCount) {
216     return EFI_NOT_FOUND;
217   }
218 
219   return EFI_SUCCESS;
220 }
221 
222