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
;
123 Peform the boot mode determination logic
124 If the box is closed, then
125 1. If it's first time to boot, it's boot with full config .
126 2. If the ChassisIntrution is selected, force to be a boot with full config
127 3. Otherwise it's boot with no change.
129 @param PeiServices General purpose services available to every PEIM.
131 @param BootMode The detected boot mode.
133 @retval EFI_SUCCESS if the boot mode could be set
137 IN EFI_PEI_SERVICES
**PeiServices
,
138 OUT EFI_BOOT_MODE
*BootMode
142 EFI_BOOT_MODE NewBootMode
;
143 PEI_CAPSULE_PPI
*Capsule
;
146 NewBootMode
= *BootMode
;
149 // Read Sticky R/W Bits
151 RegValue
= QNCAltPortRead (QUARK_SCSS_SOC_UNIT_SB_PORT_ID
, QUARK_SCSS_SOC_UNIT_CFG_STICKY_RW
);
152 DEBUG ((EFI_D_ERROR
, "RegValue = %08x\n", RegValue
));
155 // Check if we need to boot in recovery mode
157 if ((RegValue
& B_CFG_STICKY_RW_FORCE_RECOVERY
) != 0) {
158 NewBootMode
= BOOT_IN_RECOVERY_MODE
;
159 DEBUG ((EFI_D_ERROR
, "RECOVERY from sticky bit\n"));;
162 // Clear force recovery sticky bit
165 QUARK_SCSS_SOC_UNIT_SB_PORT_ID
,
166 QUARK_SCSS_SOC_UNIT_CFG_STICKY_RW
,
167 RegValue
&(~B_CFG_STICKY_RW_FORCE_RECOVERY
)
170 } else if (ValidateFvHeader (BootMode
) != EFI_SUCCESS
) {
171 NewBootMode
= BOOT_IN_RECOVERY_MODE
;
172 DEBUG ((EFI_D_ERROR
, "RECOVERY from corrupt FV\n"));;
173 } else if (QNCCheckS3AndClearState ()) {
175 // Determine if we're in capsule update mode
177 Status
= PeiServicesLocatePpi (
183 if (Status
== EFI_SUCCESS
) {
184 Status
= Capsule
->CheckCapsuleUpdate (PeiServices
);
185 if (Status
== EFI_SUCCESS
) {
186 DEBUG ((EFI_D_INFO
, "Boot mode Flash Update\n"));
187 NewBootMode
= BOOT_ON_FLASH_UPDATE
;
189 DEBUG ((EFI_D_INFO
, "Boot mode S3 resume\n"));
190 NewBootMode
= BOOT_ON_S3_RESUME
;
193 DEBUG ((EFI_D_INFO
, "Boot mode S3 resume\n"));
194 NewBootMode
= BOOT_ON_S3_RESUME
;
198 // Check if this is a power on reset
200 if (QNCCheckPowerOnResetAndClearState ()) {
201 DEBUG ((EFI_D_INFO
, "Power On Reset\n"));
203 if (IsBootWithNoChange (PeiServices
)) {
204 DEBUG ((EFI_D_INFO
, "Boot with Minimum cfg\n"));
205 NewBootMode
= BOOT_ASSUMING_NO_CONFIGURATION_CHANGES
;
207 DEBUG ((EFI_D_INFO
, "Boot with Full cfg\n"));
208 NewBootMode
= BOOT_WITH_FULL_CONFIGURATION
;
212 if (NewBootMode
== BOOT_IN_RECOVERY_MODE
) {
213 DEBUG ((EFI_D_INFO
, "Boot mode recovery\n"));
214 Status
= PeiServicesInstallPpi (&mPpiListRecoveryBootMode
);
215 ASSERT_EFI_ERROR (Status
);
218 Status
= PeiServicesSetBootMode (NewBootMode
);
219 ASSERT_EFI_ERROR (Status
);
221 *BootMode
= NewBootMode
;