]> git.proxmox.com Git - mirror_edk2.git/blob - StandaloneMmPkg/Core/FwVol.c
70cb8e71dfbde5265e52830fbb204cb2c3b9d6dd
[mirror_edk2.git] / StandaloneMmPkg / Core / FwVol.c
1 /** @file
2 Firmware volume helper interfaces.
3
4 Copyright (c) 2015, Intel Corporation. All rights reserved.<BR>
5 Copyright (c) 2016 - 2021, Arm Limited. All rights reserved.<BR>
6 SPDX-License-Identifier: BSD-2-Clause-Patent
7
8 **/
9
10 #include "StandaloneMmCore.h"
11 #include <Library/FvLib.h>
12 #include <Library/ExtractGuidedSectionLib.h>
13
14 //
15 // List of file types supported by dispatcher
16 //
17 EFI_FV_FILETYPE mMmFileTypes[] = {
18 EFI_FV_FILETYPE_MM,
19 0xE, //EFI_FV_FILETYPE_MM_STANDALONE,
20 //
21 // Note: DXE core will process the FV image file, so skip it in MM core
22 // EFI_FV_FILETYPE_FIRMWARE_VOLUME_IMAGE
23 //
24 };
25
26 EFI_STATUS
27 MmAddToDriverList (
28 IN EFI_FIRMWARE_VOLUME_HEADER *FwVolHeader,
29 IN VOID *Pe32Data,
30 IN UINTN Pe32DataSize,
31 IN VOID *Depex,
32 IN UINTN DepexSize,
33 IN EFI_GUID *DriverName
34 );
35
36 BOOLEAN
37 FvHasBeenProcessed (
38 IN EFI_FIRMWARE_VOLUME_HEADER *FwVolHeader
39 );
40
41 VOID
42 FvIsBeingProcessed (
43 IN EFI_FIRMWARE_VOLUME_HEADER *FwVolHeader
44 );
45
46 /**
47 Given the pointer to the Firmware Volume Header find the
48 MM driver and return its PE32 image.
49
50 @param [in] FwVolHeader Pointer to memory mapped FV
51
52 @retval EFI_SUCCESS Success.
53 @retval EFI_INVALID_PARAMETER Invalid parameter.
54 @retval EFI_NOT_FOUND Could not find section data.
55 @retval EFI_OUT_OF_RESOURCES Out of resources.
56 @retval EFI_VOLUME_CORRUPTED Firmware volume is corrupted.
57 @retval EFI_UNSUPPORTED Operation not supported.
58
59 **/
60 EFI_STATUS
61 MmCoreFfsFindMmDriver (
62 IN EFI_FIRMWARE_VOLUME_HEADER *FwVolHeader
63 )
64 {
65 EFI_STATUS Status;
66 EFI_STATUS DepexStatus;
67 EFI_FFS_FILE_HEADER *FileHeader;
68 EFI_FV_FILETYPE FileType;
69 VOID *Pe32Data;
70 UINTN Pe32DataSize;
71 VOID *Depex;
72 UINTN DepexSize;
73 UINTN Index;
74 EFI_COMMON_SECTION_HEADER *Section;
75 VOID *SectionData;
76 UINTN SectionDataSize;
77 UINT32 DstBufferSize;
78 VOID *ScratchBuffer;
79 UINT32 ScratchBufferSize;
80 VOID *DstBuffer;
81 UINT16 SectionAttribute;
82 UINT32 AuthenticationStatus;
83 EFI_FIRMWARE_VOLUME_HEADER *InnerFvHeader;
84
85 DEBUG ((DEBUG_INFO, "MmCoreFfsFindMmDriver - 0x%x\n", FwVolHeader));
86
87 if (FvHasBeenProcessed (FwVolHeader)) {
88 return EFI_SUCCESS;
89 }
90
91 FvIsBeingProcessed (FwVolHeader);
92
93 //
94 // First check for encapsulated compressed firmware volumes
95 //
96 FileHeader = NULL;
97 do {
98 Status = FfsFindNextFile (EFI_FV_FILETYPE_FIRMWARE_VOLUME_IMAGE,
99 FwVolHeader, &FileHeader);
100 if (EFI_ERROR (Status)) {
101 break;
102 }
103 Status = FfsFindSectionData (EFI_SECTION_GUID_DEFINED, FileHeader,
104 &SectionData, &SectionDataSize);
105 if (EFI_ERROR (Status)) {
106 break;
107 }
108 Section = (EFI_COMMON_SECTION_HEADER *)(FileHeader + 1);
109 Status = ExtractGuidedSectionGetInfo (Section, &DstBufferSize,
110 &ScratchBufferSize, &SectionAttribute);
111 if (EFI_ERROR (Status)) {
112 break;
113 }
114
115 //
116 // Allocate scratch buffer
117 //
118 ScratchBuffer = (VOID *)(UINTN)AllocatePages (EFI_SIZE_TO_PAGES (ScratchBufferSize));
119 if (ScratchBuffer == NULL) {
120 return EFI_OUT_OF_RESOURCES;
121 }
122
123 //
124 // Allocate destination buffer, extra one page for adjustment
125 //
126 DstBuffer = (VOID *)(UINTN)AllocatePages (EFI_SIZE_TO_PAGES (DstBufferSize));
127 if (DstBuffer == NULL) {
128 return EFI_OUT_OF_RESOURCES;
129 }
130
131 //
132 // Call decompress function
133 //
134 Status = ExtractGuidedSectionDecode (Section, &DstBuffer, ScratchBuffer,
135 &AuthenticationStatus);
136 FreePages (ScratchBuffer, EFI_SIZE_TO_PAGES (ScratchBufferSize));
137 if (EFI_ERROR (Status)) {
138 goto FreeDstBuffer;
139 }
140
141 DEBUG ((DEBUG_INFO,
142 "Processing compressed firmware volume (AuthenticationStatus == %x)\n",
143 AuthenticationStatus));
144
145 Status = FindFfsSectionInSections (DstBuffer, DstBufferSize,
146 EFI_SECTION_FIRMWARE_VOLUME_IMAGE, &Section);
147 if (EFI_ERROR (Status)) {
148 goto FreeDstBuffer;
149 }
150
151 InnerFvHeader = (VOID *)(Section + 1);
152 Status = MmCoreFfsFindMmDriver (InnerFvHeader);
153 if (EFI_ERROR (Status)) {
154 goto FreeDstBuffer;
155 }
156 } while (TRUE);
157
158 for (Index = 0; Index < sizeof (mMmFileTypes) / sizeof (mMmFileTypes[0]); Index++) {
159 DEBUG ((DEBUG_INFO, "Check MmFileTypes - 0x%x\n", mMmFileTypes[Index]));
160 FileType = mMmFileTypes[Index];
161 FileHeader = NULL;
162 do {
163 Status = FfsFindNextFile (FileType, FwVolHeader, &FileHeader);
164 if (!EFI_ERROR (Status)) {
165 Status = FfsFindSectionData (EFI_SECTION_PE32, FileHeader, &Pe32Data, &Pe32DataSize);
166 DEBUG ((DEBUG_INFO, "Find PE data - 0x%x\n", Pe32Data));
167 DepexStatus = FfsFindSectionData (EFI_SECTION_MM_DEPEX, FileHeader, &Depex, &DepexSize);
168 if (!EFI_ERROR (DepexStatus)) {
169 MmAddToDriverList (FwVolHeader, Pe32Data, Pe32DataSize, Depex, DepexSize, &FileHeader->Name);
170 }
171 }
172 } while (!EFI_ERROR (Status));
173 }
174
175 return EFI_SUCCESS;
176
177 FreeDstBuffer:
178 FreePages (DstBuffer, EFI_SIZE_TO_PAGES (DstBufferSize));
179
180 return Status;
181 }