]> git.proxmox.com Git - mirror_edk2.git/blame - QuarkPlatformPkg/Platform/Pei/PlatformInit/BootMode.c
QuarkPlatformPkg: Replace BSD License with BSD+Patent License
[mirror_edk2.git] / QuarkPlatformPkg / Platform / Pei / PlatformInit / BootMode.c
CommitLineData
b303605e
MK
1/** @file\r
2This file provide the function to detect boot mode\r
3\r
4Copyright (c) 2013 Intel Corporation.\r
5\r
0eb3de2e 6SPDX-License-Identifier: BSD-2-Clause-Patent\r
b303605e
MK
7\r
8**/\r
9\r
10\r
11#include "CommonHeader.h"\r
12#include <Pi/PiFirmwareVolume.h>\r
13\r
14EFI_PEI_PPI_DESCRIPTOR mPpiListRecoveryBootMode = {\r
15 (EFI_PEI_PPI_DESCRIPTOR_PPI | EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST),\r
16 &gEfiPeiBootInRecoveryModePpiGuid,\r
17 NULL\r
18};\r
19\r
20/**\r
21 If the box was opened, it's boot with full config.\r
22 If the box is closed, then\r
23 1. If it's first time to boot, it's boot with full config .\r
24 2. If the ChassisIntrution is selected, force to be a boot with full config\r
25 3. Otherwise it's boot with no change.\r
26\r
27 @param PeiServices General purpose services available to every PEIM.\r
28\r
29 @retval TRUE If it's boot with no change.\r
30\r
31 @retval FALSE If boot with no change.\r
32**/\r
33BOOLEAN\r
34IsBootWithNoChange (\r
35 IN EFI_PEI_SERVICES **PeiServices\r
36 )\r
37{\r
38 BOOLEAN IsFirstBoot = FALSE;\r
39\r
40 BOOLEAN EnableFastBoot = FALSE;\r
41 IsFirstBoot = PcdGetBool(PcdBootState);\r
42 EnableFastBoot = PcdGetBool (PcdEnableFastBoot);\r
43\r
44 DEBUG ((EFI_D_INFO, "IsFirstBoot = %x , EnableFastBoot= %x. \n", IsFirstBoot, EnableFastBoot));\r
45\r
46 if ((!IsFirstBoot) && EnableFastBoot) {\r
47 return TRUE;\r
48 } else {\r
49 return FALSE;\r
50 }\r
51}\r
52\r
53\r
54/**\r
55\r
56Routine Description:\r
57\r
58 This function is used to verify if the FV header is validate.\r
59\r
60 @param FwVolHeader - The FV header that to be verified.\r
61\r
62 @retval EFI_SUCCESS - The Fv header is valid.\r
63 @retval EFI_NOT_FOUND - The Fv header is invalid.\r
64\r
65**/\r
66EFI_STATUS\r
67ValidateFvHeader (\r
68 EFI_BOOT_MODE *BootMode\r
69 )\r
70{\r
71 UINT16 *Ptr;\r
72 UINT16 HeaderLength;\r
73 UINT16 Checksum;\r
74\r
75 EFI_FIRMWARE_VOLUME_HEADER *FwVolHeader;\r
76\r
77 if (BOOT_IN_RECOVERY_MODE == *BootMode) {\r
78 DEBUG ((EFI_D_INFO, "Boot mode recovery\n"));\r
79 return EFI_SUCCESS;\r
80 }\r
81 //\r
82 // Let's check whether FvMain header is valid, if not enter into recovery mode\r
83 //\r
84 //\r
85 // Verify the header revision, header signature, length\r
86 // Length of FvBlock cannot be 2**64-1\r
87 // HeaderLength cannot be an odd number\r
88 //\r
89 FwVolHeader = (EFI_FIRMWARE_VOLUME_HEADER *)(UINTN)PcdGet32(PcdFlashFvMainBase);\r
90 if ((FwVolHeader->Revision != EFI_FVH_REVISION)||\r
91 (FwVolHeader->Signature != EFI_FVH_SIGNATURE) ||\r
92 (FwVolHeader->FvLength == ((UINT64) -1)) ||\r
93 ((FwVolHeader->HeaderLength & 0x01) != 0)\r
94 ) {\r
95 return EFI_NOT_FOUND;\r
96 }\r
97 //\r
98 // Verify the header checksum\r
99 //\r
100 HeaderLength = (UINT16) (FwVolHeader->HeaderLength / 2);\r
101 Ptr = (UINT16 *) FwVolHeader;\r
102 Checksum = 0;\r
103 while (HeaderLength > 0) {\r
104 Checksum = Checksum +*Ptr;\r
105 Ptr++;\r
106 HeaderLength--;\r
107 }\r
108\r
109 if (Checksum != 0) {\r
110 return EFI_NOT_FOUND;\r
111 }\r
112\r
113 return EFI_SUCCESS;\r
114}\r
115\r
b303605e
MK
116/**\r
117 Peform the boot mode determination logic\r
118 If the box is closed, then\r
119 1. If it's first time to boot, it's boot with full config .\r
120 2. If the ChassisIntrution is selected, force to be a boot with full config\r
121 3. Otherwise it's boot with no change.\r
122\r
123 @param PeiServices General purpose services available to every PEIM.\r
124\r
125 @param BootMode The detected boot mode.\r
126\r
127 @retval EFI_SUCCESS if the boot mode could be set\r
128**/\r
129EFI_STATUS\r
130UpdateBootMode (\r
131 IN EFI_PEI_SERVICES **PeiServices,\r
132 OUT EFI_BOOT_MODE *BootMode\r
133 )\r
134{\r
135 EFI_STATUS Status;\r
136 EFI_BOOT_MODE NewBootMode;\r
137 PEI_CAPSULE_PPI *Capsule;\r
69a0854b
MK
138 UINT32 RegValue;\r
139\r
140 NewBootMode = *BootMode;\r
b303605e
MK
141\r
142 //\r
69a0854b 143 // Read Sticky R/W Bits\r
b303605e 144 //\r
69a0854b
MK
145 RegValue = QNCAltPortRead (QUARK_SCSS_SOC_UNIT_SB_PORT_ID, QUARK_SCSS_SOC_UNIT_CFG_STICKY_RW);\r
146 DEBUG ((EFI_D_ERROR, "RegValue = %08x\n", RegValue));\r
b303605e
MK
147\r
148 //\r
149 // Check if we need to boot in recovery mode\r
150 //\r
69a0854b 151 if ((RegValue & B_CFG_STICKY_RW_FORCE_RECOVERY) != 0) {\r
b303605e 152 NewBootMode = BOOT_IN_RECOVERY_MODE;\r
69a0854b
MK
153 DEBUG ((EFI_D_ERROR, "RECOVERY from sticky bit\n"));;\r
154\r
155 //\r
156 // Clear force recovery sticky bit\r
157 //\r
158 QNCAltPortWrite (\r
159 QUARK_SCSS_SOC_UNIT_SB_PORT_ID,\r
160 QUARK_SCSS_SOC_UNIT_CFG_STICKY_RW,\r
161 RegValue &(~B_CFG_STICKY_RW_FORCE_RECOVERY)\r
162 );\r
163\r
164 } else if (ValidateFvHeader (BootMode) != EFI_SUCCESS) {\r
b303605e 165 NewBootMode = BOOT_IN_RECOVERY_MODE;\r
69a0854b 166 DEBUG ((EFI_D_ERROR, "RECOVERY from corrupt FV\n"));;\r
b303605e
MK
167 } else if (QNCCheckS3AndClearState ()) {\r
168 //\r
169 // Determine if we're in capsule update mode\r
170 //\r
171 Status = PeiServicesLocatePpi (\r
172 &gPeiCapsulePpiGuid,\r
173 0,\r
174 NULL,\r
175 (VOID **)&Capsule\r
176 );\r
177 if (Status == EFI_SUCCESS) {\r
178 Status = Capsule->CheckCapsuleUpdate (PeiServices);\r
179 if (Status == EFI_SUCCESS) {\r
180 DEBUG ((EFI_D_INFO, "Boot mode Flash Update\n"));\r
181 NewBootMode = BOOT_ON_FLASH_UPDATE;\r
182 } else {\r
183 DEBUG ((EFI_D_INFO, "Boot mode S3 resume\n"));\r
184 NewBootMode = BOOT_ON_S3_RESUME;\r
185 }\r
186 } else {\r
187 DEBUG ((EFI_D_INFO, "Boot mode S3 resume\n"));\r
188 NewBootMode = BOOT_ON_S3_RESUME;\r
189 }\r
190 } else {\r
191 //\r
192 // Check if this is a power on reset\r
193 //\r
194 if (QNCCheckPowerOnResetAndClearState ()) {\r
195 DEBUG ((EFI_D_INFO, "Power On Reset\n"));\r
196 }\r
197 if (IsBootWithNoChange (PeiServices)) {\r
198 DEBUG ((EFI_D_INFO, "Boot with Minimum cfg\n"));\r
199 NewBootMode = BOOT_ASSUMING_NO_CONFIGURATION_CHANGES;\r
200 } else {\r
201 DEBUG ((EFI_D_INFO, "Boot with Full cfg\n"));\r
202 NewBootMode = BOOT_WITH_FULL_CONFIGURATION;\r
203 }\r
204 }\r
b303605e 205\r
b303605e 206 if (NewBootMode == BOOT_IN_RECOVERY_MODE) {\r
69a0854b
MK
207 DEBUG ((EFI_D_INFO, "Boot mode recovery\n"));\r
208 Status = PeiServicesInstallPpi (&mPpiListRecoveryBootMode);\r
209 ASSERT_EFI_ERROR (Status);\r
b303605e
MK
210 }\r
211\r
69a0854b
MK
212 Status = PeiServicesSetBootMode (NewBootMode);\r
213 ASSERT_EFI_ERROR (Status);\r
214\r
215 *BootMode = NewBootMode;\r
216\r
b303605e
MK
217 return EFI_SUCCESS;\r
218}\r