]> git.proxmox.com Git - mirror_edk2.git/blob - MdeModulePkg/Core/Dxe/FwVol/FwVolRead.c
Code Scrub for Dxe Core.
[mirror_edk2.git] / MdeModulePkg / Core / Dxe / FwVol / FwVolRead.c
1 /** @file
2 Implements functions to read firmware file
3
4 Copyright (c) 2006 - 2008, Intel Corporation. <BR>
5 All rights reserved. This program and the accompanying materials
6 are licensed and made available under the terms and conditions of the BSD License
7 which accompanies this distribution. The full text of the license may be found at
8 http://opensource.org/licenses/bsd-license.php
9
10 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
11 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
12
13 **/
14
15 #include <DxeMain.h>
16
17 /*++
18
19 Required Alignment Alignment Value in FFS Alignment Value in
20 (bytes) Attributes Field Firmware Volume Interfaces
21 1 0 0
22 2 0 1
23 4 0 2
24 8 0 3
25 16 1 4
26 128 2 7
27 512 3 9
28 1 KB 4 10
29 4 KB 5 12
30 32 KB 6 15
31 64 KB 7 16
32
33 --*/
34
35 UINT8 mFvAttributes[] = {0, 4, 7, 9, 10, 12, 15, 16};
36
37
38
39 /**
40 Convert the FFS File Attributes to FV File Attributes
41
42 @param FfsAttributes The attributes of UINT8 type.
43
44 @return The attributes of EFI_FV_FILE_ATTRIBUTES
45
46 **/
47 EFI_FV_FILE_ATTRIBUTES
48 FfsAttributes2FvFileAttributes (
49 IN EFI_FFS_FILE_ATTRIBUTES FfsAttributes
50 )
51 {
52 FfsAttributes = (EFI_FFS_FILE_ATTRIBUTES)((FfsAttributes & FFS_ATTRIB_DATA_ALIGNMENT) >> 3);
53 ASSERT (FfsAttributes < 8);
54
55 return (EFI_FV_FILE_ATTRIBUTES) mFvAttributes[FfsAttributes];
56 }
57
58
59
60 /**
61 Given the input key, search for the next matching file in the volume.
62
63 @param This Indicates the calling context.
64 @param Key Key is a pointer to a caller allocated
65 buffer that contains implementation specific
66 data that is used to track where to begin
67 the search for the next file. The size of
68 the buffer must be at least This->KeySize
69 bytes long. To reinitialize the search and
70 begin from the beginning of the firmware
71 volume, the entire buffer must be cleared to
72 zero. Other than clearing the buffer to
73 initiate a new search, the caller must not
74 modify the data in the buffer between calls
75 to GetNextFile().
76 @param FileType FileType is a pointer to a caller allocated
77 EFI_FV_FILETYPE. The GetNextFile() API can
78 filter it's search for files based on the
79 value of *FileType input. A *FileType input
80 of 0 causes GetNextFile() to search for
81 files of all types. If a file is found, the
82 file's type is returned in *FileType.
83 *FileType is not modified if no file is
84 found.
85 @param NameGuid NameGuid is a pointer to a caller allocated
86 EFI_GUID. If a file is found, the file's
87 name is returned in *NameGuid. *NameGuid is
88 not modified if no file is found.
89 @param Attributes Attributes is a pointer to a caller
90 allocated EFI_FV_FILE_ATTRIBUTES. If a file
91 is found, the file's attributes are returned
92 in *Attributes. *Attributes is not modified
93 if no file is found.
94 @param Size Size is a pointer to a caller allocated
95 UINTN. If a file is found, the file's size
96 is returned in *Size. *Size is not modified
97 if no file is found.
98
99 @retval EFI_SUCCESS Successfully find the file.
100 @retval EFI_DEVICE_ERROR Device error.
101 @retval EFI_ACCESS_DENIED Fv could not read.
102 @retval EFI_NOT_FOUND No matching file found.
103 @retval EFI_INVALID_PARAMETER Invalid parameter
104
105 **/
106 EFI_STATUS
107 EFIAPI
108 FvGetNextFile (
109 IN CONST EFI_FIRMWARE_VOLUME2_PROTOCOL *This,
110 IN OUT VOID *Key,
111 IN OUT EFI_FV_FILETYPE *FileType,
112 OUT EFI_GUID *NameGuid,
113 OUT EFI_FV_FILE_ATTRIBUTES *Attributes,
114 OUT UINTN *Size
115 )
116 {
117 EFI_STATUS Status;
118 FV_DEVICE *FvDevice;
119 EFI_FV_ATTRIBUTES FvAttributes;
120 EFI_FFS_FILE_HEADER *FfsFileHeader;
121 UINTN *KeyValue;
122 LIST_ENTRY *Link;
123 FFS_FILE_LIST_ENTRY *FfsFileEntry;
124 UINTN FileLength;
125
126 FvDevice = FV_DEVICE_FROM_THIS (This);
127
128 Status = FvGetVolumeAttributes (This, &FvAttributes);
129 if (EFI_ERROR (Status)){
130 return Status;
131 }
132
133 //
134 // Check if read operation is enabled
135 //
136 if ((FvAttributes & EFI_FV2_READ_STATUS) == 0) {
137 return EFI_ACCESS_DENIED;
138 }
139
140 if (*FileType > EFI_FV_FILETYPE_FIRMWARE_VOLUME_IMAGE) {
141 //
142 // File type needs to be in 0 - 0x0B
143 //
144 return EFI_NOT_FOUND;
145 }
146
147 KeyValue = (UINTN *)Key;
148 for (;;) {
149 if (*KeyValue == 0) {
150 //
151 // Search for 1st matching file
152 //
153 Link = &FvDevice->FfsFileListHeader;
154 } else {
155 //
156 // Key is pointer to FFsFileEntry, so get next one
157 //
158 Link = (LIST_ENTRY *)(*KeyValue);
159 }
160
161 if (Link->ForwardLink == &FvDevice->FfsFileListHeader) {
162 //
163 // Next is end of list so we did not find data
164 //
165 return EFI_NOT_FOUND;
166 }
167
168 FfsFileEntry = (FFS_FILE_LIST_ENTRY *)Link->ForwardLink;
169 FfsFileHeader = (EFI_FFS_FILE_HEADER *)FfsFileEntry->FfsHeader;
170
171 //
172 // remember the key
173 //
174 *KeyValue = (UINTN)FfsFileEntry;
175
176 if (FfsFileHeader->Type == EFI_FV_FILETYPE_FFS_PAD) {
177 //
178 // we ignore pad files
179 //
180 continue;
181 }
182
183 if (*FileType == EFI_FV_FILETYPE_ALL) {
184 //
185 // Process all file types so we have a match
186 //
187 break;
188 }
189
190 if (*FileType == FfsFileHeader->Type) {
191 //
192 // Found a matching file type
193 //
194 break;
195 }
196
197 }
198
199 //
200 // Return FileType, NameGuid, and Attributes
201 //
202 *FileType = FfsFileHeader->Type;
203 CopyGuid (NameGuid, &FfsFileHeader->Name);
204 *Attributes = FfsAttributes2FvFileAttributes (FfsFileHeader->Attributes);
205
206 //
207 // Read four bytes out of the 3 byte array and throw out extra data
208 //
209 FileLength = *(UINT32 *)&FfsFileHeader->Size[0] & 0x00FFFFFF;
210
211 //
212 // we need to substract the header size
213 //
214 *Size = FileLength - sizeof(EFI_FFS_FILE_HEADER);
215
216 return EFI_SUCCESS;
217 }
218
219
220
221 /**
222 Locates a file in the firmware volume and
223 copies it to the supplied buffer.
224
225 @param This Indicates the calling context.
226 @param NameGuid Pointer to an EFI_GUID, which is the
227 filename.
228 @param Buffer Buffer is a pointer to pointer to a buffer
229 in which the file or section contents or are
230 returned.
231 @param BufferSize BufferSize is a pointer to caller allocated
232 UINTN. On input *BufferSize indicates the
233 size in bytes of the memory region pointed
234 to by Buffer. On output, *BufferSize
235 contains the number of bytes required to
236 read the file.
237 @param FoundType FoundType is a pointer to a caller allocated
238 EFI_FV_FILETYPE that on successful return
239 from Read() contains the type of file read.
240 This output reflects the file type
241 irrespective of the value of the SectionType
242 input.
243 @param FileAttributes FileAttributes is a pointer to a caller
244 allocated EFI_FV_FILE_ATTRIBUTES. On
245 successful return from Read(),
246 *FileAttributes contains the attributes of
247 the file read.
248 @param AuthenticationStatus AuthenticationStatus is a pointer to a
249 caller allocated UINTN in which the
250 authentication status is returned.
251
252 @retval EFI_SUCCESS Successfully read to memory buffer.
253 @retval EFI_WARN_BUFFER_TOO_SMALL Buffer too small.
254 @retval EFI_NOT_FOUND Not found.
255 @retval EFI_DEVICE_ERROR Device error.
256 @retval EFI_ACCESS_DENIED Could not read.
257 @retval EFI_INVALID_PARAMETER Invalid parameter.
258 @retval EFI_OUT_OF_RESOURCES Not enough buffer to be allocated.
259
260 **/
261 EFI_STATUS
262 EFIAPI
263 FvReadFile (
264 IN CONST EFI_FIRMWARE_VOLUME2_PROTOCOL *This,
265 IN CONST EFI_GUID *NameGuid,
266 IN OUT VOID **Buffer,
267 IN OUT UINTN *BufferSize,
268 OUT EFI_FV_FILETYPE *FoundType,
269 OUT EFI_FV_FILE_ATTRIBUTES *FileAttributes,
270 OUT UINT32 *AuthenticationStatus
271 )
272 {
273 EFI_STATUS Status;
274 FV_DEVICE *FvDevice;
275 EFI_GUID SearchNameGuid;
276 EFI_FV_FILETYPE LocalFoundType;
277 EFI_FV_FILE_ATTRIBUTES LocalAttributes;
278 UINTN FileSize;
279 UINT8 *SrcPtr;
280 EFI_FFS_FILE_HEADER *FfsHeader;
281 UINTN InputBufferSize;
282
283 if (NameGuid == NULL) {
284 return EFI_INVALID_PARAMETER;
285 }
286
287 FvDevice = FV_DEVICE_FROM_THIS (This);
288
289
290 //
291 // Keep looking until we find the matching NameGuid.
292 // The Key is really an FfsFileEntry
293 //
294 FvDevice->LastKey = 0;
295 do {
296 LocalFoundType = 0;
297 Status = FvGetNextFile (
298 This,
299 &FvDevice->LastKey,
300 &LocalFoundType,
301 &SearchNameGuid,
302 &LocalAttributes,
303 &FileSize
304 );
305 if (EFI_ERROR (Status)) {
306 return EFI_NOT_FOUND;
307 }
308 } while (!CompareGuid (&SearchNameGuid, NameGuid));
309
310 //
311 // Get a pointer to the header
312 //
313 FfsHeader = FvDevice->LastKey->FfsHeader;
314
315 //
316 // Remember callers buffer size
317 //
318 InputBufferSize = *BufferSize;
319
320 //
321 // Calculate return values
322 //
323 *FoundType = FfsHeader->Type;
324 *FileAttributes = FfsAttributes2FvFileAttributes (FfsHeader->Attributes);
325 *AuthenticationStatus = 0;
326 *BufferSize = FileSize;
327
328 if (Buffer == NULL) {
329 //
330 // If Buffer is NULL, we only want to get the information colected so far
331 //
332 return EFI_SUCCESS;
333 }
334
335 //
336 // Skip over file header
337 //
338 SrcPtr = ((UINT8 *)FfsHeader) + sizeof (EFI_FFS_FILE_HEADER);
339
340 Status = EFI_SUCCESS;
341 if (*Buffer == NULL) {
342 //
343 // Caller passed in a pointer so allocate buffer for them
344 //
345 *Buffer = CoreAllocateBootServicesPool (FileSize);
346 if (*Buffer == NULL) {
347 return EFI_OUT_OF_RESOURCES;
348 }
349 } else if (FileSize > InputBufferSize) {
350 //
351 // Callers buffer was not big enough
352 //
353 Status = EFI_WARN_BUFFER_TOO_SMALL;
354 FileSize = InputBufferSize;
355 }
356
357 //
358 // Copy data into callers buffer
359 //
360 CopyMem (*Buffer, SrcPtr, FileSize);
361
362 return Status;
363 }
364
365
366
367 /**
368 Locates a section in a given FFS File and
369 copies it to the supplied buffer (not including section header).
370
371 @param This Indicates the calling context.
372 @param NameGuid Pointer to an EFI_GUID, which is the
373 filename.
374 @param SectionType Indicates the section type to return.
375 @param SectionInstance Indicates which instance of sections with a
376 type of SectionType to return.
377 @param Buffer Buffer is a pointer to pointer to a buffer
378 in which the file or section contents or are
379 returned.
380 @param BufferSize BufferSize is a pointer to caller allocated
381 UINTN.
382 @param AuthenticationStatus AuthenticationStatus is a pointer to a
383 caller allocated UINT32 in which the
384 authentication status is returned.
385
386 @retval EFI_SUCCESS Successfully read the file section into
387 buffer.
388 @retval EFI_WARN_BUFFER_TOO_SMALL Buffer too small.
389 @retval EFI_NOT_FOUND Section not found.
390 @retval EFI_DEVICE_ERROR Device error.
391 @retval EFI_ACCESS_DENIED Could not read.
392 @retval EFI_INVALID_PARAMETER Invalid parameter.
393
394 **/
395 EFI_STATUS
396 EFIAPI
397 FvReadFileSection (
398 IN CONST EFI_FIRMWARE_VOLUME2_PROTOCOL *This,
399 IN CONST EFI_GUID *NameGuid,
400 IN EFI_SECTION_TYPE SectionType,
401 IN UINTN SectionInstance,
402 IN OUT VOID **Buffer,
403 IN OUT UINTN *BufferSize,
404 OUT UINT32 *AuthenticationStatus
405 )
406 {
407 EFI_STATUS Status;
408 FV_DEVICE *FvDevice;
409 EFI_FV_FILETYPE FileType;
410 EFI_FV_FILE_ATTRIBUTES FileAttributes;
411 UINTN FileSize;
412 UINT8 *FileBuffer;
413 FFS_FILE_LIST_ENTRY *FfsEntry;
414
415 if (NameGuid == NULL || Buffer == NULL) {
416 return EFI_INVALID_PARAMETER;
417 }
418
419 FvDevice = FV_DEVICE_FROM_THIS (This);
420
421 //
422 // Read the whole file into buffer
423 //
424 FileBuffer = NULL;
425 Status = FvReadFile (
426 This,
427 NameGuid,
428 (VOID **)&FileBuffer,
429 &FileSize,
430 &FileType,
431 &FileAttributes,
432 AuthenticationStatus
433 );
434 //
435 // Get the last key used by our call to FvReadFile as it is the FfsEntry for this file.
436 //
437 FfsEntry = (FFS_FILE_LIST_ENTRY *) FvDevice->LastKey;
438
439 if (EFI_ERROR (Status)) {
440 return Status;
441 }
442
443 //
444 // Check to see that the file actually HAS sections before we go any further.
445 //
446 if (FileType == EFI_FV_FILETYPE_RAW) {
447 Status = EFI_NOT_FOUND;
448 goto Done;
449 }
450
451 //
452 // Use FfsEntry to cache Section Extraction Protocol Inforomation
453 //
454 if (FfsEntry->StreamHandle == 0) {
455 Status = OpenSectionStream (
456 FileSize,
457 FileBuffer,
458 &FfsEntry->StreamHandle
459 );
460 if (EFI_ERROR (Status)) {
461 goto Done;
462 }
463 }
464
465 //
466 // If SectionType == 0 We need the whole section stream
467 //
468 Status = GetSection (
469 FfsEntry->StreamHandle,
470 (SectionType == 0) ? NULL : &SectionType,
471 NULL,
472 (SectionType == 0) ? 0 : SectionInstance,
473 Buffer,
474 BufferSize,
475 AuthenticationStatus
476 );
477
478 //
479 // Close of stream defered to close of FfsHeader list to allow SEP to cache data
480 //
481
482 Done:
483 CoreFreePool (FileBuffer);
484
485 return Status;
486 }
487
488