• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /** @file
2 QuarkNcSocId module initialization module
3 
4 Copyright (c) 2013-2015 Intel Corporation.
5 
6 This program and the accompanying materials
7 are licensed and made available under the terms and conditions of the BSD License
8 which accompanies this distribution.  The full text of the license may be found at
9 http://opensource.org/licenses/bsd-license.php
10 
11 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
12 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
13 
14 **/
15 #include "CommonHeader.h"
16 
17 #include "LegacyRegion.h"
18 #include "DxeQNCSmbus.h"
19 
20 #include "QNCInit.h"
21 
22 //
23 // Definitions
24 //
25 #define QNC_RESERVED_ITEM_IO         0
26 #define QNC_RESERVED_ITEM_MEMORYIO   1
27 #define DXE_DEVICE_DISABLED 0
28 #define DXE_DEVICE_ENABLED 1
29 
30 typedef struct _QNC_SPACE_TABLE_ITEM {
31    UINTN                   IoOrMemory;
32    UINTN                   Type;
33    EFI_PHYSICAL_ADDRESS    BaseAddress;
34    UINT64                  Length;
35    UINTN                   Alignment;
36    BOOLEAN                 RuntimeOrNot;
37 } QNC_SPACE_TABLE_ITEM;
38 
39 typedef struct {
40   ACPI_CPU_DATA       AcpuCpuData;
41   MTRR_SETTINGS       MtrrTable;
42   IA32_DESCRIPTOR     GdtrProfile;
43   IA32_DESCRIPTOR     IdtrProfile;
44   CPU_REGISTER_TABLE  RegisterTable;
45   CPU_REGISTER_TABLE  PreSmmInitRegisterTable;
46 } ACPI_CPU_DATA_EX;
47 
48 //
49 // Spaces to be reserved in GCD
50 // Expand it to add more
51 //
52 const QNC_SPACE_TABLE_ITEM  mQNCReservedSpaceTable[] = {
53   {
54     QNC_RESERVED_ITEM_MEMORYIO,
55     EfiGcdMemoryTypeMemoryMappedIo,
56     FixedPcdGet64 (PcdIoApicBaseAddress),
57     FixedPcdGet64 (PcdIoApicSize),
58     0,
59     FALSE
60   },
61   {
62     QNC_RESERVED_ITEM_MEMORYIO,
63     EfiGcdMemoryTypeMemoryMappedIo,
64     FixedPcdGet64 (PcdHpetBaseAddress),
65     FixedPcdGet64 (PcdHpetSize),
66     0,
67     FALSE
68   }
69 };
70 
71 //
72 // Global variable for ImageHandle of QNCInit driver
73 //
74 EFI_HANDLE gQNCInitImageHandle;
75 QNC_DEVICE_ENABLES    mQNCDeviceEnables;
76 
77 
78 VOID
79 QNCInitializeResource (
80   VOID
81   );
82 
83 EFI_STATUS
84 InitializeQNCPolicy (
85   VOID
86   );
87 
88 /**
89   Allocate EfiACPIMemoryNVS below 4G memory address.
90 
91   This function allocates EfiACPIMemoryNVS below 4G memory address.
92 
93   @param Size   Size of memory to allocate.
94 
95   @return       Allocated address for output.
96 
97 **/
98 VOID *
AllocateAcpiNvsMemoryBelow4G(IN UINTN Size)99 AllocateAcpiNvsMemoryBelow4G (
100   IN UINTN  Size
101   )
102 {
103   UINTN                 Pages;
104   EFI_PHYSICAL_ADDRESS  Address;
105   EFI_STATUS            Status;
106   VOID*                 Buffer;
107 
108   Pages = EFI_SIZE_TO_PAGES (Size);
109   Address = 0xffffffff;
110 
111   Status  = gBS->AllocatePages (
112                    AllocateMaxAddress,
113                    EfiACPIMemoryNVS,
114                    Pages,
115                    &Address
116                    );
117   if (EFI_ERROR (Status)) {
118     return NULL;
119   }
120 
121   Buffer = (VOID *) (UINTN) Address;
122   ZeroMem (Buffer, Size);
123 
124   return Buffer;
125 }
126 
127 /**
128   Prepare ACPI NVS memory below 4G memory for use of S3 resume.
129 
130   This function allocates ACPI NVS memory below 4G memory for use of S3 resume,
131   and saves data into the memory region.
132 
133 **/
134 VOID
SaveCpuS3Data(VOID)135 SaveCpuS3Data (
136   VOID
137   )
138 {
139   EFI_STATUS        Status;
140   ACPI_CPU_DATA_EX  *AcpiCpuDataEx;
141   ACPI_CPU_DATA     *AcpiCpuData;
142   UINTN             GdtSize;
143   UINTN             IdtSize;
144   VOID              *Gdt;
145   VOID              *Idt;
146 
147   //
148   // Allocate ACPI NVS memory below 4G memory for use of S3 resume.
149   //
150   AcpiCpuDataEx = AllocateAcpiNvsMemoryBelow4G (sizeof (ACPI_CPU_DATA_EX));
151   AcpiCpuData = &AcpiCpuDataEx->AcpuCpuData;
152 
153   //
154   //
155   //
156   AcpiCpuData->NumberOfCpus              = 1;
157   AcpiCpuData->StackSize                 = PcdGet32 (PcdCpuApStackSize);
158   AcpiCpuData->ApMachineCheckHandlerBase = 0;
159   AcpiCpuData->ApMachineCheckHandlerSize = 0;
160   AcpiCpuData->GdtrProfile               = (EFI_PHYSICAL_ADDRESS) (UINTN) &AcpiCpuDataEx->GdtrProfile;
161   AcpiCpuData->IdtrProfile               = (EFI_PHYSICAL_ADDRESS) (UINTN) &AcpiCpuDataEx->IdtrProfile;
162   AcpiCpuData->MtrrTable                 = (EFI_PHYSICAL_ADDRESS) (UINTN) &AcpiCpuDataEx->MtrrTable;
163   AcpiCpuData->RegisterTable             = (EFI_PHYSICAL_ADDRESS) (UINTN) &AcpiCpuDataEx->RegisterTable;
164   AcpiCpuData->PreSmmInitRegisterTable   = (EFI_PHYSICAL_ADDRESS) (UINTN) &AcpiCpuDataEx->PreSmmInitRegisterTable;
165 
166   //
167   // Allocate stack space for all CPUs
168   //
169   AcpiCpuData->StackAddress = (EFI_PHYSICAL_ADDRESS) (UINTN) AllocateAcpiNvsMemoryBelow4G (AcpiCpuData->NumberOfCpus * AcpiCpuData->StackSize);
170 
171   //
172   // Get MTRR settings from currently executing CPU
173   //
174   MtrrGetAllMtrrs (&AcpiCpuDataEx->MtrrTable);
175 
176   //
177   // Get the BSP's data of GDT and IDT
178   //
179   AsmReadGdtr ((IA32_DESCRIPTOR *) &AcpiCpuDataEx->GdtrProfile);
180   AsmReadIdtr ((IA32_DESCRIPTOR *) &AcpiCpuDataEx->IdtrProfile);
181 
182   //
183   // Allocate GDT and IDT in ACPI NVS and copy in current GDT and IDT contents
184   //
185   GdtSize = AcpiCpuDataEx->GdtrProfile.Limit + 1;
186   IdtSize = AcpiCpuDataEx->IdtrProfile.Limit + 1;
187   Gdt = AllocateAcpiNvsMemoryBelow4G (GdtSize + IdtSize);
188   Idt = (VOID *)((UINTN)Gdt + GdtSize);
189   CopyMem (Gdt, (VOID *)AcpiCpuDataEx->GdtrProfile.Base, GdtSize);
190   CopyMem (Idt, (VOID *)AcpiCpuDataEx->IdtrProfile.Base, IdtSize);
191   AcpiCpuDataEx->GdtrProfile.Base = (UINTN)Gdt;
192   AcpiCpuDataEx->IdtrProfile.Base = (UINTN)Idt;
193 
194   //
195   // No RegisterTable entries
196   //
197   AcpiCpuDataEx->RegisterTable.TableLength = 0;
198 
199   //
200   // No PreSmmInitRegisterTable entries
201   //
202   AcpiCpuDataEx->PreSmmInitRegisterTable.TableLength = 0;
203 
204   //
205   // Set the base address of CPU S3 data to PcdCpuS3DataAddress
206   //
207   Status = PcdSet64S (PcdCpuS3DataAddress, (UINT64)(UINTN)AcpiCpuData);
208   ASSERT_EFI_ERROR (Status);
209 }
210 
211 /**
212    The entry function for QNCInit driver.
213 
214    This function just call initialization function for PciHostBridge,
215    LegacyRegion and QNCSmmAccess module.
216 
217    @param ImageHandle   The driver image handle for GmchInit driver
218    @param SystemTable   The pointer to System Table
219 
220    @retval EFI_SUCCESS  Success to initialize every module for GMCH driver.
221    @return EFI_STATUS   The status of initialization work.
222 
223 **/
224 EFI_STATUS
225 EFIAPI
QNCInit(IN EFI_HANDLE ImageHandle,IN EFI_SYSTEM_TABLE * SystemTable)226 QNCInit (
227   IN EFI_HANDLE         ImageHandle,
228   IN EFI_SYSTEM_TABLE   *SystemTable
229   )
230 {
231   EFI_STATUS  Status;
232 
233   S3BootScriptSaveInformationAsciiString (
234     "QNCInitDxeEntryBegin"
235     );
236 
237   gQNCInitImageHandle = ImageHandle;
238 
239   mQNCDeviceEnables.Uint32 = PcdGet32 (PcdDeviceEnables);
240 
241 
242   //
243   // Initialize PCIE root ports
244   //
245   Status = QncInitRootPorts ();
246   if (EFI_ERROR (Status)) {
247     DEBUG ((EFI_D_ERROR, "QNC Root Port initialization is failed!\n"));
248     return Status;
249   }
250 
251   Status = LegacyRegionInit ();
252   if (EFI_ERROR (Status)) {
253     DEBUG ((EFI_D_ERROR, "QNC LegacyRegion initialization is failed!\n"));
254     return Status;
255   }
256 
257 
258   Status = InitializeQNCPolicy ();
259   if (EFI_ERROR (Status)) {
260     DEBUG ((EFI_D_ERROR, "QNC Policy initialization is failed!\n"));
261     return Status;
262   }
263 
264   Status = InitializeQNCSmbus (ImageHandle,SystemTable);
265   if (EFI_ERROR (Status)) {
266     DEBUG ((EFI_D_ERROR, "QNC Smbus driver is failed!\n"));
267     return Status;
268   }
269 
270   QNCInitializeResource ();
271 
272   SaveCpuS3Data ();
273 
274   S3BootScriptSaveInformationAsciiString (
275     "QNCInitDxeEntryEnd"
276     );
277 
278   return EFI_SUCCESS;
279 }
280 
281 
282 /**
283   Reserve I/O or memory space in GCD
284 
285   @param  IoOrMemory    Switch of I/O or memory.
286   @param  GcdType       Type of the space.
287   @param  BaseAddress   Base address of the space.
288   @param  Length        Length of the space.
289   @param  Alignment     Align with 2^Alignment
290   @param  RuntimeOrNot  For runtime usage or not
291   @param  ImageHandle   Handle for the image of this driver.
292 
293   @retval EFI_SUCCESS   Reserve successful
294 **/
295 EFI_STATUS
QNCReserveSpaceInGcd(IN UINTN IoOrMemory,IN UINTN GcdType,IN EFI_PHYSICAL_ADDRESS BaseAddress,IN UINT64 Length,IN UINTN Alignment,IN BOOLEAN RuntimeOrNot,IN EFI_HANDLE ImageHandle)296 QNCReserveSpaceInGcd(
297   IN UINTN                 IoOrMemory,
298   IN UINTN                 GcdType,
299   IN EFI_PHYSICAL_ADDRESS  BaseAddress,
300   IN UINT64                Length,
301   IN UINTN                 Alignment,
302   IN BOOLEAN               RuntimeOrNot,
303   IN EFI_HANDLE            ImageHandle
304   )
305 {
306   EFI_STATUS               Status;
307 
308   if (IoOrMemory == QNC_RESERVED_ITEM_MEMORYIO) {
309     Status = gDS->AddMemorySpace (
310                     GcdType,
311                     BaseAddress,
312                     Length,
313                     EFI_MEMORY_UC
314                     );
315     if (EFI_ERROR (Status)) {
316       DEBUG ((
317         EFI_D_ERROR,
318         "Failed to add memory space :0x%x 0x%x\n",
319         BaseAddress,
320         Length
321         ));
322     }
323     ASSERT_EFI_ERROR (Status);
324     Status = gDS->AllocateMemorySpace (
325                     EfiGcdAllocateAddress,
326                     GcdType,
327                     Alignment,
328                     Length,
329                     &BaseAddress,
330                     ImageHandle,
331                     NULL
332                     );
333     ASSERT_EFI_ERROR (Status);
334     if (RuntimeOrNot) {
335       Status = gDS->SetMemorySpaceAttributes (
336                       BaseAddress,
337                       Length,
338                       EFI_MEMORY_RUNTIME | EFI_MEMORY_UC
339                      );
340       ASSERT_EFI_ERROR (Status);
341     }
342   } else {
343     Status = gDS->AddIoSpace (
344                     GcdType,
345                     BaseAddress,
346                     Length
347                     );
348     ASSERT_EFI_ERROR (Status);
349     Status = gDS->AllocateIoSpace (
350                     EfiGcdAllocateAddress,
351                     GcdType,
352                     Alignment,
353                     Length,
354                     &BaseAddress,
355                     ImageHandle,
356                     NULL
357                     );
358     ASSERT_EFI_ERROR (Status);
359   }
360   return Status;
361 }
362 
363 
364 /**
365   Initialize the memory and io resource which belong to QNC.
366   1) Report and allocate all BAR's memory to GCD.
367   2) Report PCI memory and I/O space to GCD.
368   3) Set memory attribute for <1M memory space.
369 **/
370 VOID
QNCInitializeResource()371 QNCInitializeResource (
372   )
373 {
374   EFI_PHYSICAL_ADDRESS            BaseAddress;
375   EFI_STATUS                      Status;
376   UINT64                          ExtraRegionLength;
377   EFI_GCD_MEMORY_SPACE_DESCRIPTOR Descriptor;
378   UINTN                           Index;
379 
380   // Report TSEG range
381   // This range maybe has been reportted in PEI phase via Resource Hob.
382   //
383   QNCGetTSEGMemoryRange (&BaseAddress, &ExtraRegionLength);
384   if (ExtraRegionLength != 0) {
385     Status = gDS->GetMemorySpaceDescriptor (BaseAddress, &Descriptor);
386     if (Status == EFI_NOT_FOUND) {
387       Status = gDS->AddMemorySpace (
388                       EfiGcdMemoryTypeReserved,
389                       BaseAddress,
390                       ExtraRegionLength,
391                       EFI_MEMORY_UC
392                       );
393     }
394   }
395 
396   //
397   // < 1M resource setting. The memory ranges <1M has been added into GCD via
398   // resource hob produced by PEI phase. Here will set memory attribute of these
399   // ranges for DXE phase.
400   //
401 
402   //
403   // Dos Area (0 ~ 0x9FFFFh)
404   //
405   Status = gDS->GetMemorySpaceDescriptor (0, &Descriptor);
406   DEBUG ((
407     EFI_D_INFO,
408     "DOS Area Memory: base = 0x%x, length = 0x%x, attribute = 0x%x\n",
409     Descriptor.BaseAddress,
410     Descriptor.Length,
411     Descriptor.Attributes
412     ));
413   ASSERT_EFI_ERROR (Status);
414   Status = gDS->SetMemorySpaceAttributes(
415                   0,
416                   0xA0000,
417                   EFI_MEMORY_WB
418                   );
419   ASSERT_EFI_ERROR (Status);
420 
421   //
422   // Default SMRAM UnCachable until SMBASE relocated.
423   //
424   Status = gDS->SetMemorySpaceAttributes(
425                   0x30000,
426                   0x10000,
427                   EFI_MEMORY_UC
428                   );
429   ASSERT_EFI_ERROR (Status);
430 
431   //
432   // Default SMM ABSEG area. (0xA0000 ~ 0xBFFFF)
433   //
434   Status = gDS->GetMemorySpaceDescriptor (0xA0000, &Descriptor);
435   DEBUG ((
436     EFI_D_INFO,
437     "ABSEG Memory: base = 0x%x, length = 0x%x, attribute = 0x%x\n",
438     Descriptor.BaseAddress,
439     Descriptor.Length,
440     Descriptor.Attributes
441     ));
442   ASSERT_EFI_ERROR (Status);
443   Status = gDS->SetMemorySpaceAttributes(
444                   0xA0000,
445                   0x20000,
446                   EFI_MEMORY_UC
447                   );
448   ASSERT_EFI_ERROR (Status);
449 
450   //
451   // Expansion BIOS area.
452   //
453   Status = gDS->GetMemorySpaceDescriptor (0xC0000, &Descriptor);
454   DEBUG ((
455     EFI_D_INFO,
456     "Memory base = 0x%x, length = 0x%x, attribute = 0x%x\n",
457     Descriptor.BaseAddress,
458     Descriptor.Length,
459     Descriptor.Attributes
460     ));
461   ASSERT_EFI_ERROR (Status);
462   Status = gDS->SetMemorySpaceAttributes(
463                   0xC0000,
464                   0x30000,
465                   EFI_MEMORY_UC
466                   );
467   ASSERT_EFI_ERROR (Status);
468 
469   //
470   // Report other IO resources from mQNCReservedSpaceTable in GCD
471   //
472   for (Index = 0; Index < sizeof (mQNCReservedSpaceTable) / sizeof (QNC_SPACE_TABLE_ITEM); Index++) {
473     Status = QNCReserveSpaceInGcd (
474                mQNCReservedSpaceTable[Index].IoOrMemory,
475                mQNCReservedSpaceTable[Index].Type,
476                mQNCReservedSpaceTable[Index].BaseAddress,
477                mQNCReservedSpaceTable[Index].Length,
478                mQNCReservedSpaceTable[Index].Alignment,
479                mQNCReservedSpaceTable[Index].RuntimeOrNot,
480                gQNCInitImageHandle
481                );
482     ASSERT_EFI_ERROR (Status);
483   }
484 
485   //
486   // Report unused PCIe config space as reserved.
487   //
488   if (PcdGet64 (PcdPciExpressSize) < SIZE_256MB) {
489     Status = QNCReserveSpaceInGcd (
490                QNC_RESERVED_ITEM_MEMORYIO,
491                EfiGcdMemoryTypeMemoryMappedIo,
492                (PcdGet64(PcdPciExpressBaseAddress) + PcdGet64(PcdPciExpressSize)),
493                (SIZE_256MB - PcdGet64(PcdPciExpressSize)),
494                0,
495                FALSE,
496                gQNCInitImageHandle
497                );
498     ASSERT_EFI_ERROR (Status);
499   }
500 }
501 
502 /**
503   Use the platform PCD to initialize devices in the QNC
504 
505   @param  ImageHandle   Handle for the image of this driver.
506   @retval EFI_SUCCESS   Initialize successful
507 **/
508 EFI_STATUS
InitializeQNCPolicy()509 InitializeQNCPolicy (
510   )
511 {
512   UINT8        RevisionID;
513   UINT32       PciD31F0RegBase;  // LPC
514 
515   RevisionID = LpcPciCfg8(R_QNC_LPC_REV_ID);
516 
517   PciD31F0RegBase = PciDeviceMmBase (PCI_BUS_NUMBER_QNC, PCI_DEVICE_NUMBER_QNC_LPC, PCI_FUNCTION_NUMBER_QNC_LPC);
518 
519   //
520   // Disable for smbus
521   //
522   if (mQNCDeviceEnables.Bits.Smbus == DXE_DEVICE_DISABLED) {
523     S3MmioAnd32 (PciD31F0RegBase + R_QNC_LPC_SMBUS_BASE, (~B_QNC_LPC_SMBUS_BASE_EN));
524   }
525 
526   return EFI_SUCCESS;
527 }
528