1 /** @file
2 
3   Copyright (c) 2004  - 2014, Intel Corporation. All rights reserved.<BR>
4 
5 
6   This program and the accompanying materials are licensed and made available under
7 
8   the terms and conditions of the BSD License that accompanies this distribution.
9 
10   The full text of the license may be found at
11 
12   http://opensource.org/licenses/bsd-license.php.
13 
14 
15 
16   THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
17 
18   WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
19 
20 
21 
22 
23 
24 Module Name:
25 
26     IchS3Save.c
27 
28 Abstract:
29 
30     SMM S3 handler Driver implementation file
31 
InitRuntimeScriptTable(IN EFI_SYSTEM_TABLE * SystemTable)32 Revision History
33 
34 **/
35 #include "SmmPlatform.h"
36 
37 extern  UINT16                          mAcpiBaseAddr;
38 EFI_PHYSICAL_ADDRESS                    mRuntimeScriptTableBase;
39 
40 EFI_STATUS
41 InitRuntimeScriptTable (
42   IN EFI_SYSTEM_TABLE  *SystemTable
43   )
44 {
45   EFI_STATUS        Status;
46   UINT32            VarAttrib;
47   UINTN             VarSize;
48   ACPI_VARIABLE_SET_COMPATIBILITY *AcpiVariableBase;
49 
50   //
51   // Allocate runtime ACPI script table space. We need it to save some
52   // settings done by CSM, which runs after normal script table closed
53   //
54   Status = gBS->AllocatePages (
55                   AllocateAnyPages,
56                   EfiACPIReclaimMemory,
57                   1,
58                   &mRuntimeScriptTableBase
59                   );
60   if (EFI_ERROR(Status)) {
61     return EFI_OUT_OF_RESOURCES ;
62   }
63 
64   //
65   // Save runtime script table base into global ACPI variable
66   //
67   VarAttrib = EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS
68               | EFI_VARIABLE_NON_VOLATILE;
69   VarSize   = sizeof (UINTN);
70   Status = SystemTable->RuntimeServices->GetVariable (
71                           ACPI_GLOBAL_VARIABLE,
72                           &gEfiAcpiVariableCompatiblityGuid,
73                           &VarAttrib,
74                           &VarSize,
75                           &AcpiVariableBase
76                           );
77   if (EFI_ERROR(Status)) {
SaveRuntimeScriptTable(VOID)78     return Status;
79   }
80 
81   AcpiVariableBase->RuntimeScriptTableBase = mRuntimeScriptTableBase;
82 
83   return EFI_SUCCESS;
84 }
85 
86 EFI_STATUS
87 SaveRuntimeScriptTable (
88   VOID
89   )
90 {
91   SMM_PCI_IO_ADDRESS    PciAddress;
92   UINT32                Data32;
93   UINT16                Data16;
94   UINT8                 Data8;
95   UINT8                 Mask;
96   UINTN                 Index;
97   UINTN                 Offset;
98   UINT8                 RegTable[] = {
99 
100 	  //
101     //Bus  ,   Dev,  Func,    DMI
102 	  //
103       0x00 ,  0x00,  0x00,
104 
105 	  //
106     //00-1F, 20-3F, 40-5F, 60-7F, 80-9F, A0-BF, C0-DF, E0-FF
107 	  //
108       0x00 ,  0x08,  0x00,  0x00,  0x30,  0x00,  0x00,  0xa0,
109 
110 	  //
111     //Bus  ,   Dev,  Func,    LPC device
112 	  //
113       0x00 ,  0x1F,  0x00,
114 
115 	  //
116     //00-1F, 20-3F, 40-5F, 60-7F, 80-9F, A0-BF, C0-DF, E0-FF
117     //
118       0x00 ,  0x08,  0x00,  0x07,  0x00,  0x00,  0x90,  0x00,
119 
120 	  //
121     //Bus  ,   Dev,  Func,    PCIE device
122 	 //
123       0x00 ,  0x1C,  0x00,
124 
125 	  //
126     //00-1F, 20-3F, 40-5F, 60-7F, 80-9F, A0-BF, C0-DF, E0-FF
127     //
128       0xC0 ,  0x83,  0x30,  0x00,  0x00,  0x00,  0x00,  0x00,
129 
130 	  //
131     //Bus  ,   Dev,  Func,    PCIE device
132     //
133 	  0x00 ,  0x1C,  0x00,
134 
135 	  //
136     //00-1F, 20-3F, 40-5F, 60-7F, 80-9F, A0-BF, C0-DF, E0-FF
137     //
138       0x03 ,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,
139 
140 	  //
141     //Bus  ,   Dev,  Func,    SATA device
142 	  //
143       0x00 ,  0x13,  0x00,
144 
145 	  //
146     //00-1F, 20-3F, 40-5F, 60-7F, 80-9F, A0-BF, C0-DF, E0-FF
147     //
148       0xf4 ,  0xab,  0x27,  0x10,  0xf1,  0x1d,  0x00,  0x40,
149 
150     //
151     //Bus  ,   Dev,  Func,    EHCI device
152     //
153      0x00 ,  0x1D,  0x00,
154 
155     //
156     //00-1F, 20-3F, 40-5F, 60-7F, 80-9F, A0-BF, C0-DF, E0-FF
157     //
158      0x10 ,  0x88,  0x00,  0x00,  0x00,  0x00,  0x00,  0x80,
159 
160     //
161     //Bus  ,   Dev,  Func,    SMBUS device
162     //
163      0x00 ,  0x1f,  0x03,
164 
165     //
166     //00-1F, 20-3F, 40-5F, 60-7F, 80-9F, A0-BF, C0-DF, E0-FF
167     //
168       0x10 ,  0x89,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,
169 
170     //
171     //Bus  ,   Dev,  Func,    SMBUS device
172     //
173       0x00 ,  0x1f,  0x03,
174 
175     //
176     //00-1F, 20-3F, 40-5F, 60-7F, 80-9F, A0-BF, C0-DF, E0-FF
177     //
178       0x02 ,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,
179 
180     //
181     //Bus  ,   Dev,  Func,    VGA bus1
182     //
183       0x01 ,  0x00,  0x00,
184 
185     //
186     //00-1F, 20-3F, 40-5F, 60-7F, 80-9F, A0-BF, C0-DF, E0-FF
187     //
188       0x58 ,  0x81,  0x18,  0x01,  0xb0,  0x00,  0x00,  0x00,
189 
190     //
191     //Bus  ,   Dev,  Func,    VGA bus1
192     //
193       0x01 ,  0x00,  0x00,
194 
195     //
196     //00-1F, 20-3F, 40-5F, 60-7F, 80-9F, A0-BF, C0-DF, E0-FF
197     //
198       0x02 ,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,
199 
200     //
201     //Bus  ,   Dev,  Func,    VGA bus1 function 1
202     //
203       0x01 ,  0x00,  0x01,
204 
205     //
206     //00-1F, 20-3F, 40-5F, 60-7F, 80-9F, A0-BF, C0-DF, E0-FF
207     //
208       0x51 ,  0x80,  0x80,  0x01,  0x00,  0x00,  0x00,  0x00,
209 
210     //
211     //Bus  ,   Dev,  Func,    VGA bus1 function 1
212     //
213       0x01 ,  0x00,  0x01,
214 
215     //
216     //00-1F, 20-3F, 40-5F, 60-7F, 80-9F, A0-BF, C0-DF, E0-FF
217     //
218       0x02 ,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,
219 
220     //
221     //Bus  ,   Dev,  Func,    IGD bus0 function 0
222     //
223       0x00 ,  0x02,  0x00,
224 
225     //
226     //00-1F, 20-3F, 40-5F, 60-7F, 80-9F, A0-BF, C0-DF, E0-FF
227     //
228       0x42 ,  0x81,  0x00,  0x00,  0x00,  0x00,  0x20,  0x00,
229 
230     //
231     //Bus  ,   Dev,  Func,    USB bus0 function 0
232     //
233       0x00 ,  0x16,  0x00,
234 
235     //
236     //00-1F, 20-3F, 40-5F, 60-7F, 80-9F, A0-BF, C0-DF, E0-FF
237     //
238       0x32 ,  0x80,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,
239 
240     //
241     //Bus  ,   Dev,  Func,    HD Audio bus0 function 0
242     //
243       0x00 ,  0x1B,  0x00,
244 
245     //
246     //00-1F, 20-3F, 40-5F, 60-7F, 80-9F, A0-BF, C0-DF, E0-FF
247     //
248       0x00 ,  0x00,  0x00,  0x00,  0x00,  0x00,  0x02,  0x00,
249 
250     //
251     //0xFF indicates the end of the table
252     //
253       0xFF
254  };
255 
256   //
257   // These registers have to set in byte order
258   //
259   UINT8                 ExtReg[] = { 0x9E, 0x9D };  // SMRAM settings
260 
261 
262 
263   //
264   // Save PCI-Host bridge settings (0, 0, 0). 0x90, 94 and 9c are changed by CSM
265   // and vital to S3 resume. That's why we put save code here
266   //
267   PciAddress.Bus      = 0;
268   PciAddress.Device   = 0;
269   PciAddress.Function = 0;
270   PciAddress.ExtendedRegister = 0;
271 
272   for (Index = 0; Index < 2; Index++) {
273     //
274     // Read SRAM setting from Pci(0, 0, 0)
275     //
276     PciAddress.Register = ExtReg[Index];
277     Data8 = MmioRead8 (
278               MmPciAddress (0,
279                 PciAddress.Bus,
280                 PciAddress.Device,
281                 PciAddress.Function,
282                 PciAddress.Register
283               )
284             );
285 
286     //
287     // Save latest settings to runtime script table
288     //
289     S3BootScriptSavePciCfgWrite(
290       S3BootScriptWidthUint8,
291       *(UINT64*)&PciAddress,
292       1,
293       &Data8
294       );
295   }
296 
297 
298   //
299   // Save PCI-Host bridge settings (0, 0, 0). 0x90, 94 and 9c are changed by CSM
300   // and vital to S3 resume. That's why we put save code here
301   //
302   Index = 0;
303   while (RegTable[Index] != 0xFF) {
304 
305     PciAddress.Bus      = RegTable[Index++];
306     PciAddress.Device   = RegTable[Index++];
307     PciAddress.Function = RegTable[Index++];
308     PciAddress.Register = 0;
309     PciAddress.ExtendedRegister = 0;
310 
311     Data16 = MmioRead16 (
312               MmPciAddress (0,
313                 PciAddress.Bus,
314                 PciAddress.Device,
315                 PciAddress.Function,
316                 PciAddress.Register
317               )
318             );
319 
320     if (Data16 == 0xFFFF) {
321       Index+=8;
322       continue;
323     }
324 
325     for (Offset = 0, Mask = 0x01; Offset < 256; Offset+=4, Mask<<=1) {
326 
327       if (Mask == 0x00) {
328         Mask = 0x01;
329       }
330 
331       if (RegTable[Index + Offset/32] & Mask ) {
332 
333         PciAddress.Register = (UINT8)Offset;
334         Data32 = MmioRead32 (MmPciAddress (0, PciAddress.Bus, PciAddress.Device, PciAddress.Function, PciAddress.Register));
335 
336         //
337         // Save latest settings to runtime script table
338         //
339         S3BootScriptSavePciCfgWrite (
340           S3BootScriptWidthUint32,
341           *(UINT64*)&PciAddress,
342           1,
343           &Data32
344         );
345       }
346     }
347 
348     Index += 8;
349 
350   }
351 
352 
353   //
354   // Save I/O ports to S3 script table
355   //
356 
357   //
358   // Selftest KBC
359   //
360   Data8 = 0xAA;
361   S3BootScriptSaveIoWrite (
362     S3BootScriptWidthUint8,
363     0x64,
364     (UINTN)1,
365     &Data8
366     );
367 
368   Data32 = IoRead32(mAcpiBaseAddr + R_PCH_SMI_EN);
369 
370   S3BootScriptSaveIoWrite (
371       S3BootScriptWidthUint32,
372       (mAcpiBaseAddr + R_PCH_SMI_EN),
373       1,
374       &Data32
375       );
376 
377   //
378   // Save B_ICH_TCO_CNT_LOCK so it will be done on S3 resume path.
379   //
380   Data16 = IoRead16(mAcpiBaseAddr + R_PCH_TCO_CNT);
381 
382   S3BootScriptSaveIoWrite (
383       S3BootScriptWidthUint16,
384       mAcpiBaseAddr + R_PCH_TCO_CNT,
385       1,
386       &Data16
387       );
388 
389 
390   return EFI_SUCCESS;
391 }
392