@@ -101,40 +101,45 @@ BOOLEAN gRequestDispatch = FALSE;
101
101
Loads an EFI image into SMRAM.
102
102
103
103
@param DriverEntry EFI_MM_DRIVER_ENTRY instance
104
+ @param ImageContext Allocated ImageContext to be filled out by this function
104
105
105
106
@return EFI_STATUS
106
107
107
108
**/
108
109
EFI_STATUS
109
110
EFIAPI
110
111
MmLoadImage (
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
112
114
)
113
115
{
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 ;
118
119
119
120
DEBUG ((DEBUG_INFO , "MmLoadImage - %g\n" , & DriverEntry -> FileName ));
120
121
122
+ if (ImageContext == NULL ) {
123
+ return EFI_INVALID_PARAMETER ;
124
+ }
125
+
121
126
Status = EFI_SUCCESS ;
122
127
123
128
//
124
129
// Initialize ImageContext
125
130
//
126
- ImageContext . Handle = DriverEntry -> Pe32Data ;
127
- ImageContext . ImageRead = PeCoffLoaderImageReadFromMemory ;
131
+ ImageContext -> Handle = DriverEntry -> Pe32Data ;
132
+ ImageContext -> ImageRead = PeCoffLoaderImageReadFromMemory ;
128
133
129
134
//
130
135
// Get information about the image being loaded
131
136
//
132
- Status = PeCoffLoaderGetImageInfo (& ImageContext );
137
+ Status = PeCoffLoaderGetImageInfo (ImageContext );
133
138
if (EFI_ERROR (Status )) {
134
139
return Status ;
135
140
}
136
141
137
- PageCount = (UINTN )EFI_SIZE_TO_PAGES ((UINTN )ImageContext . ImageSize + ImageContext . SectionAlignment );
142
+ PageCount = (UINTN )EFI_SIZE_TO_PAGES ((UINTN )ImageContext -> ImageSize + ImageContext -> SectionAlignment );
138
143
DstBuffer = (UINTN )(-1 );
139
144
140
145
Status = MmAllocatePages (
@@ -147,18 +152,18 @@ MmLoadImage (
147
152
return Status ;
148
153
}
149
154
150
- ImageContext . ImageAddress = (EFI_PHYSICAL_ADDRESS )DstBuffer ;
155
+ ImageContext -> ImageAddress = (EFI_PHYSICAL_ADDRESS )DstBuffer ;
151
156
152
157
//
153
158
// Align buffer on section boundary
154
159
//
155
- ImageContext . ImageAddress += ImageContext . SectionAlignment - 1 ;
156
- ImageContext . ImageAddress &= ~((EFI_PHYSICAL_ADDRESS )(ImageContext . SectionAlignment - 1 ));
160
+ ImageContext -> ImageAddress += ImageContext -> SectionAlignment - 1 ;
161
+ ImageContext -> ImageAddress &= ~((EFI_PHYSICAL_ADDRESS )(ImageContext -> SectionAlignment - 1 ));
157
162
158
163
//
159
164
// Load the image to our new buffer
160
165
//
161
- Status = PeCoffLoaderLoadImage (& ImageContext );
166
+ Status = PeCoffLoaderLoadImage (ImageContext );
162
167
if (EFI_ERROR (Status )) {
163
168
MmFreePages (DstBuffer , PageCount );
164
169
return Status ;
@@ -167,21 +172,23 @@ MmLoadImage (
167
172
//
168
173
// Relocate the image in our new buffer
169
174
//
170
- Status = PeCoffLoaderRelocateImage (& ImageContext );
175
+ Status = PeCoffLoaderRelocateImage (ImageContext );
171
176
if (EFI_ERROR (Status )) {
177
+ // if relocate fails, we don't need to call unload image here, as the extra action that may change page attributes
178
+ // only is called on a successful return
172
179
MmFreePages (DstBuffer , PageCount );
173
180
return Status ;
174
181
}
175
182
176
183
//
177
184
// Flush the instruction cache so the image data are written before we execute it
178
185
//
179
- InvalidateInstructionCacheRange ((VOID * )(UINTN )ImageContext . ImageAddress , (UINTN )ImageContext . ImageSize );
186
+ InvalidateInstructionCacheRange ((VOID * )(UINTN )ImageContext -> ImageAddress , (UINTN )ImageContext -> ImageSize );
180
187
181
188
//
182
189
// Save Image EntryPoint in DriverEntry
183
190
//
184
- DriverEntry -> ImageEntryPoint = ImageContext . EntryPoint ;
191
+ DriverEntry -> ImageEntryPoint = ImageContext -> EntryPoint ;
185
192
DriverEntry -> ImageBuffer = DstBuffer ;
186
193
DriverEntry -> NumberOfPage = PageCount ;
187
194
@@ -192,6 +199,7 @@ MmLoadImage (
192
199
(VOID * * )& DriverEntry -> LoadedImage
193
200
);
194
201
if (EFI_ERROR (Status )) {
202
+ PeCoffLoaderUnloadImage (ImageContext );
195
203
MmFreePages (DstBuffer , PageCount );
196
204
return Status ;
197
205
}
@@ -208,7 +216,7 @@ MmLoadImage (
208
216
DriverEntry -> LoadedImage -> FilePath = NULL ;
209
217
210
218
DriverEntry -> LoadedImage -> ImageBase = (VOID * )(UINTN )DriverEntry -> ImageBuffer ;
211
- DriverEntry -> LoadedImage -> ImageSize = ImageContext . ImageSize ;
219
+ DriverEntry -> LoadedImage -> ImageSize = ImageContext -> ImageSize ;
212
220
DriverEntry -> LoadedImage -> ImageCodeType = EfiRuntimeServicesCode ;
213
221
DriverEntry -> LoadedImage -> ImageDataType = EfiRuntimeServicesData ;
214
222
@@ -236,18 +244,18 @@ MmLoadImage (
236
244
DEBUG ((
237
245
DEBUG_INFO | DEBUG_LOAD ,
238
246
"Loading MM driver at 0x%11p EntryPoint=0x%11p " ,
239
- (VOID * )(UINTN )ImageContext . ImageAddress ,
240
- FUNCTION_ENTRY_POINT (ImageContext . EntryPoint )
247
+ (VOID * )(UINTN )ImageContext -> ImageAddress ,
248
+ FUNCTION_ENTRY_POINT (ImageContext -> EntryPoint )
241
249
));
242
250
243
251
//
244
252
// Print Module Name by Pdb file path.
245
253
// Windows and Unix style file path are all trimmed correctly.
246
254
//
247
- if (ImageContext . PdbPointer != NULL ) {
255
+ if (ImageContext -> PdbPointer != NULL ) {
248
256
StartIndex = 0 ;
249
- for (Index = 0 ; ImageContext . PdbPointer [Index ] != 0 ; Index ++ ) {
250
- if ((ImageContext . PdbPointer [Index ] == '\\' ) || (ImageContext . PdbPointer [Index ] == '/' )) {
257
+ for (Index = 0 ; ImageContext -> PdbPointer [Index ] != 0 ; Index ++ ) {
258
+ if ((ImageContext -> PdbPointer [Index ] == '\\' ) || (ImageContext -> PdbPointer [Index ] == '/' )) {
251
259
StartIndex = Index + 1 ;
252
260
}
253
261
}
@@ -258,7 +266,7 @@ MmLoadImage (
258
266
// If the length is bigger than 255, trim the redundant characters to avoid overflow in array boundary.
259
267
//
260
268
for (Index = 0 ; Index < sizeof (EfiFileName ) - 4 ; Index ++ ) {
261
- EfiFileName [Index ] = ImageContext . PdbPointer [Index + StartIndex ];
269
+ EfiFileName [Index ] = ImageContext -> PdbPointer [Index + StartIndex ];
262
270
if (EfiFileName [Index ] == 0 ) {
263
271
EfiFileName [Index ] = '.' ;
264
272
}
@@ -394,10 +402,11 @@ MmDispatcher (
394
402
VOID
395
403
)
396
404
{
397
- EFI_STATUS Status ;
398
- LIST_ENTRY * Link ;
399
- EFI_MM_DRIVER_ENTRY * DriverEntry ;
400
- BOOLEAN ReadyToRun ;
405
+ EFI_STATUS Status ;
406
+ LIST_ENTRY * Link ;
407
+ EFI_MM_DRIVER_ENTRY * DriverEntry ;
408
+ BOOLEAN ReadyToRun ;
409
+ PE_COFF_LOADER_IMAGE_CONTEXT ImageContext ;
401
410
402
411
DEBUG ((DEBUG_INFO , "MmDispatcher\n" ));
403
412
@@ -436,7 +445,7 @@ MmDispatcher (
436
445
// skip the LoadImage
437
446
//
438
447
if (DriverEntry -> ImageHandle == NULL ) {
439
- Status = MmLoadImage (DriverEntry );
448
+ Status = MmLoadImage (DriverEntry , & ImageContext );
440
449
441
450
//
442
451
// Update the driver state to reflect that it's been loaded
@@ -477,6 +486,11 @@ MmDispatcher (
477
486
478
487
if (EFI_ERROR (Status )) {
479
488
DEBUG ((DEBUG_INFO , "StartImage Status - %r\n" , Status ));
489
+
490
+ // we need to unload the image before we free the pages. On some architectures (e.g. x86), this is a no-op, but
491
+ // on others (e.g. AARCH64) this will remove the image memory protections set on the region so that when the
492
+ // memory is freed, it has the default attributes set and can be used generically
493
+ PeCoffLoaderUnloadImage (& ImageContext );
480
494
MmFreePages (DriverEntry -> ImageBuffer , DriverEntry -> NumberOfPage );
481
495
}
482
496
}
0 commit comments