+++ /dev/null
-/*++\r
-\r
-Copyright (c) 2006, Intel Corporation \r
-All rights reserved. This program and the accompanying materials \r
-are licensed and made available under the terms and conditions of the BSD License \r
-which accompanies this distribution. The full text of the license may be found at \r
-http://opensource.org/licenses/bsd-license.php \r
- \r
-THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, \r
-WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. \r
-\r
-Module Name:\r
-\r
- FwVolRead.c\r
-\r
-Abstract:\r
-\r
- Implements read firmware file\r
-\r
---*/\r
-\r
-#include <DxeMain.h>\r
-\r
-/*++\r
-\r
-Required Alignment Alignment Value in FFS Alignment Value in\r
-(bytes) Attributes Field Firmware Volume Interfaces\r
-1 0 0\r
-2 0 1\r
-4 0 2\r
-8 0 3\r
-16 1 4\r
-128 2 7\r
-512 3 9\r
-1 KB 4 10\r
-4 KB 5 12\r
-32 KB 6 15\r
-64 KB 7 16\r
-\r
---*/\r
-\r
-UINT8 mFvAttributes[] = {0, 4, 7, 9, 10, 12, 15, 16}; \r
-\r
-\r
-STATIC\r
-EFI_FV_FILE_ATTRIBUTES\r
-FfsAttributes2FvFileAttributes (\r
- IN EFI_FFS_FILE_ATTRIBUTES FfsAttributes\r
- )\r
-/*++\r
-\r
- Routine Description:\r
- Convert the FFS File Attributes to FV File Attributes\r
- \r
- Arguments:\r
- FfsAttributes - The attributes of UINT8 type.\r
- \r
- Returns:\r
- The attributes of EFI_FV_FILE_ATTRIBUTES\r
- \r
---*/\r
-{\r
- FfsAttributes = (EFI_FFS_FILE_ATTRIBUTES)((FfsAttributes & FFS_ATTRIB_DATA_ALIGNMENT) >> 3);\r
- ASSERT (FfsAttributes < 8);\r
-\r
- return (EFI_FV_FILE_ATTRIBUTES) mFvAttributes[FfsAttributes];\r
-}\r
-\r
-\r
-EFI_STATUS\r
-EFIAPI\r
-FvGetNextFile (\r
- IN EFI_FIRMWARE_VOLUME_PROTOCOL *This,\r
- IN OUT VOID *Key,\r
- IN OUT EFI_FV_FILETYPE *FileType,\r
- OUT EFI_GUID *NameGuid,\r
- OUT EFI_FV_FILE_ATTRIBUTES *Attributes,\r
- OUT UINTN *Size\r
- )\r
-/*++\r
-\r
-Routine Description:\r
- Given the input key, search for the next matching file in the volume.\r
-\r
-Arguments:\r
- This - Indicates the calling context.\r
- FileType - FileType is a pointer to a caller allocated\r
- EFI_FV_FILETYPE. The GetNextFile() API can filter it's\r
- search for files based on the value of *FileType input.\r
- A *FileType input of 0 causes GetNextFile() to search for\r
- files of all types. If a file is found, the file's type\r
- is returned in *FileType. *FileType is not modified if\r
- no file is found.\r
- Key - Key is a pointer to a caller allocated buffer that\r
- contains implementation specific data that is used to\r
- track where to begin the search for the next file.\r
- The size of the buffer must be at least This->KeySize\r
- bytes long. To reinitialize the search and begin from\r
- the beginning of the firmware volume, the entire buffer\r
- must be cleared to zero. Other than clearing the buffer\r
- to initiate a new search, the caller must not modify the\r
- data in the buffer between calls to GetNextFile().\r
- NameGuid - NameGuid is a pointer to a caller allocated EFI_GUID.\r
- If a file is found, the file's name is returned in\r
- *NameGuid. *NameGuid is not modified if no file is\r
- found.\r
- Attributes - Attributes is a pointer to a caller allocated\r
- EFI_FV_FILE_ATTRIBUTES. If a file is found, the file's\r
- attributes are returned in *Attributes. *Attributes is\r
- not modified if no file is found.\r
- Size - Size is a pointer to a caller allocated UINTN.\r
- If a file is found, the file's size is returned in *Size.\r
- *Size is not modified if no file is found.\r
-\r
-Returns:\r
- EFI_SUCCESS - Successfully find the file.\r
- EFI_DEVICE_ERROR - Device error.\r
- EFI_ACCESS_DENIED - Fv could not read.\r
- EFI_NOT_FOUND - No matching file found.\r
- EFI_INVALID_PARAMETER - Invalid parameter\r
-\r
---*/\r
-{\r
- EFI_STATUS Status;\r
- FV_DEVICE *FvDevice;\r
- EFI_FV_ATTRIBUTES FvAttributes;\r
- EFI_FFS_FILE_HEADER *FfsFileHeader;\r
- UINTN *KeyValue;\r
- LIST_ENTRY *Link;\r
- FFS_FILE_LIST_ENTRY *FfsFileEntry;\r
- UINTN FileLength;\r
-\r
- FvDevice = FV_DEVICE_FROM_THIS (This);\r
-\r
- Status = FvGetVolumeAttributes (This, &FvAttributes);\r
- if (EFI_ERROR (Status)){\r
- return Status;\r
- }\r
-\r
- //\r
- // Check if read operation is enabled\r
- //\r
- if ((FvAttributes & EFI_FV_READ_STATUS) == 0) {\r
- return EFI_ACCESS_DENIED;\r
- }\r
-\r
- if (*FileType > EFI_FV_FILETYPE_FIRMWARE_VOLUME_IMAGE) {\r
- //\r
- // File type needs to be in 0 - 0x0B\r
- //\r
- return EFI_INVALID_PARAMETER;\r
- }\r
-\r
- KeyValue = (UINTN *)Key;\r
- for (;;) {\r
- if (*KeyValue == 0) {\r
- //\r
- // Search for 1st matching file\r
- //\r
- Link = &FvDevice->FfsFileListHeader;\r
- } else {\r
- //\r
- // Key is pointer to FFsFileEntry, so get next one\r
- //\r
- Link = (LIST_ENTRY *)(*KeyValue);\r
- }\r
-\r
- if (Link->ForwardLink == &FvDevice->FfsFileListHeader) {\r
- //\r
- // Next is end of list so we did not find data\r
- //\r
- return EFI_NOT_FOUND;\r
- }\r
-\r
- FfsFileEntry = (FFS_FILE_LIST_ENTRY *)Link->ForwardLink;\r
- FfsFileHeader = (EFI_FFS_FILE_HEADER *)FfsFileEntry->FfsHeader;\r
-\r
- //\r
- // remember the key\r
- //\r
- *KeyValue = (UINTN)FfsFileEntry;\r
-\r
- if (FfsFileHeader->Type == EFI_FV_FILETYPE_FFS_PAD) {\r
- //\r
- // we ignore pad files\r
- //\r
- continue;\r
- }\r
-\r
- if (*FileType == 0) {\r
- //\r
- // Process all file types so we have a match\r
- //\r
- break;\r
- }\r
-\r
- if (*FileType == FfsFileHeader->Type) {\r
- //\r
- // Found a matching file type\r
- //\r
- break;\r
- }\r
-\r
- } \r
-\r
- //\r
- // Return FileType, NameGuid, and Attributes\r
- //\r
- *FileType = FfsFileHeader->Type;\r
- CopyMem (NameGuid, &FfsFileHeader->Name, sizeof (EFI_GUID));\r
- *Attributes = FfsAttributes2FvFileAttributes (FfsFileHeader->Attributes);\r
-\r
- //\r
- // Read four bytes out of the 3 byte array and throw out extra data\r
- //\r
- FileLength = *(UINT32 *)&FfsFileHeader->Size[0] & 0x00FFFFFF;\r
-\r
- //\r
- // we need to substract the header size\r
- //\r
- *Size = FileLength - sizeof(EFI_FFS_FILE_HEADER);\r
-\r
- if (FfsFileHeader->Attributes & FFS_ATTRIB_TAIL_PRESENT) {\r
- //\r
- // If tail is present substract it's size;\r
- //\r
- *Size -= sizeof(EFI_FFS_FILE_TAIL);\r
- }\r
-\r
- return EFI_SUCCESS;\r
-}\r
-\r
-\r
-EFI_STATUS\r
-EFIAPI\r
-FvReadFile (\r
- IN EFI_FIRMWARE_VOLUME_PROTOCOL *This,\r
- IN EFI_GUID *NameGuid,\r
- IN OUT VOID **Buffer,\r
- IN OUT UINTN *BufferSize,\r
- OUT EFI_FV_FILETYPE *FoundType,\r
- OUT EFI_FV_FILE_ATTRIBUTES *FileAttributes,\r
- OUT UINT32 *AuthenticationStatus\r
- )\r
-/*++\r
-\r
-Routine Description:\r
- Locates a file in the firmware volume and\r
- copies it to the supplied buffer.\r
-\r
-Arguments:\r
- This - Indicates the calling context.\r
- NameGuid - Pointer to an EFI_GUID, which is the filename.\r
- Buffer - Buffer is a pointer to pointer to a buffer in\r
- which the file or section contents or are returned.\r
- BufferSize - BufferSize is a pointer to caller allocated\r
- UINTN. On input *BufferSize indicates the size\r
- in bytes of the memory region pointed to by\r
- Buffer. On output, *BufferSize contains the number\r
- of bytes required to read the file.\r
- FoundType - FoundType is a pointer to a caller allocated\r
- EFI_FV_FILETYPE that on successful return from Read()\r
- contains the type of file read. This output reflects\r
- the file type irrespective of the value of the\r
- SectionType input.\r
- FileAttributes - FileAttributes is a pointer to a caller allocated\r
- EFI_FV_FILE_ATTRIBUTES. On successful return from\r
- Read(), *FileAttributes contains the attributes of\r
- the file read.\r
- AuthenticationStatus - AuthenticationStatus is a pointer to a caller\r
- allocated UINTN in which the authentication status\r
- is returned.\r
-Returns:\r
- EFI_SUCCESS - Successfully read to memory buffer.\r
- EFI_WARN_BUFFER_TOO_SMALL - Buffer too small.\r
- EFI_NOT_FOUND - Not found.\r
- EFI_DEVICE_ERROR - Device error.\r
- EFI_ACCESS_DENIED - Could not read.\r
- EFI_INVALID_PARAMETER - Invalid parameter.\r
- EFI_OUT_OF_RESOURCES - Not enough buffer to be allocated.\r
-\r
---*/\r
-{\r
- EFI_STATUS Status;\r
- FV_DEVICE *FvDevice;\r
- EFI_GUID SearchNameGuid;\r
- EFI_FV_FILETYPE LocalFoundType;\r
- EFI_FV_FILE_ATTRIBUTES LocalAttributes;\r
- UINTN FileSize;\r
- UINT8 *SrcPtr;\r
- EFI_FFS_FILE_HEADER *FfsHeader;\r
- UINTN InputBufferSize;\r
- \r
- if (NULL == NameGuid) {\r
- return EFI_INVALID_PARAMETER;\r
- }\r
-\r
- FvDevice = FV_DEVICE_FROM_THIS (This);\r
- \r
-\r
- //\r
- // Keep looking until we find the matching NameGuid.\r
- // The Key is really an FfsFileEntry\r
- //\r
- FvDevice->LastKey = 0;\r
- do {\r
- LocalFoundType = 0;\r
- Status = FvGetNextFile (\r
- This,\r
- &FvDevice->LastKey,\r
- &LocalFoundType,\r
- &SearchNameGuid,\r
- &LocalAttributes,\r
- &FileSize\r
- );\r
- if (EFI_ERROR (Status)) {\r
- return EFI_NOT_FOUND;\r
- }\r
- } while (!CompareGuid (&SearchNameGuid, NameGuid));\r
-\r
- //\r
- // Get a pointer to the header\r
- //\r
- FfsHeader = FvDevice->LastKey->FfsHeader;\r
-\r
- //\r
- // Remember callers buffer size\r
- //\r
- InputBufferSize = *BufferSize;\r
-\r
- //\r
- // Calculate return values\r
- //\r
- *FoundType = FfsHeader->Type;\r
- *FileAttributes = FfsAttributes2FvFileAttributes (FfsHeader->Attributes);\r
- *AuthenticationStatus = 0;\r
- *BufferSize = FileSize;\r
-\r
- if (Buffer == NULL) {\r
- //\r
- // If Buffer is NULL, we only want to get the information colected so far\r
- //\r
- return EFI_SUCCESS;\r
- }\r
-\r
- //\r
- // Skip over file header\r
- //\r
- SrcPtr = ((UINT8 *)FfsHeader) + sizeof (EFI_FFS_FILE_HEADER);\r
-\r
- Status = EFI_SUCCESS;\r
- if (*Buffer == NULL) {\r
- //\r
- // Caller passed in a pointer so allocate buffer for them\r
- //\r
- *Buffer = CoreAllocateBootServicesPool (FileSize);\r
- if (*Buffer == NULL) {\r
- return EFI_OUT_OF_RESOURCES;\r
- }\r
- } else if (FileSize > InputBufferSize) {\r
- //\r
- // Callers buffer was not big enough\r
- // \r
- Status = EFI_WARN_BUFFER_TOO_SMALL;\r
- FileSize = InputBufferSize;\r
- }\r
- \r
- //\r
- // Copy data into callers buffer \r
- //\r
- CopyMem (*Buffer, SrcPtr, FileSize);\r
-\r
- return Status;\r
-}\r
-\r
-\r
-EFI_STATUS\r
-EFIAPI\r
-FvReadFileSection (\r
- IN EFI_FIRMWARE_VOLUME_PROTOCOL *This,\r
- IN EFI_GUID *NameGuid,\r
- IN EFI_SECTION_TYPE SectionType,\r
- IN UINTN SectionInstance,\r
- IN OUT VOID **Buffer,\r
- IN OUT UINTN *BufferSize,\r
- OUT UINT32 *AuthenticationStatus\r
- )\r
-/*++\r
-\r
- Routine Description:\r
- Locates a section in a given FFS File and\r
- copies it to the supplied buffer (not including section header).\r
-\r
- Arguments:\r
- This - Indicates the calling context.\r
- NameGuid - Pointer to an EFI_GUID, which is the filename.\r
- SectionType - Indicates the section type to return.\r
- SectionInstance - Indicates which instance of sections with a type of\r
- SectionType to return.\r
- Buffer - Buffer is a pointer to pointer to a buffer in which\r
- the file or section contents or are returned.\r
- BufferSize - BufferSize is a pointer to caller allocated UINTN.\r
- AuthenticationStatus -AuthenticationStatus is a pointer to a caller\r
- allocated UINT32 in which the authentication status\r
- is returned.\r
-\r
- Returns:\r
- EFI_SUCCESS - Successfully read the file section into buffer.\r
- EFI_WARN_BUFFER_TOO_SMALL - Buffer too small.\r
- EFI_NOT_FOUND - Section not found.\r
- EFI_DEVICE_ERROR - Device error.\r
- EFI_ACCESS_DENIED - Could not read.\r
- EFI_INVALID_PARAMETER - Invalid parameter.\r
-\r
---*/\r
-{\r
- EFI_STATUS Status;\r
- FV_DEVICE *FvDevice;\r
- EFI_FV_FILETYPE FileType;\r
- EFI_FV_FILE_ATTRIBUTES FileAttributes;\r
- UINTN FileSize;\r
- UINT8 *FileBuffer;\r
- EFI_SECTION_EXTRACTION_PROTOCOL *Sep;\r
- FFS_FILE_LIST_ENTRY *FfsEntry;\r
- \r
- if (NULL == NameGuid || Buffer == NULL) {\r
- return EFI_INVALID_PARAMETER;\r
- }\r
-\r
- FvDevice = FV_DEVICE_FROM_THIS (This);\r
-\r
- //\r
- // Read the whole file into buffer\r
- //\r
- FileBuffer = NULL;\r
- Status = FvReadFile (\r
- This,\r
- NameGuid,\r
- (VOID **)&FileBuffer,\r
- &FileSize,\r
- &FileType,\r
- &FileAttributes,\r
- AuthenticationStatus\r
- ); \r
- //\r
- // Get the last key used by our call to FvReadFile as it is the FfsEntry for this file.\r
- // \r
- FfsEntry = (FFS_FILE_LIST_ENTRY *)FvDevice->LastKey;\r
-\r
- if (EFI_ERROR (Status)) {\r
- return Status;\r
- }\r
- \r
- //\r
- // Check to see that the file actually HAS sections before we go any further.\r
- //\r
- if (FileType == EFI_FV_FILETYPE_RAW) {\r
- Status = EFI_NOT_FOUND;\r
- goto Done;\r
- }\r
-\r
- //\r
- // Use FfsEntry to cache Section Extraction Protocol Inforomation\r
- //\r
- if (FfsEntry->StreamHandle == 0) {\r
- //\r
- // Located the protocol\r
- //\r
- Status = CoreLocateProtocol (&gEfiSectionExtractionProtocolGuid, NULL, (VOID **)&Sep);\r
- //\r
- // Section Extraction Protocol is part of Dxe Core so this should never fail\r
- //\r
- ASSERT_EFI_ERROR (Status);\r
-\r
- Status = Sep->OpenSectionStream (\r
- Sep,\r
- FileSize,\r
- FileBuffer,\r
- &FfsEntry->StreamHandle\r
- );\r
- if (EFI_ERROR (Status)) {\r
- goto Done;\r
- }\r
-\r
- FfsEntry->Sep = Sep;\r
- } else {\r
- //\r
- // Get cached copy of Sep\r
- //\r
- Sep = FfsEntry->Sep;\r
- }\r
-\r
- //\r
- // If SectionType == 0 We need the whole section stream\r
- //\r
- Status = Sep->GetSection (\r
- Sep,\r
- FfsEntry->StreamHandle,\r
- (SectionType == 0) ? NULL : &SectionType,\r
- NULL,\r
- (SectionType == 0) ? 0 : SectionInstance,\r
- Buffer,\r
- BufferSize,\r
- AuthenticationStatus\r
- );\r
-\r
- //\r
- // Close of stream defered to close of FfsHeader list to allow SEP to cache data\r
- //\r
-\r
-Done:\r
- CoreFreePool (FileBuffer);\r
-\r
- return Status;\r
-}\r
-\r