]> git.proxmox.com Git - mirror_edk2.git/blob - EdkCompatibilityPkg/Compatibility/SmmBaseOnSmmBase2Thunk/SmmBaseOnSmmBase2Thunk.c
Change RegisterProtocolNotify for dependent protocols to [Depex] expression
[mirror_edk2.git] / EdkCompatibilityPkg / Compatibility / SmmBaseOnSmmBase2Thunk / SmmBaseOnSmmBase2Thunk.c
1 /** @file
2 SMM Base Protocol on SMM Base2 Protocol Thunk driver.
3
4 This driver co-operates with SMM Base Helper SMM driver to provide SMM Base Protocol
5 based on SMM Base2 Protocol.
6
7 This thunk driver is expected to be loaded before PI SMM IPL driver so that
8 SMM BASE Protocol can be published immediately after SMM Base2 Protocol is installed to
9 make SMM Base Protocol.InSmm() as early as possible.
10
11 Copyright (c) 2009 - 2010, Intel Corporation
12 All rights reserved. This program and the accompanying materials
13 are licensed and made available under the terms and conditions of the BSD License
14 which accompanies this distribution. The full text of the license may be found at
15 http://opensource.org/licenses/bsd-license.php
16
17 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
18 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
19
20 **/
21
22 #include <PiDxe.h>
23 #include <FrameworkSmm.h>
24
25 #include <Protocol/SmmBase2.h>
26 #include <Protocol/SmmCommunication.h>
27 #include <Protocol/SmmBaseHelperReady.h>
28
29 #include <Guid/SmmBaseThunkCommunication.h>
30 #include <Guid/EventGroup.h>
31
32 #include <Library/DebugLib.h>
33 #include <Library/UefiBootServicesTableLib.h>
34 #include <Library/UefiDriverEntryPoint.h>
35 #include <Library/UefiLib.h>
36 #include <Library/UefiRuntimeLib.h>
37
38 //
39 // SMM Base Protocol function ptoyotypes
40 //
41 EFI_STATUS
42 EFIAPI
43 SmmBaseRegister (
44 IN EFI_SMM_BASE_PROTOCOL *This,
45 IN EFI_DEVICE_PATH_PROTOCOL *FilePath,
46 IN VOID *SourceBuffer,
47 IN UINTN SourceSize,
48 OUT EFI_HANDLE *ImageHandle,
49 IN BOOLEAN LegacyIA32Binary
50 );
51
52 EFI_STATUS
53 EFIAPI
54 SmmBaseUnregister (
55 IN EFI_SMM_BASE_PROTOCOL *This,
56 IN EFI_HANDLE ImageHandle
57 );
58
59 EFI_STATUS
60 EFIAPI
61 SmmBaseCommunicate (
62 IN EFI_SMM_BASE_PROTOCOL *This,
63 IN EFI_HANDLE ImageHandle,
64 IN OUT VOID *CommunicationBuffer,
65 IN OUT UINTN *BufferSize
66 );
67
68 EFI_STATUS
69 EFIAPI
70 SmmBaseRegisterCallback (
71 IN EFI_SMM_BASE_PROTOCOL *This,
72 IN EFI_HANDLE SmmImageHandle,
73 IN EFI_SMM_CALLBACK_ENTRY_POINT CallbackAddress,
74 IN BOOLEAN MakeLast,
75 IN BOOLEAN FloatingPointSave
76 );
77
78 EFI_STATUS
79 EFIAPI
80 SmmBaseInSmm (
81 IN EFI_SMM_BASE_PROTOCOL *This,
82 OUT BOOLEAN *InSmm
83 );
84
85 EFI_STATUS
86 EFIAPI
87 SmmBaseSmmAllocatePool (
88 IN EFI_SMM_BASE_PROTOCOL *This,
89 IN EFI_MEMORY_TYPE PoolType,
90 IN UINTN Size,
91 OUT VOID **Buffer
92 );
93
94 EFI_STATUS
95 EFIAPI
96 SmmBaseSmmFreePool (
97 IN EFI_SMM_BASE_PROTOCOL *This,
98 IN VOID *Buffer
99 );
100
101 EFI_STATUS
102 EFIAPI
103 SmmBaseGetSmstLocation (
104 IN EFI_SMM_BASE_PROTOCOL *This,
105 OUT EFI_SMM_SYSTEM_TABLE **Smst
106 );
107
108 ///
109 /// SMM Base Protocol instance
110 ///
111 EFI_SMM_BASE_PROTOCOL mSmmBase = {
112 SmmBaseRegister,
113 SmmBaseUnregister,
114 SmmBaseCommunicate,
115 SmmBaseRegisterCallback,
116 SmmBaseInSmm,
117 SmmBaseSmmAllocatePool,
118 SmmBaseSmmFreePool,
119 SmmBaseGetSmstLocation
120 };
121
122 SMMBASETHUNK_COMMUNICATION_DATA mCommunicationData = {
123 EFI_SMM_BASE_THUNK_COMMUNICATION_GUID,
124 sizeof (SMMBASE_FUNCTION_DATA)
125 };
126
127 EFI_HANDLE mSmmBaseHandle = NULL;
128 EFI_SMM_BASE2_PROTOCOL *mSmmBase2 = NULL;
129 EFI_SMM_COMMUNICATION_PROTOCOL *mSmmCommunication = NULL;
130 EFI_SMM_BASE_HELPER_READY_PROTOCOL *mSmmBaseHelperReady = NULL;
131
132 /**
133 Determine if in SMM mode.
134
135 @retval TRUE In SMM mode.
136 @retval FALSE Not in SMM mode.
137 **/
138 BOOLEAN
139 IsInSmm (
140 VOID
141 )
142 {
143 EFI_STATUS Status;
144 BOOLEAN InSmm;
145
146 Status = mSmmBase2->InSmm (mSmmBase2, &InSmm);
147 ASSERT_EFI_ERROR (Status);
148 return InSmm;
149 }
150
151 /**
152 Invoke services provided by SMM Base Helper SMM driver.
153 **/
154 VOID
155 SmmBaseHelperService (
156 VOID
157 )
158 {
159 UINTN DataSize;
160
161 mCommunicationData.FunctionData.Status = EFI_UNSUPPORTED;
162
163 if (IsInSmm()) {
164 ///
165 /// If in SMM mode, directly call services in SMM Base Helper.
166 ///
167 if (mSmmBaseHelperReady == NULL) {
168 ASSERT (FALSE);
169 return;
170 }
171
172 DataSize = (UINTN)(sizeof (SMMBASE_FUNCTION_DATA));
173 mSmmBaseHelperReady->ServiceEntry (
174 NULL,
175 NULL,
176 &mCommunicationData.FunctionData,
177 &DataSize
178 );
179 } else {
180 ///
181 /// If in non-SMM mode, call services in SMM Base Helper via SMM Communication Protocol.
182 ///
183 if (mSmmCommunication == NULL) {
184 ASSERT (FALSE);
185 return;
186 }
187
188 DataSize = (UINTN)(sizeof (mCommunicationData));
189 mSmmCommunication->Communicate (
190 mSmmCommunication,
191 &mCommunicationData,
192 &DataSize
193 );
194 }
195 }
196
197 /**
198 Register a given driver into SMRAM. This is the equivalent of performing
199 the LoadImage/StartImage into System Management Mode.
200
201 @param[in] This Protocol instance pointer.
202 @param[in] FilePath Location of the image to be installed as the handler.
203 @param[in] SourceBuffer Optional source buffer in case the image file
204 is in memory.
205 @param[in] SourceSize Size of the source image file, if in memory.
206 @param[out] ImageHandle The handle that the base driver uses to decode
207 the handler. Unique among SMM handlers only,
208 not unique across DXE/EFI.
209 @param[in] LegacyIA32Binary An optional parameter specifying that the associated
210 file is a real-mode IA-32 binary.
211
212 @retval EFI_SUCCESS The operation was successful.
213 @retval EFI_OUT_OF_RESOURCES There were no additional SMRAM resources to load the handler
214 @retval EFI_UNSUPPORTED This platform does not support 16-bit handlers.
215 @retval EFI_UNSUPPORTED Platform is in runtime.
216 @retval EFI_INVALID_PARAMETER The handlers was not the correct image type
217 **/
218 EFI_STATUS
219 EFIAPI
220 SmmBaseRegister (
221 IN EFI_SMM_BASE_PROTOCOL *This,
222 IN EFI_DEVICE_PATH_PROTOCOL *FilePath,
223 IN VOID *SourceBuffer,
224 IN UINTN SourceSize,
225 OUT EFI_HANDLE *ImageHandle,
226 IN BOOLEAN LegacyIA32Binary
227 )
228 {
229 if (LegacyIA32Binary) {
230 return EFI_UNSUPPORTED;
231 }
232
233 mCommunicationData.FunctionData.Function = SMMBASE_REGISTER;
234 mCommunicationData.FunctionData.Args.Register.FilePath = FilePath;
235 mCommunicationData.FunctionData.Args.Register.SourceBuffer = SourceBuffer;
236 mCommunicationData.FunctionData.Args.Register.SourceSize = SourceSize;
237 mCommunicationData.FunctionData.Args.Register.ImageHandle = ImageHandle;
238 mCommunicationData.FunctionData.Args.Register.LegacyIA32Binary = LegacyIA32Binary;
239
240 SmmBaseHelperService ();
241 return mCommunicationData.FunctionData.Status;
242 }
243
244 /**
245 Removes a handler from execution within SMRAM. This is the equivalent of performing
246 the UnloadImage in System Management Mode.
247
248 @param[in] This Protocol instance pointer.
249 @param[in] ImageHandle The handler to be removed.
250
251 @retval EFI_SUCCESS The operation was successful
252 @retval EFI_INVALID_PARAMETER The handler did not exist
253 @retval EFI_UNSUPPORTED Platform is in runtime.
254 **/
255 EFI_STATUS
256 EFIAPI
257 SmmBaseUnregister (
258 IN EFI_SMM_BASE_PROTOCOL *This,
259 IN EFI_HANDLE ImageHandle
260 )
261 {
262 mCommunicationData.FunctionData.Function = SMMBASE_UNREGISTER;
263 mCommunicationData.FunctionData.Args.UnRegister.ImageHandle = ImageHandle;
264
265 SmmBaseHelperService ();
266 return mCommunicationData.FunctionData.Status;
267 }
268
269 /**
270 The SMM Inter-module Communicate Service Communicate() function
271 provides a service to send/receive messages from a registered
272 EFI service. The BASE protocol driver is responsible for doing
273 any of the copies such that the data lives in boot-service-accessible RAM.
274
275 @param[in] This Protocol instance pointer.
276 @param[in] ImageHandle The handle of the registered driver.
277 @param[in,out] CommunicationBuffer Pointer to the buffer to convey into SMRAM.
278 @param[in,out] BufferSize The size of the data buffer being passed in.
279 On exit, the size of data being returned.
280 Zero if the handler does not wish to reply with any data.
281
282 @retval EFI_SUCCESS The message was successfully posted
283 @retval EFI_INVALID_PARAMETER The buffer was NULL
284 **/
285 EFI_STATUS
286 EFIAPI
287 SmmBaseCommunicate (
288 IN EFI_SMM_BASE_PROTOCOL *This,
289 IN EFI_HANDLE ImageHandle,
290 IN OUT VOID *CommunicationBuffer,
291 IN OUT UINTN *BufferSize
292 )
293 {
294 if (mSmmCommunication == NULL) {
295 ASSERT (FALSE);
296 return EFI_UNSUPPORTED;
297 }
298
299 return mSmmCommunication->Communicate (
300 mSmmCommunication,
301 CommunicationBuffer,
302 BufferSize
303 );
304 }
305
306 /**
307 Register a callback to execute within SMM.
308 This allows receipt of messages created with EFI_SMM_BASE_PROTOCOL.Communicate().
309
310 @param[in] This Protocol instance pointer.
311 @param[in] SmmImageHandle Handle of the callback service.
312 @param[in] CallbackAddress Address of the callback service.
313 @param[in] MakeLast If present, will stipulate that the handler is posted to
314 be executed last in the dispatch table.
315 @param[in] FloatingPointSave An optional parameter that informs the
316 EFI_SMM_ACCESS_PROTOCOL Driver core if it needs to save
317 the floating point register state. If any handler
318 require this, the state will be saved for all handlers.
319
320 @retval EFI_SUCCESS The operation was successful
321 @retval EFI_OUT_OF_RESOURCES Not enough space in the dispatch queue
322 @retval EFI_UNSUPPORTED Platform is in runtime.
323 @retval EFI_UNSUPPORTED The caller is not in SMM.
324 **/
325 EFI_STATUS
326 EFIAPI
327 SmmBaseRegisterCallback (
328 IN EFI_SMM_BASE_PROTOCOL *This,
329 IN EFI_HANDLE SmmImageHandle,
330 IN EFI_SMM_CALLBACK_ENTRY_POINT CallbackAddress,
331 IN BOOLEAN MakeLast,
332 IN BOOLEAN FloatingPointSave
333 )
334 {
335 if (!IsInSmm()) {
336 return EFI_UNSUPPORTED;
337 }
338
339 mCommunicationData.FunctionData.Function = SMMBASE_REGISTER_CALLBACK;
340 mCommunicationData.FunctionData.Args.RegisterCallback.SmmImageHandle = SmmImageHandle;
341 mCommunicationData.FunctionData.Args.RegisterCallback.CallbackAddress = CallbackAddress;
342 mCommunicationData.FunctionData.Args.RegisterCallback.MakeLast = MakeLast;
343 mCommunicationData.FunctionData.Args.RegisterCallback.FloatingPointSave = FloatingPointSave;
344
345 SmmBaseHelperService();
346 return mCommunicationData.FunctionData.Status;
347 }
348
349 /**
350 This routine tells caller if execution context is SMM or not.
351
352 @param[in] This Protocol instance pointer.
353 @param[out] InSmm Whether the caller is inside SMM for IA-32
354 or servicing a PMI for the Itanium processor
355 family.
356
357 @retval EFI_SUCCESS The operation was successful
358 @retval EFI_INVALID_PARAMETER InSmm was NULL.
359 **/
360 EFI_STATUS
361 EFIAPI
362 SmmBaseInSmm (
363 IN EFI_SMM_BASE_PROTOCOL *This,
364 OUT BOOLEAN *InSmm
365 )
366 {
367 return mSmmBase2->InSmm (mSmmBase2, InSmm);
368 }
369
370 /**
371 The SmmAllocatePool() function allocates a memory region of Size bytes from memory of
372 type PoolType and returns the address of the allocated memory in the location referenced
373 by Buffer. This function allocates pages from EFI SMRAM Memory as needed to grow the
374 requested pool type. All allocations are eight-byte aligned.
375
376 @param[in] This Protocol instance pointer.
377 @param[in] PoolType The type of pool to allocate.
378 The only supported type is EfiRuntimeServicesData;
379 the interface will internally map this runtime request to
380 SMRAM for IA-32 and leave as this type for the Itanium
381 processor family. Other types can be ignored.
382 @param[in] Size The number of bytes to allocate from the pool.
383 @param[out] Buffer A pointer to a pointer to the allocated buffer if the call
384 succeeds; undefined otherwise.
385
386 @retval EFI_SUCCESS The requested number of bytes was allocated.
387 @retval EFI_OUT_OF_RESOURCES The pool requested could not be allocated.
388 @retval EFI_UNSUPPORTED Platform is in runtime.
389 **/
390 EFI_STATUS
391 EFIAPI
392 SmmBaseSmmAllocatePool (
393 IN EFI_SMM_BASE_PROTOCOL *This,
394 IN EFI_MEMORY_TYPE PoolType,
395 IN UINTN Size,
396 OUT VOID **Buffer
397 )
398 {
399 mCommunicationData.FunctionData.Function = SMMBASE_ALLOCATE_POOL;
400 mCommunicationData.FunctionData.Args.AllocatePool.PoolType = PoolType;
401 mCommunicationData.FunctionData.Args.AllocatePool.Size = Size;
402 mCommunicationData.FunctionData.Args.AllocatePool.Buffer = Buffer;
403
404 SmmBaseHelperService ();
405 return mCommunicationData.FunctionData.Status;
406 }
407
408 /**
409 The SmmFreePool() function returns the memory specified by Buffer to the system.
410 On return, the memory's type is EFI SMRAM Memory. The Buffer that is freed must
411 have been allocated by SmmAllocatePool().
412
413 @param[in] This Protocol instance pointer.
414 @param[in] Buffer Pointer to the buffer allocation.
415
416 @retval EFI_SUCCESS The memory was returned to the system.
417 @retval EFI_INVALID_PARAMETER Buffer was invalid.
418 @retval EFI_UNSUPPORTED Platform is in runtime.
419 **/
420 EFI_STATUS
421 EFIAPI
422 SmmBaseSmmFreePool (
423 IN EFI_SMM_BASE_PROTOCOL *This,
424 IN VOID *Buffer
425 )
426 {
427 mCommunicationData.FunctionData.Function = SMMBASE_FREE_POOL;
428 mCommunicationData.FunctionData.Args.FreePool.Buffer = Buffer;
429
430 SmmBaseHelperService ();
431 return mCommunicationData.FunctionData.Status;
432 }
433
434 /**
435 The GetSmstLocation() function returns the location of the System Management
436 Service Table. The use of the API is such that a driver can discover the
437 location of the SMST in its entry point and then cache it in some driver
438 global variable so that the SMST can be invoked in subsequent callbacks.
439
440 @param[in] This Protocol instance pointer.
441 @param[in] Smst Pointer to the SMST.
442
443 @retval EFI_SUCCESS The operation was successful
444 @retval EFI_INVALID_PARAMETER Smst was invalid.
445 @retval EFI_UNSUPPORTED Not in SMM.
446 **/
447 EFI_STATUS
448 EFIAPI
449 SmmBaseGetSmstLocation (
450 IN EFI_SMM_BASE_PROTOCOL *This,
451 OUT EFI_SMM_SYSTEM_TABLE **Smst
452 )
453 {
454 if (mSmmBaseHelperReady == NULL) {
455 ASSERT (FALSE);
456 return EFI_UNSUPPORTED;
457 }
458
459 if (!IsInSmm ()) {
460 return EFI_UNSUPPORTED;
461 }
462
463 if (Smst == NULL) {
464 return EFI_INVALID_PARAMETER;
465 }
466
467 *Smst = mSmmBaseHelperReady->FrameworkSmst;
468 return EFI_SUCCESS;
469 }
470
471 /**
472 Notification function of EVT_SIGNAL_VIRTUAL_ADDRESS_CHANGE
473
474 This is a notification function registered on EVT_SIGNAL_VIRTUAL_ADDRESS_CHANGE event.
475 It convers pointer to new virtual address.
476
477 @param Event Event whose notification function is being invoked
478 @param Context Pointer to the notification function's context
479 **/
480 VOID
481 EFIAPI
482 SmmBaseAddressChangeEvent (
483 IN EFI_EVENT Event,
484 IN VOID *Context
485 )
486 {
487 if (mSmmCommunication != NULL) {
488 EfiConvertPointer (0x0, (VOID **) &mSmmCommunication);
489 }
490 }
491
492 /**
493 Entry Point for SMM Base Protocol on SMM Base2 Protocol Thunk driver.
494
495 @param[in] ImageHandle Image handle of this driver.
496 @param[in] SystemTable A Pointer to the EFI System Table.
497
498 @retval EFI_SUCCESS The entry point is executed successfully.
499 **/
500 EFI_STATUS
501 EFIAPI
502 SmmBaseThunkMain (
503 IN EFI_HANDLE ImageHandle,
504 IN EFI_SYSTEM_TABLE *SystemTable
505 )
506 {
507 EFI_STATUS Status;
508 EFI_EVENT Event;
509
510 //
511 // Assume only one instance of SMM Base2 Protocol in the system
512 // Locate SMM Base2 Protocol
513 //
514 Status = gBS->LocateProtocol (&gEfiSmmBase2ProtocolGuid, NULL, (VOID **) &mSmmBase2);
515 ASSERT_EFI_ERROR (Status);
516
517 //
518 // Assume only one instance of SMM Communication Protocol in the system
519 // Locate SMM Communication Protocol
520 //
521 gBS->LocateProtocol (&gEfiSmmCommunicationProtocolGuid, NULL, (VOID **) &mSmmCommunication);
522 ASSERT_EFI_ERROR (Status);
523
524 //
525 // Assume only one instance of SMM Base Helper Ready Protocol in the system
526 // Locate SMM Base Helper Ready Protocol
527 //
528 Status = gBS->LocateProtocol (&gEfiSmmBaseHelperReadyProtocolGuid, NULL, (VOID **) &mSmmBaseHelperReady);
529 ASSERT_EFI_ERROR (Status);
530
531 //
532 // Create event on SetVirtualAddressMap() to convert mSmmCommunication from a physical address to a virtual address
533 //
534 Status = gBS->CreateEventEx (
535 EVT_NOTIFY_SIGNAL,
536 TPL_NOTIFY,
537 SmmBaseAddressChangeEvent,
538 NULL,
539 &gEfiEventVirtualAddressChangeGuid,
540 &Event
541 );
542 ASSERT_EFI_ERROR (Status);
543
544 //
545 // Publish Framework SMM BASE Protocol immediately after SMM Base2 Protocol is installed to
546 // make SMM Base Protocol.InSmm() available as early as possible.
547 //
548 Status = gBS->InstallMultipleProtocolInterfaces (
549 &mSmmBaseHandle,
550 &gEfiSmmBaseProtocolGuid, &mSmmBase,
551 NULL
552 );
553 ASSERT_EFI_ERROR (Status);
554
555 return EFI_SUCCESS;
556 }