]> git.proxmox.com Git - mirror_edk2.git/blame - MdeModulePkg/Core/Dxe/Image/ImageFile.c
edk2/IntelFrameworkModulePkg/Bus/Isa/IsaSerialDxe/IsaSerialDxe.inf:
[mirror_edk2.git] / MdeModulePkg / Core / Dxe / Image / ImageFile.c
CommitLineData
28a00297 1/*++\r
2\r
cfe9de52 3Copyright (c) 2006 - 2007, Intel Corporation\r
4All rights reserved. This program and the accompanying materials\r
5are licensed and made available under the terms and conditions of the BSD License\r
6which accompanies this distribution. The full text of the license may be found at\r
7http://opensource.org/licenses/bsd-license.php\r
8\r
9THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
10WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
28a00297 11\r
12Module Name:\r
cfe9de52 13\r
28a00297 14 ImageFile.c\r
15\r
16\r
17Abstract:\r
18\r
cfe9de52 19\r
28a00297 20\r
21\r
22Revision History\r
23\r
24--*/\r
25\r
26#include <DxeMain.h>\r
27\r
28EFI_STATUS\r
29CoreOpenImageFile (\r
30 IN BOOLEAN BootPolicy,\r
31 IN VOID *SourceBuffer OPTIONAL,\r
32 IN UINTN SourceSize,\r
cfe9de52 33 IN OUT EFI_DEVICE_PATH_PROTOCOL **FilePath,\r
28a00297 34 OUT EFI_HANDLE *DeviceHandle,\r
35 IN IMAGE_FILE_HANDLE *ImageFileHandle,\r
36 OUT UINT32 *AuthenticationStatus\r
37 )\r
38/*++\r
39\r
40Routine Description:\r
41\r
42 Opens a file for (simple) reading. The simple read abstraction\r
43 will access the file either from a memory copy, from a file\r
44 system interface, or from the load file interface.\r
45\r
46Arguments:\r
47\r
48 BootPolicy - Policy for Open Image File.\r
49 SourceBuffer - Pointer to the memory location containing copy\r
50 of the image to be loaded.\r
51 SourceSize - The size in bytes of SourceBuffer.\r
52 FilePath - The specific file path from which the image is loaded\r
53 DeviceHandle - Pointer to the return device handle.\r
54 ImageFileHandle - Pointer to the image file handle.\r
cfe9de52 55 AuthenticationStatus - Pointer to a caller-allocated UINT32 in which the authentication status is returned.\r
56\r
28a00297 57Returns:\r
58\r
59 EFI_SUCCESS - Image file successfully opened.\r
cfe9de52 60\r
28a00297 61 EFI_LOAD_ERROR - If the caller passed a copy of the file, and SourceSize is 0.\r
cfe9de52 62\r
28a00297 63 EFI_INVALID_PARAMETER - File path is not valid.\r
cfe9de52 64\r
28a00297 65 EFI_NOT_FOUND - File not found.\r
66\r
67--*/\r
68{\r
69 EFI_STATUS Status;\r
70 EFI_DEVICE_PATH_PROTOCOL *TempFilePath;\r
71 FILEPATH_DEVICE_PATH *FilePathNode;\r
72 MEDIA_FW_VOL_FILEPATH_DEVICE_PATH *FwVolFilePathNode;\r
73 EFI_SIMPLE_FILE_SYSTEM_PROTOCOL *Volume;\r
74 EFI_FILE_HANDLE FileHandle;\r
75 EFI_FILE_HANDLE LastHandle;\r
76 EFI_LOAD_FILE_PROTOCOL *LoadFile;\r
0c2b5da8 77 EFI_FIRMWARE_VOLUME2_PROTOCOL *FwVol;\r
28a00297 78 EFI_SECTION_TYPE SectionType;\r
79 UINT8 *Pe32Buffer;\r
80 UINTN Pe32BufferSize;\r
81 EFI_FV_FILETYPE Type;\r
82 EFI_FV_FILE_ATTRIBUTES Attrib;\r
83 EFI_FILE_INFO *FileInfo;\r
84 UINTN FileInfoSize;\r
85 EFI_GUID *NameGuid;\r
86\r
87 *AuthenticationStatus = 0;\r
88 ZeroMem (ImageFileHandle, sizeof (IMAGE_FILE_HANDLE));\r
89 ImageFileHandle->Signature = IMAGE_FILE_HANDLE_SIGNATURE;\r
90\r
91 //\r
92 // If the caller passed a copy of the file, then just use it\r
93 //\r
94 if (SourceBuffer != NULL) {\r
95 ImageFileHandle->Source = SourceBuffer;\r
96 ImageFileHandle->SourceSize = SourceSize;\r
97 *DeviceHandle = NULL;\r
cfe9de52 98 CoreLocateDevicePath (&gEfiDevicePathProtocolGuid, FilePath, DeviceHandle);\r
28a00297 99 if (SourceSize > 0) {\r
100 Status = EFI_SUCCESS;\r
101 } else {\r
102 Status = EFI_LOAD_ERROR;\r
103 }\r
104 goto Done;\r
105 }\r
106\r
107 //\r
108 // Make sure FilePath is valid\r
109 //\r
cfe9de52 110 if (*FilePath == NULL) {\r
28a00297 111 return EFI_INVALID_PARAMETER;\r
112 }\r
113\r
114 //\r
115 // Check to see if it's in a Firmware Volume\r
116 //\r
cfe9de52 117 FwVolFilePathNode = (MEDIA_FW_VOL_FILEPATH_DEVICE_PATH *) *FilePath;\r
28a00297 118 Status = CoreDevicePathToInterface (\r
cfe9de52 119 &gEfiFirmwareVolume2ProtocolGuid,\r
120 (EFI_DEVICE_PATH_PROTOCOL **)&FwVolFilePathNode,\r
121 (VOID*)&FwVol,\r
28a00297 122 DeviceHandle\r
123 );\r
124 if (!EFI_ERROR (Status)) {\r
125 //\r
126 // For FwVol File system there is only a single file name that is a GUID.\r
127 //\r
128 NameGuid = EfiGetNameGuidFromFwVolDevicePathNode (FwVolFilePathNode);\r
129 if (NameGuid != NULL) {\r
130\r
131 SectionType = EFI_SECTION_PE32;\r
132 Pe32Buffer = NULL;\r
133 Status = FwVol->ReadSection (\r
cfe9de52 134 FwVol,\r
135 NameGuid,\r
136 SectionType,\r
28a00297 137 0,\r
138 (VOID **)&Pe32Buffer,\r
139 &Pe32BufferSize,\r
140 AuthenticationStatus\r
141 );\r
142 if (EFI_ERROR (Status)) {\r
143 //\r
144 // Try a raw file, since a PE32 SECTION does not exist\r
145 //\r
146 if (Pe32Buffer != NULL) {\r
147 CoreFreePool (Pe32Buffer);\r
148 *AuthenticationStatus = 0;\r
149 }\r
150 Pe32Buffer = NULL;\r
151 Status = FwVol->ReadFile (\r
cfe9de52 152 FwVol,\r
153 NameGuid,\r
28a00297 154 (VOID **)&Pe32Buffer,\r
155 &Pe32BufferSize,\r
156 &Type,\r
157 &Attrib,\r
158 AuthenticationStatus\r
159 );\r
160 }\r
cfe9de52 161\r
28a00297 162 if (!EFI_ERROR (Status)) {\r
163 //\r
164 // One of the reads passed so we are done\r
165 //\r
166 ImageFileHandle->Source = Pe32Buffer;\r
167 ImageFileHandle->SourceSize = Pe32BufferSize;\r
168 ImageFileHandle->FreeBuffer = TRUE;\r
169 goto Done;\r
170 }\r
171 }\r
172 }\r
173\r
174 //\r
175 // Attempt to access the file via a file system interface\r
176 //\r
cfe9de52 177 FilePathNode = (FILEPATH_DEVICE_PATH *) *FilePath;\r
28a00297 178 Status = CoreDevicePathToInterface (\r
cfe9de52 179 &gEfiSimpleFileSystemProtocolGuid,\r
180 (EFI_DEVICE_PATH_PROTOCOL **)&FilePathNode,\r
181 (VOID*)&Volume,\r
28a00297 182 DeviceHandle\r
183 );\r
184 if (!EFI_ERROR (Status)) {\r
185 //\r
186 // Open the Volume to get the File System handle\r
187 //\r
188 Status = Volume->OpenVolume (Volume, &FileHandle);\r
189 if (!EFI_ERROR (Status)) {\r
cfe9de52 190\r
28a00297 191 //\r
192 // Parse each MEDIA_FILEPATH_DP node. There may be more than one, since the\r
193 // directory information and filename can be seperate. The goal is to inch\r
194 // our way down each device path node and close the previous node\r
195 //\r
196 while (!IsDevicePathEnd (&FilePathNode->Header)) {\r
197 if (DevicePathType (&FilePathNode->Header) != MEDIA_DEVICE_PATH ||\r
198 DevicePathSubType (&FilePathNode->Header) != MEDIA_FILEPATH_DP) {\r
199 Status = EFI_UNSUPPORTED;\r
200 }\r
201\r
202 if (EFI_ERROR (Status)) {\r
203 //\r
204 // Exit loop on Error\r
205 //\r
206 break;\r
207 }\r
208\r
209 LastHandle = FileHandle;\r
210 FileHandle = NULL;\r
211 Status = LastHandle->Open (\r
212 LastHandle,\r
213 &FileHandle,\r
214 FilePathNode->PathName,\r
215 EFI_FILE_MODE_READ,\r
216 0\r
217 );\r
218\r
219 //\r
220 // Close the previous node\r
221 //\r
222 LastHandle->Close (LastHandle);\r
223\r
224 FilePathNode = (FILEPATH_DEVICE_PATH *) NextDevicePathNode (&FilePathNode->Header);\r
225 }\r
226\r
227 if (!EFI_ERROR (Status)) {\r
228 //\r
229 // We have found the file. Now we need to read it. Before we can read the file we need to\r
230 // figure out how big the file is.\r
231 //\r
232 FileInfo = NULL;\r
233 FileInfoSize = sizeof (EFI_FILE_INFO);\r
234 while (CoreGrowBuffer (&Status, (VOID **)&FileInfo, FileInfoSize)) {\r
235 //\r
236 // Automatically allocate buffer of the correct size and make the call\r
237 //\r
238 Status = FileHandle->GetInfo (\r
239 FileHandle,\r
240 &gEfiFileInfoGuid,\r
241 &FileInfoSize,\r
cfe9de52 242 FileInfo\r
28a00297 243 );\r
244 }\r
245 if (!EFI_ERROR (Status)) {\r
246 //\r
247 // Allocate space for the file\r
248 //\r
249 ImageFileHandle->Source = CoreAllocateBootServicesPool ((UINTN)FileInfo->FileSize);\r
250 if (ImageFileHandle->Source != NULL) {\r
251 //\r
252 // Read the file into the buffer we allocated\r
253 //\r
254 ImageFileHandle->SourceSize = (UINTN)FileInfo->FileSize;\r
255 ImageFileHandle->FreeBuffer = TRUE;\r
256 Status = FileHandle->Read (FileHandle, &ImageFileHandle->SourceSize, ImageFileHandle->Source);\r
257\r
258 //\r
259 // Close the file since we are done\r
260 //\r
261 FileHandle->Close (FileHandle);\r
262 } else {\r
263 Status = EFI_OUT_OF_RESOURCES;\r
264 }\r
265\r
266 goto Done;\r
267 }\r
268 }\r
269 }\r
cfe9de52 270 }\r
28a00297 271\r
272\r
273 //\r
274 // Try LoadFile style\r
275 //\r
276\r
cfe9de52 277 TempFilePath = *FilePath;\r
28a00297 278 Status = CoreDevicePathToInterface (\r
279 &gEfiLoadFileProtocolGuid,\r
280 &TempFilePath,\r
281 (VOID*)&LoadFile,\r
282 DeviceHandle\r
283 );\r
284 if (!EFI_ERROR (Status)) {\r
285 //\r
286 // Call LoadFile with the correct buffer size\r
287 //\r
288 while (CoreGrowBuffer (&Status, (VOID **)&ImageFileHandle->Source, ImageFileHandle->SourceSize)) {\r
289 Status = LoadFile->LoadFile (\r
290 LoadFile,\r
291 TempFilePath,\r
292 BootPolicy,\r
293 &ImageFileHandle->SourceSize,\r
294 ImageFileHandle->Source\r
295 );\r
296 //\r
297 // If success or other error happens, stop loop\r
298 //\r
299 if (Status != EFI_BUFFER_TOO_SMALL) {\r
300 break;\r
301 }\r
302 }\r
303\r
304 if (!EFI_ERROR (Status) || Status == EFI_ALREADY_STARTED) {\r
305 ImageFileHandle->FreeBuffer = TRUE;\r
306 goto Done;\r
307 }\r
308 }\r
309\r
310 //\r
311 // Nothing else to try\r
312 //\r
313 DEBUG ((EFI_D_LOAD|EFI_D_WARN, "CoreOpenImageFile: Device did not support a known load protocol\n"));\r
314 Status = EFI_NOT_FOUND;\r
315\r
316Done:\r
317\r
318 //\r
319 // If the file was not accessed, clean up\r
320 //\r
321 if (EFI_ERROR (Status) && (Status != EFI_ALREADY_STARTED)) {\r
322 if (ImageFileHandle->FreeBuffer) {\r
323 //\r
324 // Free the source buffer if we allocated it\r
325 //\r
326 CoreFreePool (ImageFileHandle->Source);\r
327 }\r
328 }\r
329\r
330 return Status;\r
331}\r
332\r
333\r
334\r
335EFI_STATUS\r
336EFIAPI\r
337CoreReadImageFile (\r
338 IN VOID *UserHandle,\r
339 IN UINTN Offset,\r
340 IN OUT UINTN *ReadSize,\r
341 OUT VOID *Buffer\r
342 )\r
343/*++\r
344\r
345Routine Description:\r
346\r
347 Read image file (specified by UserHandle) into user specified buffer with specified offset\r
348 and length.\r
349\r
350Arguments:\r
351\r
352 UserHandle - Image file handle\r
cfe9de52 353\r
28a00297 354 Offset - Offset to the source file\r
cfe9de52 355\r
28a00297 356 ReadSize - For input, pointer of size to read;\r
357 For output, pointer of size actually read.\r
cfe9de52 358\r
28a00297 359 Buffer - Buffer to write into\r
360\r
361Returns:\r
362\r
363 EFI_SUCCESS - Successfully read the specified part of file into buffer.\r
364\r
365--*/\r
366{\r
367 UINTN EndPosition;\r
368 IMAGE_FILE_HANDLE *FHand;\r
369\r
370 FHand = (IMAGE_FILE_HANDLE *)UserHandle;\r
371 ASSERT (FHand->Signature == IMAGE_FILE_HANDLE_SIGNATURE);\r
372\r
373 //\r
374 // Move data from our local copy of the file\r
375 //\r
376 EndPosition = Offset + *ReadSize;\r
377 if (EndPosition > FHand->SourceSize) {\r
378 *ReadSize = (UINT32)(FHand->SourceSize - Offset);\r
cfe9de52 379 }\r
28a00297 380 if (Offset >= FHand->SourceSize) {\r
381 *ReadSize = 0;\r
382 }\r
383\r
384 CopyMem (Buffer, (CHAR8 *)FHand->Source + Offset, *ReadSize);\r
385 return EFI_SUCCESS;\r
386}\r
387\r
388EFI_STATUS\r
389CoreDevicePathToInterface (\r
390 IN EFI_GUID *Protocol,\r
391 IN EFI_DEVICE_PATH_PROTOCOL **FilePath,\r
392 OUT VOID **Interface,\r
393 OUT EFI_HANDLE *Handle\r
394 )\r
395/*++\r
396\r
397Routine Description:\r
398\r
399 Search a handle to a device on a specified device path that supports a specified protocol,\r
400 interface of that protocol on that handle is another output.\r
401\r
402Arguments:\r
403\r
404 Protocol - The protocol to search for\r
cfe9de52 405\r
28a00297 406 FilePath - The specified device path\r
cfe9de52 407\r
28a00297 408 Interface - Interface of the protocol on the handle\r
cfe9de52 409\r
28a00297 410 Handle - The handle to the device on the specified device path that supports the protocol.\r
cfe9de52 411\r
28a00297 412Returns:\r
413\r
414 Status code.\r
415\r
416--*/\r
417{\r
418 EFI_STATUS Status;\r
419\r
420 Status = CoreLocateDevicePath (Protocol, FilePath, Handle);\r
421 if (!EFI_ERROR (Status)) {\r
422 Status = CoreHandleProtocol (*Handle, Protocol, Interface);\r
423 }\r
424 return Status;\r
425}\r
426\r
427BOOLEAN\r
428CoreGrowBuffer (\r
429 IN OUT EFI_STATUS *Status,\r
430 IN OUT VOID **Buffer,\r
431 IN UINTN BufferSize\r
432 )\r
433/*++\r
434\r
435Routine Description:\r
436\r
437 Helper function called as part of the code needed\r
cfe9de52 438 to allocate the proper sized buffer for various\r
28a00297 439 EFI interfaces.\r
440\r
441Arguments:\r
442\r
443 Status - Current status\r
444\r
445 Buffer - Current allocated buffer, or NULL\r
446\r
447 BufferSize - Current buffer size needed\r
cfe9de52 448\r
28a00297 449Returns:\r
cfe9de52 450\r
451 TRUE - if the buffer was reallocated and the caller\r
28a00297 452 should try the API again.\r
453\r
454 FALSE - buffer could not be allocated and the caller\r
455 should not try the API again.\r
456\r
457--*/\r
458{\r
459 BOOLEAN TryAgain;\r
460\r
461 TryAgain = FALSE;\r
462 //\r
463 // If this is an initial request, buffer will be null with a new buffer size\r
464 //\r
465 if (*Buffer == NULL) {\r
466 *Status = EFI_BUFFER_TOO_SMALL;\r
467 }\r
468\r
469 if (BufferSize == 0) {\r
470 return TRUE;\r
471 }\r
472\r
473 //\r
474 // If the status code is "buffer too small", resize the buffer\r
475 //\r
cfe9de52 476\r
28a00297 477 if (*Status == EFI_BUFFER_TOO_SMALL) {\r
478 if (*Buffer != NULL) {\r
479 CoreFreePool (*Buffer);\r
480 }\r
481\r
482 *Buffer = CoreAllocateBootServicesPool (BufferSize);\r
483 if (*Buffer != NULL) {\r
484 TryAgain = TRUE;\r
cfe9de52 485 } else {\r
28a00297 486 *Status = EFI_OUT_OF_RESOURCES;\r
cfe9de52 487 }\r
28a00297 488 }\r
489\r
490 //\r
491 // If there's an error, free the buffer\r
492 //\r
493 if ((!TryAgain) && (EFI_ERROR (*Status)) && (*Buffer)) {\r
494 CoreFreePool (*Buffer);\r
495 *Buffer = NULL;\r
496 }\r
497\r
498 return TryAgain;\r
499}\r
500\r