BootMode.c 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434
  1. /** @file
  2. Copyright (c) 2004 - 2014, 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 "PlatformEarlyInit.h"
  10. #define NORMALMODE 0
  11. #define RECOVERYMODE 1
  12. #define SAFEMODE 2
  13. #define MANUFACTURINGMODE 3
  14. #define GPIO_SSUS_OFFSET 0x2000
  15. #define PMU_PWRBTN_B_OFFSET 0x88
  16. EFI_PEI_PPI_DESCRIPTOR mPpiListRecoveryBootMode = {
  17. (EFI_PEI_PPI_DESCRIPTOR_PPI | EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST),
  18. &gEfiPeiBootInRecoveryModePpiGuid,
  19. NULL
  20. };
  21. /**
  22. Return the setting of the Bios configuration jumper
  23. @param VOID
  24. @retval RECOVERYMODE jumper set to recovery mode
  25. @retval SAFEMODE jumper set to config mode
  26. @retval NORMALMODE jumper in normal mode
  27. **/
  28. UINTN
  29. GetConfigJumper(
  30. IN CONST EFI_PEI_SERVICES **PeiServices,
  31. IN OUT EFI_PLATFORM_INFO_HOB *PlatformInfoHob
  32. )
  33. {
  34. //
  35. // Do the Forced recovery detection based on logic chart above
  36. //
  37. if (IsRecoveryJumper(PeiServices, PlatformInfoHob)) {
  38. return RECOVERYMODE;
  39. } else {
  40. return NORMALMODE;
  41. }
  42. }
  43. BOOLEAN
  44. CheckIfRecoveryMode(
  45. IN CONST EFI_PEI_SERVICES **PeiServices,
  46. IN OUT EFI_PLATFORM_INFO_HOB *PlatformInfoHob
  47. )
  48. {
  49. if (GetConfigJumper(PeiServices, PlatformInfoHob) == RECOVERYMODE) {
  50. return TRUE;
  51. }
  52. return FALSE;
  53. }
  54. BOOLEAN
  55. CheckIfSafeMode(
  56. IN CONST EFI_PEI_SERVICES **PeiServices,
  57. IN OUT EFI_PLATFORM_INFO_HOB *PlatformInfoHob
  58. )
  59. {
  60. if (GetConfigJumper(PeiServices, PlatformInfoHob) == SAFEMODE) {
  61. return TRUE;
  62. }
  63. return FALSE;
  64. }
  65. BOOLEAN
  66. CheckIfManufacturingMode (
  67. IN CONST EFI_PEI_SERVICES **PeiServices
  68. )
  69. {
  70. EFI_STATUS Status;
  71. EFI_PEI_READ_ONLY_VARIABLE2_PPI *Variable;
  72. UINT32 Attributes;
  73. UINTN DataSize;
  74. CHAR16 VarName[] = MFGMODE_VARIABLE_NAME;
  75. UINT8 MfgMode;
  76. Status = (*PeiServices)->LocatePpi (
  77. PeiServices,
  78. &gEfiPeiReadOnlyVariable2PpiGuid,
  79. 0,
  80. NULL,
  81. (void **)&Variable
  82. );
  83. ASSERT_EFI_ERROR (Status);
  84. //
  85. // Check if SW MMJ mode
  86. //
  87. Attributes = (EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS);
  88. DataSize = sizeof (MFG_MODE_VAR);
  89. Status = Variable->GetVariable (
  90. Variable,
  91. VarName,
  92. &gMfgModeVariableGuid,
  93. &Attributes,
  94. &DataSize,
  95. &MfgMode
  96. );
  97. if (!(EFI_ERROR (Status))) {
  98. return TRUE;
  99. }
  100. return FALSE;
  101. }
  102. EFI_STATUS
  103. UpdateBootMode (
  104. IN CONST EFI_PEI_SERVICES **PeiServices,
  105. IN OUT EFI_PLATFORM_INFO_HOB *PlatformInfoHob
  106. )
  107. {
  108. EFI_STATUS Status;
  109. EFI_BOOT_MODE BootMode;
  110. UINT16 SleepType;
  111. CHAR16 *strBootMode;
  112. PEI_CAPSULE_PPI *Capsule;
  113. EFI_PEI_READ_ONLY_VARIABLE2_PPI *Variable;
  114. SYSTEM_CONFIGURATION SystemConfiguration;
  115. UINTN VarSize;
  116. volatile UINT32 GpioValue;
  117. BOOLEAN IsFirstBoot;
  118. UINT32 Data32;
  119. Status = (*PeiServices)->GetBootMode(
  120. PeiServices,
  121. &BootMode
  122. );
  123. ASSERT_EFI_ERROR (Status);
  124. if (BootMode == BOOT_IN_RECOVERY_MODE){
  125. return Status;
  126. }
  127. GetWakeupEventAndSaveToHob (PeiServices);
  128. //
  129. // Let's assume things are OK if not told otherwise
  130. //
  131. BootMode = BOOT_WITH_FULL_CONFIGURATION;
  132. //
  133. // When this boot is WDT reset, the system needs booting with CrashDump function eanbled.
  134. //
  135. Data32 = IoRead32 (ACPI_BASE_ADDRESS + R_PCH_TCO_STS);
  136. //
  137. // Check Power Button, click the power button, the system will boot in fast boot mode,
  138. // if it is pressed and hold for a second, it will boot in FullConfiguration/setup mode.
  139. //
  140. GpioValue = MmioRead32 (IO_BASE_ADDRESS + GPIO_SSUS_OFFSET + PMU_PWRBTN_B_OFFSET); // The value of GPIOS_16 (PMU_PWRBTN_B)
  141. if (((GpioValue & BIT0) != 0)&&((Data32 & B_PCH_TCO_STS_SECOND_TO) != B_PCH_TCO_STS_SECOND_TO)){
  142. IsFirstBoot = PcdGetBool(PcdBootState);
  143. if (!IsFirstBoot){
  144. VarSize = sizeof (SYSTEM_CONFIGURATION);
  145. ZeroMem (&SystemConfiguration, sizeof (SYSTEM_CONFIGURATION));
  146. Status = (*PeiServices)->LocatePpi (
  147. PeiServices,
  148. &gEfiPeiReadOnlyVariable2PpiGuid,
  149. 0,
  150. NULL,
  151. (void **)&Variable
  152. );
  153. ASSERT_EFI_ERROR (Status);
  154. //
  155. // Use normal setup default from NVRAM variable,
  156. // the Platform Mode (manufacturing/safe/normal) is handle in PeiGetVariable.
  157. //
  158. VarSize = sizeof(SYSTEM_CONFIGURATION);
  159. Status = Variable->GetVariable (
  160. Variable,
  161. L"Setup",
  162. &gEfiSetupVariableGuid,
  163. NULL,
  164. &VarSize,
  165. &SystemConfiguration
  166. );
  167. if (EFI_ERROR (Status) || VarSize != sizeof(SYSTEM_CONFIGURATION)) {
  168. //The setup variable is corrupted
  169. VarSize = sizeof(SYSTEM_CONFIGURATION);
  170. Status = Variable->GetVariable(
  171. Variable,
  172. L"SetupRecovery",
  173. &gEfiSetupVariableGuid,
  174. NULL,
  175. &VarSize,
  176. &SystemConfiguration
  177. );
  178. ASSERT_EFI_ERROR (Status);
  179. }
  180. if (SystemConfiguration.FastBoot == 1) {
  181. BootMode = BOOT_WITH_MINIMAL_CONFIGURATION;
  182. }
  183. }
  184. }
  185. //
  186. // Check if we need to boot in forced recovery mode
  187. //
  188. if (CheckIfRecoveryMode(PeiServices, PlatformInfoHob)) {
  189. BootMode = BOOT_IN_RECOVERY_MODE;
  190. }
  191. if (BootMode == BOOT_IN_RECOVERY_MODE) {
  192. Status = (*PeiServices)->InstallPpi (
  193. PeiServices,
  194. &mPpiListRecoveryBootMode
  195. );
  196. ASSERT_EFI_ERROR (Status);
  197. } else {
  198. if (GetSleepTypeAfterWakeup (PeiServices, &SleepType)) {
  199. switch (SleepType) {
  200. case V_PCH_ACPI_PM1_CNT_S3:
  201. BootMode = BOOT_ON_S3_RESUME;
  202. //
  203. // Determine if we're in capsule update mode
  204. //
  205. Status = (*PeiServices)->LocatePpi (
  206. PeiServices,
  207. &gPeiCapsulePpiGuid,
  208. 0,
  209. NULL,
  210. (void **)&Capsule
  211. );
  212. if (Status == EFI_SUCCESS) {
  213. if (Capsule->CheckCapsuleUpdate ((EFI_PEI_SERVICES**)PeiServices) == EFI_SUCCESS) {
  214. BootMode = BOOT_ON_FLASH_UPDATE;
  215. }
  216. }
  217. break;
  218. case V_PCH_ACPI_PM1_CNT_S4:
  219. BootMode = BOOT_ON_S4_RESUME;
  220. break;
  221. case V_PCH_ACPI_PM1_CNT_S5:
  222. BootMode = BOOT_ON_S5_RESUME;
  223. break;
  224. } // switch (SleepType)
  225. }
  226. //
  227. // Check for Safe Mode
  228. //
  229. }
  230. switch (BootMode) {
  231. case BOOT_WITH_FULL_CONFIGURATION:
  232. strBootMode = L"BOOT_WITH_FULL_CONFIGURATION";
  233. break;
  234. case BOOT_WITH_MINIMAL_CONFIGURATION:
  235. strBootMode = L"BOOT_WITH_MINIMAL_CONFIGURATION";
  236. break;
  237. case BOOT_ASSUMING_NO_CONFIGURATION_CHANGES:
  238. strBootMode = L"BOOT_ASSUMING_NO_CONFIGURATION_CHANGES";
  239. break;
  240. case BOOT_WITH_FULL_CONFIGURATION_PLUS_DIAGNOSTICS:
  241. strBootMode = L"BOOT_WITH_FULL_CONFIGURATION_PLUS_DIAGNOSTICS";
  242. break;
  243. case BOOT_WITH_DEFAULT_SETTINGS:
  244. strBootMode = L"BOOT_WITH_DEFAULT_SETTINGS";
  245. break;
  246. case BOOT_ON_S4_RESUME:
  247. strBootMode = L"BOOT_ON_S4_RESUME";
  248. break;
  249. case BOOT_ON_S5_RESUME:
  250. strBootMode = L"BOOT_ON_S5_RESUME";
  251. break;
  252. case BOOT_ON_S2_RESUME:
  253. strBootMode = L"BOOT_ON_S2_RESUME";
  254. break;
  255. case BOOT_ON_S3_RESUME:
  256. strBootMode = L"BOOT_ON_S3_RESUME";
  257. break;
  258. case BOOT_ON_FLASH_UPDATE:
  259. strBootMode = L"BOOT_ON_FLASH_UPDATE";
  260. break;
  261. case BOOT_IN_RECOVERY_MODE:
  262. strBootMode = L"BOOT_IN_RECOVERY_MODE";
  263. break;
  264. default:
  265. strBootMode = L"Unknown boot mode";
  266. } // switch (BootMode)
  267. DEBUG ((EFI_D_ERROR, "Setting BootMode to %s\n", strBootMode));
  268. Status = (*PeiServices)->SetBootMode(
  269. PeiServices,
  270. BootMode
  271. );
  272. ASSERT_EFI_ERROR (Status);
  273. return Status;
  274. }
  275. /**
  276. Get sleep type after wakeup
  277. @param PeiServices Pointer to the PEI Service Table.
  278. @param SleepType Sleep type to be returned.
  279. @retval TRUE A wake event occured without power failure.
  280. @retval FALSE Power failure occured or not a wakeup.
  281. **/
  282. BOOLEAN
  283. GetSleepTypeAfterWakeup (
  284. IN CONST EFI_PEI_SERVICES **PeiServices,
  285. OUT UINT16 *SleepType
  286. )
  287. {
  288. UINT16 Pm1Sts;
  289. UINT16 Pm1Cnt;
  290. UINT16 GenPmCon1;
  291. GenPmCon1 = MmioRead16 (PMC_BASE_ADDRESS + R_PCH_PMC_GEN_PMCON_1);
  292. //
  293. // Read the ACPI registers
  294. //
  295. Pm1Sts = IoRead16 (ACPI_BASE_ADDRESS + R_PCH_ACPI_PM1_STS);
  296. Pm1Cnt = IoRead16 (ACPI_BASE_ADDRESS + R_PCH_ACPI_PM1_CNT);
  297. if ((GenPmCon1 & (B_PCH_PMC_GEN_PMCON_SUS_PWR_FLR | B_PCH_PMC_GEN_PMCON_GEN_RST_STS)) ||
  298. (Pm1Sts & B_PCH_ACPI_PM1_STS_PRBTNOR)) {
  299. //
  300. // If power failure indicator, then don't attempt s3 resume.
  301. // Clear PM1_CNT of S3 and set it to S5 as we just had a power failure, and memory has
  302. // lost already. This is to make sure no one will use PM1_CNT to check for S3 after
  303. // power failure.
  304. //
  305. if ((Pm1Cnt & B_PCH_ACPI_PM1_CNT_SLP_TYP) == V_PCH_ACPI_PM1_CNT_S3) {
  306. Pm1Cnt = ((Pm1Cnt & ~B_PCH_ACPI_PM1_CNT_SLP_TYP) | V_PCH_ACPI_PM1_CNT_S5);
  307. IoWrite16 (ACPI_BASE_ADDRESS + R_PCH_ACPI_PM1_CNT, Pm1Cnt);
  308. }
  309. //
  310. // Clear Wake Status (WAK_STS)
  311. //
  312. IoWrite16 ((ACPI_BASE_ADDRESS + R_PCH_ACPI_PM1_STS), B_PCH_ACPI_PM1_STS_WAK);
  313. }
  314. //
  315. // Get sleep type if a wake event occurred and there is no power failure
  316. //
  317. if ((Pm1Cnt & B_PCH_ACPI_PM1_CNT_SLP_TYP) == V_PCH_ACPI_PM1_CNT_S3) {
  318. *SleepType = Pm1Cnt & B_PCH_ACPI_PM1_CNT_SLP_TYP;
  319. return TRUE;
  320. } else if ((Pm1Cnt & B_PCH_ACPI_PM1_CNT_SLP_TYP) == V_PCH_ACPI_PM1_CNT_S4){
  321. *SleepType = Pm1Cnt & B_PCH_ACPI_PM1_CNT_SLP_TYP;
  322. return TRUE;
  323. }
  324. return FALSE;
  325. }
  326. VOID
  327. SetPlatformBootMode (
  328. IN CONST EFI_PEI_SERVICES **PeiServices,
  329. IN OUT EFI_PLATFORM_INFO_HOB *PlatformInfoHob
  330. )
  331. {
  332. EFI_PLATFORM_SETUP_ID PlatformSetupId;
  333. ZeroMem(&PlatformSetupId, sizeof (EFI_PLATFORM_SETUP_ID));
  334. CopyMem (&PlatformSetupId.SetupGuid,
  335. &gEfiNormalSetupGuid,
  336. sizeof (EFI_GUID));
  337. if (CheckIfRecoveryMode(PeiServices, PlatformInfoHob)) {
  338. //
  339. // Recovery mode
  340. //
  341. CopyMem (&PlatformSetupId.SetupName,
  342. &NORMAL_SETUP_NAME,
  343. StrSize (NORMAL_SETUP_NAME));
  344. PlatformSetupId.PlatformBootMode = PLATFORM_RECOVERY_MODE;
  345. } else if (CheckIfSafeMode(PeiServices, PlatformInfoHob)) {
  346. //
  347. // Safe mode also called config mode or maintenace mode.
  348. //
  349. CopyMem (&PlatformSetupId.SetupName,
  350. &NORMAL_SETUP_NAME,
  351. StrSize (NORMAL_SETUP_NAME));
  352. PlatformSetupId.PlatformBootMode = PLATFORM_SAFE_MODE;
  353. } else if(0) { // else if (CheckIfManufacturingMode(PeiServices)) {
  354. //
  355. // Manufacturing mode
  356. //
  357. CopyMem (&PlatformSetupId.SetupName,
  358. MANUFACTURE_SETUP_NAME,
  359. StrSize (MANUFACTURE_SETUP_NAME));
  360. PlatformSetupId.PlatformBootMode = PLATFORM_MANUFACTURING_MODE;
  361. } else {
  362. //
  363. // Default to normal mode.
  364. //
  365. CopyMem (&PlatformSetupId.SetupName,
  366. &NORMAL_SETUP_NAME,
  367. StrSize (NORMAL_SETUP_NAME));
  368. PlatformSetupId.PlatformBootMode = PLATFORM_NORMAL_MODE;
  369. }
  370. BuildGuidDataHob (
  371. &gEfiPlatformBootModeGuid,
  372. &PlatformSetupId,
  373. sizeof (EFI_PLATFORM_SETUP_ID)
  374. );
  375. return;
  376. }