1 /** @file
2   This driver is responsible for the registration of child drivers
3   and the abstraction of the PCH SMI sources.
4 
5 Copyright (c) 2017, Intel Corporation. All rights reserved.<BR>
6 SPDX-License-Identifier: BSD-2-Clause-Patent
7 
8 **/
9 #include "PchSmmHelpers.h"
10 
11 //
12 // Help handle porting bit shifts to IA-64.
13 //
14 #define BIT_ZERO  0x00000001
15 
16 /**
17   Publish SMI Dispatch protocols.
18 
19 
20 **/
21 VOID
PchSmmPublishDispatchProtocols(VOID)22 PchSmmPublishDispatchProtocols (
23   VOID
24   )
25 {
26   EFI_STATUS Status = EFI_SUCCESS;
27   UINTN      Index;
28   //
29   // Install protocol interfaces.
30   //
31   for (Index = 0; Index < PCH_SMM_PROTOCOL_TYPE_MAX; Index++) {
32     Status = gSmst->SmmInstallProtocolInterface (
33                       &mPrivateData.InstallMultProtHandle,
34                       mPrivateData.Protocols[Index].Guid,
35                       EFI_NATIVE_INTERFACE,
36                       &mPrivateData.Protocols[Index].Protocols.Generic
37                       );
38   }
39   ASSERT_EFI_ERROR (Status);
40 }
41 
42 /**
43   Initialize bits that aren't necessarily related to an SMI source.
44 
45 
46   @retval EFI_SUCCESS             SMI source initialization completed.
47   @retval Asserts                 Global Smi Bit is not enabled successfully.
48 **/
49 EFI_STATUS
PchSmmInitHardware(VOID)50 PchSmmInitHardware (
51   VOID
52   )
53 {
54   EFI_STATUS  Status;
55 
56   ///
57   /// Clear all SMIs
58   ///
59   PchSmmClearSmi ();
60 
61   Status = PchSmmEnableGlobalSmiBit ();
62   ASSERT_EFI_ERROR (Status);
63 
64   ///
65   /// Be *really* sure to clear all SMIs
66   ///
67   PchSmmClearSmi ();
68 
69   return EFI_SUCCESS;
70 }
71 
72 /**
73   Enables the PCH to generate SMIs. Note that no SMIs will be generated
74   if no SMI sources are enabled. Conversely, no enabled SMI source will
75   generate SMIs if SMIs are not globally enabled. This is the main
76   switchbox for SMI generation.
77 
78 
79   @retval EFI_SUCCESS             Enable Global Smi Bit completed
80 **/
81 EFI_STATUS
PchSmmEnableGlobalSmiBit(VOID)82 PchSmmEnableGlobalSmiBit (
83   VOID
84   )
85 {
86   UINT32  SmiEn;
87 
88   SmiEn = IoRead32 ((UINTN) (mAcpiBaseAddr + R_PCH_SMI_EN));
89 
90   ///
91   /// Set the "global smi enable" bit
92   ///
93   SmiEn |= B_PCH_SMI_EN_GBL_SMI;
94 
95   IoWrite32 ((UINTN) (mAcpiBaseAddr + R_PCH_SMI_EN), SmiEn);
96 
97   return EFI_SUCCESS;
98 }
99 
100 /**
101   Clears the SMI after all SMI source have been processed.
102   Note that this function will not work correctly (as it is
103   written) unless all SMI sources have been processed.
104   A revision of this function could manually clear all SMI
105   status bits to guarantee success.
106 
107 
108   @retval EFI_SUCCESS             Clears the SMIs completed
109   @retval Asserts                 EOS was not set to a 1
110 **/
111 EFI_STATUS
PchSmmClearSmi(VOID)112 PchSmmClearSmi (
113   VOID
114   )
115 {
116   BOOLEAN     EosSet;
117   BOOLEAN     SciEn;
118   UINT32      Pm1Cnt;
119   UINT16      Pm1Sts;
120   UINT32      Gpe0Sts;
121   UINT32      SmiSts;
122   UINT16      DevActSts;
123   UINT16      Tco1Sts;
124 
125   Gpe0Sts      = 0;
126   ///
127   /// Determine whether an ACPI OS is present (via the SCI_EN bit)
128   ///
129   Pm1Cnt = IoRead32 ((UINTN) (mAcpiBaseAddr + R_PCH_ACPI_PM1_CNT));
130   SciEn  = (BOOLEAN) ((Pm1Cnt & B_PCH_ACPI_PM1_CNT_SCI_EN) == B_PCH_ACPI_PM1_CNT_SCI_EN);
131   if (!SciEn) {
132     ///
133     /// Clear any SMIs that double as SCIs (when SCI_EN==0)
134     ///
135     Pm1Sts   = IoRead16 ((UINTN) (mAcpiBaseAddr + R_PCH_ACPI_PM1_STS));
136     Gpe0Sts  = IoRead32 ((UINTN) (mAcpiBaseAddr + R_PCH_ACPI_GPE0_STS_127_96));
137 
138     Pm1Sts |=
139     (
140       B_PCH_ACPI_PM1_STS_WAK |
141       B_PCH_ACPI_PM1_STS_PRBTNOR |
142       B_PCH_ACPI_PM1_STS_RTC |
143       B_PCH_ACPI_PM1_STS_PWRBTN |
144       B_PCH_ACPI_PM1_STS_GBL |
145       B_PCH_ACPI_PM1_STS_TMROF
146       );
147 
148     Gpe0Sts |=
149     (
150       B_PCH_ACPI_GPE0_STS_127_96_PME_B0 |
151       B_PCH_ACPI_GPE0_STS_127_96_PME |
152       B_PCH_ACPI_GPE0_STS_127_96_BATLOW |
153       B_PCH_ACPI_GPE0_STS_127_96_PCI_EXP |
154       B_PCH_ACPI_GPE0_STS_127_96_RI |
155       B_PCH_ACPI_GPE0_STS_127_96_SMB_WAK |
156       B_PCH_ACPI_GPE0_STS_127_96_TC0SCI |
157       B_PCH_ACPI_GPE0_STS_127_96_HOT_PLUG |
158       B_PCH_ACPI_GPE0_STS_127_96_BATLOW |
159       B_PCH_ACPI_GPE0_STS_127_96_LAN_WAKE
160       );
161 
162     IoWrite16 ((UINTN) (mAcpiBaseAddr + R_PCH_ACPI_PM1_STS), (UINT16) Pm1Sts);
163     IoWrite32 ((UINTN) (mAcpiBaseAddr + R_PCH_ACPI_GPE0_STS_127_96), (UINT32) Gpe0Sts);
164   }
165   ///
166   /// Clear all SMIs that are unaffected by SCI_EN
167   ///
168   SmiSts        = IoRead32 ((UINTN) (mAcpiBaseAddr + R_PCH_SMI_STS));
169   DevActSts     = IoRead16 ((UINTN) (mAcpiBaseAddr + R_PCH_DEVACT_STS));
170   Tco1Sts       = IoRead16 ((UINTN) (mTcoBaseAddr + R_PCH_TCO1_STS));
171 
172   SmiSts |=
173   (
174     B_PCH_SMI_STS_SMBUS |
175     B_PCH_SMI_STS_PERIODIC |
176     B_PCH_SMI_STS_TCO |
177     B_PCH_SMI_STS_MCSMI |
178     B_PCH_SMI_STS_SWSMI_TMR |
179     B_PCH_SMI_STS_APM |
180     B_PCH_SMI_STS_ON_SLP_EN |
181     B_PCH_SMI_STS_BIOS
182     );
183   DevActSts |=
184   (
185     B_PCH_DEVACT_STS_KBC |
186     B_PCH_DEVACT_STS_PIRQDH |
187     B_PCH_DEVACT_STS_PIRQCG |
188     B_PCH_DEVACT_STS_PIRQBF |
189     B_PCH_DEVACT_STS_PIRQAE
190     );
191   Tco1Sts |=
192   (
193     B_PCH_TCO1_STS_DMISERR |
194     B_PCH_TCO1_STS_DMISMI |
195     B_PCH_TCO1_STS_DMISCI |
196     B_PCH_TCO1_STS_BIOSWR |
197     B_PCH_TCO1_STS_NEWCENTURY |
198     B_PCH_TCO1_STS_TIMEOUT |
199     B_PCH_TCO1_STS_TCO_INT |
200     B_PCH_TCO1_STS_SW_TCO_SMI
201     );
202 
203   GpioClearAllGpiSmiSts ();
204 
205   //
206   // If NewCentury Sts is set here, it must clear the NewCentury Sts separately.
207   //
208   PchTcoClearNewCenturySts (NULL);
209 
210   IoWrite16 ((UINTN) (mTcoBaseAddr + R_PCH_TCO1_STS), Tco1Sts);
211 
212   //
213   // We do not want to write 1 to clear INTRD_DET bit.
214   //
215   IoWrite16 ((UINTN) (mTcoBaseAddr + R_PCH_TCO2_STS), (UINT16) ~B_PCH_TCO2_STS_INTRD_DET);
216 
217   IoWrite32 ((UINTN) (mAcpiBaseAddr + R_PCH_SMI_STS), SmiSts);
218 
219   IoWrite16 ((UINTN) (mAcpiBaseAddr + R_PCH_DEVACT_STS), DevActSts);
220 
221   ///
222   /// Try to clear the EOS bit. ASSERT on an error
223   ///
224   EosSet = PchSmmSetAndCheckEos ();
225   ASSERT (EosSet);
226 
227   return EFI_SUCCESS;
228 }
229 
230 /**
231   Set the SMI EOS bit after all SMI source have been processed.
232 
233 
234   @retval FALSE                   EOS was not set to a 1; this is an error
235   @retval TRUE                    EOS was correctly set to a 1
236 **/
237 BOOLEAN
PchSmmSetAndCheckEos(VOID)238 PchSmmSetAndCheckEos (
239   VOID
240   )
241 {
242   UINT32  SmiEn;
243 
244   SmiEn = IoRead32 ((UINTN) (mAcpiBaseAddr + R_PCH_SMI_EN));
245 
246   ///
247   /// Reset the PCH to generate subsequent SMIs
248   ///
249   SmiEn |= B_PCH_SMI_EN_EOS;
250 
251   IoWrite32 ((UINTN) (mAcpiBaseAddr + R_PCH_SMI_EN), SmiEn);
252 
253   ///
254   /// Double check that the assert worked
255   ///
256   SmiEn = IoRead32 ((UINTN) (mAcpiBaseAddr + R_PCH_SMI_EN));
257 
258   ///
259   /// Return TRUE if EOS is set correctly
260   ///
261   if ((SmiEn & B_PCH_SMI_EN_EOS) == 0) {
262     ///
263     /// EOS was not set to a 1; this is an error
264     ///
265     return FALSE;
266   } else {
267     ///
268     /// EOS was correctly set to a 1
269     ///
270     return TRUE;
271   }
272 }
273 
274 /**
275   Determine whether an ACPI OS is present (via the SCI_EN bit)
276 
277 
278   @retval TRUE                    ACPI OS is present
279   @retval FALSE                   ACPI OS is not present
280 **/
281 BOOLEAN
PchSmmGetSciEn(VOID)282 PchSmmGetSciEn (
283   VOID
284   )
285 {
286   BOOLEAN SciEn;
287   UINT32  Pm1Cnt;
288 
289   ///
290   /// Determine whether an ACPI OS is present (via the SCI_EN bit)
291   ///
292   Pm1Cnt  = IoRead32 ((UINTN) (mAcpiBaseAddr + R_PCH_ACPI_PM1_CNT));
293   SciEn   = (BOOLEAN) ((Pm1Cnt & B_PCH_ACPI_PM1_CNT_SCI_EN) == B_PCH_ACPI_PM1_CNT_SCI_EN);
294 
295   return SciEn;
296 }
297 
298 /**
299   Read a specifying bit with the register
300   These may or may not need to change w/ the PCH version; they're highly IA-32 dependent, though.
301 
302   @param[in] BitDesc              The struct that includes register address, size in byte and bit number
303 
304   @retval TRUE                    The bit is enabled
305   @retval FALSE                   The bit is disabled
306 **/
307 BOOLEAN
ReadBitDesc(CONST PCH_SMM_BIT_DESC * BitDesc)308 ReadBitDesc (
309   CONST PCH_SMM_BIT_DESC  *BitDesc
310   )
311 {
312   EFI_STATUS  Status;
313   UINT64      Register;
314   UINT32      PciBus;
315   UINT32      PciDev;
316   UINT32      PciFun;
317   UINT32      PciReg;
318   UINTN       RegSize;
319   BOOLEAN     BitWasOne;
320   UINTN       ShiftCount;
321   UINTN       RegisterOffset;
322   UINT32      BaseAddr;
323   UINTN       PciBaseAddress;
324 
325   ASSERT (BitDesc != NULL);
326   ASSERT (!IS_BIT_DESC_NULL (*BitDesc));
327 
328   RegSize     = 0;
329   Register    = 0;
330   ShiftCount  = 0;
331   BitWasOne   = FALSE;
332 
333   switch (BitDesc->Reg.Type) {
334 
335     case ACPI_ADDR_TYPE:
336     case TCO_ADDR_TYPE:
337       if (BitDesc->Reg.Type == ACPI_ADDR_TYPE) {
338         RegisterOffset  = BitDesc->Reg.Data.acpi;
339         BaseAddr        = mAcpiBaseAddr;
340       } else {
341         RegisterOffset  = BitDesc->Reg.Data.tco;
342         BaseAddr        = mTcoBaseAddr;
343       }
344       switch (BitDesc->SizeInBytes) {
345 
346         case 0:
347           ///
348           /// Chances are that this field didn't get initialized.
349           /// Check your assignments to bit descriptions.
350           ///
351           ASSERT (FALSE);
352           break;
353 
354         case 1:
355           RegSize = SMM_IO_UINT8;
356           break;
357 
358         case 2:
359           RegSize = SMM_IO_UINT16;
360           break;
361 
362         case 4:
363           RegSize = SMM_IO_UINT32;
364           break;
365 
366         case 8:
367           RegSize = SMM_IO_UINT64;
368           break;
369 
370         default:
371           ///
372           /// Unsupported or invalid register size
373           ///
374           ASSERT (FALSE);
375           break;
376       }
377       ///
378       /// Double check that we correctly read in the acpi base address
379       ///
380       ASSERT ((BaseAddr != 0x0) && ((BaseAddr & 0x1) != 0x1));
381 
382       ShiftCount      = BitDesc->Bit;
383       ///
384       /// As current CPU Smm Io can only support at most
385       /// 32-bit read/write,if Operation is 64 bit,
386       /// we do a 32 bit operation according to BitDesc->Bit
387       ///
388       if (RegSize == SMM_IO_UINT64) {
389         RegSize = SMM_IO_UINT32;
390         ///
391         /// If the operation is for high 32 bits
392         ///
393         if (BitDesc->Bit >= 32) {
394           RegisterOffset += 4;
395           ShiftCount -= 32;
396         }
397       }
398 
399       Status = gSmst->SmmIo.Io.Read (
400                                  &gSmst->SmmIo,
401                                  RegSize,
402                                  BaseAddr + RegisterOffset,
403                                  1,
404                                  &Register
405                                  );
406       ASSERT_EFI_ERROR (Status);
407 
408       if ((Register & (LShiftU64 (BIT_ZERO, ShiftCount))) != 0) {
409         BitWasOne = TRUE;
410       } else {
411         BitWasOne = FALSE;
412       }
413       break;
414 
415     case GPIO_ADDR_TYPE:
416     case MEMORY_MAPPED_IO_ADDRESS_TYPE:
417       ///
418       /// Read the register, and it with the bit to read
419       ///
420       switch (BitDesc->SizeInBytes) {
421         case 1:
422           Register = (UINT64) MmioRead8 ((UINTN) BitDesc->Reg.Data.Mmio);
423           break;
424 
425         case 2:
426           Register = (UINT64) MmioRead16 ((UINTN) BitDesc->Reg.Data.Mmio);
427           break;
428 
429         case 4:
430           Register = (UINT64) MmioRead32 ((UINTN) BitDesc->Reg.Data.Mmio);
431           break;
432 
433         case 8:
434           Register                      = (UINT64) MmioRead32 ((UINTN) BitDesc->Reg.Data.Mmio);
435           *((UINT32 *) (&Register) + 1) = MmioRead32 ((UINTN) BitDesc->Reg.Data.Mmio + 4);
436           break;
437 
438         default:
439           ///
440           /// Unsupported or invalid register size
441           ///
442           ASSERT (FALSE);
443           break;
444       }
445 
446       Register = Register & (LShiftU64 (BIT0, BitDesc->Bit));
447       if (Register) {
448         BitWasOne = TRUE;
449       } else {
450         BitWasOne = FALSE;
451       }
452       break;
453 
454     case PCIE_ADDR_TYPE:
455       PciBus  = BitDesc->Reg.Data.pcie.Fields.Bus;
456       PciDev  = BitDesc->Reg.Data.pcie.Fields.Dev;
457       PciFun  = BitDesc->Reg.Data.pcie.Fields.Fnc;
458       PciReg  = BitDesc->Reg.Data.pcie.Fields.Reg;
459       PciBaseAddress = MmPciBase (PciBus, PciDev, PciFun);
460       switch (BitDesc->SizeInBytes) {
461 
462         case 0:
463           ///
464           /// Chances are that this field didn't get initialized.
465           /// Check your assignments to bit descriptions.
466           ///
467           ASSERT (FALSE);
468           break;
469 
470         case 1:
471           Register = (UINT64) MmioRead8 (PciBaseAddress + PciReg);
472           break;
473 
474         case 2:
475           Register = (UINT64) MmioRead16 (PciBaseAddress + PciReg);
476           break;
477 
478         case 4:
479           Register = (UINT64) MmioRead32 (PciBaseAddress + PciReg);
480           break;
481 
482         default:
483           ///
484           /// Unsupported or invalid register size
485           ///
486           ASSERT (FALSE);
487           break;
488       }
489 
490       if ((Register & (LShiftU64 (BIT_ZERO, BitDesc->Bit))) != 0) {
491         BitWasOne = TRUE;
492       } else {
493         BitWasOne = FALSE;
494       }
495       break;
496 
497     case PCR_ADDR_TYPE:
498       ///
499       /// Read the register, and it with the bit to read
500       ///
501       switch (BitDesc->SizeInBytes) {
502         case 1:
503           PchPcrRead8  (BitDesc->Reg.Data.Pcr.Fields.Pid, BitDesc->Reg.Data.Pcr.Fields.Offset, (UINT8*)  &Register);
504           break;
505 
506         case 2:
507           PchPcrRead16 (BitDesc->Reg.Data.Pcr.Fields.Pid, BitDesc->Reg.Data.Pcr.Fields.Offset, (UINT16*) &Register);
508           break;
509 
510         case 4:
511           PchPcrRead32 (BitDesc->Reg.Data.Pcr.Fields.Pid, BitDesc->Reg.Data.Pcr.Fields.Offset, (UINT32*) &Register);
512           break;
513 
514         default:
515           ///
516           /// Unsupported or invalid register size
517           ///
518           ASSERT (FALSE);
519           break;
520       }
521 
522       Register = Register & (LShiftU64 (BIT0, BitDesc->Bit));
523       if (Register) {
524         BitWasOne = TRUE;
525       } else {
526         BitWasOne = FALSE;
527       }
528       break;
529 
530     default:
531       ///
532       /// This address type is not yet implemented
533       ///
534       ASSERT (FALSE);
535       break;
536   }
537 
538   return BitWasOne;
539 }
540 
541 /**
542   Write a specifying bit with the register
543 
544   @param[in] BitDesc              The struct that includes register address, size in byte and bit number
545   @param[in] ValueToWrite         The value to be wrote
546   @param[in] WriteClear           If the rest bits of the register is write clear
547 
548 **/
549 VOID
WriteBitDesc(CONST PCH_SMM_BIT_DESC * BitDesc,CONST BOOLEAN ValueToWrite,CONST BOOLEAN WriteClear)550 WriteBitDesc (
551   CONST PCH_SMM_BIT_DESC  *BitDesc,
552   CONST BOOLEAN           ValueToWrite,
553   CONST BOOLEAN           WriteClear
554   )
555 {
556   EFI_STATUS  Status;
557   UINT64      Register;
558   UINT64      AndVal;
559   UINT64      OrVal;
560   UINT32      RegSize;
561   UINT32      PciBus;
562   UINT32      PciDev;
563   UINT32      PciFun;
564   UINT32      PciReg;
565   UINTN       RegisterOffset;
566   UINT32      BaseAddr;
567   UINTN       PciBaseAddress;
568 
569   ASSERT (BitDesc != NULL);
570   ASSERT (!IS_BIT_DESC_NULL (*BitDesc));
571 
572   RegSize   = 0;
573   Register  = 0;
574 
575   if (WriteClear) {
576     AndVal = LShiftU64 (BIT_ZERO, BitDesc->Bit);
577   } else {
578     AndVal = ~(LShiftU64 (BIT_ZERO, BitDesc->Bit));
579   }
580 
581   OrVal = (LShiftU64 ((UINT32) ValueToWrite, BitDesc->Bit));
582 
583   switch (BitDesc->Reg.Type) {
584 
585     case ACPI_ADDR_TYPE:
586     case TCO_ADDR_TYPE:
587       if (BitDesc->Reg.Type == ACPI_ADDR_TYPE) {
588         RegisterOffset  = BitDesc->Reg.Data.acpi;
589         BaseAddr        = mAcpiBaseAddr;
590       } else {
591         RegisterOffset  = BitDesc->Reg.Data.tco;
592         BaseAddr        = mTcoBaseAddr;
593       }
594 
595       switch (BitDesc->SizeInBytes) {
596 
597         case 0:
598           ///
599           /// Chances are that this field didn't get initialized.
600           /// Check your assignments to bit descriptions.
601           ///
602           ASSERT (FALSE);
603           break;
604 
605         case 1:
606           RegSize = SMM_IO_UINT8;
607           break;
608 
609         case 2:
610           RegSize = SMM_IO_UINT16;
611           break;
612 
613         case 4:
614           RegSize = SMM_IO_UINT32;
615           break;
616 
617         case 8:
618           RegSize = SMM_IO_UINT64;
619           break;
620 
621         default:
622           ///
623           /// Unsupported or invalid register size
624           ///
625           ASSERT (FALSE);
626           break;
627       }
628       ///
629       /// Double check that we correctly read in the acpi base address
630       ///
631       ASSERT ((BaseAddr != 0x0) && ((BaseAddr & 0x1) != 0x1));
632 
633       ///
634       /// As current CPU Smm Io can only support at most
635       /// 32-bit read/write,if Operation is 64 bit,
636       /// we do a 32 bit operation according to BitDesc->Bit
637       ///
638       if (RegSize == SMM_IO_UINT64) {
639         RegSize = SMM_IO_UINT32;
640         ///
641         /// If the operation is for high 32 bits
642         ///
643         if (BitDesc->Bit >= 32) {
644           RegisterOffset += 4;
645 
646           if (WriteClear) {
647             AndVal = LShiftU64 (BIT_ZERO, BitDesc->Bit - 32);
648           } else {
649             AndVal = ~(LShiftU64 (BIT_ZERO, BitDesc->Bit - 32));
650           }
651 
652           OrVal = LShiftU64 ((UINT32) ValueToWrite, BitDesc->Bit - 32);
653         }
654       }
655 
656       Status = gSmst->SmmIo.Io.Read (
657                                  &gSmst->SmmIo,
658                                  RegSize,
659                                  BaseAddr + RegisterOffset,
660                                  1,
661                                  &Register
662                                  );
663       ASSERT_EFI_ERROR (Status);
664 
665       Register &= AndVal;
666       Register |= OrVal;
667 
668       Status = gSmst->SmmIo.Io.Write (
669                                  &gSmst->SmmIo,
670                                  RegSize,
671                                  BaseAddr + RegisterOffset,
672                                  1,
673                                  &Register
674                                  );
675       ASSERT_EFI_ERROR (Status);
676       break;
677 
678     case GPIO_ADDR_TYPE:
679     case MEMORY_MAPPED_IO_ADDRESS_TYPE:
680       ///
681       /// Read the register, or it with the bit to set, then write it back.
682       ///
683       switch (BitDesc->SizeInBytes) {
684         case 1:
685           MmioAndThenOr8  ((UINTN) BitDesc->Reg.Data.Mmio, (UINT8)  AndVal, (UINT8)  OrVal);
686           break;
687 
688         case 2:
689           MmioAndThenOr16 ((UINTN) BitDesc->Reg.Data.Mmio, (UINT16) AndVal, (UINT16) OrVal);
690           break;
691 
692         case 4:
693           MmioAndThenOr32 ((UINTN) BitDesc->Reg.Data.Mmio, (UINT32) AndVal, (UINT32) OrVal);
694           break;
695 
696         case 8:
697           Register                      = (UINT64) MmioRead32 ((UINTN) BitDesc->Reg.Data.Mmio);
698           *((UINT32 *) (&Register) + 1) = MmioRead32 ((UINTN) BitDesc->Reg.Data.Mmio + 4);
699           Register &= AndVal;
700           Register |= OrVal;
701           MmioWrite32 ((UINTN) BitDesc->Reg.Data.Mmio, (UINT32) Register);
702           MmioWrite32 ((UINTN) BitDesc->Reg.Data.Mmio + 4, *((UINT32 *) (&Register) + 1));
703           break;
704 
705         default:
706           ///
707           /// Unsupported or invalid register size
708           ///
709           ASSERT (FALSE);
710           break;
711       }
712       break;
713 
714     case PCIE_ADDR_TYPE:
715       PciBus  = BitDesc->Reg.Data.pcie.Fields.Bus;
716       PciDev  = BitDesc->Reg.Data.pcie.Fields.Dev;
717       PciFun  = BitDesc->Reg.Data.pcie.Fields.Fnc;
718       PciReg  = BitDesc->Reg.Data.pcie.Fields.Reg;
719       PciBaseAddress = MmPciBase (PciBus, PciDev, PciFun);
720       switch (BitDesc->SizeInBytes) {
721 
722         case 0:
723           ///
724           /// Chances are that this field didn't get initialized -- check your assignments
725           /// to bit descriptions.
726           ///
727           ASSERT (FALSE);
728           break;
729 
730         case 1:
731           MmioAndThenOr8 (PciBaseAddress + PciReg, (UINT8) AndVal, (UINT8) OrVal);
732           break;
733 
734         case 2:
735           MmioAndThenOr16 (PciBaseAddress + PciReg, (UINT16) AndVal, (UINT16) OrVal);
736           break;
737 
738         case 4:
739           MmioAndThenOr32 (PciBaseAddress + PciReg, (UINT32) AndVal, (UINT32) OrVal);
740           break;
741 
742         default:
743           ///
744           /// Unsupported or invalid register size
745           ///
746           ASSERT (FALSE);
747           break;
748       }
749       break;
750 
751     case PCR_ADDR_TYPE:
752       ///
753       /// Read the register, or it with the bit to set, then write it back.
754       ///
755       switch (BitDesc->SizeInBytes) {
756         case 1:
757           PchPcrAndThenOr8  ((PCH_SBI_PID) BitDesc->Reg.Data.Pcr.Fields.Pid, (UINT16) BitDesc->Reg.Data.Pcr.Fields.Offset, (UINT8)  AndVal, (UINT8)  OrVal);
758           break;
759 
760         case 2:
761           PchPcrAndThenOr16 ((PCH_SBI_PID) BitDesc->Reg.Data.Pcr.Fields.Pid, (UINT16) BitDesc->Reg.Data.Pcr.Fields.Offset, (UINT16) AndVal, (UINT16) OrVal);
762           break;
763 
764         case 4:
765           PchPcrAndThenOr32 ((PCH_SBI_PID) BitDesc->Reg.Data.Pcr.Fields.Pid, (UINT16) BitDesc->Reg.Data.Pcr.Fields.Offset, (UINT32) AndVal, (UINT32) OrVal);
766           break;
767 
768         default:
769           ///
770           /// Unsupported or invalid register size
771           ///
772           ASSERT (FALSE);
773           break;
774       }
775       break;
776 
777     default:
778       ///
779       /// This address type is not yet implemented
780       ///
781       ASSERT (FALSE);
782       break;
783   }
784 }
785