]> git.proxmox.com Git - mirror_edk2.git/blob - Vlv2TbltDevicePkg/PlatformPei/BootMode.c
Vlv2TbltDevicePkg: Replace BSD License with BSD+Patent License
[mirror_edk2.git] / Vlv2TbltDevicePkg / PlatformPei / BootMode.c
1 /** @file
2
3 Copyright (c) 2004 - 2018, Intel Corporation. All rights reserved.<BR>
4
5 SPDX-License-Identifier: BSD-2-Clause-Patent
6
7
8
9 Module Name:
10
11
12 BootMode.c
13
14 Abstract:
15
16 EFI PEIM to provide the platform support functionality on the Thurley.
17
18
19 --*/
20 #include "CommonHeader.h"
21 #include "Platform.h"
22 #include "PlatformBaseAddresses.h"
23 #include "PchAccess.h"
24 #include "PlatformBootMode.h"
25 #include <Guid/SetupVariable.h>
26
27 //
28 // Priority of our boot modes, highest priority first
29 //
30 EFI_BOOT_MODE mBootModePriority[] = {
31 BOOT_IN_RECOVERY_MODE,
32 BOOT_WITH_DEFAULT_SETTINGS,
33 BOOT_ON_FLASH_UPDATE,
34 BOOT_ON_S2_RESUME,
35 BOOT_ON_S3_RESUME,
36 BOOT_ON_S4_RESUME,
37 BOOT_WITH_MINIMAL_CONFIGURATION,
38 BOOT_ASSUMING_NO_CONFIGURATION_CHANGES,
39 BOOT_WITH_FULL_CONFIGURATION_PLUS_DIAGNOSTICS,
40 BOOT_WITH_FULL_CONFIGURATION,
41 BOOT_ON_S5_RESUME
42 };
43
44 EFI_PEI_NOTIFY_DESCRIPTOR mCapsuleNotifyList[1] = {
45 {
46 (EFI_PEI_PPI_DESCRIPTOR_NOTIFY_CALLBACK | EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST),
47 &gPeiCapsulePpiGuid,
48 CapsulePpiNotifyCallback
49 }
50 };
51
52 BOOLEAN
53 GetSleepTypeAfterWakeup (
54 IN CONST EFI_PEI_SERVICES **PeiServices,
55 OUT UINT16 *SleepType
56 );
57
58 EFI_STATUS
59 EFIAPI
60 CapsulePpiNotifyCallback (
61 IN EFI_PEI_SERVICES **PeiServices,
62 IN EFI_PEI_NOTIFY_DESCRIPTOR *NotifyDescriptor,
63 IN VOID *Ppi
64 )
65 {
66 EFI_STATUS Status;
67 EFI_BOOT_MODE BootMode;
68 PEI_CAPSULE_PPI *Capsule;
69
70 Status = (*PeiServices)->GetBootMode((const EFI_PEI_SERVICES **)PeiServices, &BootMode);
71 ASSERT_EFI_ERROR (Status);
72
73 if (BootMode == BOOT_ON_S3_RESUME) {
74 //
75 // Determine if we're in capsule update mode
76 //
77 Status = (*PeiServices)->LocatePpi ((const EFI_PEI_SERVICES **)PeiServices,
78 &gPeiCapsulePpiGuid,
79 0,
80 NULL,
81 (VOID **)&Capsule
82 );
83
84 if (Status == EFI_SUCCESS) {
85 if (Capsule->CheckCapsuleUpdate ((EFI_PEI_SERVICES**)PeiServices) == EFI_SUCCESS) {
86 BootMode = BOOT_ON_FLASH_UPDATE;
87 Status = (*PeiServices)->SetBootMode((const EFI_PEI_SERVICES **)PeiServices, BootMode);
88 ASSERT_EFI_ERROR (Status);
89 }
90 }
91 }
92
93 return Status;
94 }
95
96 #ifdef NOCS_S3_SUPPORT
97 EFI_STATUS
98 UpdateBootMode (
99 IN CONST EFI_PEI_SERVICES **PeiServices
100 )
101 {
102 EFI_STATUS Status;
103 EFI_BOOT_MODE BootMode;
104 UINT16 SleepType;
105 CHAR16 *strBootMode;
106
107 Status = (*PeiServices)->GetBootMode(PeiServices, &BootMode);
108 ASSERT_EFI_ERROR (Status);
109 if (BootMode == BOOT_IN_RECOVERY_MODE){
110 return Status;
111 }
112
113 //
114 // Let's assume things are OK if not told otherwise
115 //
116 BootMode = BOOT_WITH_FULL_CONFIGURATION;
117
118 if (GetSleepTypeAfterWakeup (PeiServices, &SleepType)) {
119 switch (SleepType) {
120 case V_PCH_ACPI_PM1_CNT_S3:
121 BootMode = BOOT_ON_S3_RESUME;
122 Status = (*PeiServices)->NotifyPpi (PeiServices, &mCapsuleNotifyList[0]);
123 ASSERT_EFI_ERROR (Status);
124 break;
125
126 case V_PCH_ACPI_PM1_CNT_S4:
127 BootMode = BOOT_ON_S4_RESUME;
128 break;
129
130 case V_PCH_ACPI_PM1_CNT_S5:
131 BootMode = BOOT_ON_S5_RESUME;
132 break;
133 } // switch (SleepType)
134 }
135
136 if (IsFastBootEnabled (PeiServices)) {
137 DEBUG ((EFI_D_INFO, "Prioritizing Boot mode to BOOT_WITH_MINIMAL_CONFIGURATION\n"));
138 PrioritizeBootMode (&BootMode, BOOT_WITH_MINIMAL_CONFIGURATION);
139 }
140
141 switch (BootMode) {
142 case BOOT_WITH_FULL_CONFIGURATION:
143 strBootMode = L"BOOT_WITH_FULL_CONFIGURATION";
144 break;
145 case BOOT_WITH_MINIMAL_CONFIGURATION:
146 strBootMode = L"BOOT_WITH_MINIMAL_CONFIGURATION";
147 break;
148 case BOOT_ASSUMING_NO_CONFIGURATION_CHANGES:
149 strBootMode = L"BOOT_ASSUMING_NO_CONFIGURATION_CHANGES";
150 break;
151 case BOOT_WITH_FULL_CONFIGURATION_PLUS_DIAGNOSTICS:
152 strBootMode = L"BOOT_WITH_FULL_CONFIGURATION_PLUS_DIAGNOSTICS";
153 break;
154 case BOOT_WITH_DEFAULT_SETTINGS:
155 strBootMode = L"BOOT_WITH_DEFAULT_SETTINGS";
156 break;
157 case BOOT_ON_S4_RESUME:
158 strBootMode = L"BOOT_ON_S4_RESUME";
159 break;
160 case BOOT_ON_S5_RESUME:
161 strBootMode = L"BOOT_ON_S5_RESUME";
162 break;
163 case BOOT_ON_S2_RESUME:
164 strBootMode = L"BOOT_ON_S2_RESUME";
165 break;
166 case BOOT_ON_S3_RESUME:
167 strBootMode = L"BOOT_ON_S3_RESUME";
168
169 break;
170 case BOOT_ON_FLASH_UPDATE:
171 strBootMode = L"BOOT_ON_FLASH_UPDATE";
172 break;
173 case BOOT_IN_RECOVERY_MODE:
174 strBootMode = L"BOOT_IN_RECOVERY_MODE";
175 break;
176 default:
177 strBootMode = L"Unknown boot mode";
178 } // switch (BootMode)
179
180 DEBUG ((EFI_D_ERROR, "Setting BootMode to %s\n", strBootMode));
181 Status = (*PeiServices)->SetBootMode(PeiServices, BootMode);
182 ASSERT_EFI_ERROR (Status);
183
184 return Status;
185 }
186 #endif
187
188 /**
189 Get sleep type after wakeup
190
191 @param PeiServices Pointer to the PEI Service Table.
192 @param SleepType Sleep type to be returned.
193
194 @retval TRUE A wake event occured without power failure.
195 @retval FALSE Power failure occured or not a wakeup.
196
197 **/
198 BOOLEAN
199 GetSleepTypeAfterWakeup (
200 IN CONST EFI_PEI_SERVICES **PeiServices,
201 OUT UINT16 *SleepType
202 )
203 {
204 UINT16 Pm1Sts;
205 UINT16 Pm1Cnt;
206 UINT16 GenPmCon1;
207 //
208 // VLV BIOS Specification 0.6.2 - Section 18.4, "Power Failure Consideration"
209 //
210 // When the SUS_PWR_FLR bit is set, it indicates the SUS well power is lost.
211 // This bit is in the SUS Well and defaults to 1\92b1 based on RSMRST# assertion (not cleared by any type of reset).
212 // System BIOS should follow cold boot path if SUS_PWR_FLR (PBASE + 0x20[14]),
213 // GEN_RST_STS (PBASE + 0x20[9]) or PWRBTNOR_STS (ABASE + 0x00[11]) is set to 1\92b1
214 // regardless of the value in the SLP_TYP (ABASE + 0x04[12:10]) field.
215 //
216 GenPmCon1 = MmioRead16 (PMC_BASE_ADDRESS + R_PCH_PMC_GEN_PMCON_1);
217
218 //
219 // Read the ACPI registers
220 //
221 Pm1Sts = IoRead16 (ACPI_BASE_ADDRESS + R_PCH_ACPI_PM1_STS);
222 Pm1Cnt = IoRead16 (ACPI_BASE_ADDRESS + R_PCH_ACPI_PM1_CNT);
223
224 if ((GenPmCon1 & (B_PCH_PMC_GEN_PMCON_SUS_PWR_FLR | B_PCH_PMC_GEN_PMCON_GEN_RST_STS)) ||
225 (Pm1Sts & B_PCH_ACPI_PM1_STS_PRBTNOR)) {
226 //
227 // If power failure indicator, then don't attempt s3 resume.
228 // Clear PM1_CNT of S3 and set it to S5 as we just had a power failure, and memory has
229 // lost already. This is to make sure no one will use PM1_CNT to check for S3 after
230 // power failure.
231 //
232 if ((Pm1Cnt & B_PCH_ACPI_PM1_CNT_SLP_TYP) == V_PCH_ACPI_PM1_CNT_S3) {
233 Pm1Cnt = ((Pm1Cnt & ~B_PCH_ACPI_PM1_CNT_SLP_TYP) | V_PCH_ACPI_PM1_CNT_S5);
234 IoWrite16 (ACPI_BASE_ADDRESS + R_PCH_ACPI_PM1_CNT, Pm1Cnt);
235 }
236 //
237 // Clear Wake Status (WAK_STS)
238 //
239 }
240 //
241 // Get sleep type if a wake event occurred and there is no power failure
242 //
243 if ((Pm1Cnt & B_PCH_ACPI_PM1_CNT_SLP_TYP) == V_PCH_ACPI_PM1_CNT_S3) {
244 *SleepType = Pm1Cnt & B_PCH_ACPI_PM1_CNT_SLP_TYP;
245 return TRUE;
246 } else if ((Pm1Cnt & B_PCH_ACPI_PM1_CNT_SLP_TYP) == V_PCH_ACPI_PM1_CNT_S4) {
247 *SleepType = Pm1Cnt & B_PCH_ACPI_PM1_CNT_SLP_TYP;
248 return TRUE;
249 }
250 return FALSE;
251 }
252
253 BOOLEAN
254 EFIAPI
255 IsFastBootEnabled (
256 IN CONST EFI_PEI_SERVICES **PeiServices
257 )
258 {
259 EFI_STATUS Status;
260 EFI_PEI_READ_ONLY_VARIABLE2_PPI *PeiReadOnlyVarPpi;
261 UINTN VarSize;
262 SYSTEM_CONFIGURATION SystemConfiguration;
263 BOOLEAN FastBootEnabledStatus;
264
265 FastBootEnabledStatus = FALSE;
266 Status = (**PeiServices).LocatePpi (
267 PeiServices,
268 &gEfiPeiReadOnlyVariable2PpiGuid,
269 0,
270 NULL,
271 (void **)&PeiReadOnlyVarPpi
272 );
273 if (Status == EFI_SUCCESS) {
274 VarSize = sizeof (SYSTEM_CONFIGURATION);
275 Status = PeiReadOnlyVarPpi->GetVariable (
276 PeiReadOnlyVarPpi,
277 PLATFORM_SETUP_VARIABLE_NAME,
278 &gEfiSetupVariableGuid,
279 NULL,
280 &VarSize,
281 &SystemConfiguration
282 );
283 if (Status == EFI_SUCCESS) {
284 if (SystemConfiguration.FastBoot != 0) {
285 FastBootEnabledStatus = TRUE;
286 }
287 }
288 }
289
290 return FastBootEnabledStatus;
291 }
292
293 /**
294 Given the current boot mode, and a proposed new boot mode, determine
295 which has priority. If the new boot mode has higher priority, then
296 make it the current boot mode.
297
298 @param CurrentBootMode pointer to current planned boot mode
299 @param NewBootMode proposed boot mode
300
301 @retval EFI_NOT_FOUND if either boot mode is not recognized
302 @retval EFI_SUCCESS if both boot mode values were recognized and
303 were processed.
304 **/
305 EFI_STATUS
306 PrioritizeBootMode (
307 IN OUT EFI_BOOT_MODE *CurrentBootMode,
308 IN EFI_BOOT_MODE NewBootMode
309 )
310 {
311 UINT32 CurrentIndex;
312 UINT32 NewIndex;
313
314 //
315 // Find the position of the current boot mode in our priority array
316 //
317 for ( CurrentIndex = 0;
318 CurrentIndex < ARRAY_SIZE (mBootModePriority);
319 CurrentIndex++) {
320 if (mBootModePriority[CurrentIndex] == *CurrentBootMode) {
321 break;
322 }
323 }
324 if (CurrentIndex >= ARRAY_SIZE (mBootModePriority)) {
325 return EFI_NOT_FOUND;
326 }
327
328 //
329 // Find the position of the new boot mode in our priority array
330 //
331 for ( NewIndex = 0;
332 NewIndex < ARRAY_SIZE (mBootModePriority);
333 NewIndex++) {
334 if (mBootModePriority[NewIndex] == NewBootMode) {
335 //
336 // If this new boot mode occurs before the current boot mode in the
337 // priority array, then take it.
338 //
339 if (NewIndex < CurrentIndex) {
340 *CurrentBootMode = NewBootMode;
341 }
342 return EFI_SUCCESS;
343 }
344 }
345 return EFI_NOT_FOUND;
346 }