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