1 /** @file
2   Implementation of Fsp SA Policy Initialization.
3 
4 Copyright (c) 2017, Intel Corporation. All rights reserved.<BR>
5 SPDX-License-Identifier: BSD-2-Clause-Patent
6 
7 **/
8 
9 #include <PeiFspPolicyInitLib.h>
10 
11 #include <Ppi/SiPolicy.h>
12 #include <ConfigBlock/MemoryConfig.h>
13 #include <Library/IoLib.h>
14 #include <Library/BaseMemoryLib.h>
15 #include <Library/SmbusLib.h>
16 #include <Library/MmPciLib.h>
17 #include <Library/ConfigBlockLib.h>
18 #include <Library/PcdLib.h>
19 
20 #include <IndustryStandard/Pci.h>
21 #include <MrcSpdData.h>
22 #include <PchAccess.h>
23 #include <Ppi/FirmwareVolume.h>
24 #include <Pi/PiFirmwareFile.h>
25 #include <Pi/PiPeiCis.h>
26 
27 #define MAX_SPD_PAGE_COUNT           (2)
28 #define MAX_SPD_PAGE_SIZE            (256)
29 #define MAX_SPD_SIZE                 (MAX_SPD_PAGE_SIZE * MAX_SPD_PAGE_COUNT)
30 #define SPD_PAGE_ADDRESS_0           (0x6C)
31 #define SPD_PAGE_ADDRESS_1           (0x6E)
32 #define SPD_DDR3_SDRAM_TYPE_OFFSET   (0x02)
33 #define SPD_DDR3_SDRAM_TYPE_NUMBER   (0x0B)
34 #define SPD_DDR4_SDRAM_TYPE_NUMBER   (0x0C)
35 #define SPD_LPDDR3_SDRAM_TYPE_NUMBER (0xF1)
36 #define SPD_JEDEC_LPDDR3_SDRAM_TYPE_NUMBER (0x0F)
37 #define XMP_ID_STRING                (0x4A0C)
38 #define SPD3_MANUF_START             (117)
39 #define SPD3_MANUF_END               (127)
40 #define SPD4_MANUF_START             (320)
41 #define SPD4_MANUF_END               (328)
42 #define SPDLP_MANUF_START            (320)
43 #define SPDLP_MANUF_END              (328)
44 
45 GLOBAL_REMOVE_IF_UNREFERENCED const SPD_OFFSET_TABLE mSpdDdr3Table[] = {
46   {   0,               1,             (1 << SpdCold),},
47   {   2,               2,             (1 << SpdCold) | (1 << SpdFast),},
48   {   3,              41,             (1 << SpdCold),},
49   {  60,              63,             (1 << SpdCold),},
50   { SPD3_MANUF_START, SPD3_MANUF_END, (1 << SpdCold) | (1 << SpdFast),},
51   { 128,             145,             (1 << SpdCold),},
52 #ifdef SUPPORT_SPD_CRC
53   {  39,              59,             (1 << SpdCold),},
54   {  64,             125,             (1 << SpdCold),},
55 #endif
56   { 176,             179,             (1 << SpdCold),},
57   { 180,             184,             (1 << SpdCold),},
58   { 185,             215,             (1 << SpdCold),},
59   { 220,             250,             (1 << SpdCold),},
60 };
61 
62 GLOBAL_REMOVE_IF_UNREFERENCED const SPD_OFFSET_TABLE mSpdDdr4Table[] = {
63   {   0,               1,             (1 << SpdCold),},
64   {   2,               2,             (1 << SpdCold) | (1 << SpdFast),},
65   {   3,              40,             (1 << SpdCold),},
66   { 117,             131,             (1 << SpdCold),},
67   { SPD4_MANUF_START, SPD4_MANUF_END, (1 << SpdCold) | (1 << SpdFast),},
68   { 329,             348,             (1 << SpdCold),},
69 #ifdef SUPPORT_SPD_CRC
70   {  32,             119,             (1 << SpdCold),},
71   { 126,             255,             (1 << SpdCold),},
72   { 349,             383,             (1 << SpdCold),},
73 #endif
74   { 384,             387,             (1 << SpdCold),},
75   { 388,             389,             (1 << SpdCold),},
76   { 393,             431,             (1 << SpdCold),},
77   { 440,             478,             (1 << SpdCold),},
78 };
79 
80 GLOBAL_REMOVE_IF_UNREFERENCED const SPD_OFFSET_TABLE mSpdLpddrTable[] = {
81   {   0,               1,               (1 << SpdCold),},
82   {   2,               2,               (1 << SpdCold) | (1 << SpdFast),},
83   {   3,              32,               (1 << SpdCold),},
84   { 120,             130,               (1 << SpdCold),},
85   { SPDLP_MANUF_START, SPDLP_MANUF_END, (1 << SpdCold) | (1 << SpdFast),},
86   { 329,             348,               (1 << SpdCold),},
87 #ifdef SUPPORT_SPD_CRC
88   {  31,             121,               (1 << SpdCold),},
89   { 126,             255,               (1 << SpdCold),},
90   { 349,             383,               (1 << SpdCold),},
91 #endif
92   { 384,             387,               (1 << SpdCold),},
93   { 388,             389,               (1 << SpdCold),},
94   { 393,             431,               (1 << SpdCold),},
95   { 440,             478,               (1 << SpdCold),},
96 };
97 
98 
99 /**
100   Read the SPD data over the SMBus, at the specified SPD address, starting at
101   the specified starting offset and read the given amount of data.
102 
103   @param[in] SpdAddress  - SPD SMBUS address
104   @param[in, out] Buffer - Buffer to store the data.
105   @param[in] Start       - Starting SPD offset
106   @param[in] Size        - The number of bytes of data to read and also the size of the buffer.
107   @param[in, out] Page   - The final page that is being pointed to.
108 
109   @retval EFI_SUCCESS if the read is successful, otherwise error status.
110 **/
111 static
112 EFI_STATUS
InternalDoSpdRead(IN const UINT8 SpdAddress,IN OUT UINT8 * const Buffer,IN const UINT16 Start,IN UINT16 Size,IN OUT UINT8 * const Page)113 InternalDoSpdRead (
114   IN     const UINT8  SpdAddress,
115   IN OUT UINT8        *const Buffer,
116   IN     const UINT16 Start,
117   IN           UINT16 Size,
118   IN OUT UINT8        *const Page
119   )
120 {
121   EFI_STATUS    EfiStatus;
122   BOOLEAN       PageUpdate;
123   UINT16        Count;
124   UINT16        Index;
125 
126   EfiStatus = EFI_DEVICE_ERROR;
127   if ((Buffer != NULL) && (Start < MAX_SPD_SIZE) && ((Start + Size) < MAX_SPD_SIZE)) {
128     Count = 0;
129     PageUpdate = FALSE;
130     while (Size--) {
131       Index = Start + Count;
132       if ((Index / MAX_SPD_PAGE_SIZE) != *Page) {
133         *Page = (UINT8) (Index / MAX_SPD_PAGE_SIZE);
134         PageUpdate = TRUE;
135       }
136       Index %= MAX_SPD_PAGE_SIZE;
137       if (PageUpdate == TRUE) {
138         PageUpdate = FALSE;
139         SmBusWriteDataByte ((*Page == 0) ? SPD_PAGE_ADDRESS_0 : SPD_PAGE_ADDRESS_1, 0, &EfiStatus);
140       }
141       Buffer[Count] = SmBusReadDataByte (SpdAddress | ((UINT32) Index << 8), &EfiStatus);
142       if (EFI_SUCCESS != EfiStatus) {
143         Buffer[Count] = 0;
144         break;
145       }
146       Count++;
147     }
148     EfiStatus = EFI_SUCCESS;
149   }
150   return (EfiStatus);
151 }
152 
153 /**
154   See if there is valid XMP SPD data.
155 
156   @param[in] Debug    - Mrc debug structure.
157   @param[in, out] Spd - Mrc SPD structure.
158   @param[in] XmpStart - The current offset in the SPD.
159 
160   @retval TRUE if valid, FALSE in not.
161 **/
162 static
163 BOOLEAN
InternalVerifyXmp(IN OUT MrcSpd * const Spd,IN const UINT16 XmpStart)164 InternalVerifyXmp (
165   IN OUT MrcSpd *const Spd,
166   IN const UINT16 XmpStart
167   )
168 {
169   SPD_EXTREME_MEMORY_PROFILE_HEADER      *Header1;
170   SPD_EXTREME_MEMORY_PROFILE_HEADER_2_0  *Header2;
171   BOOLEAN                                 Xmp;
172 
173   Xmp = FALSE;
174 
175   switch (((UINT8 *)Spd)[2]) {
176     case SPD_DDR3_SDRAM_TYPE_NUMBER:
177       Header1 = &Spd->Ddr3.Xmp.Header;
178       if (XmpStart == ((UINT32) (Header1) - (UINT32) Spd)) {
179         Xmp = TRUE;
180         if ((Header1->XmpRevision.Data & 0xFE) == 0x12) {
181           return (TRUE);
182         } else {
183           Header1->XmpId            = 0;
184           Header1->XmpOrgConf.Data  = 0;
185           Header1->XmpRevision.Data = 0;
186         }
187       }
188       break;
189     case SPD_DDR4_SDRAM_TYPE_NUMBER:
190       Header2 = &Spd->Ddr4.EndUser.Xmp.Header;
191       if (XmpStart == ((UINT32) (Header2) - (UINT32) Spd)) {
192         Xmp = TRUE;
193         if ((Header2->XmpRevision.Data) == 0x20) {
194           return (TRUE);
195         } else {
196           Header2->XmpId            = 0;
197           Header2->XmpOrgConf.Data  = 0;
198           Header2->XmpRevision.Data = 0;
199         }
200       }
201       break;
202     case SPD_JEDEC_LPDDR3_SDRAM_TYPE_NUMBER:
203     case SPD_LPDDR3_SDRAM_TYPE_NUMBER:
204       return (TRUE);
205     default:
206       return (FALSE);
207   }
208   if (!Xmp) {
209     return (TRUE);
210   }
211   return (FALSE);
212 }
213 
214 /**
215   Read the SPD data over the SMBus, at the given SmBus SPD address and copy the data to the data structure.
216   The SPD data locations read is controlled by the current boot mode.
217 
218   @param[in] BootMode          - The current MRC boot mode.
219   @param[in] Address           - SPD SmBus address offset.
220   @param[in] Buffer            - Buffer that contains the data read from the SPD.
221   @param[in] SpdDdr3Table      - Indicates which SPD bytes to read.
222   @param[in] SpdDdr3TableSize  - Size of SpdDdr3Table in bytes.
223   @param[in] SpdDdr4Table      - Indicates which SPD bytes to read.
224   @param[in] SpdDdr4TableSize  - Size of SpdDdr4Table in bytes.
225   @param[in] SpdLpddrTable     - Indicates which SPD bytes to read.
226   @param[in] SpdLpddrTableSize - Size of SpdLpddrTable in bytes.
227 
228   @retval TRUE if the read is successful, otherwise FALSE on error.
229 **/
230 BOOLEAN
InternalGetSpdData(IN SPD_BOOT_MODE BootMode,IN UINT8 Address,IN OUT UINT8 * Buffer,IN UINT8 * SpdDdr3Table,IN UINT32 SpdDdr3TableSize,IN UINT8 * SpdDdr4Table,IN UINT32 SpdDdr4TableSize,IN UINT8 * SpdLpddrTable,IN UINT32 SpdLpddrTableSize)231 InternalGetSpdData (
232   IN SPD_BOOT_MODE BootMode,
233   IN UINT8         Address,
234   IN OUT   UINT8   *Buffer,
235   IN UINT8         *SpdDdr3Table,
236   IN UINT32        SpdDdr3TableSize,
237   IN UINT8         *SpdDdr4Table,
238   IN UINT32        SpdDdr4TableSize,
239   IN UINT8         *SpdLpddrTable,
240   IN UINT32        SpdLpddrTableSize
241   )
242 {
243   const SPD_OFFSET_TABLE *Tbl;
244   const SPD_OFFSET_TABLE *TableSelect;
245   EFI_STATUS             Status;
246   UINT32                 Byte;
247   UINT32                 Stop;
248   UINT8                  Page;
249 
250   Page   = (UINT8) (~0);
251   Status = InternalDoSpdRead (Address, &Buffer[SPD_DDR3_SDRAM_TYPE_OFFSET], 2, 1, &Page);
252   if (EFI_SUCCESS == Status) {
253     switch (Buffer[SPD_DDR3_SDRAM_TYPE_OFFSET]) {
254       case SPD_DDR3_SDRAM_TYPE_NUMBER:
255       case SPD_LPDDR3_SDRAM_TYPE_NUMBER:
256       default:
257         TableSelect = (SPD_OFFSET_TABLE *) SpdDdr3Table;
258         Stop = (SpdDdr3TableSize / sizeof (SPD_OFFSET_TABLE));
259         break;
260       case SPD_DDR4_SDRAM_TYPE_NUMBER:
261         TableSelect = (SPD_OFFSET_TABLE *) SpdDdr4Table;
262         Stop = (SpdDdr4TableSize / sizeof (SPD_OFFSET_TABLE));
263         break;
264       case SPD_JEDEC_LPDDR3_SDRAM_TYPE_NUMBER:
265         TableSelect = (SPD_OFFSET_TABLE *) SpdLpddrTable;
266         Stop = (SpdLpddrTableSize / sizeof (SPD_OFFSET_TABLE));
267         break;
268     }
269     for (Byte = 0; (EFI_SUCCESS == Status) && (Byte < Stop); Byte++) {
270       Tbl = &TableSelect[Byte];
271       if ((1 << BootMode) & Tbl->BootMode) {
272         Status = InternalDoSpdRead (Address, &Buffer[Tbl->Start], Tbl->Start, Tbl->End - Tbl->Start + 1, &Page);
273         if (Status == EFI_SUCCESS) {
274           if (SpdCold == BootMode) {
275             if (FALSE == InternalVerifyXmp ((MrcSpd *) Buffer, Tbl->Start)) {
276               break;
277             }
278           }
279         } else {
280           break;
281         }
282       }
283     }
284   }
285 
286   return ((EFI_SUCCESS == Status) ? TRUE : FALSE);
287 }
288 
289 /**
290   Initialize the Smbus PPI and program the Smbus BAR
291 
292   @retval EFI_SUCCESS             The function completes successfully
293   @retval EFI_OUT_OF_RESOURCES    Insufficient resources to create database
294 **/
295 EFI_STATUS
InternalInitializePchSmbus(VOID)296 InternalInitializePchSmbus (
297   VOID
298   )
299 {
300   UINTN          SmbusRegBase;
301   SmbusRegBase = MmPciBase (
302                    DEFAULT_PCI_BUS_NUMBER_PCH,
303                    PCI_DEVICE_NUMBER_PCH_SMBUS,
304                    PCI_FUNCTION_NUMBER_PCH_SMBUS
305                    );
306 
307   ///
308   /// Since PEI has no PCI enumerator, set the BAR & I/O space enable ourselves
309   ///
310   MmioAndThenOr32 (SmbusRegBase + R_PCH_SMBUS_BASE, B_PCH_SMBUS_BASE_BAR, PcdGet16 (PcdSmbusBaseAddress));
311 
312   MmioOr8 (SmbusRegBase + PCI_COMMAND_OFFSET, EFI_PCI_COMMAND_IO_SPACE);
313 
314   ///
315   /// Reset the SMBus host controller
316   ///
317   MmioOr8 (SmbusRegBase + R_PCH_SMBUS_HOSTC, B_PCH_SMBUS_HOSTC_SSRESET);
318 
319   ///
320   /// Enable the SMBus host controller
321   ///
322   MmioAndThenOr8 (
323     SmbusRegBase + R_PCH_SMBUS_HOSTC,
324     (UINT8)(~(B_PCH_SMBUS_HOSTC_SMI_EN | B_PCH_SMBUS_HOSTC_I2C_EN)),
325     B_PCH_SMBUS_HOSTC_HST_EN
326     );
327 
328   ///
329   /// Clear Status Register before anyone uses the interfaces
330   ///
331   IoWrite8 (PcdGet16(PcdSmbusBaseAddress) + R_PCH_SMBUS_HSTS, B_PCH_SMBUS_HSTS_ALL);
332 
333   return EFI_SUCCESS;
334 }
335 
336 /**
337   Update Spd Data
338 
339   @param[in][out] FspmUpd              Pointer to FSP UPD Data.
340   @param[in]      MemConfigNoCrc       Pointer to Mem Config No Crc.
341   @param[in]      MiscPeiPreMemConfig  Pointer to Misc Config.
342 
343   @retval         EFI_SUCCESS          The function completes successfully
344   @retval         Other                The function fail
345 **/
346 VOID
347 EFIAPI
InternalUpdateSpdData(IN OUT FSPM_UPD * FspmUpd,IN MEMORY_CONFIG_NO_CRC * MemConfigNoCrc,IN SA_MISC_PEI_PREMEM_CONFIG * MiscPeiPreMemConfig)348 InternalUpdateSpdData (
349   IN OUT FSPM_UPD               *FspmUpd,
350   IN MEMORY_CONFIG_NO_CRC       *MemConfigNoCrc,
351   IN SA_MISC_PEI_PREMEM_CONFIG  *MiscPeiPreMemConfig
352   )
353 {
354   UINT8                     Socket;
355   UINT8                     *SpdData;
356 
357   InternalInitializePchSmbus ();
358 
359   DEBUG ((DEBUG_INFO, "Updating UPD:Memory Spd Pointers...\n"));
360   if (FspmUpd == NULL || MemConfigNoCrc == NULL) {
361     DEBUG ((DEBUG_ERROR, "EFI_INVALID_PARAMETER.\n"));
362     DEBUG ((DEBUG_ERROR, "Fail to access SPD from SiPolicyPpi\n"));
363     return;
364   }
365 
366   if (*((UINT32 *)MiscPeiPreMemConfig->SpdAddressTable) != 0x0) {
367     //
368     // Update MemConfigNoCrc->SpdData->SpdData
369     //
370     for (Socket = 0; Socket < SA_MC_MAX_SOCKETS; Socket++) {
371       SpdData = (UINT8 *)((UINT32)MemConfigNoCrc->SpdData->SpdData + (Socket * SA_MC_MAX_SPD_SIZE));
372       InternalGetSpdData (
373         0,
374         MiscPeiPreMemConfig->SpdAddressTable[Socket],
375         (UINT8 *)SpdData,
376         (UINT8 *)&mSpdDdr3Table,
377         sizeof(mSpdDdr3Table),
378         (UINT8 *)&mSpdDdr4Table,
379         sizeof(mSpdDdr4Table),
380         (UINT8 *)&mSpdLpddrTable,
381         sizeof(mSpdLpddrTable)
382         );
383     }
384   }
385 
386   FspmUpd->FspmConfig.MemorySpdPtr00 = (UINT32)MemConfigNoCrc->SpdData->SpdData;
387   FspmUpd->FspmConfig.MemorySpdPtr01 = (UINT32)MemConfigNoCrc->SpdData->SpdData + (1 * SA_MC_MAX_SPD_SIZE);
388   FspmUpd->FspmConfig.MemorySpdPtr10 = (UINT32)MemConfigNoCrc->SpdData->SpdData + (2 * SA_MC_MAX_SPD_SIZE);
389   FspmUpd->FspmConfig.MemorySpdPtr11 = (UINT32)MemConfigNoCrc->SpdData->SpdData + (3 * SA_MC_MAX_SPD_SIZE);
390 
391   DEBUG ((DEBUG_INFO, "UPD:MemorySpdPtr Updated\n"));
392 }
393 
394 /**
395   Performs FSP SA PEI Policy initialization in pre-memory.
396 
397   @param[in][out]  FspmUpd             Pointer to FSP UPD Data.
398 
399   @retval          EFI_SUCCESS         FSP UPD Data is updated.
400   @retval          EFI_NOT_FOUND       Fail to locate required PPI.
401   @retval          Other               FSP UPD Data update process fail.
402 **/
403 EFI_STATUS
404 EFIAPI
PeiFspSaPolicyInitPreMem(IN OUT FSPM_UPD * FspmUpd)405 PeiFspSaPolicyInitPreMem (
406   IN OUT FSPM_UPD    *FspmUpd
407   )
408 {
409   EFI_STATUS                  Status;
410   SA_MISC_PEI_PREMEM_CONFIG   *MiscPeiPreMemConfig;
411   MEMORY_CONFIGURATION        *MemConfig;
412   MEMORY_CONFIG_NO_CRC        *MemConfigNoCrc;
413   SI_PREMEM_POLICY_PPI        *SiPreMemPolicyPpi;
414 
415   //
416   // Locate SiPreMemPolicyPpi
417   //
418   SiPreMemPolicyPpi = NULL;
419   MiscPeiPreMemConfig = NULL;
420   MemConfig = NULL;
421   MemConfigNoCrc = NULL;
422 
423 
424   Status = PeiServicesLocatePpi(
425              &gSiPreMemPolicyPpiGuid,
426              0,
427              NULL,
428              (VOID **) &SiPreMemPolicyPpi
429              );
430   ASSERT_EFI_ERROR (Status);
431   if (EFI_ERROR (Status) == FALSE) {
432     Status = GetConfigBlock ((VOID *) SiPreMemPolicyPpi, &gSaMiscPeiPreMemConfigGuid, (VOID *) &MiscPeiPreMemConfig);
433     ASSERT_EFI_ERROR (Status);
434     Status = GetConfigBlock ((VOID *) SiPreMemPolicyPpi, &gMemoryConfigNoCrcGuid, (VOID *) &MemConfigNoCrc);
435     ASSERT_EFI_ERROR (Status);
436     Status = GetConfigBlock ((VOID *) SiPreMemPolicyPpi, &gMemoryConfigGuid, (VOID *) &MemConfig);
437     ASSERT_EFI_ERROR (Status);
438  }
439 
440   //
441   // Update UPD:DqPinsInterleaved
442   //
443   FspmUpd->FspmConfig.DqPinsInterleaved = (UINT8)MemConfig->DqPinsInterleaved;
444 
445   //
446   // Update UPD:DqPinsInterleaved
447   //
448   FspmUpd->FspmConfig.CaVrefConfig  = MemConfig->CaVrefConfig;
449 
450   //
451   // Update UPD:MemorySpdPtrXX
452   //
453   InternalUpdateSpdData (FspmUpd, MemConfigNoCrc, MiscPeiPreMemConfig);
454 
455   //
456   // Update UPD:MemorySpdDataLen
457   //
458   FspmUpd->FspmConfig.MemorySpdDataLen = SA_MC_MAX_SPD_SIZE;
459 
460   //
461   // Update UPD:PlatformMemorySize
462   //
463   //
464   // @todo: This value is used since #183932. Revisit.
465   //
466   FspmUpd->FspmConfig.PlatformMemorySize = MemConfigNoCrc->PlatformMemorySize;
467   FspmUpd->FspmConfig.SaGv = MemConfig->SaGv;
468   FspmUpd->FspmConfig.RMT = (UINT8) MemConfig->RMT;
469   FspmUpd->FspmConfig.DdrFreqLimit = MemConfig->DdrFreqLimit;
470 
471   FspmUpd->FspmConfig.SpdProfileSelected = MemConfig->SpdProfileSelected;
472   FspmUpd->FspmConfig.VddVoltage         = MemConfig->VddVoltage;
473   FspmUpd->FspmConfig.RefClk             = MemConfig->RefClk;
474   FspmUpd->FspmConfig.Ratio              = MemConfig->Ratio;
475   FspmUpd->FspmConfig.OddRatioMode       = (UINT8) MemConfig->OddRatioMode;
476   FspmUpd->FspmConfig.tCL                = (UINT8) MemConfig->tCL;
477   FspmUpd->FspmConfig.tCWL               = (UINT8) MemConfig->tCWL;
478   FspmUpd->FspmConfig.tFAW               = MemConfig->tFAW;
479   FspmUpd->FspmConfig.tRAS               = MemConfig->tRAS;
480   FspmUpd->FspmConfig.tRCDtRP            = (UINT8) MemConfig->tRCDtRP;
481   FspmUpd->FspmConfig.tREFI              = MemConfig->tREFI;
482   FspmUpd->FspmConfig.tRFC               = MemConfig->tRFC;
483   FspmUpd->FspmConfig.tRRD               = (UINT8) MemConfig->tRRD;
484   FspmUpd->FspmConfig.tRTP               = (UINT8) MemConfig->tRTP;
485   FspmUpd->FspmConfig.tWR                = (UINT8) MemConfig->tWR;
486   FspmUpd->FspmConfig.tWTR               = (UINT8) MemConfig->tWTR;
487   FspmUpd->FspmConfig.NModeSupport       = MemConfig->NModeSupport;
488   FspmUpd->FspmConfig.DllBwEn0           = MemConfig->DllBwEn0;
489   FspmUpd->FspmConfig.DllBwEn1           = MemConfig->DllBwEn1;
490   FspmUpd->FspmConfig.DllBwEn2           = MemConfig->DllBwEn2;
491   FspmUpd->FspmConfig.DllBwEn3           = MemConfig->DllBwEn3;
492   FspmUpd->FspmConfig.EvLoader           = (UINT8) MemConfig->EvLoader;
493 
494   //
495   // Update UPD:SmramMask
496   //
497   if (MemConfig != NULL) {
498     FspmUpd->FspmConfig.SmramMask = MemConfig->SmramMask;
499   }
500 
501   return EFI_SUCCESS;
502 }
503 
504 /**
505   Performs FSP SA PEI Policy initialization.
506 
507   @param[in][out]  FspsUpd             Pointer to FSP UPD Data.
508 
509   @retval          EFI_SUCCESS         FSP UPD Data is updated.
510   @retval          EFI_NOT_FOUND       Fail to locate required PPI.
511   @retval          Other               FSP UPD Data update process fail.
512 **/
513 EFI_STATUS
514 EFIAPI
PeiFspSaPolicyInit(IN OUT FSPS_UPD * FspsUpd)515 PeiFspSaPolicyInit (
516   IN OUT FSPS_UPD    *FspsUpd
517   )
518 {
519   EFI_STATUS                Status;
520   SI_POLICY_PPI             *SiPolicyPpi;
521   GRAPHICS_PEI_CONFIG       *GtConfig;
522   VTD_CONFIG                *Vtd;
523   //
524   // Locate SiPolicyPpi
525   //
526   SiPolicyPpi = NULL;
527   Status = PeiServicesLocatePpi(
528              &gSiPolicyPpiGuid,
529              0,
530              NULL,
531              (VOID **)&SiPolicyPpi
532              );
533   if ((Status == EFI_SUCCESS) && (SiPolicyPpi != NULL)) {
534     GtConfig = NULL;
535     Status = GetConfigBlock ((VOID *) SiPolicyPpi, &gGraphicsPeiConfigGuid, (VOID *) &GtConfig);
536     ASSERT_EFI_ERROR (Status);
537 
538     Vtd = NULL;
539     Status = GetConfigBlock ((VOID *) SiPolicyPpi, &gVtdConfigGuid, (VOID *) &Vtd);
540     ASSERT_EFI_ERROR (Status);
541 
542   }
543 
544   DEBUG ((DEBUG_INFO | DEBUG_INIT, "FSP UpdatePeiSaPolicy\n"));
545   if (GtConfig != NULL) {
546     //
547     // For FSP, FspsUpd->FspsConfig.PeiGraphicsPeimInit is always enabled as default.
548     //
549     FspsUpd->FspsConfig.PeiGraphicsPeimInit = (UINT8) GtConfig->PeiGraphicsPeimInit; // SA: InternalOnly: For Internal validation we still need to enable both Enable/Disable Cases
550 
551     //
552     // Update UPD: VBT & LogoPtr
553     //
554     FspsUpd->FspsConfig.GraphicsConfigPtr = (UINT32) GtConfig->GraphicsConfigPtr;
555     DEBUG(( DEBUG_INFO, "VbtPtr from GraphicsPeiConfig is 0x%x\n", FspsUpd->FspsConfig.GraphicsConfigPtr));
556 
557     FspsUpd->FspsConfig.LogoPtr  = (UINT32) GtConfig->LogoPtr;
558     FspsUpd->FspsConfig.LogoSize = GtConfig->LogoSize;
559     DEBUG(( DEBUG_INFO, "LogoPtr from PeiFspSaPolicyInit GraphicsPeiConfig is 0x%x\n", FspsUpd->FspsConfig.LogoPtr));
560     DEBUG(( DEBUG_INFO, "LogoSize from PeiFspSaPolicyInit GraphicsPeiConfig is 0x%x\n", FspsUpd->FspsConfig.LogoSize));
561 
562 
563 
564   }
565   if (Vtd != NULL) {
566     FspsUpd->FspsConfig.X2ApicOptOut = (UINT8) Vtd->X2ApicOptOut;
567     FspsUpd->FspsConfig.VtdBaseAddress[0] = Vtd->BaseAddress[0];
568     FspsUpd->FspsConfig.VtdBaseAddress[1] = Vtd->BaseAddress[1];
569     FspsUpd->FspsTestConfig.VtdDisable = (UINT8) Vtd->VtdDisable;
570   }
571   return EFI_SUCCESS;
572 }
573