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