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