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