]> git.proxmox.com Git - mirror_edk2.git/blob - IntelFrameworkModulePkg/Universal/BdsDxe/BdsEntry.c
Fix the potential issue that using integrate as BOOLEAN value in judgment.
[mirror_edk2.git] / IntelFrameworkModulePkg / Universal / BdsDxe / BdsEntry.c
1 /** @file
2 This module produce main entry for BDS phase - BdsEntry.
3 When this module was dispatched by DxeCore, gEfiBdsArchProtocolGuid will be installed
4 which contains interface of BdsEntry.
5 After DxeCore finish DXE phase, gEfiBdsArchProtocolGuid->BdsEntry will be invoked
6 to enter BDS phase.
7
8 Copyright (c) 2004 - 2008, Intel Corporation. <BR>
9 All rights reserved. This program and the accompanying materials
10 are licensed and made available under the terms and conditions of the BSD License
11 which accompanies this distribution. The full text of the license may be found at
12 http://opensource.org/licenses/bsd-license.php
13
14 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
15 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
16
17 **/
18
19 #include "Bds.h"
20 #include "Language.h"
21 #include "FrontPage.h"
22 #include "Hotkey.h"
23 #include "HwErrRecSupport.h"
24
25 ///
26 /// BDS arch protocol instance initial value.
27 ///
28 /// Note: Current BDS not directly get the BootMode, DefaultBoot,
29 /// TimeoutDefault, MemoryTestLevel value from the BDS arch protocol.
30 /// Please refer to the library useage of BdsLibGetBootMode, BdsLibGetTimeout
31 /// and PlatformBdsDiagnostics in BdsPlatform.c
32 ///
33 EFI_HANDLE gBdsHandle = NULL;
34
35 EFI_BDS_ARCH_PROTOCOL gBds = {
36 BdsEntry
37 };
38
39 UINT16 *mBootNext = NULL;
40
41 EFI_HANDLE mBdsImageHandle;
42
43 /**
44
45 Install Boot Device Selection Protocol
46
47 @param ImageHandle The image handle.
48 @param SystemTable The system table.
49
50 @retval EFI_SUCEESS BDS has finished initializing.
51 Return the dispatcher and recall BDS.Entry
52 @retval Other Return status from AllocatePool() or gBS->InstallProtocolInterface
53
54 **/
55 EFI_STATUS
56 EFIAPI
57 BdsInitialize (
58 IN EFI_HANDLE ImageHandle,
59 IN EFI_SYSTEM_TABLE *SystemTable
60 )
61 {
62 EFI_STATUS Status;
63
64 mBdsImageHandle = ImageHandle;
65
66 //
67 // Install protocol interface
68 //
69 Status = gBS->InstallMultipleProtocolInterfaces (
70 &gBdsHandle,
71 &gEfiBdsArchProtocolGuid, &gBds,
72 NULL
73 );
74 ASSERT_EFI_ERROR (Status);
75
76 return Status;
77 }
78
79 /**
80
81 This function attempts to boot for the boot order specified
82 by platform policy.
83
84 **/
85 VOID
86 BdsBootDeviceSelect (
87 VOID
88 )
89 {
90 EFI_STATUS Status;
91 LIST_ENTRY *Link;
92 BDS_COMMON_OPTION *BootOption;
93 UINTN ExitDataSize;
94 CHAR16 *ExitData;
95 UINT16 Timeout;
96 LIST_ENTRY BootLists;
97 CHAR16 Buffer[20];
98 BOOLEAN BootNextExist;
99 LIST_ENTRY *LinkBootNext;
100
101 //
102 // Got the latest boot option
103 //
104 BootNextExist = FALSE;
105 LinkBootNext = NULL;
106 InitializeListHead (&BootLists);
107
108 //
109 // First check the boot next option
110 //
111 ZeroMem (Buffer, sizeof (Buffer));
112
113 if (mBootNext != NULL) {
114 //
115 // Indicate we have the boot next variable, so this time
116 // boot will always have this boot option
117 //
118 BootNextExist = TRUE;
119
120 //
121 // Clear the this variable so it's only exist in this time boot
122 //
123 gRT->SetVariable (
124 L"BootNext",
125 &gEfiGlobalVariableGuid,
126 EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS | EFI_VARIABLE_NON_VOLATILE,
127 0,
128 mBootNext
129 );
130
131 //
132 // Add the boot next boot option
133 //
134 UnicodeSPrint (Buffer, sizeof (Buffer), L"Boot%04x", *mBootNext);
135 BootOption = BdsLibVariableToOption (&BootLists, Buffer);
136
137 //
138 // If fail to get boot option from variable, just return and do nothing.
139 //
140 if (BootOption == NULL) {
141 return;
142 }
143
144 BootOption->BootCurrent = *mBootNext;
145 }
146 //
147 // Parse the boot order to get boot option
148 //
149 BdsLibBuildOptionFromVar (&BootLists, L"BootOrder");
150 Link = BootLists.ForwardLink;
151
152 //
153 // Parameter check, make sure the loop will be valid
154 //
155 if (Link == NULL) {
156 return ;
157 }
158 //
159 // Here we make the boot in a loop, every boot success will
160 // return to the front page
161 //
162 for (;;) {
163 //
164 // Check the boot option list first
165 //
166 if (Link == &BootLists) {
167 //
168 // There are two ways to enter here:
169 // 1. There is no active boot option, give user chance to
170 // add new boot option
171 // 2. All the active boot option processed, and there is no
172 // one is success to boot, then we back here to allow user
173 // add new active boot option
174 //
175 Timeout = 0xffff;
176 PlatformBdsEnterFrontPage (Timeout, FALSE);
177 InitializeListHead (&BootLists);
178 BdsLibBuildOptionFromVar (&BootLists, L"BootOrder");
179 Link = BootLists.ForwardLink;
180 continue;
181 }
182 //
183 // Get the boot option from the link list
184 //
185 BootOption = CR (Link, BDS_COMMON_OPTION, Link, BDS_LOAD_OPTION_SIGNATURE);
186
187 //
188 // According to EFI Specification, if a load option is not marked
189 // as LOAD_OPTION_ACTIVE, the boot manager will not automatically
190 // load the option.
191 //
192 if (!IS_LOAD_OPTION_TYPE (BootOption->Attribute, LOAD_OPTION_ACTIVE)) {
193 //
194 // skip the header of the link list, becuase it has no boot option
195 //
196 Link = Link->ForwardLink;
197 continue;
198 }
199 //
200 // Make sure the boot option device path connected,
201 // but ignore the BBS device path
202 //
203 if (DevicePathType (BootOption->DevicePath) != BBS_DEVICE_PATH) {
204 //
205 // Notes: the internal shell can not been connected with device path
206 // so we do not check the status here
207 //
208 BdsLibConnectDevicePath (BootOption->DevicePath);
209 }
210 //
211 // All the driver options should have been processed since
212 // now boot will be performed.
213 //
214 Status = BdsLibBootViaBootOption (BootOption, BootOption->DevicePath, &ExitDataSize, &ExitData);
215 if (EFI_ERROR (Status)) {
216 //
217 // Call platform action to indicate the boot fail
218 //
219 BootOption->StatusString = GetStringById (STRING_TOKEN (STR_BOOT_FAILED));
220 PlatformBdsBootFail (BootOption, Status, ExitData, ExitDataSize);
221
222 //
223 // Check the next boot option
224 //
225 Link = Link->ForwardLink;
226
227 } else {
228 //
229 // Call platform action to indicate the boot success
230 //
231 BootOption->StatusString = GetStringById (STRING_TOKEN (STR_BOOT_SUCCEEDED));
232 PlatformBdsBootSuccess (BootOption);
233
234 //
235 // Boot success, then stop process the boot order, and
236 // present the boot manager menu, front page
237 //
238 Timeout = 0xffff;
239 PlatformBdsEnterFrontPage (Timeout, FALSE);
240
241 //
242 // Rescan the boot option list, avoid pertential risk of the boot
243 // option change in front page
244 //
245 if (BootNextExist) {
246 LinkBootNext = BootLists.ForwardLink;
247 }
248
249 InitializeListHead (&BootLists);
250 if (LinkBootNext != NULL) {
251 //
252 // Reserve the boot next option
253 //
254 InsertTailList (&BootLists, LinkBootNext);
255 }
256
257 BdsLibBuildOptionFromVar (&BootLists, L"BootOrder");
258 Link = BootLists.ForwardLink;
259 }
260 }
261
262 }
263
264 /**
265
266 Service routine for BdsInstance->Entry(). Devices are connected, the
267 consoles are initialized, and the boot options are tried.
268
269 @param This Protocol Instance structure.
270
271 **/
272 VOID
273 EFIAPI
274 BdsEntry (
275 IN EFI_BDS_ARCH_PROTOCOL *This
276 )
277 {
278 LIST_ENTRY DriverOptionList;
279 LIST_ENTRY BootOptionList;
280 UINTN BootNextSize;
281
282 //
283 // Insert the performance probe
284 //
285 PERF_END (0, "DXE", NULL, 0);
286 PERF_START (0, "BDS", NULL, 0);
287
288 //
289 // Initialize the global system boot option and driver option
290 //
291 InitializeListHead (&DriverOptionList);
292 InitializeListHead (&BootOptionList);
293
294 //
295 // Initialize hotkey service
296 //
297 InitializeHotkeyService ();
298
299 //
300 // Do the platform init, can be customized by OEM/IBV
301 //
302 PERF_START (0, "PlatformBds", "BDS", 0);
303 PlatformBdsInit ();
304
305 InitializeHwErrRecSupport();
306
307 //
308 // bugbug: platform specific code
309 // Initialize the platform specific string and language
310 //
311 InitializeStringSupport ();
312 InitializeLanguage (TRUE);
313 InitializeFrontPage (TRUE);
314
315 //
316 // Set up the device list based on EFI 1.1 variables
317 // process Driver#### and Load the driver's in the
318 // driver option list
319 //
320 BdsLibBuildOptionFromVar (&DriverOptionList, L"DriverOrder");
321 if (!IsListEmpty (&DriverOptionList)) {
322 BdsLibLoadDrivers (&DriverOptionList);
323 }
324 //
325 // Check if we have the boot next option
326 //
327 mBootNext = BdsLibGetVariableAndSize (
328 L"BootNext",
329 &gEfiGlobalVariableGuid,
330 &BootNextSize
331 );
332
333 //
334 // Setup some platform policy here
335 //
336 PlatformBdsPolicyBehavior (&DriverOptionList, &BootOptionList);
337 PERF_END (0, "PlatformBds", "BDS", 0);
338
339 //
340 // BDS select the boot device to load OS
341 //
342 BdsBootDeviceSelect ();
343
344 //
345 // Only assert here since this is the right behavior, we should never
346 // return back to DxeCore.
347 //
348 ASSERT (FALSE);
349
350 return ;
351 }