@@ -101,40 +101,45 @@ BOOLEAN gRequestDispatch = FALSE;
101101 Loads an EFI image into SMRAM.
102102
103103 @param DriverEntry EFI_MM_DRIVER_ENTRY instance
104+ @param ImageContext Allocated ImageContext to be filled out by this function
104105
105106 @return EFI_STATUS
106107
107108**/
108109EFI_STATUS
109110EFIAPI
110111MmLoadImage (
111- IN OUT EFI_MM_DRIVER_ENTRY * DriverEntry
112+ IN OUT EFI_MM_DRIVER_ENTRY * DriverEntry ,
113+ IN OUT PE_COFF_LOADER_IMAGE_CONTEXT * ImageContext
112114 )
113115{
114- UINTN PageCount ;
115- EFI_STATUS Status ;
116- EFI_PHYSICAL_ADDRESS DstBuffer ;
117- PE_COFF_LOADER_IMAGE_CONTEXT ImageContext ;
116+ UINTN PageCount ;
117+ EFI_STATUS Status ;
118+ EFI_PHYSICAL_ADDRESS DstBuffer ;
118119
119120 DEBUG ((DEBUG_INFO , "MmLoadImage - %g\n" , & DriverEntry -> FileName ));
120121
122+ if (ImageContext == NULL ) {
123+ return EFI_INVALID_PARAMETER ;
124+ }
125+
121126 Status = EFI_SUCCESS ;
122127
123128 //
124129 // Initialize ImageContext
125130 //
126- ImageContext . Handle = DriverEntry -> Pe32Data ;
127- ImageContext . ImageRead = PeCoffLoaderImageReadFromMemory ;
131+ ImageContext -> Handle = DriverEntry -> Pe32Data ;
132+ ImageContext -> ImageRead = PeCoffLoaderImageReadFromMemory ;
128133
129134 //
130135 // Get information about the image being loaded
131136 //
132- Status = PeCoffLoaderGetImageInfo (& ImageContext );
137+ Status = PeCoffLoaderGetImageInfo (ImageContext );
133138 if (EFI_ERROR (Status )) {
134139 return Status ;
135140 }
136141
137- PageCount = (UINTN )EFI_SIZE_TO_PAGES ((UINTN )ImageContext . ImageSize + ImageContext . SectionAlignment );
142+ PageCount = (UINTN )EFI_SIZE_TO_PAGES ((UINTN )ImageContext -> ImageSize + ImageContext -> SectionAlignment );
138143 DstBuffer = (UINTN )(-1 );
139144
140145 Status = MmAllocatePages (
@@ -148,18 +153,18 @@ MmLoadImage (
148153 return Status ;
149154 }
150155
151- ImageContext . ImageAddress = (EFI_PHYSICAL_ADDRESS )DstBuffer ;
156+ ImageContext -> ImageAddress = (EFI_PHYSICAL_ADDRESS )DstBuffer ;
152157
153158 //
154159 // Align buffer on section boundary
155160 //
156- ImageContext . ImageAddress += ImageContext . SectionAlignment - 1 ;
157- ImageContext . ImageAddress &= ~((EFI_PHYSICAL_ADDRESS )(ImageContext . SectionAlignment - 1 ));
161+ ImageContext -> ImageAddress += ImageContext -> SectionAlignment - 1 ;
162+ ImageContext -> ImageAddress &= ~((EFI_PHYSICAL_ADDRESS )(ImageContext -> SectionAlignment - 1 ));
158163
159164 //
160165 // Load the image to our new buffer
161166 //
162- Status = PeCoffLoaderLoadImage (& ImageContext );
167+ Status = PeCoffLoaderLoadImage (ImageContext );
163168 if (EFI_ERROR (Status )) {
164169 MmFreePages (DstBuffer , PageCount );
165170 return Status ;
@@ -168,21 +173,23 @@ MmLoadImage (
168173 //
169174 // Relocate the image in our new buffer
170175 //
171- Status = PeCoffLoaderRelocateImage (& ImageContext );
176+ Status = PeCoffLoaderRelocateImage (ImageContext );
172177 if (EFI_ERROR (Status )) {
178+ // if relocate fails, we don't need to call unload image here, as the extra action that may change page attributes
179+ // only is called on a successful return
173180 MmFreePages (DstBuffer , PageCount );
174181 return Status ;
175182 }
176183
177184 //
178185 // Flush the instruction cache so the image data are written before we execute it
179186 //
180- InvalidateInstructionCacheRange ((VOID * )(UINTN )ImageContext . ImageAddress , (UINTN )ImageContext . ImageSize );
187+ InvalidateInstructionCacheRange ((VOID * )(UINTN )ImageContext -> ImageAddress , (UINTN )ImageContext -> ImageSize );
181188
182189 //
183190 // Save Image EntryPoint in DriverEntry
184191 //
185- DriverEntry -> ImageEntryPoint = ImageContext . EntryPoint ;
192+ DriverEntry -> ImageEntryPoint = ImageContext -> EntryPoint ;
186193 DriverEntry -> ImageBuffer = DstBuffer ;
187194 DriverEntry -> NumberOfPage = PageCount ;
188195
@@ -197,7 +204,7 @@ MmLoadImage (
197204 DriverEntry -> LoadedImage .FilePath = NULL ;
198205
199206 DriverEntry -> LoadedImage .ImageBase = (VOID * )(UINTN )DriverEntry -> ImageBuffer ;
200- DriverEntry -> LoadedImage .ImageSize = ImageContext . ImageSize ;
207+ DriverEntry -> LoadedImage .ImageSize = ImageContext -> ImageSize ;
201208 DriverEntry -> LoadedImage .ImageCodeType = EfiRuntimeServicesCode ;
202209 DriverEntry -> LoadedImage .ImageDataType = EfiRuntimeServicesData ;
203210
@@ -223,18 +230,18 @@ MmLoadImage (
223230 DEBUG ((
224231 DEBUG_INFO | DEBUG_LOAD ,
225232 "Loading MM driver at 0x%11p EntryPoint=0x%11p " ,
226- (VOID * )(UINTN )ImageContext . ImageAddress ,
227- FUNCTION_ENTRY_POINT (ImageContext . EntryPoint )
233+ (VOID * )(UINTN )ImageContext -> ImageAddress ,
234+ FUNCTION_ENTRY_POINT (ImageContext -> EntryPoint )
228235 ));
229236
230237 //
231238 // Print Module Name by Pdb file path.
232239 // Windows and Unix style file path are all trimmed correctly.
233240 //
234- if (ImageContext . PdbPointer != NULL ) {
241+ if (ImageContext -> PdbPointer != NULL ) {
235242 StartIndex = 0 ;
236- for (Index = 0 ; ImageContext . PdbPointer [Index ] != 0 ; Index ++ ) {
237- if ((ImageContext . PdbPointer [Index ] == '\\' ) || (ImageContext . PdbPointer [Index ] == '/' )) {
243+ for (Index = 0 ; ImageContext -> PdbPointer [Index ] != 0 ; Index ++ ) {
244+ if ((ImageContext -> PdbPointer [Index ] == '\\' ) || (ImageContext -> PdbPointer [Index ] == '/' )) {
238245 StartIndex = Index + 1 ;
239246 }
240247 }
@@ -245,7 +252,7 @@ MmLoadImage (
245252 // If the length is bigger than 255, trim the redundant characters to avoid overflow in array boundary.
246253 //
247254 for (Index = 0 ; Index < sizeof (EfiFileName ) - 4 ; Index ++ ) {
248- EfiFileName [Index ] = ImageContext . PdbPointer [Index + StartIndex ];
255+ EfiFileName [Index ] = ImageContext -> PdbPointer [Index + StartIndex ];
249256 if (EfiFileName [Index ] == 0 ) {
250257 EfiFileName [Index ] = '.' ;
251258 }
@@ -381,11 +388,12 @@ MmDispatcher (
381388 VOID
382389 )
383390{
384- EFI_STATUS Status ;
385- LIST_ENTRY * Link ;
386- EFI_MM_DRIVER_ENTRY * DriverEntry ;
387- BOOLEAN ReadyToRun ;
388- BOOLEAN PreviousMmEntryPointRegistered ;
391+ EFI_STATUS Status ;
392+ LIST_ENTRY * Link ;
393+ EFI_MM_DRIVER_ENTRY * DriverEntry ;
394+ BOOLEAN ReadyToRun ;
395+ BOOLEAN PreviousMmEntryPointRegistered ;
396+ PE_COFF_LOADER_IMAGE_CONTEXT ImageContext ;
389397
390398 DEBUG ((DEBUG_INFO , "MmDispatcher\n" ));
391399
@@ -424,7 +432,7 @@ MmDispatcher (
424432 // skip the LoadImage
425433 //
426434 if (DriverEntry -> ImageHandle == NULL ) {
427- Status = MmLoadImage (DriverEntry );
435+ Status = MmLoadImage (DriverEntry , & ImageContext );
428436
429437 //
430438 // Update the driver state to reflect that it's been loaded
@@ -461,6 +469,11 @@ MmDispatcher (
461469 Status = ((MM_IMAGE_ENTRY_POINT )(UINTN )DriverEntry -> ImageEntryPoint )(DriverEntry -> ImageHandle , & gMmCoreMmst );
462470 if (EFI_ERROR (Status )) {
463471 DEBUG ((DEBUG_INFO , "StartImage Status - %r\n" , Status ));
472+
473+ // we need to unload the image before we free the pages. On some architectures (e.g. x86), this is a no-op, but
474+ // on others (e.g. AARCH64) this will remove the image memory protections set on the region so that when the
475+ // memory is freed, it has the default attributes set and can be used generically
476+ PeCoffLoaderUnloadImage (& ImageContext );
464477 MmFreePages (DriverEntry -> ImageBuffer , DriverEntry -> NumberOfPage );
465478 if (DriverEntry -> ImageHandle != NULL ) {
466479 MmUninstallProtocolInterface (
0 commit comments