]> git.proxmox.com Git - mirror_edk2.git/blame - MdeModulePkg/Core/Dxe/Image/ImageFile.c
Add assertion to ensure pointer dereference has been checked against NULL pointer.
[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
0c2b5da8 93 EFI_FIRMWARE_VOLUME2_PROTOCOL *FwVol;\r
28a00297 94 EFI_SECTION_TYPE SectionType;\r
95 UINT8 *Pe32Buffer;\r
96 UINTN Pe32BufferSize;\r
97 EFI_FV_FILETYPE Type;\r
98 EFI_FV_FILE_ATTRIBUTES Attrib;\r
99 EFI_FILE_INFO *FileInfo;\r
100 UINTN FileInfoSize;\r
101 EFI_GUID *NameGuid;\r
1564e9ac 102 FILEPATH_DEVICE_PATH *OriginalFilePathNode;\r
28a00297 103\r
1564e9ac 104 OriginalFilePathNode = NULL;\r
28a00297 105 *AuthenticationStatus = 0;\r
106 ZeroMem (ImageFileHandle, sizeof (IMAGE_FILE_HANDLE));\r
107 ImageFileHandle->Signature = IMAGE_FILE_HANDLE_SIGNATURE;\r
108\r
109 //\r
110 // If the caller passed a copy of the file, then just use it\r
111 //\r
112 if (SourceBuffer != NULL) {\r
113 ImageFileHandle->Source = SourceBuffer;\r
114 ImageFileHandle->SourceSize = SourceSize;\r
e94a9ff7 115 *DeviceHandle = NULL;\r
cfe9de52 116 CoreLocateDevicePath (&gEfiDevicePathProtocolGuid, FilePath, DeviceHandle);\r
28a00297 117 if (SourceSize > 0) {\r
118 Status = EFI_SUCCESS;\r
119 } else {\r
120 Status = EFI_LOAD_ERROR;\r
121 }\r
122 goto Done;\r
123 }\r
124\r
125 //\r
126 // Make sure FilePath is valid\r
127 //\r
cfe9de52 128 if (*FilePath == NULL) {\r
28a00297 129 return EFI_INVALID_PARAMETER;\r
130 }\r
131\r
132 //\r
133 // Check to see if it's in a Firmware Volume\r
134 //\r
cfe9de52 135 FwVolFilePathNode = (MEDIA_FW_VOL_FILEPATH_DEVICE_PATH *) *FilePath;\r
28a00297 136 Status = CoreDevicePathToInterface (\r
cfe9de52 137 &gEfiFirmwareVolume2ProtocolGuid,\r
138 (EFI_DEVICE_PATH_PROTOCOL **)&FwVolFilePathNode,\r
139 (VOID*)&FwVol,\r
28a00297 140 DeviceHandle\r
141 );\r
142 if (!EFI_ERROR (Status)) {\r
143 //\r
144 // For FwVol File system there is only a single file name that is a GUID.\r
145 //\r
146 NameGuid = EfiGetNameGuidFromFwVolDevicePathNode (FwVolFilePathNode);\r
147 if (NameGuid != NULL) {\r
148\r
149 SectionType = EFI_SECTION_PE32;\r
150 Pe32Buffer = NULL;\r
151 Status = FwVol->ReadSection (\r
cfe9de52 152 FwVol,\r
153 NameGuid,\r
154 SectionType,\r
28a00297 155 0,\r
156 (VOID **)&Pe32Buffer,\r
157 &Pe32BufferSize,\r
158 AuthenticationStatus\r
159 );\r
160 if (EFI_ERROR (Status)) {\r
161 //\r
162 // Try a raw file, since a PE32 SECTION does not exist\r
163 //\r
164 if (Pe32Buffer != NULL) {\r
165 CoreFreePool (Pe32Buffer);\r
166 *AuthenticationStatus = 0;\r
167 }\r
168 Pe32Buffer = NULL;\r
169 Status = FwVol->ReadFile (\r
cfe9de52 170 FwVol,\r
171 NameGuid,\r
28a00297 172 (VOID **)&Pe32Buffer,\r
173 &Pe32BufferSize,\r
174 &Type,\r
175 &Attrib,\r
176 AuthenticationStatus\r
177 );\r
178 }\r
cfe9de52 179\r
28a00297 180 if (!EFI_ERROR (Status)) {\r
181 //\r
182 // One of the reads passed so we are done\r
183 //\r
184 ImageFileHandle->Source = Pe32Buffer;\r
185 ImageFileHandle->SourceSize = Pe32BufferSize;\r
186 ImageFileHandle->FreeBuffer = TRUE;\r
187 goto Done;\r
188 }\r
189 }\r
190 }\r
191\r
192 //\r
193 // Attempt to access the file via a file system interface\r
194 //\r
cfe9de52 195 FilePathNode = (FILEPATH_DEVICE_PATH *) *FilePath;\r
28a00297 196 Status = CoreDevicePathToInterface (\r
cfe9de52 197 &gEfiSimpleFileSystemProtocolGuid,\r
198 (EFI_DEVICE_PATH_PROTOCOL **)&FilePathNode,\r
199 (VOID*)&Volume,\r
28a00297 200 DeviceHandle\r
201 );\r
202 if (!EFI_ERROR (Status)) {\r
203 //\r
204 // Open the Volume to get the File System handle\r
205 //\r
206 Status = Volume->OpenVolume (Volume, &FileHandle);\r
207 if (!EFI_ERROR (Status)) {\r
28a00297 208 //\r
1564e9ac 209 // Duplicate the device path to avoid the access to unaligned device path node.\r
210 // Because the device path consists of one or more FILE PATH MEDIA DEVICE PATH\r
022c6d45 211 // nodes, It assures the fields in device path nodes are 2 byte aligned.\r
28a00297 212 //\r
9c4ac31c 213 FilePathNode = (FILEPATH_DEVICE_PATH *)DuplicateDevicePath((EFI_DEVICE_PATH_PROTOCOL *)(UINTN)FilePathNode);\r
1564e9ac 214 if (FilePathNode == NULL) {\r
215 FileHandle->Close (FileHandle);\r
216 Status = EFI_OUT_OF_RESOURCES;\r
217 } else {\r
218 OriginalFilePathNode = FilePathNode;\r
219 //\r
220 // Parse each MEDIA_FILEPATH_DP node. There may be more than one, since the\r
221 // directory information and filename can be seperate. The goal is to inch\r
222 // our way down each device path node and close the previous node\r
223 //\r
224 while (!IsDevicePathEnd (&FilePathNode->Header)) {\r
225 if (DevicePathType (&FilePathNode->Header) != MEDIA_DEVICE_PATH ||\r
226 DevicePathSubType (&FilePathNode->Header) != MEDIA_FILEPATH_DP) {\r
227 Status = EFI_UNSUPPORTED;\r
228 }\r
229\r
230 if (EFI_ERROR (Status)) {\r
231 //\r
232 // Exit loop on Error\r
233 //\r
234 break;\r
235 }\r
236\r
237 LastHandle = FileHandle;\r
238 FileHandle = NULL;\r
239\r
240 Status = LastHandle->Open (\r
241 LastHandle,\r
242 &FileHandle,\r
243 FilePathNode->PathName,\r
244 EFI_FILE_MODE_READ,\r
245 0\r
246 );\r
28a00297 247\r
28a00297 248 //\r
1564e9ac 249 // Close the previous node\r
28a00297 250 //\r
1564e9ac 251 LastHandle->Close (LastHandle);\r
28a00297 252\r
1564e9ac 253 FilePathNode = (FILEPATH_DEVICE_PATH *) NextDevicePathNode (&FilePathNode->Header);\r
254 }\r
28a00297 255 //\r
022c6d45 256 // Free the allocated memory pool\r
28a00297 257 //\r
1564e9ac 258 CoreFreePool(OriginalFilePathNode);\r
28a00297 259 }\r
260\r
261 if (!EFI_ERROR (Status)) {\r
262 //\r
263 // We have found the file. Now we need to read it. Before we can read the file we need to\r
264 // figure out how big the file is.\r
265 //\r
266 FileInfo = NULL;\r
61ad8a41 267 FileInfoSize = 0;\r
268 Status = FileHandle->GetInfo (\r
269 FileHandle,\r
270 &gEfiFileInfoGuid,\r
271 &FileInfoSize,\r
272 FileInfo\r
273 );\r
274 if (Status == EFI_BUFFER_TOO_SMALL) {\r
275 FileInfo = AllocatePool (FileInfoSize);\r
276 if (FileInfo != NULL) {\r
277 Status = FileHandle->GetInfo (\r
278 FileHandle,\r
279 &gEfiFileInfoGuid,\r
280 &FileInfoSize,\r
281 FileInfo\r
282 );\r
283 } else {\r
284 Status = EFI_OUT_OF_RESOURCES;\r
285 goto Done;\r
286 }\r
28a00297 287 }\r
61ad8a41 288 \r
28a00297 289 if (!EFI_ERROR (Status)) {\r
290 //\r
291 // Allocate space for the file\r
292 //\r
20bcdbcb 293 ASSERT (FileInfo != NULL);\r
9c4ac31c 294 ImageFileHandle->Source = AllocatePool ((UINTN)FileInfo->FileSize);\r
28a00297 295 if (ImageFileHandle->Source != NULL) {\r
296 //\r
297 // Read the file into the buffer we allocated\r
298 //\r
e94a9ff7 299 ImageFileHandle->SourceSize = (UINTN) FileInfo->FileSize;\r
28a00297 300 ImageFileHandle->FreeBuffer = TRUE;\r
301 Status = FileHandle->Read (FileHandle, &ImageFileHandle->SourceSize, ImageFileHandle->Source);\r
302\r
303 //\r
304 // Close the file since we are done\r
305 //\r
306 FileHandle->Close (FileHandle);\r
61ad8a41 307 CoreFreePool (FileInfo);\r
28a00297 308 } else {\r
309 Status = EFI_OUT_OF_RESOURCES;\r
310 }\r
311\r
312 goto Done;\r
313 }\r
314 }\r
315 }\r
cfe9de52 316 }\r
28a00297 317\r
318\r
319 //\r
320 // Try LoadFile style\r
321 //\r
322\r
cfe9de52 323 TempFilePath = *FilePath;\r
28a00297 324 Status = CoreDevicePathToInterface (\r
e94a9ff7 325 &gEfiLoadFileProtocolGuid,\r
326 &TempFilePath,\r
327 (VOID*) &LoadFile,\r
328 DeviceHandle\r
329 );\r
28a00297 330 if (!EFI_ERROR (Status)) {\r
331 //\r
332 // Call LoadFile with the correct buffer size\r
333 //\r
61ad8a41 334 ASSERT (ImageFileHandle->SourceSize == 0);\r
335 ASSERT (ImageFileHandle->Source == NULL);\r
336 Status = LoadFile->LoadFile (\r
337 LoadFile,\r
338 TempFilePath,\r
339 BootPolicy,\r
340 &ImageFileHandle->SourceSize,\r
341 ImageFileHandle->Source\r
342 );\r
343 if (Status == EFI_BUFFER_TOO_SMALL) {\r
344 ImageFileHandle->Source = AllocatePool (ImageFileHandle->SourceSize);\r
345 if (ImageFileHandle->Source == NULL) {\r
346 Status = EFI_OUT_OF_RESOURCES;\r
347 } else {\r
348 Status = LoadFile->LoadFile (\r
349 LoadFile,\r
350 TempFilePath,\r
351 BootPolicy,\r
352 &ImageFileHandle->SourceSize,\r
353 ImageFileHandle->Source\r
354 );\r
28a00297 355 }\r
356 }\r
357\r
4792a1a6 358 if (!EFI_ERROR (Status)) {\r
28a00297 359 ImageFileHandle->FreeBuffer = TRUE;\r
360 goto Done;\r
361 }\r
362 }\r
363\r
364 //\r
365 // Nothing else to try\r
366 //\r
61ad8a41 367 DEBUG ((DEBUG_LOAD|DEBUG_WARN, "CoreOpenImageFile: Device did not support a known load protocol\n"));\r
28a00297 368 Status = EFI_NOT_FOUND;\r
369\r
370Done:\r
28a00297 371 //\r
372 // If the file was not accessed, clean up\r
373 //\r
4792a1a6 374 if (EFI_ERROR (Status)) {\r
28a00297 375 if (ImageFileHandle->FreeBuffer) {\r
376 //\r
377 // Free the source buffer if we allocated it\r
378 //\r
379 CoreFreePool (ImageFileHandle->Source);\r
380 }\r
381 }\r
382\r
383 return Status;\r
384}\r
385\r
386\r
387\r
162ed594 388/**\r
389 Read image file (specified by UserHandle) into user specified buffer with specified offset\r
390 and length.\r
391\r
022c6d45 392 @param UserHandle Image file handle\r
393 @param Offset Offset to the source file\r
394 @param ReadSize For input, pointer of size to read; For output,\r
395 pointer of size actually read.\r
396 @param Buffer Buffer to write into\r
162ed594 397\r
022c6d45 398 @retval EFI_SUCCESS Successfully read the specified part of file\r
162ed594 399 into buffer.\r
400\r
401**/\r
28a00297 402EFI_STATUS\r
403EFIAPI\r
404CoreReadImageFile (\r
405 IN VOID *UserHandle,\r
406 IN UINTN Offset,\r
407 IN OUT UINTN *ReadSize,\r
408 OUT VOID *Buffer\r
409 )\r
28a00297 410{\r
411 UINTN EndPosition;\r
412 IMAGE_FILE_HANDLE *FHand;\r
413\r
414 FHand = (IMAGE_FILE_HANDLE *)UserHandle;\r
415 ASSERT (FHand->Signature == IMAGE_FILE_HANDLE_SIGNATURE);\r
416\r
417 //\r
418 // Move data from our local copy of the file\r
419 //\r
420 EndPosition = Offset + *ReadSize;\r
421 if (EndPosition > FHand->SourceSize) {\r
422 *ReadSize = (UINT32)(FHand->SourceSize - Offset);\r
cfe9de52 423 }\r
28a00297 424 if (Offset >= FHand->SourceSize) {\r
425 *ReadSize = 0;\r
426 }\r
427\r
428 CopyMem (Buffer, (CHAR8 *)FHand->Source + Offset, *ReadSize);\r
429 return EFI_SUCCESS;\r
430}\r
431\r