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