2 This file provide the function to detect boot mode
4 Copyright (c) 2013 Intel Corporation.
6 This program and the accompanying materials
7 are licensed and made available under the terms and conditions of the BSD License
8 which accompanies this distribution. The full text of the license may be found at
9 http://opensource.org/licenses/bsd-license.php
11 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
12 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
17 #include "CommonHeader.h"
18 #include <Pi/PiFirmwareVolume.h>
20 EFI_PEI_PPI_DESCRIPTOR mPpiListRecoveryBootMode
= {
21 (EFI_PEI_PPI_DESCRIPTOR_PPI
| EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST
),
22 &gEfiPeiBootInRecoveryModePpiGuid
,
27 If the box was opened, it's boot with full config.
28 If the box is closed, then
29 1. If it's first time to boot, it's boot with full config .
30 2. If the ChassisIntrution is selected, force to be a boot with full config
31 3. Otherwise it's boot with no change.
33 @param PeiServices General purpose services available to every PEIM.
35 @retval TRUE If it's boot with no change.
37 @retval FALSE If boot with no change.
41 IN EFI_PEI_SERVICES
**PeiServices
44 BOOLEAN IsFirstBoot
= FALSE
;
46 BOOLEAN EnableFastBoot
= FALSE
;
47 IsFirstBoot
= PcdGetBool(PcdBootState
);
48 EnableFastBoot
= PcdGetBool (PcdEnableFastBoot
);
50 DEBUG ((EFI_D_INFO
, "IsFirstBoot = %x , EnableFastBoot= %x. \n", IsFirstBoot
, EnableFastBoot
));
52 if ((!IsFirstBoot
) && EnableFastBoot
) {
64 This function is used to verify if the FV header is validate.
66 @param FwVolHeader - The FV header that to be verified.
68 @retval EFI_SUCCESS - The Fv header is valid.
69 @retval EFI_NOT_FOUND - The Fv header is invalid.
74 EFI_BOOT_MODE
*BootMode
81 EFI_FIRMWARE_VOLUME_HEADER
*FwVolHeader
;
83 if (BOOT_IN_RECOVERY_MODE
== *BootMode
) {
84 DEBUG ((EFI_D_INFO
, "Boot mode recovery\n"));
88 // Let's check whether FvMain header is valid, if not enter into recovery mode
91 // Verify the header revision, header signature, length
92 // Length of FvBlock cannot be 2**64-1
93 // HeaderLength cannot be an odd number
95 FwVolHeader
= (EFI_FIRMWARE_VOLUME_HEADER
*)(UINTN
)PcdGet32(PcdFlashFvMainBase
);
96 if ((FwVolHeader
->Revision
!= EFI_FVH_REVISION
)||
97 (FwVolHeader
->Signature
!= EFI_FVH_SIGNATURE
) ||
98 (FwVolHeader
->FvLength
== ((UINT64
) -1)) ||
99 ((FwVolHeader
->HeaderLength
& 0x01) != 0)
101 return EFI_NOT_FOUND
;
104 // Verify the header checksum
106 HeaderLength
= (UINT16
) (FwVolHeader
->HeaderLength
/ 2);
107 Ptr
= (UINT16
*) FwVolHeader
;
109 while (HeaderLength
> 0) {
110 Checksum
= Checksum
+*Ptr
;
116 return EFI_NOT_FOUND
;
124 Check whether go to recovery path
125 @retval TRUE Go to recovery path
126 @retval FALSE Go to normal path
130 OemRecoveryBootMode ()
132 return PlatformIsBootWithRecoveryStage1 ();
136 Peform the boot mode determination logic
137 If the box is closed, then
138 1. If it's first time to boot, it's boot with full config .
139 2. If the ChassisIntrution is selected, force to be a boot with full config
140 3. Otherwise it's boot with no change.
142 @param PeiServices General purpose services available to every PEIM.
144 @param BootMode The detected boot mode.
146 @retval EFI_SUCCESS if the boot mode could be set
150 IN EFI_PEI_SERVICES
**PeiServices
,
151 OUT EFI_BOOT_MODE
*BootMode
155 EFI_BOOT_MODE NewBootMode
;
156 PEI_CAPSULE_PPI
*Capsule
;
161 // Read Straps. Used later if recovery boot.
163 Straps32
= QNCAltPortRead (QUARK_SCSS_SOC_UNIT_SB_PORT_ID
, QUARK_SCSS_SOC_UNIT_STPDDRCFG
);
166 // Check if we need to boot in recovery mode
168 if ((ValidateFvHeader (BootMode
) != EFI_SUCCESS
)) {
169 DEBUG ((EFI_D_INFO
, "Force Boot mode recovery\n"));
170 NewBootMode
= BOOT_IN_RECOVERY_MODE
;
171 Status
= PeiServicesInstallPpi (&mPpiListRecoveryBootMode
);
172 ASSERT_EFI_ERROR (Status
);
173 if (OemRecoveryBootMode () == FALSE
) {
174 DEBUG ((EFI_D_INFO
, "Recovery stage1 not Active, reboot to activate recovery stage1 image\n"));
175 OemInitiateRecoveryAndWait ();
177 } else if (OemRecoveryBootMode ()) {
178 DEBUG ((EFI_D_INFO
, "Boot mode recovery\n"));
179 NewBootMode
= BOOT_IN_RECOVERY_MODE
;
180 Status
= PeiServicesInstallPpi (&mPpiListRecoveryBootMode
);
181 ASSERT_EFI_ERROR (Status
);
182 } else if (QNCCheckS3AndClearState ()) {
184 // Determine if we're in capsule update mode
186 Status
= PeiServicesLocatePpi (
192 if (Status
== EFI_SUCCESS
) {
193 Status
= Capsule
->CheckCapsuleUpdate (PeiServices
);
194 if (Status
== EFI_SUCCESS
) {
195 DEBUG ((EFI_D_INFO
, "Boot mode Flash Update\n"));
196 NewBootMode
= BOOT_ON_FLASH_UPDATE
;
198 DEBUG ((EFI_D_INFO
, "Boot mode S3 resume\n"));
199 NewBootMode
= BOOT_ON_S3_RESUME
;
202 DEBUG ((EFI_D_INFO
, "Boot mode S3 resume\n"));
203 NewBootMode
= BOOT_ON_S3_RESUME
;
207 // Check if this is a power on reset
209 if (QNCCheckPowerOnResetAndClearState ()) {
210 DEBUG ((EFI_D_INFO
, "Power On Reset\n"));
212 if (IsBootWithNoChange (PeiServices
)) {
213 DEBUG ((EFI_D_INFO
, "Boot with Minimum cfg\n"));
214 NewBootMode
= BOOT_ASSUMING_NO_CONFIGURATION_CHANGES
;
216 DEBUG ((EFI_D_INFO
, "Boot with Full cfg\n"));
217 NewBootMode
= BOOT_WITH_FULL_CONFIGURATION
;
220 *BootMode
= NewBootMode
;
221 Status
= PeiServicesSetBootMode (NewBootMode
);
222 ASSERT_EFI_ERROR (Status
);
225 // If Recovery Boot then prompt the user to insert a USB key with recovery nodule and
226 // continue with the recovery. Also give the user a chance to retry a normal boot.
228 if (NewBootMode
== BOOT_IN_RECOVERY_MODE
) {
229 if ((Straps32
& B_STPDDRCFG_FORCE_RECOVERY
) == 0) {
230 DEBUG ((EFI_D_ERROR
, "*****************************************************************\n"));
231 DEBUG ((EFI_D_ERROR
, "***** Force Recovery Jumper Detected. *****\n"));
232 DEBUG ((EFI_D_ERROR
, "***** Attempting auto recovery of system flash. *****\n"));
233 DEBUG ((EFI_D_ERROR
, "***** Expecting USB key with recovery module connected. *****\n"));
234 DEBUG ((EFI_D_ERROR
, "***** PLEASE REMOVE FORCE RECOVERY JUMPER. *****\n"));
235 DEBUG ((EFI_D_ERROR
, "*****************************************************************\n"));
237 DEBUG ((EFI_D_ERROR
, "*****************************************************************\n"));
238 DEBUG ((EFI_D_ERROR
, "***** ERROR: System boot failure!!!!!!! *****\n"));
239 DEBUG ((EFI_D_ERROR
, "***** - Press 'R' if you wish to force system recovery *****\n"));
240 DEBUG ((EFI_D_ERROR
, "***** (connect USB key with recovery module first) *****\n"));
241 DEBUG ((EFI_D_ERROR
, "***** - Press any other key to attempt another boot *****\n"));
242 DEBUG ((EFI_D_ERROR
, "*****************************************************************\n"));
244 UserSelection
= PlatformDebugPortGetChar8 ();
245 if ((UserSelection
!= 'R') && (UserSelection
!= 'r')) {
246 DEBUG ((EFI_D_ERROR
, "New boot attempt selected........\n"));
248 // Initialte the cold reset
252 DEBUG ((EFI_D_ERROR
, "Recovery boot selected..........\n"));