BootMode.c 10 KB

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