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