1 /** @file
2 This function handle the register/unregister of PCH specific SMI events.
3
4 Copyright (c) 2021, Intel Corporation. All rights reserved.<BR>
5 SPDX-License-Identifier: BSD-2-Clause-Patent
6 **/
7 #include "PchSmmHelpers.h"
8 #include <Library/SmiHandlerProfileLib.h>
9 #include <Register/PchRegs.h>
10 #include <Register/PchPcrRegs.h>
11 #include <Register/PmcRegs.h>
12 #include <Register/PchRegsLpc.h>
13 #include <Register/SpiRegs.h>
14 #include <Register/PchPcieRpRegs.h>
15 #include <Register/PchRegsPsth.h>
16 #include <Library/PchPciBdfLib.h>
17 #include <Library/S3BootScriptLib.h>
18 #include <PchBdfAssignment.h>
19 #include "PchSmiHelper.h"
20
21 /**
22 The internal function used to create and insert a database record
23 for SMI record of Pch Smi types.
24
25 @param[in] SrcDesc The pointer to the SMI source description
26 @param[in] DispatchFunction Pointer to dispatch function to be invoked for this SMI source
27 @param[in] PchSmiType Specific SMI type of PCH SMI
28 @param[out] DispatchHandle Handle of dispatch function to register.
29
30 @retval EFI_INVALID_PARAMETER Error with NULL SMI source description
31 @retval EFI_OUT_OF_RESOURCES Fail to allocate pool for database record
32 @retval EFI_SUCCESS The database record is created successfully.
33 **/
34 EFI_STATUS
PchSmiRecordInsert(IN CONST PCH_SMM_SOURCE_DESC * SrcDesc,IN PCH_SMI_CALLBACK_FUNCTIONS DispatchFunction,IN PCH_SMI_TYPES PchSmiType,OUT EFI_HANDLE * DispatchHandle)35 PchSmiRecordInsert (
36 IN CONST PCH_SMM_SOURCE_DESC *SrcDesc,
37 IN PCH_SMI_CALLBACK_FUNCTIONS DispatchFunction,
38 IN PCH_SMI_TYPES PchSmiType,
39 OUT EFI_HANDLE *DispatchHandle
40 )
41 {
42 EFI_STATUS Status;
43 DATABASE_RECORD Record;
44
45 if (SrcDesc == NULL) {
46 return EFI_INVALID_PARAMETER;
47 }
48
49 ZeroMem (&Record, sizeof (DATABASE_RECORD));
50 //
51 // Gather information about the registration request
52 //
53 Record.Signature = DATABASE_RECORD_SIGNATURE;
54 Record.PchSmiCallback = DispatchFunction;
55 Record.ProtocolType = PchSmiDispatchType;
56 Record.PchSmiType = PchSmiType;
57
58 CopyMem (&Record.SrcDesc, SrcDesc, sizeof (PCH_SMM_SOURCE_DESC));
59 Status = SmmCoreInsertRecord (
60 &Record,
61 DispatchHandle
62 );
63 ASSERT_EFI_ERROR (Status);
64
65 return EFI_SUCCESS;
66 }
67
68
69 //
70 // TCO_STS bit that needs to be cleared
71 //
72 GLOBAL_REMOVE_IF_UNREFERENCED CONST PCH_SMM_SOURCE_DESC mDescSrcTcoSts = {
73 PCH_SMM_NO_FLAGS,
74 {
75 NULL_BIT_DESC_INITIALIZER,
76 NULL_BIT_DESC_INITIALIZER
77 },
78 {
79 {
80 {
81 ACPI_ADDR_TYPE,
82 {R_ACPI_IO_SMI_STS}
83 },
84 S_ACPI_IO_SMI_STS,
85 N_ACPI_IO_SMI_STS_TCO
86 }
87 },
88 NULL_BIT_DESC_INITIALIZER
89 };
90
91 /**
92 Clear the TCO SMI status bit and block after the SMI handling is done
93
94 @param[in] SrcDesc Pointer to the PCH SMI source description table
95
96 **/
97 VOID
98 EFIAPI
PchTcoSmiClearSourceAndBlock(CONST PCH_SMM_SOURCE_DESC * SrcDesc)99 PchTcoSmiClearSourceAndBlock (
100 CONST PCH_SMM_SOURCE_DESC *SrcDesc
101 )
102 {
103 PchSmmClearSourceAndBlock (SrcDesc);
104 //
105 // Any TCO-based status bits require special handling.
106 // SMI_STS.TCO_STS must be cleared in addition to the status bit in the TCO registers
107 //
108 PchSmmClearSource (&mDescSrcTcoSts);
109 }
110
111 /**
112 Clear the TCO SMI status bit after the SMI handling is done
113
114 @param[in] SrcDesc Pointer to the PCH SMI source description table
115
116 **/
117 VOID
118 EFIAPI
PchTcoSmiClearSource(CONST PCH_SMM_SOURCE_DESC * SrcDesc)119 PchTcoSmiClearSource (
120 CONST PCH_SMM_SOURCE_DESC *SrcDesc
121 )
122 {
123 PchSmmClearSource (SrcDesc);
124 //
125 // Any TCO-based status bits require special handling.
126 // SMI_STS.TCO_STS must be cleared in addition to the status bit in the TCO registers
127 //
128 PchSmmClearSource (&mDescSrcTcoSts);
129 }
130
131 /**
132 Initialize Source descriptor structure
133
134 @param[in] SrcDesc Pointer to the PCH SMI source description table
135
136 **/
137 VOID
138 EFIAPI
NullInitSourceDesc(PCH_SMM_SOURCE_DESC * SrcDesc)139 NullInitSourceDesc (
140 PCH_SMM_SOURCE_DESC *SrcDesc
141 )
142 {
143 ZeroMem (SrcDesc, sizeof (PCH_SMM_SOURCE_DESC));
144 SrcDesc->En[0].Reg.Type = PCH_SMM_ADDR_TYPE_NULL;
145 SrcDesc->En[1].Reg.Type = PCH_SMM_ADDR_TYPE_NULL;
146 SrcDesc->Sts[0].Reg.Type = PCH_SMM_ADDR_TYPE_NULL;
147 SrcDesc->PmcSmiSts.Reg.Type = PCH_SMM_ADDR_TYPE_NULL;
148 }
149
150 //
151 // Mch srcdesc
152 //
153 GLOBAL_REMOVE_IF_UNREFERENCED CONST PCH_SMM_SOURCE_DESC mSrcDescMch = {
154 PCH_SMM_NO_FLAGS,
155 {
156 {
157 {
158 ACPI_ADDR_TYPE,
159 {R_ACPI_IO_SMI_EN}
160 },
161 S_ACPI_IO_SMI_EN,
162 N_ACPI_IO_SMI_EN_TCO
163 },
164 NULL_BIT_DESC_INITIALIZER
165 },
166 {
167 {
168 {
169 TCO_ADDR_TYPE,
170 {R_TCO_IO_TCO1_STS}
171 },
172 S_TCO_IO_TCO1_STS,
173 N_TCO_IO_TCO1_STS_DMISMI
174 }
175 },
176 {
177 {
178 ACPI_ADDR_TYPE,
179 {R_ACPI_IO_SMI_STS}
180 },
181 S_ACPI_IO_SMI_STS,
182 N_ACPI_IO_SMI_STS_TCO
183 }
184 };
185
186 /**
187 The register function used to register SMI handler of MCH event.
188
189 @param[in] This The pointer to the protocol itself
190 @param[in] DispatchFunction Pointer to dispatch function to be invoked for this SMI source
191 @param[out] DispatchHandle Handle of dispatch function to register.
192
193 @retval EFI_INVALID_PARAMETER Error with NULL SMI source description
194 @retval EFI_OUT_OF_RESOURCES Fail to allocate pool for database record
195 @retval EFI_SUCCESS The database record is created successfully.
196 @retval EFI_ACCESS_DENIED Return access denied if the SmmReadyToLock event has been triggered
197 **/
198 EFI_STATUS
199 EFIAPI
PchTcoSmiMchRegister(IN PCH_TCO_SMI_DISPATCH_PROTOCOL * This,IN PCH_TCO_SMI_DISPATCH_CALLBACK DispatchFunction,OUT EFI_HANDLE * DispatchHandle)200 PchTcoSmiMchRegister (
201 IN PCH_TCO_SMI_DISPATCH_PROTOCOL *This,
202 IN PCH_TCO_SMI_DISPATCH_CALLBACK DispatchFunction,
203 OUT EFI_HANDLE *DispatchHandle
204 )
205 {
206 EFI_STATUS Status;
207 DATABASE_RECORD *Record;
208
209 //
210 // Return access denied if the SmmReadyToLock event has been triggered
211 //
212 if (mReadyToLock == TRUE) {
213 DEBUG ((DEBUG_ERROR, "Register is not allowed if the SmmReadyToLock event has been triggered! \n"));
214 return EFI_ACCESS_DENIED;
215 }
216
217 Status = PchSmiRecordInsert (
218 &mSrcDescMch,
219 (PCH_SMI_CALLBACK_FUNCTIONS) DispatchFunction,
220 PchTcoSmiMchType,
221 DispatchHandle
222 );
223 if (!EFI_ERROR (Status)) {
224 Record = DATABASE_RECORD_FROM_LINK (*DispatchHandle);
225 Record->ClearSource = PchTcoSmiClearSource;
226 PchSmmClearSource (&Record->SrcDesc);
227 PchSmmEnableSource (&Record->SrcDesc);
228 SmiHandlerProfileRegisterHandler (&gPchTcoSmiDispatchProtocolGuid, (EFI_SMM_HANDLER_ENTRY_POINT2)DispatchFunction, (UINTN)RETURN_ADDRESS (0), NULL, 0);
229 }
230 return Status;
231 }
232
233 //
234 // TcoTimeout srcdesc
235 //
236 GLOBAL_REMOVE_IF_UNREFERENCED CONST PCH_SMM_SOURCE_DESC mSrcDescTcoTimeout = {
237 PCH_SMM_NO_FLAGS,
238 {
239 {
240 {
241 ACPI_ADDR_TYPE,
242 {R_ACPI_IO_SMI_EN}
243 },
244 S_ACPI_IO_SMI_EN,
245 N_ACPI_IO_SMI_EN_TCO
246 },
247 NULL_BIT_DESC_INITIALIZER
248 },
249 {
250 {
251 {
252 TCO_ADDR_TYPE,
253 {R_TCO_IO_TCO1_STS}
254 },
255 S_TCO_IO_TCO1_STS,
256 N_TCO_IO_TCO1_STS_TIMEOUT
257 }
258 },
259 {
260 {
261 ACPI_ADDR_TYPE,
262 {R_ACPI_IO_SMI_STS}
263 },
264 S_ACPI_IO_SMI_STS,
265 N_ACPI_IO_SMI_STS_TCO
266 }
267 };
268
269 /**
270 The register function used to register SMI handler of TcoTimeout event.
271
272 @param[in] This The pointer to the protocol itself
273 @param[in] DispatchFunction Pointer to dispatch function to be invoked for this SMI source
274 @param[out] DispatchHandle Handle of dispatch function to register.
275
276 @retval EFI_INVALID_PARAMETER Error with NULL SMI source description
277 @retval EFI_OUT_OF_RESOURCES Fail to allocate pool for database record
278 @retval EFI_SUCCESS The database record is created successfully.
279 @retval EFI_ACCESS_DENIED Return access denied if the SmmReadyToLock event has been triggered
280 **/
281 EFI_STATUS
282 EFIAPI
PchTcoSmiTcoTimeoutRegister(IN PCH_TCO_SMI_DISPATCH_PROTOCOL * This,IN PCH_TCO_SMI_DISPATCH_CALLBACK DispatchFunction,OUT EFI_HANDLE * DispatchHandle)283 PchTcoSmiTcoTimeoutRegister (
284 IN PCH_TCO_SMI_DISPATCH_PROTOCOL *This,
285 IN PCH_TCO_SMI_DISPATCH_CALLBACK DispatchFunction,
286 OUT EFI_HANDLE *DispatchHandle
287 )
288 {
289 EFI_STATUS Status;
290 DATABASE_RECORD *Record;
291
292 //
293 // Return access denied if the SmmReadyToLock event has been triggered
294 //
295 if (mReadyToLock == TRUE) {
296 DEBUG ((DEBUG_ERROR, "Register is not allowed if the SmmReadyToLock event has been triggered! \n"));
297 return EFI_ACCESS_DENIED;
298 }
299
300 Status = PchSmiRecordInsert (
301 &mSrcDescTcoTimeout,
302 (PCH_SMI_CALLBACK_FUNCTIONS) DispatchFunction,
303 PchTcoSmiTcoTimeoutType,
304 DispatchHandle
305 );
306 if (!EFI_ERROR (Status)) {
307 Record = DATABASE_RECORD_FROM_LINK (*DispatchHandle);
308 Record->ClearSource = PchTcoSmiClearSource;
309 PchSmmClearSource (&Record->SrcDesc);
310 PchSmmEnableSource (&Record->SrcDesc);
311 SmiHandlerProfileRegisterHandler (&gPchTcoSmiDispatchProtocolGuid, (EFI_SMM_HANDLER_ENTRY_POINT2)DispatchFunction, (UINTN)RETURN_ADDRESS (0), NULL, 0);
312 }
313 return Status;
314 }
315
316 //
317 // OsTco srcdesc
318 //
319 GLOBAL_REMOVE_IF_UNREFERENCED CONST PCH_SMM_SOURCE_DESC mSrcDescOsTco = {
320 PCH_SMM_NO_FLAGS,
321 {
322 {
323 {
324 ACPI_ADDR_TYPE,
325 {R_ACPI_IO_SMI_EN}
326 },
327 S_ACPI_IO_SMI_EN,
328 N_ACPI_IO_SMI_EN_TCO
329 },
330 NULL_BIT_DESC_INITIALIZER
331 },
332 {
333 {
334 {
335 TCO_ADDR_TYPE,
336 {R_TCO_IO_TCO1_STS}
337 },
338 S_TCO_IO_TCO1_STS,
339 N_TCO_IO_TCO1_STS_SW_TCO_SMI
340 }
341 },
342 {
343 {
344 ACPI_ADDR_TYPE,
345 {R_ACPI_IO_SMI_STS}
346 },
347 S_ACPI_IO_SMI_STS,
348 N_ACPI_IO_SMI_STS_TCO
349 }
350 };
351
352 /**
353 The register function used to register SMI handler of OS TCO event.
354
355 @param[in] This The pointer to the protocol itself
356 @param[in] DispatchFunction Pointer to dispatch function to be invoked for this SMI source
357 @param[out] DispatchHandle Handle of dispatch function to register.
358
359 @retval EFI_INVALID_PARAMETER Error with NULL SMI source description
360 @retval EFI_OUT_OF_RESOURCES Fail to allocate pool for database record
361 @retval EFI_SUCCESS The database record is created successfully.
362 @retval EFI_ACCESS_DENIED Return access denied if the SmmReadyToLock event has been triggered
363 **/
364 EFI_STATUS
365 EFIAPI
PchTcoSmiOsTcoRegister(IN PCH_TCO_SMI_DISPATCH_PROTOCOL * This,IN PCH_TCO_SMI_DISPATCH_CALLBACK DispatchFunction,OUT EFI_HANDLE * DispatchHandle)366 PchTcoSmiOsTcoRegister (
367 IN PCH_TCO_SMI_DISPATCH_PROTOCOL *This,
368 IN PCH_TCO_SMI_DISPATCH_CALLBACK DispatchFunction,
369 OUT EFI_HANDLE *DispatchHandle
370 )
371 {
372 EFI_STATUS Status;
373 DATABASE_RECORD *Record;
374
375 //
376 // Return access denied if the SmmReadyToLock event has been triggered
377 //
378 if (mReadyToLock == TRUE) {
379 DEBUG ((DEBUG_ERROR, "Register is not allowed if the SmmReadyToLock event has been triggered! \n"));
380 return EFI_ACCESS_DENIED;
381 }
382
383 Status = PchSmiRecordInsert (
384 &mSrcDescOsTco,
385 (PCH_SMI_CALLBACK_FUNCTIONS) DispatchFunction,
386 PchTcoSmiOsTcoType,
387 DispatchHandle
388 );
389 if (!EFI_ERROR (Status)) {
390 Record = DATABASE_RECORD_FROM_LINK (*DispatchHandle);
391 Record->ClearSource = PchTcoSmiClearSource;
392 PchSmmClearSource (&Record->SrcDesc);
393 PchSmmEnableSource (&Record->SrcDesc);
394 SmiHandlerProfileRegisterHandler (&gPchTcoSmiDispatchProtocolGuid, (EFI_SMM_HANDLER_ENTRY_POINT2)DispatchFunction, (UINTN)RETURN_ADDRESS (0), NULL, 0);
395 }
396 return Status;
397 }
398
399 //
400 // Nmi
401 //
402 GLOBAL_REMOVE_IF_UNREFERENCED CONST PCH_SMM_SOURCE_DESC mSrcDescNmi = {
403 PCH_SMM_NO_FLAGS,
404 {
405 {
406 {
407 TCO_ADDR_TYPE,
408 {R_TCO_IO_TCO1_CNT}
409 },
410 S_TCO_IO_TCO1_CNT,
411 N_TCO_IO_TCO1_CNT_NMI2SMI_EN
412 },
413 NULL_BIT_DESC_INITIALIZER
414 },
415 {
416 {
417 {
418 TCO_ADDR_TYPE,
419 {R_TCO_IO_TCO1_STS}
420 },
421 S_TCO_IO_TCO1_STS,
422 N_TCO_IO_TCO1_STS_NMI2SMI
423 }
424 },
425 //
426 // NOTE: The status of NMI2SMI won't reflect to PMC SMI_STS.
427 // So skip the top level status check and check the TCO1_STS directly.
428 //
429 NULL_BIT_DESC_INITIALIZER
430 };
431
432 /**
433 The register function used to register SMI handler of NMI event.
434
435 @param[in] This The pointer to the protocol itself
436 @param[in] DispatchFunction Pointer to dispatch function to be invoked for this SMI source
437 @param[out] DispatchHandle Handle of dispatch function to register.
438
439 @retval EFI_INVALID_PARAMETER Error with NULL SMI source description
440 @retval EFI_OUT_OF_RESOURCES Fail to allocate pool for database record
441 @retval EFI_SUCCESS The database record is created successfully.
442 @retval EFI_ACCESS_DENIED Return access denied if the SmmReadyToLock event has been triggered
443 **/
444 EFI_STATUS
445 EFIAPI
PchTcoSmiNmiRegister(IN PCH_TCO_SMI_DISPATCH_PROTOCOL * This,IN PCH_TCO_SMI_DISPATCH_CALLBACK DispatchFunction,OUT EFI_HANDLE * DispatchHandle)446 PchTcoSmiNmiRegister (
447 IN PCH_TCO_SMI_DISPATCH_PROTOCOL *This,
448 IN PCH_TCO_SMI_DISPATCH_CALLBACK DispatchFunction,
449 OUT EFI_HANDLE *DispatchHandle
450 )
451 {
452 EFI_STATUS Status;
453 DATABASE_RECORD *Record;
454 //
455 // Return access denied if the SmmReadyToLock event has been triggered
456 //
457 if (mReadyToLock == TRUE) {
458 DEBUG ((DEBUG_ERROR, "Register is not allowed if the SmmReadyToLock event has been triggered! \n"));
459 return EFI_ACCESS_DENIED;
460 }
461
462 Status = PchSmiRecordInsert (
463 &mSrcDescNmi,
464 (PCH_SMI_CALLBACK_FUNCTIONS) DispatchFunction,
465 PchTcoSmiNmiType,
466 DispatchHandle
467 );
468 if (!EFI_ERROR (Status)) {
469 Record = DATABASE_RECORD_FROM_LINK (*DispatchHandle);
470 Record->ClearSource = PchTcoSmiClearSource;
471 PchSmmClearSource (&Record->SrcDesc);
472 PchSmmEnableSource (&Record->SrcDesc);
473 SmiHandlerProfileRegisterHandler (&gPchTcoSmiDispatchProtocolGuid, (EFI_SMM_HANDLER_ENTRY_POINT2)DispatchFunction, (UINTN)RETURN_ADDRESS (0), NULL, 0);
474 }
475 return Status;
476 }
477
478 //
479 // IntruderDetect srcdesc
480 //
481 GLOBAL_REMOVE_IF_UNREFERENCED CONST PCH_SMM_SOURCE_DESC mSrcDescIntruderDet = {
482 PCH_SMM_NO_FLAGS,
483 {
484 {
485 {
486 ACPI_ADDR_TYPE,
487 {R_ACPI_IO_SMI_EN}
488 },
489 S_ACPI_IO_SMI_EN,
490 N_ACPI_IO_SMI_EN_TCO
491 },
492 {
493 {
494 TCO_ADDR_TYPE,
495 {R_TCO_IO_TCO2_CNT}
496 },
497 S_TCO_IO_TCO2_CNT,
498 N_TCO_IO_TCO2_CNT_INTRD_SEL
499 }
500 },
501 {
502 {
503 {
504 TCO_ADDR_TYPE,
505 {R_TCO_IO_TCO2_STS}
506 },
507 S_TCO_IO_TCO2_STS,
508 N_TCO_IO_TCO2_STS_INTRD_DET
509 }
510 },
511 {
512 {
513 ACPI_ADDR_TYPE,
514 {R_ACPI_IO_SMI_STS}
515 },
516 S_ACPI_IO_SMI_STS,
517 N_ACPI_IO_SMI_STS_TCO
518 }
519 };
520
521 /**
522 The register function used to register SMI handler of Intruder Detect event.
523
524 @param[in] This The pointer to the protocol itself
525 @param[in] DispatchFunction Pointer to dispatch function to be invoked for this SMI source
526 @param[out] DispatchHandle Handle of dispatch function to register.
527
528 @retval EFI_INVALID_PARAMETER Error with NULL SMI source description
529 @retval EFI_OUT_OF_RESOURCES Fail to allocate pool for database record
530 @retval EFI_SUCCESS The database record is created successfully.
531 @retval EFI_ACCESS_DENIED Return access denied if the SmmReadyToLock event has been triggered
532 **/
533 EFI_STATUS
534 EFIAPI
PchTcoSmiIntruderDetRegister(IN PCH_TCO_SMI_DISPATCH_PROTOCOL * This,IN PCH_TCO_SMI_DISPATCH_CALLBACK DispatchFunction,OUT EFI_HANDLE * DispatchHandle)535 PchTcoSmiIntruderDetRegister (
536 IN PCH_TCO_SMI_DISPATCH_PROTOCOL *This,
537 IN PCH_TCO_SMI_DISPATCH_CALLBACK DispatchFunction,
538 OUT EFI_HANDLE *DispatchHandle
539 )
540 {
541 EFI_STATUS Status;
542 DATABASE_RECORD *Record;
543
544 //
545 // Return access denied if the SmmReadyToLock event has been triggered
546 //
547 if (mReadyToLock == TRUE) {
548 DEBUG ((DEBUG_ERROR, "Register is not allowed if the SmmReadyToLock event has been triggered! \n"));
549 return EFI_ACCESS_DENIED;
550 }
551
552 Status = PchSmiRecordInsert (
553 &mSrcDescIntruderDet,
554 (PCH_SMI_CALLBACK_FUNCTIONS) DispatchFunction,
555 PchTcoSmiIntruderDetectType,
556 DispatchHandle
557 );
558 if (!EFI_ERROR (Status)) {
559 Record = DATABASE_RECORD_FROM_LINK (*DispatchHandle);
560 Record->ClearSource = PchTcoSmiClearSourceAndBlock;
561 PchSmmClearSource (&Record->SrcDesc);
562 PchSmmEnableSource (&Record->SrcDesc);
563 SmiHandlerProfileRegisterHandler (&gPchTcoSmiDispatchProtocolGuid, (EFI_SMM_HANDLER_ENTRY_POINT2)DispatchFunction, (UINTN)RETURN_ADDRESS (0), NULL, 0);
564 }
565 return Status;
566 }
567
568 //
569 // SpiBiosWp srcdesc
570 //
571 GLOBAL_REMOVE_IF_UNREFERENCED CONST PCH_SMM_SOURCE_DESC mSrcDescSpiBiosWp = {
572 PCH_SMM_NO_FLAGS,
573 {
574 {
575 {
576 ACPI_ADDR_TYPE,
577 {R_ACPI_IO_SMI_EN}
578 },
579 S_ACPI_IO_SMI_EN,
580 N_ACPI_IO_SMI_EN_TCO
581 },
582 {
583 {
584 PCIE_ADDR_TYPE,
585 { (
586 (DEFAULT_PCI_BUS_NUMBER_PCH << 24) |
587 (PCI_DEVICE_NUMBER_PCH_SPI << 19) |
588 (PCI_FUNCTION_NUMBER_PCH_SPI << 16) |
589 R_SPI_CFG_BC
590 ) }
591 },
592 S_SPI_CFG_BC,
593 N_SPI_CFG_BC_BLE
594 },
595 },
596 {
597 {
598 {
599 PCIE_ADDR_TYPE,
600 { (
601 (DEFAULT_PCI_BUS_NUMBER_PCH << 24) |
602 (PCI_DEVICE_NUMBER_PCH_SPI << 19) |
603 (PCI_FUNCTION_NUMBER_PCH_SPI << 16) |
604 R_SPI_CFG_BC
605 ) }
606 },
607 S_SPI_CFG_BC,
608 N_SPI_CFG_BC_SYNC_SS
609 }
610 },
611 {
612 {
613 ACPI_ADDR_TYPE,
614 {R_ACPI_IO_SMI_STS}
615 },
616 S_ACPI_IO_SMI_STS,
617 N_ACPI_IO_SMI_STS_TCO
618 }
619 };
620
621 /**
622 Special handling for SPI Write Protect
623
624 @param[in] SrcDesc Not used
625 **/
626 VOID
627 EFIAPI
PchTcoSpiWpClearSource(CONST PCH_SMM_SOURCE_DESC * SrcDesc)628 PchTcoSpiWpClearSource (
629 CONST PCH_SMM_SOURCE_DESC *SrcDesc
630 )
631 {
632 UINT64 SpiRegBase;
633 UINT32 BiosControl;
634 UINT32 Timeout;
635
636 SpiRegBase = SpiPciCfgBase ();
637 PciSegmentAndThenOr32 (
638 SpiRegBase + R_SPI_CFG_BC,
639 (UINT32) ~B_SPI_CFG_BC_ASYNC_SS,
640 B_SPI_CFG_BC_SYNC_SS
641 );
642 //
643 // Ensure the SYNC is cleared
644 //
645 Timeout = 1000;
646 do {
647 BiosControl = PciSegmentRead32 (SpiRegBase + R_SPI_CFG_BC);
648 Timeout--;
649 } while ((BiosControl & B_SPI_CFG_BC_SYNC_SS) && (Timeout > 0));
650
651 //
652 // Any TCO-based status bits require special handling.
653 // SMI_STS.TCO_STS must be cleared in addition to the status bit in the TCO registers
654 //
655 PchSmmClearSource (&mDescSrcTcoSts);
656 }
657
658 /**
659 Set SMI_EN_TCO to enable TCO SMI.
660 **/
661 STATIC
662 VOID
PchSetSmiEnTco(VOID)663 PchSetSmiEnTco (
664 VOID
665 )
666 {
667 IoOr32 (mAcpiBaseAddr + R_ACPI_IO_SMI_EN, B_ACPI_IO_SMI_EN_TCO);
668 }
669
670 /**
671 The register function used to register SMI handler of BIOS write protect event.
672
673 @param[in] This The pointer to the protocol itself
674 @param[in] DispatchFunction Pointer to dispatch function to be invoked for this SMI source
675 @param[out] DispatchHandle Handle of dispatch function to register.
676
677 @retval EFI_INVALID_PARAMETER Error with NULL SMI source description
678 @retval EFI_OUT_OF_RESOURCES Fail to allocate pool for database record
679 @retval EFI_SUCCESS The database record is created successfully.
680 @retval EFI_ACCESS_DENIED Return access denied if the SmmReadyToLock event has been triggered
681 **/
682 EFI_STATUS
683 EFIAPI
PchTcoSmiSpiBiosWpRegister(IN PCH_TCO_SMI_DISPATCH_PROTOCOL * This,IN PCH_TCO_SMI_DISPATCH_CALLBACK DispatchFunction,OUT EFI_HANDLE * DispatchHandle)684 PchTcoSmiSpiBiosWpRegister (
685 IN PCH_TCO_SMI_DISPATCH_PROTOCOL *This,
686 IN PCH_TCO_SMI_DISPATCH_CALLBACK DispatchFunction,
687 OUT EFI_HANDLE *DispatchHandle
688 )
689 {
690 EFI_STATUS Status;
691 DATABASE_RECORD *Record;
692
693 //
694 // Return access denied if the SmmReadyToLock event has been triggered
695 //
696 if (mReadyToLock == TRUE) {
697 DEBUG ((DEBUG_ERROR, "Register is not allowed if the SmmReadyToLock event has been triggered! \n"));
698 return EFI_ACCESS_DENIED;
699 }
700
701 Status = PchSmiRecordInsert (
702 &mSrcDescSpiBiosWp,
703 (PCH_SMI_CALLBACK_FUNCTIONS) DispatchFunction,
704 PchTcoSmiSpiBiosWpType,
705 DispatchHandle
706 );
707 if (!EFI_ERROR (Status)) {
708 Record = DATABASE_RECORD_FROM_LINK (*DispatchHandle);
709 Record->ClearSource = PchTcoSpiWpClearSource;
710 PchTcoSpiWpClearSource (NULL);
711 //
712 // It doesn't enable the BIOSLOCK here. Enable it by policy in DXE.
713 // Only enable SMI_EN_TCO.
714 //
715 PchSetSmiEnTco ();
716 SmiHandlerProfileRegisterHandler (&gPchTcoSmiDispatchProtocolGuid, (EFI_SMM_HANDLER_ENTRY_POINT2)DispatchFunction, (UINTN)RETURN_ADDRESS (0), NULL, 0);
717 }
718 return Status;
719 }
720
721 //
722 // LpcBiosWp srcdesc
723 //
724 GLOBAL_REMOVE_IF_UNREFERENCED CONST PCH_SMM_SOURCE_DESC mSrcDescLpcBiosWp = {
725 PCH_SMM_NO_FLAGS,
726 {
727 {
728 {
729 ACPI_ADDR_TYPE,
730 {R_ACPI_IO_SMI_EN}
731 },
732 S_ACPI_IO_SMI_EN,
733 N_ACPI_IO_SMI_EN_TCO
734 },
735 {
736 {
737 PCIE_ADDR_TYPE,
738 { (
739 (DEFAULT_PCI_BUS_NUMBER_PCH << 24) |
740 (PCI_DEVICE_NUMBER_PCH_LPC << 19) |
741 (PCI_FUNCTION_NUMBER_PCH_LPC << 16) |
742 R_LPC_CFG_BC
743 ) }
744 },
745 S_LPC_CFG_BC,
746 N_LPC_CFG_BC_LE
747 }
748 },
749 {
750 {
751 {
752 TCO_ADDR_TYPE,
753 {R_TCO_IO_TCO1_STS}
754 },
755 S_TCO_IO_TCO1_STS,
756 N_TCO_IO_TCO1_STS_BIOSWR
757 }
758 },
759 {
760 {
761 ACPI_ADDR_TYPE,
762 {R_ACPI_IO_SMI_STS}
763 },
764 S_ACPI_IO_SMI_STS,
765 N_ACPI_IO_SMI_STS_TCO
766 }
767 };
768
769 /**
770 The register function used to register SMI handler of LPC BIOS write protect event.
771
772 @param[in] This The pointer to the protocol itself
773 @param[in] DispatchFunction Pointer to dispatch function to be invoked for this SMI source
774 @param[out] DispatchHandle Handle of dispatch function to register.
775
776 @retval EFI_INVALID_PARAMETER Error with NULL SMI source description
777 @retval EFI_OUT_OF_RESOURCES Fail to allocate pool for database record
778 @retval EFI_SUCCESS The database record is created successfully.
779 @retval EFI_ACCESS_DENIED Return access denied if the SmmReadyToLock event has been triggered
780 **/
781 EFI_STATUS
782 EFIAPI
PchTcoSmiLpcBiosWpRegister(IN PCH_TCO_SMI_DISPATCH_PROTOCOL * This,IN PCH_TCO_SMI_DISPATCH_CALLBACK DispatchFunction,OUT EFI_HANDLE * DispatchHandle)783 PchTcoSmiLpcBiosWpRegister (
784 IN PCH_TCO_SMI_DISPATCH_PROTOCOL *This,
785 IN PCH_TCO_SMI_DISPATCH_CALLBACK DispatchFunction,
786 OUT EFI_HANDLE *DispatchHandle
787 )
788 {
789 EFI_STATUS Status;
790 DATABASE_RECORD *Record;
791
792 //
793 // Return access denied if the SmmReadyToLock event has been triggered
794 //
795 if (mReadyToLock == TRUE) {
796 DEBUG ((DEBUG_ERROR, "Register is not allowed if the SmmReadyToLock event has been triggered! \n"));
797 return EFI_ACCESS_DENIED;
798 }
799
800 if (IsEspiEnabled ()) {
801 //
802 // Status is D31F0's PCBC.BWPDS
803 //
804 ASSERT (FALSE);
805 return EFI_UNSUPPORTED;
806 }
807
808 Status = PchSmiRecordInsert (
809 &mSrcDescLpcBiosWp,
810 (PCH_SMI_CALLBACK_FUNCTIONS) DispatchFunction,
811 PchTcoSmiLpcBiosWpType,
812 DispatchHandle
813 );
814 if (!EFI_ERROR (Status)) {
815 Record = DATABASE_RECORD_FROM_LINK (*DispatchHandle);
816 Record->ClearSource = PchTcoSmiClearSource;
817 PchSmmClearSource (&Record->SrcDesc);
818 //
819 // It doesn't enable the BIOSLOCK here. Enable it by policy in DXE.
820 // Only enable SMI_EN_TCO.
821 //
822 PchSetSmiEnTco ();
823 SmiHandlerProfileRegisterHandler (&gPchTcoSmiDispatchProtocolGuid, (EFI_SMM_HANDLER_ENTRY_POINT2)DispatchFunction, (UINTN)RETURN_ADDRESS (0), NULL, 0);
824 }
825 return Status;
826 }
827
828 //
829 // NEWCENTURY_STS bit that needs to be cleared
830 //
831 GLOBAL_REMOVE_IF_UNREFERENCED CONST PCH_SMM_SOURCE_DESC mSrcDescNewCentury = {
832 PCH_SMM_NO_FLAGS,
833 {
834 {
835 {
836 ACPI_ADDR_TYPE,
837 {R_ACPI_IO_SMI_EN}
838 },
839 S_ACPI_IO_SMI_EN,
840 N_ACPI_IO_SMI_EN_TCO
841 },
842 NULL_BIT_DESC_INITIALIZER
843 },
844 {
845 {
846 {
847 TCO_ADDR_TYPE,
848 {R_TCO_IO_TCO1_STS}
849 },
850 S_TCO_IO_TCO1_STS,
851 N_TCO_IO_TCO1_STS_NEWCENTURY
852 }
853 },
854 {
855 {
856 ACPI_ADDR_TYPE,
857 {R_ACPI_IO_SMI_STS}
858 },
859 S_ACPI_IO_SMI_STS,
860 N_ACPI_IO_SMI_STS_TCO
861 }
862 };
863
864 /**
865 The register function used to register SMI handler of NEW CENTURY event.
866
867 @param[in] This The pointer to the protocol itself
868 @param[in] DispatchFunction Pointer to dispatch function to be invoked for this SMI source
869 @param[out] DispatchHandle Handle of dispatch function to register.
870
871 @retval EFI_INVALID_PARAMETER Error with NULL SMI source description
872 @retval EFI_OUT_OF_RESOURCES Fail to allocate pool for database record
873 @retval EFI_SUCCESS The database record is created successfully.
874 @retval EFI_ACCESS_DENIED Return access denied if the SmmReadyToLock event has been triggered
875 **/
876 EFI_STATUS
877 EFIAPI
PchTcoSmiNewCenturyRegister(IN PCH_TCO_SMI_DISPATCH_PROTOCOL * This,IN PCH_TCO_SMI_DISPATCH_CALLBACK DispatchFunction,OUT EFI_HANDLE * DispatchHandle)878 PchTcoSmiNewCenturyRegister (
879 IN PCH_TCO_SMI_DISPATCH_PROTOCOL *This,
880 IN PCH_TCO_SMI_DISPATCH_CALLBACK DispatchFunction,
881 OUT EFI_HANDLE *DispatchHandle
882 )
883 {
884 EFI_STATUS Status;
885 DATABASE_RECORD *Record;
886
887 //
888 // Return access denied if the SmmReadyToLock event has been triggered
889 //
890 if (mReadyToLock == TRUE) {
891 DEBUG ((DEBUG_ERROR, "Register is not allowed if the SmmReadyToLock event has been triggered! \n"));
892 return EFI_ACCESS_DENIED;
893 }
894
895 Status = PchSmiRecordInsert (
896 &mSrcDescNewCentury,
897 (PCH_SMI_CALLBACK_FUNCTIONS) DispatchFunction,
898 PchTcoSmiNewCenturyType,
899 DispatchHandle
900 );
901 if (!EFI_ERROR (Status)) {
902 Record = DATABASE_RECORD_FROM_LINK (*DispatchHandle);
903 Record->ClearSource = PchTcoSmiClearSourceAndBlock;
904 PchSmmClearSource (&Record->SrcDesc);
905 PchSmmEnableSource (&Record->SrcDesc);
906 SmiHandlerProfileRegisterHandler (&gPchTcoSmiDispatchProtocolGuid, (EFI_SMM_HANDLER_ENTRY_POINT2)DispatchFunction, (UINTN)RETURN_ADDRESS (0), NULL, 0);
907 }
908 return Status;
909 }
910
911 /**
912 Unregister a child SMI source dispatch function with a parent SMM driver
913
914 @param[in] This Protocol instance pointer.
915 @param[in] DispatchHandle Handle of dispatch function to deregister.
916
917 @retval EFI_SUCCESS The dispatch function has been successfully
918 unregistered and the SMI source has been disabled
919 if there are no other registered child dispatch
920 functions for this SMI source.
921 @retval EFI_INVALID_PARAMETER Handle is invalid.
922 @retval EFI_ACCESS_DENIED Return access denied if the SmmReadyToLock event has been triggered
923 **/
924 EFI_STATUS
925 EFIAPI
PchTcoSmiUnRegister(IN PCH_TCO_SMI_DISPATCH_PROTOCOL * This,IN EFI_HANDLE DispatchHandle)926 PchTcoSmiUnRegister (
927 IN PCH_TCO_SMI_DISPATCH_PROTOCOL *This,
928 IN EFI_HANDLE DispatchHandle
929 )
930 {
931 DATABASE_RECORD *Record;
932 EFI_STATUS Status;
933
934 Record = DATABASE_RECORD_FROM_LINK (DispatchHandle);
935 if ((Record->SrcDesc.En[1].Reg.Type == ACPI_ADDR_TYPE) &&
936 (Record->SrcDesc.En[1].Reg.Data.pcie.Fields.Dev == SpiDevNumber ()) &&
937 (Record->SrcDesc.En[1].Reg.Data.pcie.Fields.Fnc == SpiFuncNumber ()) &&
938 (Record->SrcDesc.En[1].Reg.Data.pcie.Fields.Reg == R_SPI_CFG_BC) &&
939 (Record->SrcDesc.En[1].Bit == N_SPI_CFG_BC_BLE)) {
940 //
941 // SPI Write Protect cannot be disabled
942 //
943 return EFI_ACCESS_DENIED;
944 } else if ((Record->SrcDesc.En[1].Reg.Type == ACPI_ADDR_TYPE) &&
945 (Record->SrcDesc.En[1].Reg.Data.pcie.Fields.Dev == LpcDevNumber ()) &&
946 (Record->SrcDesc.En[1].Reg.Data.pcie.Fields.Fnc == LpcFuncNumber ()) &&
947 (Record->SrcDesc.En[1].Reg.Data.pcie.Fields.Reg == R_LPC_CFG_BC) &&
948 (Record->SrcDesc.En[1].Bit == N_LPC_CFG_BC_LE)) {
949 //
950 // eSPI/LPC Write Protect cannot be disabled
951 //
952 return EFI_ACCESS_DENIED;
953 }
954
955 Status = PchSmmCoreUnRegister (NULL, DispatchHandle);
956 if (!EFI_ERROR (Status)) {
957 SmiHandlerProfileUnregisterHandler (&gPchTcoSmiDispatchProtocolGuid, Record->Callback, NULL, 0);
958 }
959 return Status;
960 }
961
962
963 //
964 // PcieRpHotPlug srcdesc
965 //
966 GLOBAL_REMOVE_IF_UNREFERENCED PCH_SMM_SOURCE_DESC PchPcieSmiRpHotPlugTemplate = {
967 PCH_SMM_NO_FLAGS,
968 {
969 {
970 {
971 PCIE_ADDR_TYPE,
972 {R_PCH_PCIE_CFG_MPC}
973 },
974 S_PCH_PCIE_CFG_MPC,
975 N_PCH_PCIE_CFG_MPC_HPME
976 },
977 NULL_BIT_DESC_INITIALIZER
978 },
979 {
980 {
981 {
982 PCIE_ADDR_TYPE,
983 {R_PCH_PCIE_CFG_SMSCS}
984 },
985 S_PCH_PCIE_CFG_SMSCS,
986 N_PCH_PCIE_CFG_SMSCS_HPPDM
987 }
988 },
989 {
990 {
991 ACPI_ADDR_TYPE,
992 {R_ACPI_IO_SMI_STS}
993 },
994 S_ACPI_IO_SMI_STS,
995 N_ACPI_IO_SMI_STS_PCI_EXP
996 }
997 };
998
999 /**
1000 The register function used to register SMI handler of PCIE RP hotplug event.
1001
1002 @param[in] This The pointer to the protocol itself
1003 @param[in] DispatchFunction Pointer to dispatch function to be invoked for this SMI source
1004 @param[in] RpIndex Refer PCIE_COMBINED_RPINDEX for PCH RP index and CPU RP index.
1005 @param[out] DispatchHandle Handle of dispatch function to register.
1006
1007 @retval EFI_INVALID_PARAMETER Error with NULL SMI source description
1008 @retval EFI_OUT_OF_RESOURCES Fail to allocate pool for database record
1009 @retval EFI_SUCCESS The database record is created successfully.
1010 @retval EFI_ACCESS_DENIED Return access denied if the SmmReadyToLock event has been triggered
1011 **/
1012 EFI_STATUS
1013 EFIAPI
PchPcieSmiHotPlugRegister(IN PCH_PCIE_SMI_DISPATCH_PROTOCOL * This,IN PCH_PCIE_SMI_RP_DISPATCH_CALLBACK DispatchFunction,IN UINTN RpIndex,OUT EFI_HANDLE * DispatchHandle)1014 PchPcieSmiHotPlugRegister (
1015 IN PCH_PCIE_SMI_DISPATCH_PROTOCOL *This,
1016 IN PCH_PCIE_SMI_RP_DISPATCH_CALLBACK DispatchFunction,
1017 IN UINTN RpIndex,
1018 OUT EFI_HANDLE *DispatchHandle
1019 )
1020 {
1021 EFI_STATUS Status;
1022 UINTN RpDev;
1023 UINTN RpFun;
1024 PCH_SMM_PCIE_REGISTER_CONTEXT Context;
1025 DATABASE_RECORD *Record;
1026 //
1027 // Return access denied if the SmmReadyToLock event has been triggered
1028 //
1029 if (mReadyToLock == TRUE) {
1030 DEBUG ((DEBUG_ERROR, "Register is not allowed if the SmmReadyToLock event has been triggered! \n"));
1031 return EFI_ACCESS_DENIED;
1032 }
1033 GetPcieRpDevFun (RpIndex, &RpDev, &RpFun);
1034
1035 PchPcieSmiRpHotPlugTemplate.En[0].Reg.Data.pcie.Fields.Dev = (UINT8) RpDev;
1036 PchPcieSmiRpHotPlugTemplate.En[0].Reg.Data.pcie.Fields.Fnc = (UINT8) RpFun;
1037 PchPcieSmiRpHotPlugTemplate.Sts[0].Reg.Data.pcie.Fields.Dev = (UINT8) RpDev;
1038 PchPcieSmiRpHotPlugTemplate.Sts[0].Reg.Data.pcie.Fields.Fnc = (UINT8) RpFun;
1039
1040 Status = PchSmiRecordInsert (
1041 &PchPcieSmiRpHotPlugTemplate,
1042 (PCH_SMI_CALLBACK_FUNCTIONS) DispatchFunction,
1043 PchPcieSmiRpHotplugType,
1044 DispatchHandle
1045 );
1046 if (!EFI_ERROR (Status)) {
1047 Record = DATABASE_RECORD_FROM_LINK (*DispatchHandle);
1048 Record->ChildContext.Pcie.PchSmiType = PchPcieSmiRpHotplugType;
1049 Record->ChildContext.Pcie.RpIndex = RpIndex;
1050 Record->ContextSize = sizeof (PCH_SMM_PCIE_REGISTER_CONTEXT);
1051 SmiHandlerProfileRegisterHandler (
1052 &gPchPcieSmiDispatchProtocolGuid,
1053 (EFI_SMM_HANDLER_ENTRY_POINT2)DispatchFunction,
1054 (UINTN)RETURN_ADDRESS (0),
1055 &Context,
1056 sizeof (Context)
1057 );
1058 }
1059 PchSmmClearSource (&PchPcieSmiRpHotPlugTemplate);
1060 PchSmmEnableSource (&PchPcieSmiRpHotPlugTemplate);
1061
1062 return Status;
1063 }
1064
1065 //
1066 // PcieRpLinkActive srcdesc
1067 //
1068 GLOBAL_REMOVE_IF_UNREFERENCED PCH_SMM_SOURCE_DESC PchPcieSmiRpLinkActiveTemplate = {
1069 PCH_SMM_NO_FLAGS,
1070 {
1071 {
1072 {
1073 PCIE_ADDR_TYPE,
1074 {R_PCH_PCIE_CFG_MPC}
1075 },
1076 S_PCH_PCIE_CFG_MPC,
1077 N_PCH_PCIE_CFG_MPC_HPME
1078 },
1079 NULL_BIT_DESC_INITIALIZER
1080 },
1081 {
1082 {
1083 {
1084 PCIE_ADDR_TYPE,
1085 {R_PCH_PCIE_CFG_SMSCS}
1086 },
1087 S_PCH_PCIE_CFG_SMSCS,
1088 N_PCH_PCIE_CFG_SMSCS_HPLAS
1089 }
1090 },
1091 {
1092 {
1093 ACPI_ADDR_TYPE,
1094 {R_ACPI_IO_SMI_STS}
1095 },
1096 S_ACPI_IO_SMI_STS,
1097 N_ACPI_IO_SMI_STS_PCI_EXP
1098 }
1099 };
1100
1101 /**
1102 The register function used to register SMI handler of PCIE RP link active event.
1103
1104 @param[in] This The pointer to the protocol itself
1105 @param[in] DispatchFunction Pointer to dispatch function to be invoked for this SMI source
1106 @param[in] RpIndex Refer PCIE_COMBINED_RPINDEX for PCH RP index and CPU RP index.
1107 @param[out] DispatchHandle Handle of dispatch function to register.
1108
1109 @retval EFI_INVALID_PARAMETER Error with NULL SMI source description
1110 @retval EFI_OUT_OF_RESOURCES Fail to allocate pool for database record
1111 @retval EFI_SUCCESS The database record is created successfully.
1112 @retval EFI_ACCESS_DENIED Return access denied if the SmmReadyToLock event has been triggered
1113 **/
1114 EFI_STATUS
1115 EFIAPI
PchPcieSmiLinkActiveRegister(IN PCH_PCIE_SMI_DISPATCH_PROTOCOL * This,IN PCH_PCIE_SMI_RP_DISPATCH_CALLBACK DispatchFunction,IN UINTN RpIndex,OUT EFI_HANDLE * DispatchHandle)1116 PchPcieSmiLinkActiveRegister (
1117 IN PCH_PCIE_SMI_DISPATCH_PROTOCOL *This,
1118 IN PCH_PCIE_SMI_RP_DISPATCH_CALLBACK DispatchFunction,
1119 IN UINTN RpIndex,
1120 OUT EFI_HANDLE *DispatchHandle
1121 )
1122 {
1123 EFI_STATUS Status;
1124 UINTN RpDev;
1125 UINTN RpFun;
1126 PCH_SMM_PCIE_REGISTER_CONTEXT Context;
1127 DATABASE_RECORD *Record;
1128 //
1129 // Return access denied if the SmmReadyToLock event has been triggered
1130 //
1131 if (mReadyToLock == TRUE) {
1132 DEBUG ((DEBUG_ERROR, "Register is not allowed if the SmmReadyToLock event has been triggered! \n"));
1133 return EFI_ACCESS_DENIED;
1134 }
1135
1136 GetPcieRpDevFun (RpIndex, &RpDev, &RpFun);
1137
1138
1139 PchPcieSmiRpLinkActiveTemplate.En[0].Reg.Data.pcie.Fields.Dev = (UINT8) RpDev;
1140 PchPcieSmiRpLinkActiveTemplate.En[0].Reg.Data.pcie.Fields.Fnc = (UINT8) RpFun;
1141 PchPcieSmiRpLinkActiveTemplate.Sts[0].Reg.Data.pcie.Fields.Dev = (UINT8) RpDev;
1142 PchPcieSmiRpLinkActiveTemplate.Sts[0].Reg.Data.pcie.Fields.Fnc = (UINT8) RpFun;
1143
1144 Status = PchSmiRecordInsert (
1145 &PchPcieSmiRpLinkActiveTemplate,
1146 (PCH_SMI_CALLBACK_FUNCTIONS) DispatchFunction,
1147 PchPcieSmiRpLinkActiveType,
1148 DispatchHandle
1149 );
1150 if (!EFI_ERROR (Status)) {
1151 Record = DATABASE_RECORD_FROM_LINK (*DispatchHandle);
1152 Record->ChildContext.Pcie.PchSmiType = PchPcieSmiRpLinkActiveType;
1153 Record->ChildContext.Pcie.RpIndex = RpIndex;
1154 Record->ContextSize = sizeof (PCH_SMM_PCIE_REGISTER_CONTEXT);
1155 SmiHandlerProfileRegisterHandler (
1156 &gPchPcieSmiDispatchProtocolGuid,
1157 (EFI_SMM_HANDLER_ENTRY_POINT2)DispatchFunction,
1158 (UINTN)RETURN_ADDRESS (0),
1159 &Context,
1160 sizeof (Context)
1161 );
1162 }
1163 PchSmmClearSource (&PchPcieSmiRpLinkActiveTemplate);
1164 PchSmmEnableSource (&PchPcieSmiRpLinkActiveTemplate);
1165
1166 return Status;
1167 }
1168
1169 //
1170 // PcieRpLinkEq srcdesc
1171 //
1172 GLOBAL_REMOVE_IF_UNREFERENCED PCH_SMM_SOURCE_DESC PchPcieSmiRpLinkEqTemplate = {
1173 PCH_SMM_NO_FLAGS,
1174 {
1175 {
1176 {
1177 PCIE_ADDR_TYPE,
1178 {R_PCH_PCIE_CFG_EQCFG1}
1179 },
1180 S_PCH_PCIE_CFG_EQCFG1,
1181 N_PCH_PCIE_CFG_EQCFG1_LERSMIE
1182 },
1183 NULL_BIT_DESC_INITIALIZER
1184 },
1185 {
1186 {
1187 {
1188 PCIE_ADDR_TYPE,
1189 {R_PCH_PCIE_CFG_SMSCS}
1190 },
1191 S_PCH_PCIE_CFG_SMSCS,
1192 N_PCH_PCIE_CFG_SMSCS_LERSMIS
1193 }
1194 },
1195 {
1196 {
1197 ACPI_ADDR_TYPE,
1198 {R_ACPI_IO_SMI_STS}
1199 },
1200 S_ACPI_IO_SMI_STS,
1201 N_ACPI_IO_SMI_STS_PCI_EXP
1202 }
1203 };
1204 /**
1205 The register function used to register SMI handler of PCIE RP Link Equalization Request event.
1206
1207 @param[in] This The pointer to the protocol itself
1208 @param[in] DispatchFunction Pointer to dispatch function to be invoked for this SMI source
1209 @param[in] RpIndex Refer PCIE_COMBINED_RPINDEX for PCH RP index and CPU RP index.
1210 @param[out] DispatchHandle Handle of dispatch function to register.
1211
1212 @retval EFI_INVALID_PARAMETER Error with NULL SMI source description
1213 @retval EFI_OUT_OF_RESOURCES Fail to allocate pool for database record
1214 @retval EFI_SUCCESS The database record is created successfully.
1215 @retval EFI_ACCESS_DENIED Return access denied if the SmmReadyToLock event has been triggered
1216 **/
1217 EFI_STATUS
1218 EFIAPI
PchPcieSmiLinkEqRegister(IN PCH_PCIE_SMI_DISPATCH_PROTOCOL * This,IN PCH_PCIE_SMI_RP_DISPATCH_CALLBACK DispatchFunction,IN UINTN RpIndex,OUT EFI_HANDLE * DispatchHandle)1219 PchPcieSmiLinkEqRegister (
1220 IN PCH_PCIE_SMI_DISPATCH_PROTOCOL *This,
1221 IN PCH_PCIE_SMI_RP_DISPATCH_CALLBACK DispatchFunction,
1222 IN UINTN RpIndex,
1223 OUT EFI_HANDLE *DispatchHandle
1224 )
1225 {
1226 UINTN RpDev;
1227 UINTN RpFun;
1228 EFI_STATUS Status;
1229 PCH_SMM_PCIE_REGISTER_CONTEXT Context;
1230 DATABASE_RECORD *Record;
1231
1232 //
1233 // Return access denied if the SmmReadyToLock event has been triggered
1234 //
1235 if (mReadyToLock == TRUE) {
1236 DEBUG ((DEBUG_ERROR, "Register is not allowed if the SmmReadyToLock event has been triggered! \n"));
1237 return EFI_ACCESS_DENIED;
1238 }
1239
1240 GetPcieRpDevFun (RpIndex, &RpDev, &RpFun);
1241
1242 //
1243 // Patch the RP device number and function number of srcdesc.
1244 //
1245 PchPcieSmiRpLinkEqTemplate.En[0].Reg.Data.pcie.Fields.Dev = (UINT8) RpDev;
1246 PchPcieSmiRpLinkEqTemplate.En[0].Reg.Data.pcie.Fields.Fnc = (UINT8) RpFun;
1247 PchPcieSmiRpLinkEqTemplate.Sts[0].Reg.Data.pcie.Fields.Dev = (UINT8) RpDev;
1248 PchPcieSmiRpLinkEqTemplate.Sts[0].Reg.Data.pcie.Fields.Fnc = (UINT8) RpFun;
1249
1250 Status = PchSmiRecordInsert (
1251 &PchPcieSmiRpLinkEqTemplate,
1252 (PCH_SMI_CALLBACK_FUNCTIONS) DispatchFunction,
1253 PchPcieSmiRpLinkEqType,
1254 DispatchHandle
1255 );
1256 if (!EFI_ERROR (Status)) {
1257 Record = DATABASE_RECORD_FROM_LINK (*DispatchHandle);
1258 Record->ChildContext.Pcie.PchSmiType = PchPcieSmiRpLinkEqType;
1259 Record->ChildContext.Pcie.RpIndex = RpIndex;
1260 Record->ContextSize = sizeof (PCH_SMM_PCIE_REGISTER_CONTEXT);
1261 SmiHandlerProfileRegisterHandler (
1262 &gPchPcieSmiDispatchProtocolGuid,
1263 (EFI_SMM_HANDLER_ENTRY_POINT2) DispatchFunction,
1264 (UINTN)RETURN_ADDRESS (0),
1265 &Context,
1266 sizeof (Context)
1267 );
1268 }
1269 return Status;
1270 }
1271
1272 /**
1273 Unregister a child SMI source dispatch function with a parent SMM driver
1274
1275 @param[in] This Protocol instance pointer.
1276 @param[in] DispatchHandle Handle of dispatch function to deregister.
1277
1278 @retval EFI_SUCCESS The dispatch function has been successfully
1279 unregistered and the SMI source has been disabled
1280 if there are no other registered child dispatch
1281 functions for this SMI source.
1282 @retval EFI_INVALID_PARAMETER Handle is invalid.
1283 @retval EFI_ACCESS_DENIED Return access denied if the SmmReadyToLock event has been triggered
1284 **/
1285 EFI_STATUS
1286 EFIAPI
PchPcieSmiUnRegister(IN PCH_PCIE_SMI_DISPATCH_PROTOCOL * This,IN EFI_HANDLE DispatchHandle)1287 PchPcieSmiUnRegister (
1288 IN PCH_PCIE_SMI_DISPATCH_PROTOCOL *This,
1289 IN EFI_HANDLE DispatchHandle
1290 )
1291 {
1292 DATABASE_RECORD *RecordToDelete;
1293 EFI_STATUS Status;
1294
1295 RecordToDelete = DATABASE_RECORD_FROM_LINK (DispatchHandle);
1296 Status = PchSmmCoreUnRegister (NULL, DispatchHandle);
1297 if (!EFI_ERROR (Status)) {
1298 SmiHandlerProfileUnregisterHandler (
1299 &gPchPcieSmiDispatchProtocolGuid,
1300 RecordToDelete->Callback,
1301 &RecordToDelete->ChildContext,
1302 sizeof (RecordToDelete->ContextSize)
1303 );
1304 }
1305 return Status;
1306 }
1307
1308 //
1309 // Pme srcdesc
1310 //
1311 GLOBAL_REMOVE_IF_UNREFERENCED CONST PCH_SMM_SOURCE_DESC mSrcDescPme = {
1312 PCH_SMM_SCI_EN_DEPENDENT,
1313 {
1314 {
1315 {
1316 ACPI_ADDR_TYPE,
1317 {R_ACPI_IO_GPE0_EN_127_96}
1318 },
1319 S_ACPI_IO_GPE0_EN_127_96,
1320 N_ACPI_IO_GPE0_EN_127_96_PME
1321 },
1322 NULL_BIT_DESC_INITIALIZER
1323 },
1324 {
1325 {
1326 {
1327 ACPI_ADDR_TYPE,
1328 {R_ACPI_IO_GPE0_STS_127_96}
1329 },
1330 S_ACPI_IO_GPE0_STS_127_96,
1331 N_ACPI_IO_GPE0_STS_127_96_PME
1332 }
1333 },
1334 {
1335 {
1336 ACPI_ADDR_TYPE,
1337 {R_ACPI_IO_SMI_STS}
1338 },
1339 S_ACPI_IO_SMI_STS,
1340 N_ACPI_IO_SMI_STS_GPE0
1341 }
1342 };
1343
1344 /**
1345 The register function used to register SMI handler of PME event.
1346
1347 @param[in] This The pointer to the protocol itself
1348 @param[in] DispatchFunction Pointer to dispatch function to be invoked for this SMI source
1349 @param[out] DispatchHandle Handle of dispatch function to register.
1350
1351 @retval EFI_INVALID_PARAMETER Error with NULL SMI source description
1352 @retval EFI_OUT_OF_RESOURCES Fail to allocate pool for database record
1353 @retval EFI_SUCCESS The database record is created successfully.
1354 @retval EFI_ACCESS_DENIED Return access denied if the SmmReadyToLock event has been triggered
1355 **/
1356 EFI_STATUS
1357 EFIAPI
PchAcpiSmiPmeRegister(IN PCH_ACPI_SMI_DISPATCH_PROTOCOL * This,IN PCH_ACPI_SMI_DISPATCH_CALLBACK DispatchFunction,OUT EFI_HANDLE * DispatchHandle)1358 PchAcpiSmiPmeRegister (
1359 IN PCH_ACPI_SMI_DISPATCH_PROTOCOL *This,
1360 IN PCH_ACPI_SMI_DISPATCH_CALLBACK DispatchFunction,
1361 OUT EFI_HANDLE *DispatchHandle
1362 )
1363 {
1364 EFI_STATUS Status;
1365
1366 //
1367 // Return access denied if the SmmReadyToLock event has been triggered
1368 //
1369 if (mReadyToLock == TRUE) {
1370 DEBUG ((DEBUG_ERROR, "Register is not allowed if the SmmReadyToLock event has been triggered! \n"));
1371 return EFI_ACCESS_DENIED;
1372 }
1373
1374 Status = PchSmiRecordInsert (
1375 &mSrcDescPme,
1376 (PCH_SMI_CALLBACK_FUNCTIONS) DispatchFunction,
1377 PchAcpiSmiPmeType,
1378 DispatchHandle
1379 );
1380 PchSmmClearSource (&mSrcDescPme);
1381 PchSmmEnableSource (&mSrcDescPme);
1382 if (!EFI_ERROR (Status)) {
1383 SmiHandlerProfileRegisterHandler (&gPchAcpiSmiDispatchProtocolGuid, (EFI_SMM_HANDLER_ENTRY_POINT2)DispatchFunction, (UINTN)RETURN_ADDRESS (0), NULL, 0);
1384 }
1385 return Status;
1386 }
1387
1388 //
1389 // PmeB0 srcdesc
1390 //
1391 GLOBAL_REMOVE_IF_UNREFERENCED CONST PCH_SMM_SOURCE_DESC mSrcDescPmeB0 = {
1392 PCH_SMM_SCI_EN_DEPENDENT,
1393 {
1394 {
1395 {
1396 ACPI_ADDR_TYPE,
1397 {R_ACPI_IO_GPE0_EN_127_96}
1398 },
1399 S_ACPI_IO_GPE0_EN_127_96,
1400 N_ACPI_IO_GPE0_EN_127_96_PME_B0
1401 },
1402 NULL_BIT_DESC_INITIALIZER
1403 },
1404 {
1405 {
1406 {
1407 ACPI_ADDR_TYPE,
1408 {R_ACPI_IO_GPE0_STS_127_96}
1409 },
1410 S_ACPI_IO_GPE0_STS_127_96,
1411 N_ACPI_IO_GPE0_STS_127_96_PME_B0
1412 }
1413 },
1414 {
1415 {
1416 ACPI_ADDR_TYPE,
1417 {R_ACPI_IO_SMI_STS}
1418 },
1419 S_ACPI_IO_SMI_STS,
1420 N_ACPI_IO_SMI_STS_GPE0
1421 }
1422 };
1423 /**
1424 The register function used to register SMI handler of PME B0 event.
1425
1426 @param[in] This The pointer to the protocol itself
1427 @param[in] DispatchFunction Pointer to dispatch function to be invoked for this SMI source
1428 @param[out] DispatchHandle Handle of dispatch function to register.
1429
1430 @retval EFI_INVALID_PARAMETER Error with NULL SMI source description
1431 @retval EFI_OUT_OF_RESOURCES Fail to allocate pool for database record
1432 @retval EFI_SUCCESS The database record is created successfully.
1433 @retval EFI_ACCESS_DENIED Return access denied if the SmmReadyToLock event has been triggered
1434 **/
1435 EFI_STATUS
1436 EFIAPI
PchAcpiSmiPmeB0Register(IN PCH_ACPI_SMI_DISPATCH_PROTOCOL * This,IN PCH_ACPI_SMI_DISPATCH_CALLBACK DispatchFunction,OUT EFI_HANDLE * DispatchHandle)1437 PchAcpiSmiPmeB0Register (
1438 IN PCH_ACPI_SMI_DISPATCH_PROTOCOL *This,
1439 IN PCH_ACPI_SMI_DISPATCH_CALLBACK DispatchFunction,
1440 OUT EFI_HANDLE *DispatchHandle
1441 )
1442 {
1443 EFI_STATUS Status;
1444
1445 //
1446 // Return access denied if the SmmReadyToLock event has been triggered
1447 //
1448 if (mReadyToLock == TRUE) {
1449 DEBUG ((DEBUG_ERROR, "Register is not allowed if the SmmReadyToLock event has been triggered! \n"));
1450 return EFI_ACCESS_DENIED;
1451 }
1452
1453 Status = PchSmiRecordInsert (
1454 &mSrcDescPmeB0,
1455 (PCH_SMI_CALLBACK_FUNCTIONS) DispatchFunction,
1456 PchAcpiSmiPmeB0Type,
1457 DispatchHandle
1458 );
1459 PchSmmClearSource (&mSrcDescPmeB0);
1460 PchSmmEnableSource (&mSrcDescPmeB0);
1461 if (!EFI_ERROR (Status)) {
1462 SmiHandlerProfileRegisterHandler (&gPchAcpiSmiDispatchProtocolGuid, (EFI_SMM_HANDLER_ENTRY_POINT2)DispatchFunction, (UINTN)RETURN_ADDRESS (0), NULL, 0);
1463 }
1464 return Status;
1465 }
1466
1467 //
1468 // RtcAlarm srcdesc
1469 //
1470 GLOBAL_REMOVE_IF_UNREFERENCED CONST PCH_SMM_SOURCE_DESC mSrcDescRtcAlarm = {
1471 PCH_SMM_SCI_EN_DEPENDENT,
1472 {
1473 {
1474 {
1475 ACPI_ADDR_TYPE,
1476 {R_ACPI_IO_PM1_EN}
1477 },
1478 S_ACPI_IO_PM1_EN,
1479 N_ACPI_IO_PM1_EN_RTC
1480 },
1481 NULL_BIT_DESC_INITIALIZER
1482 },
1483 {
1484 {
1485 {
1486 ACPI_ADDR_TYPE,
1487 {R_ACPI_IO_PM1_STS}
1488 },
1489 S_ACPI_IO_PM1_STS,
1490 N_ACPI_IO_PM1_STS_RTC
1491 }
1492 },
1493 {
1494 {
1495 ACPI_ADDR_TYPE,
1496 {R_ACPI_IO_SMI_STS}
1497 },
1498 S_ACPI_IO_SMI_STS,
1499 N_ACPI_IO_SMI_STS_PM1_STS_REG
1500 }
1501 };
1502
1503 /**
1504 The register function used to register SMI handler of RTC alarm event.
1505
1506 @param[in] This The pointer to the protocol itself
1507 @param[in] DispatchFunction Pointer to dispatch function to be invoked for this SMI source
1508 @param[out] DispatchHandle Handle of dispatch function to register.
1509
1510 @retval EFI_INVALID_PARAMETER Error with NULL SMI source description
1511 @retval EFI_OUT_OF_RESOURCES Fail to allocate pool for database record
1512 @retval EFI_SUCCESS The database record is created successfully.
1513 @retval EFI_ACCESS_DENIED Return access denied if the SmmReadyToLock event has been triggered
1514 **/
1515 EFI_STATUS
1516 EFIAPI
PchAcpiSmiRtcAlarmRegister(IN PCH_ACPI_SMI_DISPATCH_PROTOCOL * This,IN PCH_ACPI_SMI_DISPATCH_CALLBACK DispatchFunction,OUT EFI_HANDLE * DispatchHandle)1517 PchAcpiSmiRtcAlarmRegister (
1518 IN PCH_ACPI_SMI_DISPATCH_PROTOCOL *This,
1519 IN PCH_ACPI_SMI_DISPATCH_CALLBACK DispatchFunction,
1520 OUT EFI_HANDLE *DispatchHandle
1521 )
1522 {
1523 EFI_STATUS Status;
1524
1525 //
1526 // Return access denied if the SmmReadyToLock event has been triggered
1527 //
1528 if (mReadyToLock == TRUE) {
1529 DEBUG ((DEBUG_ERROR, "Register is not allowed if the SmmReadyToLock event has been triggered! \n"));
1530 return EFI_ACCESS_DENIED;
1531 }
1532
1533 Status = PchSmiRecordInsert (
1534 &mSrcDescRtcAlarm,
1535 (PCH_SMI_CALLBACK_FUNCTIONS) DispatchFunction,
1536 PchAcpiSmiRtcAlarmType,
1537 DispatchHandle
1538 );
1539
1540 PchSmmClearSource (&mSrcDescRtcAlarm);
1541 PchSmmEnableSource (&mSrcDescRtcAlarm);
1542 if (!EFI_ERROR (Status)) {
1543 SmiHandlerProfileRegisterHandler (&gPchAcpiSmiDispatchProtocolGuid, (EFI_SMM_HANDLER_ENTRY_POINT2)DispatchFunction, (UINTN)RETURN_ADDRESS (0), NULL, 0);
1544 }
1545 return Status;
1546 }
1547
1548 //
1549 // TmrOverflow srcdesc
1550 //
1551 GLOBAL_REMOVE_IF_UNREFERENCED CONST PCH_SMM_SOURCE_DESC mSrcDescTmrOverflow = {
1552 PCH_SMM_SCI_EN_DEPENDENT,
1553 {
1554 {
1555 {
1556 ACPI_ADDR_TYPE,
1557 {R_ACPI_IO_PM1_EN}
1558 },
1559 S_ACPI_IO_PM1_EN,
1560 N_ACPI_IO_PM1_EN_TMROF
1561 },
1562 NULL_BIT_DESC_INITIALIZER
1563 },
1564 {
1565 {
1566 {
1567 ACPI_ADDR_TYPE,
1568 {R_ACPI_IO_PM1_STS}
1569 },
1570 S_ACPI_IO_PM1_STS,
1571 N_ACPI_IO_PM1_STS_TMROF
1572 }
1573 },
1574 {
1575 {
1576 ACPI_ADDR_TYPE,
1577 {R_ACPI_IO_SMI_STS}
1578 },
1579 S_ACPI_IO_SMI_STS,
1580 N_ACPI_IO_SMI_STS_PM1_STS_REG
1581 }
1582 };
1583
1584 /**
1585 The register function used to register SMI handler of Timer Overflow event.
1586
1587 @param[in] This The pointer to the protocol itself
1588 @param[in] DispatchFunction Pointer to dispatch function to be invoked for this SMI source
1589 @param[out] DispatchHandle Handle of dispatch function to register.
1590
1591 @retval EFI_INVALID_PARAMETER Error with NULL SMI source description
1592 @retval EFI_OUT_OF_RESOURCES Fail to allocate pool for database record
1593 @retval EFI_SUCCESS The database record is created successfully.
1594 @retval EFI_ACCESS_DENIED Return access denied if the SmmReadyToLock event has been triggered
1595 **/
1596 EFI_STATUS
1597 EFIAPI
PchAcpiSmiTmrOverflowRegister(IN PCH_ACPI_SMI_DISPATCH_PROTOCOL * This,IN PCH_ACPI_SMI_DISPATCH_CALLBACK DispatchFunction,OUT EFI_HANDLE * DispatchHandle)1598 PchAcpiSmiTmrOverflowRegister (
1599 IN PCH_ACPI_SMI_DISPATCH_PROTOCOL *This,
1600 IN PCH_ACPI_SMI_DISPATCH_CALLBACK DispatchFunction,
1601 OUT EFI_HANDLE *DispatchHandle
1602 )
1603 {
1604 EFI_STATUS Status;
1605
1606 //
1607 // Return access denied if the SmmReadyToLock event has been triggered
1608 //
1609 if (mReadyToLock == TRUE) {
1610 DEBUG ((DEBUG_ERROR, "Register is not allowed if the SmmReadyToLock event has been triggered! \n"));
1611 return EFI_ACCESS_DENIED;
1612 }
1613
1614 Status = PchSmiRecordInsert (
1615 &mSrcDescTmrOverflow,
1616 (PCH_SMI_CALLBACK_FUNCTIONS) DispatchFunction,
1617 PchAcpiSmiTmrOverflowType,
1618 DispatchHandle
1619 );
1620 PchSmmClearSource (&mSrcDescTmrOverflow);
1621 PchSmmEnableSource (&mSrcDescTmrOverflow);
1622 if (!EFI_ERROR (Status)) {
1623 SmiHandlerProfileRegisterHandler (&gPchAcpiSmiDispatchProtocolGuid, (EFI_SMM_HANDLER_ENTRY_POINT2)DispatchFunction, (UINTN)RETURN_ADDRESS (0), NULL, 0);
1624 }
1625
1626 return Status;
1627 }
1628
1629 /**
1630 Unregister a child SMI source dispatch function with a parent SMM driver
1631
1632 @param[in] This Protocol instance pointer.
1633 @param[in] DispatchHandle Handle of dispatch function to deregister.
1634
1635 @retval EFI_SUCCESS The dispatch function has been successfully
1636 unregistered and the SMI source has been disabled
1637 if there are no other registered child dispatch
1638 functions for this SMI source.
1639 @retval EFI_INVALID_PARAMETER Handle is invalid.
1640 @retval EFI_ACCESS_DENIED Return access denied if the SmmReadyToLock event has been triggered
1641 **/
1642 EFI_STATUS
1643 EFIAPI
PchAcpiSmiUnRegister(IN PCH_ACPI_SMI_DISPATCH_PROTOCOL * This,IN EFI_HANDLE DispatchHandle)1644 PchAcpiSmiUnRegister (
1645 IN PCH_ACPI_SMI_DISPATCH_PROTOCOL *This,
1646 IN EFI_HANDLE DispatchHandle
1647 )
1648 {
1649 DATABASE_RECORD *RecordToDelete;
1650 EFI_STATUS Status;
1651
1652 RecordToDelete = DATABASE_RECORD_FROM_LINK (DispatchHandle);
1653 Status = PchSmmCoreUnRegister (NULL, DispatchHandle);
1654 if (!EFI_ERROR (Status)) {
1655 SmiHandlerProfileUnregisterHandler (&gPchAcpiSmiDispatchProtocolGuid, RecordToDelete->Callback, NULL, 0);
1656 }
1657 return Status;
1658 }
1659
1660 //
1661 // SerialIrq srcdesc
1662 //
1663 GLOBAL_REMOVE_IF_UNREFERENCED CONST PCH_SMM_SOURCE_DESC mSrcDescSerialIrq = {
1664 PCH_SMM_NO_FLAGS,
1665 {
1666 NULL_BIT_DESC_INITIALIZER,
1667 NULL_BIT_DESC_INITIALIZER
1668 },
1669 {
1670 {
1671 {
1672 ACPI_ADDR_TYPE,
1673 {R_ACPI_IO_SMI_STS}
1674 },
1675 S_ACPI_IO_SMI_STS,
1676 N_ACPI_IO_SMI_STS_SERIRQ
1677 }
1678 },
1679 {
1680 {
1681 ACPI_ADDR_TYPE,
1682 {R_ACPI_IO_SMI_STS}
1683 },
1684 S_ACPI_IO_SMI_STS,
1685 N_ACPI_IO_SMI_STS_SERIRQ
1686 }
1687 };
1688
1689 /**
1690 The register function used to register SMI handler of Serial IRQ event.
1691
1692 @param[in] This The pointer to the protocol itself
1693 @param[in] DispatchFunction Pointer to dispatch function to be invoked for this SMI source
1694 @param[out] DispatchHandle Handle of dispatch function to register.
1695
1696 @retval EFI_INVALID_PARAMETER Error with NULL SMI source description
1697 @retval EFI_OUT_OF_RESOURCES Fail to allocate pool for database record
1698 @retval EFI_SUCCESS The database record is created successfully.
1699 @retval EFI_ACCESS_DENIED Return access denied if the SmmReadyToLock event has been triggered
1700 **/
1701 EFI_STATUS
1702 EFIAPI
PchSmiSerialIrqRegister(IN PCH_SMI_DISPATCH_PROTOCOL * This,IN PCH_SMI_DISPATCH_CALLBACK DispatchFunction,OUT EFI_HANDLE * DispatchHandle)1703 PchSmiSerialIrqRegister (
1704 IN PCH_SMI_DISPATCH_PROTOCOL *This,
1705 IN PCH_SMI_DISPATCH_CALLBACK DispatchFunction,
1706 OUT EFI_HANDLE *DispatchHandle
1707 )
1708 {
1709 EFI_STATUS Status;
1710
1711 //
1712 // Return access denied if the SmmReadyToLock event has been triggered
1713 //
1714 if (mReadyToLock == TRUE) {
1715 DEBUG ((DEBUG_ERROR, "Register is not allowed if the SmmReadyToLock event has been triggered! \n"));
1716 return EFI_ACCESS_DENIED;
1717 }
1718
1719 Status = PchSmiRecordInsert (
1720 &mSrcDescSerialIrq,
1721 (PCH_SMI_CALLBACK_FUNCTIONS) DispatchFunction,
1722 PchSmiSerialIrqType,
1723 DispatchHandle
1724 );
1725 PchSmmClearSource (&mSrcDescSerialIrq);
1726 PchSmmEnableSource (&mSrcDescSerialIrq);
1727 if (!EFI_ERROR (Status)) {
1728 SmiHandlerProfileRegisterHandler (&gPchSmiDispatchProtocolGuid, (EFI_SMM_HANDLER_ENTRY_POINT2)DispatchFunction, (UINTN)RETURN_ADDRESS (0), NULL, 0);
1729 }
1730 return Status;
1731 }
1732
1733 //
1734 // McSmi srcdesc
1735 //
1736 GLOBAL_REMOVE_IF_UNREFERENCED CONST PCH_SMM_SOURCE_DESC mSrcDescMcSmi = {
1737 PCH_SMM_NO_FLAGS,
1738 {
1739 {
1740 {
1741 ACPI_ADDR_TYPE,
1742 {R_ACPI_IO_SMI_EN}
1743 },
1744 S_ACPI_IO_SMI_EN,
1745 N_ACPI_IO_SMI_EN_MCSMI
1746 },
1747 NULL_BIT_DESC_INITIALIZER
1748 },
1749 {
1750 {
1751 {
1752 ACPI_ADDR_TYPE,
1753 {R_ACPI_IO_SMI_STS}
1754 },
1755 S_ACPI_IO_SMI_STS,
1756 N_ACPI_IO_SMI_STS_MCSMI
1757 }
1758 },
1759 {
1760 {
1761 ACPI_ADDR_TYPE,
1762 {R_ACPI_IO_SMI_STS}
1763 },
1764 S_ACPI_IO_SMI_STS,
1765 N_ACPI_IO_SMI_STS_MCSMI
1766 }
1767 };
1768
1769 /**
1770 The register function used to register SMI handler of MCSMI event.
1771
1772 @param[in] This The pointer to the protocol itself
1773 @param[in] DispatchFunction Pointer to dispatch function to be invoked for this SMI source
1774 @param[out] DispatchHandle Handle of dispatch function to register.
1775
1776 @retval EFI_INVALID_PARAMETER Error with NULL SMI source description
1777 @retval EFI_OUT_OF_RESOURCES Fail to allocate pool for database record
1778 @retval EFI_SUCCESS The database record is created successfully.
1779 @retval EFI_ACCESS_DENIED Return access denied if the SmmReadyToLock event has been triggered
1780 **/
1781 EFI_STATUS
1782 EFIAPI
PchSmiMcSmiRegister(IN PCH_SMI_DISPATCH_PROTOCOL * This,IN PCH_SMI_DISPATCH_CALLBACK DispatchFunction,OUT EFI_HANDLE * DispatchHandle)1783 PchSmiMcSmiRegister (
1784 IN PCH_SMI_DISPATCH_PROTOCOL *This,
1785 IN PCH_SMI_DISPATCH_CALLBACK DispatchFunction,
1786 OUT EFI_HANDLE *DispatchHandle
1787 )
1788 {
1789 EFI_STATUS Status;
1790
1791 //
1792 // Return access denied if the SmmReadyToLock event has been triggered
1793 //
1794 if (mReadyToLock == TRUE) {
1795 DEBUG ((DEBUG_ERROR, "Register is not allowed if the SmmReadyToLock event has been triggered! \n"));
1796 return EFI_ACCESS_DENIED;
1797 }
1798
1799 Status = PchSmiRecordInsert (
1800 &mSrcDescMcSmi,
1801 (PCH_SMI_CALLBACK_FUNCTIONS) DispatchFunction,
1802 PchSmiMcSmiType,
1803 DispatchHandle
1804 );
1805 PchSmmClearSource (&mSrcDescMcSmi);
1806 PchSmmEnableSource (&mSrcDescMcSmi);
1807 if (!EFI_ERROR (Status)) {
1808 SmiHandlerProfileRegisterHandler (&gPchSmiDispatchProtocolGuid, (EFI_SMM_HANDLER_ENTRY_POINT2)DispatchFunction, (UINTN)RETURN_ADDRESS (0), NULL, 0);
1809 }
1810 return Status;
1811 }
1812
1813 //
1814 // SmBus srcdesc
1815 //
1816 GLOBAL_REMOVE_IF_UNREFERENCED CONST PCH_SMM_SOURCE_DESC mSrcDescSmbus = {
1817 PCH_SMM_NO_FLAGS,
1818 {
1819 NULL_BIT_DESC_INITIALIZER,
1820 NULL_BIT_DESC_INITIALIZER
1821 },
1822 {
1823 {
1824 {
1825 ACPI_ADDR_TYPE,
1826 {R_ACPI_IO_SMI_STS}
1827 },
1828 S_ACPI_IO_SMI_STS,
1829 N_ACPI_IO_SMI_STS_SMBUS
1830 }
1831 },
1832 {
1833 {
1834 ACPI_ADDR_TYPE,
1835 {R_ACPI_IO_SMI_STS}
1836 },
1837 S_ACPI_IO_SMI_STS,
1838 N_ACPI_IO_SMI_STS_SMBUS
1839 }
1840 };
1841
1842 /**
1843 The register function used to register SMI handler of SMBUS event.
1844
1845 @param[in] This The pointer to the protocol itself
1846 @param[in] DispatchFunction Pointer to dispatch function to be invoked for this SMI source
1847 @param[out] DispatchHandle Handle of dispatch function to register.
1848
1849 @retval EFI_INVALID_PARAMETER Error with NULL SMI source description
1850 @retval EFI_OUT_OF_RESOURCES Fail to allocate pool for database record
1851 @retval EFI_SUCCESS The database record is created successfully.
1852 @retval EFI_ACCESS_DENIED Return access denied if the SmmReadyToLock event has been triggered
1853 **/
1854 EFI_STATUS
1855 EFIAPI
PchSmiSmbusRegister(IN PCH_SMI_DISPATCH_PROTOCOL * This,IN PCH_SMI_DISPATCH_CALLBACK DispatchFunction,OUT EFI_HANDLE * DispatchHandle)1856 PchSmiSmbusRegister (
1857 IN PCH_SMI_DISPATCH_PROTOCOL *This,
1858 IN PCH_SMI_DISPATCH_CALLBACK DispatchFunction,
1859 OUT EFI_HANDLE *DispatchHandle
1860 )
1861 {
1862 EFI_STATUS Status;
1863
1864 //
1865 // Return access denied if the SmmReadyToLock event has been triggered
1866 //
1867 if (mReadyToLock == TRUE) {
1868 DEBUG ((DEBUG_ERROR, "Register is not allowed if the SmmReadyToLock event has been triggered! \n"));
1869 return EFI_ACCESS_DENIED;
1870 }
1871
1872 Status = PchSmiRecordInsert (
1873 &mSrcDescSmbus,
1874 (PCH_SMI_CALLBACK_FUNCTIONS) DispatchFunction,
1875 PchSmiSmBusType,
1876 DispatchHandle
1877 );
1878 PchSmmClearSource (&mSrcDescSmbus);
1879 PchSmmEnableSource (&mSrcDescSmbus);
1880 if (!EFI_ERROR (Status)) {
1881 SmiHandlerProfileRegisterHandler (&gPchSmiDispatchProtocolGuid, (EFI_SMM_HANDLER_ENTRY_POINT2)DispatchFunction, (UINTN)RETURN_ADDRESS (0), NULL, 0);
1882 }
1883 return Status;
1884 }
1885
1886 //
1887 // SpiAsyncSmi srcdesc
1888 //
1889 GLOBAL_REMOVE_IF_UNREFERENCED CONST PCH_SMM_SOURCE_DESC mSrcDescSpiAsyncSmi = {
1890 PCH_SMM_NO_FLAGS,
1891 {
1892 {
1893 {
1894 PCIE_ADDR_TYPE,
1895 { (
1896 (DEFAULT_PCI_BUS_NUMBER_PCH << 24) |
1897 (PCI_DEVICE_NUMBER_PCH_SPI << 19) |
1898 (PCI_FUNCTION_NUMBER_PCH_SPI << 16) |
1899 R_SPI_CFG_BC
1900 ) }
1901 },
1902 S_SPI_CFG_BC,
1903 N_SPI_CFG_BC_ASE_BWP
1904 },
1905 NULL_BIT_DESC_INITIALIZER
1906 },
1907 {
1908 {
1909 {
1910 PCIE_ADDR_TYPE,
1911 { (
1912 (DEFAULT_PCI_BUS_NUMBER_PCH << 24) |
1913 (PCI_DEVICE_NUMBER_PCH_SPI << 19) |
1914 (PCI_FUNCTION_NUMBER_PCH_SPI << 16) |
1915 R_SPI_CFG_BC
1916 ) }
1917 },
1918 S_SPI_CFG_BC,
1919 N_SPI_CFG_BC_ASYNC_SS
1920 }
1921 },
1922 {
1923 {
1924 ACPI_ADDR_TYPE,
1925 {R_ACPI_IO_SMI_STS}
1926 },
1927 S_ACPI_IO_SMI_STS,
1928 N_ACPI_IO_SMI_STS_SPI
1929 }
1930 };
1931
1932 /**
1933 Special handling for SPI Asynchronous SMI.
1934 If SPI ASYNC SMI is enabled, De-assert SMI is sent when Flash Cycle Done
1935 transitions from 1 to 0 or when the SMI enable becomes false.
1936
1937 @param[in] SrcDesc Not used
1938 **/
1939 VOID
1940 EFIAPI
PchSmiSpiAsyncClearSource(CONST PCH_SMM_SOURCE_DESC * SrcDesc)1941 PchSmiSpiAsyncClearSource (
1942 CONST PCH_SMM_SOURCE_DESC *SrcDesc
1943 )
1944 {
1945 UINT64 SpiRegBase;
1946 UINT32 SpiBar0;
1947
1948 SpiRegBase = SpiPciCfgBase ();
1949 SpiBar0 = PciSegmentRead32 (SpiRegBase + R_SPI_CFG_BAR0) & ~(B_SPI_CFG_BAR0_MASK);
1950 if (SpiBar0 != PCH_SPI_BASE_ADDRESS) {
1951 //
1952 // Temporary disable MSE, and override with SPI reserved MMIO address, then enable MSE.
1953 //
1954 SpiBar0 = PCH_SPI_BASE_ADDRESS;
1955 PciSegmentAnd8 (SpiRegBase + PCI_COMMAND_OFFSET, (UINT8) ~EFI_PCI_COMMAND_MEMORY_SPACE);
1956 PciSegmentWrite32 (SpiRegBase + R_SPI_CFG_BAR0, SpiBar0);
1957 PciSegmentOr8 (SpiRegBase + PCI_COMMAND_OFFSET, EFI_PCI_COMMAND_MEMORY_SPACE);
1958 }
1959
1960 MmioOr32 (SpiBar0 + R_SPI_MEM_HSFSC, B_SPI_MEM_HSFSC_FDONE);
1961 }
1962
1963 /**
1964 Special handling to enable SPI Asynchronous SMI
1965 **/
1966 VOID
PchSmiSpiAsyncEnableSource(VOID)1967 PchSmiSpiAsyncEnableSource (
1968 VOID
1969 )
1970 {
1971 UINT64 SpiRegBase;
1972 UINT32 Data32And;
1973 UINT32 Data32Or;
1974
1975 SpiRegBase = SpiPciCfgBase ();
1976 Data32And = (UINT32) ~B_SPI_CFG_BC_SYNC_SS;
1977 Data32Or = B_SPI_CFG_BC_ASE_BWP;
1978
1979 PciSegmentAndThenOr32 (
1980 SpiRegBase + R_SPI_CFG_BC,
1981 Data32And,
1982 Data32Or
1983 );
1984 S3BootScriptSavePciCfgReadWrite (
1985 S3BootScriptWidthUint32,
1986 SpiRegBase + R_SPI_CFG_BC,
1987 (VOID*) &Data32Or,
1988 (VOID*) &Data32And
1989 );
1990
1991 //
1992 // Clear the source
1993 //
1994 PchSmiSpiAsyncClearSource (NULL);
1995 }
1996
1997 /**
1998 The register function used to register SMI handler of SPI Asynchronous event.
1999
2000 @param[in] This The pointer to the protocol itself
2001 @param[in] DispatchFunction Pointer to dispatch function to be invoked for this SMI source
2002 @param[out] DispatchHandle Handle of dispatch function to register.
2003
2004 @retval EFI_INVALID_PARAMETER Error with NULL SMI source description
2005 @retval EFI_OUT_OF_RESOURCES Fail to allocate pool for database record
2006 @retval EFI_SUCCESS The database record is created successfully.
2007 @retval EFI_ACCESS_DENIED Return access denied if the SmmReadyToLock event has been triggered
2008 **/
2009 EFI_STATUS
2010 EFIAPI
PchSmiSpiAsyncRegister(IN PCH_SMI_DISPATCH_PROTOCOL * This,IN PCH_SMI_DISPATCH_CALLBACK DispatchFunction,OUT EFI_HANDLE * DispatchHandle)2011 PchSmiSpiAsyncRegister (
2012 IN PCH_SMI_DISPATCH_PROTOCOL *This,
2013 IN PCH_SMI_DISPATCH_CALLBACK DispatchFunction,
2014 OUT EFI_HANDLE *DispatchHandle
2015 )
2016 {
2017 EFI_STATUS Status;
2018 DATABASE_RECORD *Record;
2019
2020 //
2021 // Return access denied if the SmmReadyToLock event has been triggered
2022 //
2023 if (mReadyToLock == TRUE) {
2024 DEBUG ((DEBUG_ERROR, "Register is not allowed if the SmmReadyToLock event has been triggered! \n"));
2025 return EFI_ACCESS_DENIED;
2026 }
2027
2028 Status = PchSmiRecordInsert (
2029 &mSrcDescSpiAsyncSmi,
2030 (PCH_SMI_CALLBACK_FUNCTIONS) DispatchFunction,
2031 PchSmiSpiAsyncType,
2032 DispatchHandle
2033 );
2034
2035 if (!EFI_ERROR (Status)) {
2036 Record = DATABASE_RECORD_FROM_LINK (*DispatchHandle);
2037 Record->ClearSource = PchSmiSpiAsyncClearSource;
2038 PchSmiSpiAsyncClearSource (NULL);
2039 PchSmiSpiAsyncEnableSource ();
2040 SmiHandlerProfileRegisterHandler (&gPchSmiDispatchProtocolGuid, (EFI_SMM_HANDLER_ENTRY_POINT2)DispatchFunction, (UINTN)RETURN_ADDRESS (0), NULL, 0);
2041 }
2042 return Status;
2043 }
2044
2045 /**
2046 Unregister a child SMI source dispatch function with a parent SMM driver
2047
2048 @param[in] This Protocol instance pointer.
2049 @param[in] DispatchHandle Handle of dispatch function to deregister.
2050
2051 @retval EFI_SUCCESS The dispatch function has been successfully
2052 unregistered and the SMI source has been disabled
2053 if there are no other registered child dispatch
2054 functions for this SMI source.
2055 @retval EFI_INVALID_PARAMETER Handle is invalid.
2056 @retval EFI_ACCESS_DENIED Return access denied if the SmmReadyToLock event has been triggered
2057 @retval EFI_ACCESS_DENIED Return access denied since SPI aync SMI handler is not able to disabled.
2058 **/
2059 EFI_STATUS
2060 EFIAPI
PchSmiUnRegister(IN PCH_SMI_DISPATCH_PROTOCOL * This,IN EFI_HANDLE DispatchHandle)2061 PchSmiUnRegister (
2062 IN PCH_SMI_DISPATCH_PROTOCOL *This,
2063 IN EFI_HANDLE DispatchHandle
2064 )
2065 {
2066 DATABASE_RECORD *Record;
2067 UINT64 SpiRegBase;
2068 EFI_STATUS Status;
2069
2070 Record = DATABASE_RECORD_FROM_LINK (DispatchHandle);
2071 if ((Record->SrcDesc.En[0].Reg.Type == PCIE_ADDR_TYPE) &&
2072 (Record->SrcDesc.En[0].Reg.Data.pcie.Fields.Dev == SpiDevNumber ()) &&
2073 (Record->SrcDesc.En[0].Reg.Data.pcie.Fields.Fnc == SpiFuncNumber ()) &&
2074 (Record->SrcDesc.En[0].Reg.Data.pcie.Fields.Reg == R_SPI_CFG_BC) &&
2075 (Record->SrcDesc.En[0].Bit == N_SPI_CFG_BC_ASE_BWP)) {
2076 SpiRegBase = SpiPciCfgBase ();
2077 if (PciSegmentRead8 (SpiRegBase + R_SPI_CFG_BC) & B_SPI_CFG_BC_BILD) {
2078 //
2079 // SPI Asynchronous SMI cannot be disabled
2080 //
2081 return EFI_ACCESS_DENIED;
2082 }
2083 }
2084 Status = PchSmmCoreUnRegister (NULL, DispatchHandle);
2085 if (!EFI_ERROR (Status)) {
2086 SmiHandlerProfileUnregisterHandler (&gPchSmiDispatchProtocolGuid, Record->Callback, NULL, 0);
2087 }
2088 return Status;
2089 }
2090
2091
2092 /**
2093 Declaration of PCH TCO SMI DISPATCH PROTOCOL instance
2094 **/
2095 PCH_TCO_SMI_DISPATCH_PROTOCOL mPchTcoSmiDispatchProtocol = {
2096 PCH_TCO_SMI_DISPATCH_REVISION, // Revision
2097 PchTcoSmiUnRegister, // Unregister
2098 PchTcoSmiMchRegister, // Mch
2099 PchTcoSmiTcoTimeoutRegister, // TcoTimeout
2100 PchTcoSmiOsTcoRegister, // OsTco
2101 PchTcoSmiNmiRegister, // Nmi
2102 PchTcoSmiIntruderDetRegister, // IntruderDectect
2103 PchTcoSmiSpiBiosWpRegister, // SpiBiosWp
2104 PchTcoSmiLpcBiosWpRegister, // LpcBiosWp
2105 PchTcoSmiNewCenturyRegister // NewCentury
2106 };
2107
2108 /**
2109 Declaration of PCH PCIE SMI DISPATCH PROTOCOL instance
2110 **/
2111 PCH_PCIE_SMI_DISPATCH_PROTOCOL mPchPcieSmiDispatchProtocol = {
2112 PCH_PCIE_SMI_DISPATCH_REVISION, // Revision
2113 PchPcieSmiUnRegister, // Unregister
2114 PchPcieSmiHotPlugRegister, // PcieRpXHotPlug
2115 PchPcieSmiLinkActiveRegister, // PcieRpXLinkActive
2116 PchPcieSmiLinkEqRegister // PcieRpXLinkEq
2117 };
2118
2119 /**
2120 Declaration of PCH ACPI SMI DISPATCH PROTOCOL instance
2121 **/
2122 PCH_ACPI_SMI_DISPATCH_PROTOCOL mPchAcpiSmiDispatchProtocol = {
2123 PCH_ACPI_SMI_DISPATCH_REVISION, // Revision
2124 PchAcpiSmiUnRegister, // Unregister
2125 PchAcpiSmiPmeRegister, // Pme
2126 PchAcpiSmiPmeB0Register, // PmeB0
2127 PchAcpiSmiRtcAlarmRegister, // RtcAlarm
2128 PchAcpiSmiTmrOverflowRegister // TmrOverflow
2129 };
2130
2131 /**
2132 Declaration of MISC PCH SMI DISPATCH PROTOCOL instance
2133 **/
2134 PCH_SMI_DISPATCH_PROTOCOL mPchSmiDispatchProtocol = {
2135 PCH_SMI_DISPATCH_REVISION, // Revision
2136 PchSmiUnRegister, // Unregister
2137 PchSmiSerialIrqRegister, // SerialIrq
2138 PchSmiMcSmiRegister, // McSmi
2139 PchSmiSmbusRegister, // SmBus
2140 PchSmiSpiAsyncRegister // SpiAsync
2141 };
2142
2143 /**
2144 Install protocols of PCH specifics SMI types, including
2145 PCH TCO SMI types, PCH PCIE SMI types, PCH ACPI SMI types, PCH MISC SMI types.
2146
2147 @retval the result of protocol installation
2148 **/
2149 EFI_STATUS
InstallPchSmiDispatchProtocols(VOID)2150 InstallPchSmiDispatchProtocols (
2151 VOID
2152 )
2153 {
2154 EFI_HANDLE Handle;
2155 EFI_STATUS Status;
2156
2157 Handle = NULL;
2158 Status = gSmst->SmmInstallProtocolInterface (
2159 &Handle,
2160 &gPchTcoSmiDispatchProtocolGuid,
2161 EFI_NATIVE_INTERFACE,
2162 &mPchTcoSmiDispatchProtocol
2163 );
2164 Status = gSmst->SmmInstallProtocolInterface (
2165 &Handle,
2166 &gPchPcieSmiDispatchProtocolGuid,
2167 EFI_NATIVE_INTERFACE,
2168 &mPchPcieSmiDispatchProtocol
2169 );
2170 Status = gSmst->SmmInstallProtocolInterface (
2171 &Handle,
2172 &gPchAcpiSmiDispatchProtocolGuid,
2173 EFI_NATIVE_INTERFACE,
2174 &mPchAcpiSmiDispatchProtocol
2175 );
2176 Status = gSmst->SmmInstallProtocolInterface (
2177 &Handle,
2178 &gPchSmiDispatchProtocolGuid,
2179 EFI_NATIVE_INTERFACE,
2180 &mPchSmiDispatchProtocol
2181 );
2182
2183 return Status;
2184 }
2185
2186 /**
2187 The function to dispatch all callback function of PCH SMI types.
2188
2189 @retval EFI_SUCCESS Function successfully completed
2190 @retval EFI_UNSUPPORTED no
2191 **/
2192 EFI_STATUS
PchSmiTypeCallbackDispatcher(IN DATABASE_RECORD * Record)2193 PchSmiTypeCallbackDispatcher (
2194 IN DATABASE_RECORD *Record
2195 )
2196 {
2197 EFI_STATUS Status;
2198 PCH_SMI_TYPES PchSmiType;
2199 UINTN RpIndex;
2200 PCH_PCIE_SMI_RP_CONTEXT RpContext;
2201
2202 PchSmiType = Record->PchSmiType;
2203 Status = EFI_SUCCESS;
2204
2205 switch (PchSmiType) {
2206 case PchTcoSmiMchType:
2207 case PchTcoSmiTcoTimeoutType:
2208 case PchTcoSmiOsTcoType:
2209 case PchTcoSmiNmiType:
2210 case PchTcoSmiIntruderDetectType:
2211 case PchTcoSmiSpiBiosWpType:
2212 case PchTcoSmiLpcBiosWpType:
2213 case PchTcoSmiNewCenturyType:
2214 ((PCH_TCO_SMI_DISPATCH_CALLBACK) (Record->PchSmiCallback)) ((EFI_HANDLE)&Record->Link);
2215 break;
2216 case PchPcieSmiRpHotplugType:
2217 case PchPcieSmiRpLinkActiveType:
2218 case PchPcieSmiRpLinkEqType:
2219 RpContext.BusNum = DEFAULT_PCI_BUS_NUMBER_PCH;
2220 RpContext.DevNum = (UINT8) Record->SrcDesc.En[0].Reg.Data.pcie.Fields.Dev;
2221 RpContext.FuncNum = (UINT8) Record->SrcDesc.En[0].Reg.Data.pcie.Fields.Fnc;
2222 GetPcieRpNumber (RpContext.DevNum, RpContext.FuncNum, &RpIndex);
2223 RpContext.RpIndex = (UINT8) RpIndex;
2224 ((PCH_PCIE_SMI_RP_DISPATCH_CALLBACK) (Record->PchSmiCallback)) ((EFI_HANDLE)&Record->Link, &RpContext);
2225 break;
2226 case PchAcpiSmiPmeType:
2227 case PchAcpiSmiPmeB0Type:
2228 case PchAcpiSmiRtcAlarmType:
2229 case PchAcpiSmiTmrOverflowType:
2230 ((PCH_ACPI_SMI_DISPATCH_CALLBACK) (Record->PchSmiCallback)) ((EFI_HANDLE)&Record->Link);
2231 break;
2232 case PchEspiSmiEspiSlaveType:
2233 ((PCH_ESPI_SMI_DISPATCH_CALLBACK) (Record->PchSmiCallback)) ((EFI_HANDLE)&Record->Link);
2234 break;
2235 case PchSmiSerialIrqType:
2236 case PchSmiMcSmiType:
2237 case PchSmiSmBusType:
2238 case PchSmiSpiAsyncType:
2239 case PchIoTrapSmiType: ///< internal type for IoTrap
2240 ((PCH_SMI_DISPATCH_CALLBACK) (Record->PchSmiCallback)) ((EFI_HANDLE)&Record->Link);
2241 break;
2242 default:
2243 Status = EFI_UNSUPPORTED;
2244 break;
2245 }
2246
2247 return Status;
2248 }
2249
2250 GLOBAL_REMOVE_IF_UNREFERENCED CONST PCH_SMM_SOURCE_DESC mSrcDescIoTrap[4] = {
2251 //
2252 // PCH I/O Trap register 0 monitor
2253 //
2254 {
2255 PCH_SMM_NO_FLAGS,
2256 {
2257 {
2258 {
2259 PCR_ADDR_TYPE,
2260 {PCH_PCR_ADDRESS (PID_PSTH, R_PSTH_PCR_TRPREG0) }
2261 },
2262 4,
2263 0
2264 },
2265 NULL_BIT_DESC_INITIALIZER
2266 },
2267 {
2268 {
2269 {
2270 PCR_ADDR_TYPE,
2271 {PCH_PCR_ADDRESS (PID_PSTH, R_PSTH_PCR_TRPST) }
2272 },
2273 1,
2274 0
2275 }
2276 },
2277 {
2278 {
2279 ACPI_ADDR_TYPE,
2280 {R_ACPI_IO_SMI_STS}
2281 },
2282 S_ACPI_IO_SMI_STS,
2283 N_ACPI_IO_SMI_STS_MONITOR
2284 }
2285 },
2286 //
2287 // PCH I/O Trap register 1 monitor
2288 //
2289 {
2290 PCH_SMM_NO_FLAGS,
2291 {
2292 {
2293 {
2294 PCR_ADDR_TYPE,
2295 {PCH_PCR_ADDRESS (PID_PSTH, R_PSTH_PCR_TRPREG1) }
2296 },
2297 4,
2298 0
2299 },
2300 NULL_BIT_DESC_INITIALIZER
2301 },
2302 {
2303 {
2304 {
2305 PCR_ADDR_TYPE,
2306 {PCH_PCR_ADDRESS (PID_PSTH, R_PSTH_PCR_TRPST) }
2307 },
2308 1,
2309 1
2310 }
2311 },
2312 {
2313 {
2314 ACPI_ADDR_TYPE,
2315 {R_ACPI_IO_SMI_STS}
2316 },
2317 S_ACPI_IO_SMI_STS,
2318 N_ACPI_IO_SMI_STS_MONITOR
2319 }
2320 },
2321 //
2322 // PCH I/O Trap register 2 monitor
2323 //
2324 {
2325 PCH_SMM_NO_FLAGS,
2326 {
2327 {
2328 {
2329 PCR_ADDR_TYPE,
2330 {PCH_PCR_ADDRESS (PID_PSTH, R_PSTH_PCR_TRPREG2) }
2331 },
2332 4,
2333 0
2334 },
2335 NULL_BIT_DESC_INITIALIZER
2336 },
2337 {
2338 {
2339 {
2340 PCR_ADDR_TYPE,
2341 {PCH_PCR_ADDRESS (PID_PSTH, R_PSTH_PCR_TRPST) }
2342 },
2343 1,
2344 2
2345 }
2346 },
2347 {
2348 {
2349 ACPI_ADDR_TYPE,
2350 {R_ACPI_IO_SMI_STS}
2351 },
2352 S_ACPI_IO_SMI_STS,
2353 N_ACPI_IO_SMI_STS_MONITOR
2354 }
2355 },
2356 //
2357 // PCH I/O Trap register 3 monitor,
2358 //
2359 {
2360 PCH_SMM_NO_FLAGS,
2361 {
2362 {
2363 {
2364 PCR_ADDR_TYPE,
2365 {PCH_PCR_ADDRESS (PID_PSTH, R_PSTH_PCR_TRPREG3) }
2366 },
2367 4,
2368 0
2369 },
2370 NULL_BIT_DESC_INITIALIZER
2371 },
2372 {
2373 {
2374 {
2375 PCR_ADDR_TYPE,
2376 {PCH_PCR_ADDRESS (PID_PSTH, R_PSTH_PCR_TRPST) }
2377 },
2378 1,
2379 3
2380 }
2381 },
2382 {
2383 {
2384 ACPI_ADDR_TYPE,
2385 {R_ACPI_IO_SMI_STS}
2386 },
2387 S_ACPI_IO_SMI_STS,
2388 N_ACPI_IO_SMI_STS_MONITOR
2389 }
2390 }
2391 };
2392
2393 /**
2394 The register function used to register SMI handler of IoTrap event.
2395 This is internal function and only used by Iotrap module.
2396
2397 @param[in] DispatchFunction Pointer to dispatch function to be invoked for this SMI source
2398 @param[in] IoTrapIndex Index number of IOTRAP register
2399 @param[out] DispatchHandle Handle of dispatch function to register.
2400
2401 @retval EFI_INVALID_PARAMETER Error with NULL SMI source description
2402 @retval EFI_OUT_OF_RESOURCES Fail to allocate pool for database record
2403 @retval EFI_SUCCESS The database record is created successfully.
2404 **/
2405 EFI_STATUS
PchInternalIoTrapSmiRegister(IN PCH_SMI_DISPATCH_CALLBACK DispatchFunction,IN UINTN IoTrapIndex,OUT EFI_HANDLE * DispatchHandle)2406 PchInternalIoTrapSmiRegister (
2407 IN PCH_SMI_DISPATCH_CALLBACK DispatchFunction,
2408 IN UINTN IoTrapIndex,
2409 OUT EFI_HANDLE *DispatchHandle
2410 )
2411 {
2412 EFI_STATUS Status;
2413
2414 Status = PchSmiRecordInsert (
2415 &mSrcDescIoTrap[IoTrapIndex],
2416 (PCH_SMI_CALLBACK_FUNCTIONS) DispatchFunction,
2417 PchIoTrapSmiType,
2418 DispatchHandle
2419 );
2420 PchSmmClearSource (&mSrcDescIoTrap[IoTrapIndex]);
2421 PchSmmEnableSource (&mSrcDescIoTrap[IoTrapIndex]);
2422 return Status;
2423 }
2424
2425 /**
2426 Unregister a child SMI source dispatch function with a parent SMM driver
2427
2428 @param[in] DispatchHandle Handle of dispatch function to deregister.
2429
2430 @retval EFI_SUCCESS The dispatch function has been successfully
2431 unregistered and the SMI source has been disabled
2432 if there are no other registered child dispatch
2433 functions for this SMI source.
2434 @retval EFI_INVALID_PARAMETER Handle is invalid.
2435 **/
2436 EFI_STATUS
PchInternalIoTrapSmiUnRegister(IN EFI_HANDLE DispatchHandle)2437 PchInternalIoTrapSmiUnRegister (
2438 IN EFI_HANDLE DispatchHandle
2439 )
2440 {
2441 return PchSmmCoreUnRegister (NULL, DispatchHandle);
2442 }
2443