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
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
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.
21 #include "FrontPage.h"
23 #include "HwErrRecSupport.h"
26 /// BDS arch protocol instance initial value.
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
33 EFI_BDS_ARCH_PROTOCOL_INSTANCE gBdsInstanceTemplate
= {
34 EFI_BDS_ARCH_PROTOCOL_INSTANCE_SIGNATURE
,
43 UINT16
*mBootNext
= NULL
;
45 EFI_HANDLE mBdsImageHandle
;
49 Install Boot Device Selection Protocol
51 @param ImageHandle The image handle.
52 @param SystemTable The system table.
54 @retval EFI_SUCEESS BDS has finished initializing.
55 Return the dispatcher and recall BDS.Entry
56 @retval Other Return status from AllocatePool() or gBS->InstallProtocolInterface
62 IN EFI_HANDLE ImageHandle
,
63 IN EFI_SYSTEM_TABLE
*SystemTable
68 mBdsImageHandle
= ImageHandle
;
71 // Install protocol interface
73 Status
= gBS
->InstallProtocolInterface (
74 &gBdsInstanceTemplate
.Handle
,
75 &gEfiBdsArchProtocolGuid
,
77 &gBdsInstanceTemplate
.Bds
79 ASSERT_EFI_ERROR (Status
);
86 This function attempts to boot for the boot order specified
97 BDS_COMMON_OPTION
*BootOption
;
101 LIST_ENTRY BootLists
;
103 BOOLEAN BootNextExist
;
104 LIST_ENTRY
*LinkBootNext
;
107 // Got the latest boot option
109 BootNextExist
= FALSE
;
111 InitializeListHead (&BootLists
);
114 // First check the boot next option
116 ZeroMem (Buffer
, sizeof (Buffer
));
118 if (mBootNext
!= NULL
) {
120 // Indicate we have the boot next variable, so this time
121 // boot will always have this boot option
123 BootNextExist
= TRUE
;
126 // Clear the this variable so it's only exist in this time boot
130 &gEfiGlobalVariableGuid
,
131 EFI_VARIABLE_BOOTSERVICE_ACCESS
| EFI_VARIABLE_RUNTIME_ACCESS
| EFI_VARIABLE_NON_VOLATILE
,
137 // Add the boot next boot option
139 UnicodeSPrint (Buffer
, sizeof (Buffer
), L
"Boot%04x", *mBootNext
);
140 BootOption
= BdsLibVariableToOption (&BootLists
, Buffer
);
143 // If fail to get boot option from variable, just return and do nothing.
145 if (BootOption
== NULL
) {
149 BootOption
->BootCurrent
= *mBootNext
;
152 // Parse the boot order to get boot option
154 BdsLibBuildOptionFromVar (&BootLists
, L
"BootOrder");
155 Link
= BootLists
.ForwardLink
;
158 // Parameter check, make sure the loop will be valid
164 // Here we make the boot in a loop, every boot success will
165 // return to the front page
169 // Check the boot option list first
171 if (Link
== &BootLists
) {
173 // There are two ways to enter here:
174 // 1. There is no active boot option, give user chance to
175 // add new boot option
176 // 2. All the active boot option processed, and there is no
177 // one is success to boot, then we back here to allow user
178 // add new active boot option
181 PlatformBdsEnterFrontPage (Timeout
, FALSE
);
182 InitializeListHead (&BootLists
);
183 BdsLibBuildOptionFromVar (&BootLists
, L
"BootOrder");
184 Link
= BootLists
.ForwardLink
;
188 // Get the boot option from the link list
190 BootOption
= CR (Link
, BDS_COMMON_OPTION
, Link
, BDS_LOAD_OPTION_SIGNATURE
);
193 // According to EFI Specification, if a load option is not marked
194 // as LOAD_OPTION_ACTIVE, the boot manager will not automatically
197 if (!IS_LOAD_OPTION_TYPE (BootOption
->Attribute
, LOAD_OPTION_ACTIVE
)) {
199 // skip the header of the link list, becuase it has no boot option
201 Link
= Link
->ForwardLink
;
205 // Make sure the boot option device path connected,
206 // but ignore the BBS device path
208 if (DevicePathType (BootOption
->DevicePath
) != BBS_DEVICE_PATH
) {
210 // Notes: the internal shell can not been connected with device path
211 // so we do not check the status here
213 BdsLibConnectDevicePath (BootOption
->DevicePath
);
216 // All the driver options should have been processed since
217 // now boot will be performed.
219 Status
= BdsLibBootViaBootOption (BootOption
, BootOption
->DevicePath
, &ExitDataSize
, &ExitData
);
220 if (EFI_ERROR (Status
)) {
222 // Call platform action to indicate the boot fail
224 BootOption
->StatusString
= GetStringById (STRING_TOKEN (STR_BOOT_FAILED
));
225 PlatformBdsBootFail (BootOption
, Status
, ExitData
, ExitDataSize
);
228 // Check the next boot option
230 Link
= Link
->ForwardLink
;
234 // Call platform action to indicate the boot success
236 BootOption
->StatusString
= GetStringById (STRING_TOKEN (STR_BOOT_SUCCEEDED
));
237 PlatformBdsBootSuccess (BootOption
);
240 // Boot success, then stop process the boot order, and
241 // present the boot manager menu, front page
244 PlatformBdsEnterFrontPage (Timeout
, FALSE
);
247 // Rescan the boot option list, avoid pertential risk of the boot
248 // option change in front page
251 LinkBootNext
= BootLists
.ForwardLink
;
254 InitializeListHead (&BootLists
);
255 if (LinkBootNext
!= NULL
) {
257 // Reserve the boot next option
259 InsertTailList (&BootLists
, LinkBootNext
);
262 BdsLibBuildOptionFromVar (&BootLists
, L
"BootOrder");
263 Link
= BootLists
.ForwardLink
;
271 Service routine for BdsInstance->Entry(). Devices are connected, the
272 consoles are initialized, and the boot options are tried.
274 @param This Protocol Instance structure.
280 IN EFI_BDS_ARCH_PROTOCOL
*This
283 EFI_BDS_ARCH_PROTOCOL_INSTANCE
*PrivateData
;
284 LIST_ENTRY DriverOptionList
;
285 LIST_ENTRY BootOptionList
;
289 // Insert the performance probe
291 PERF_END (0, "DXE", NULL
, 0);
292 PERF_START (0, "BDS", NULL
, 0);
295 // Initialize the global system boot option and driver option
297 InitializeListHead (&DriverOptionList
);
298 InitializeListHead (&BootOptionList
);
301 // Initialize hotkey service
303 InitializeHotkeyService ();
306 // Get the BDS private data
308 PrivateData
= EFI_BDS_ARCH_PROTOCOL_INSTANCE_FROM_THIS (This
);
311 // Do the platform init, can be customized by OEM/IBV
313 PERF_START (0, "PlatformBds", "BDS", 0);
314 PlatformBdsInit (PrivateData
);
316 InitializeHwErrRecSupport();
319 // bugbug: platform specific code
320 // Initialize the platform specific string and language
322 InitializeStringSupport ();
323 InitializeLanguage (TRUE
);
324 InitializeFrontPage (TRUE
);
327 // Set up the device list based on EFI 1.1 variables
328 // process Driver#### and Load the driver's in the
329 // driver option list
331 BdsLibBuildOptionFromVar (&DriverOptionList
, L
"DriverOrder");
332 if (!IsListEmpty (&DriverOptionList
)) {
333 BdsLibLoadDrivers (&DriverOptionList
);
336 // Check if we have the boot next option
338 mBootNext
= BdsLibGetVariableAndSize (
340 &gEfiGlobalVariableGuid
,
345 // Setup some platform policy here
347 PlatformBdsPolicyBehavior (PrivateData
, &DriverOptionList
, &BootOptionList
);
348 PERF_END (0, "PlatformBds", "BDS", 0);
351 // BDS select the boot device to load OS
353 BdsBootDeviceSelect ();
356 // Only assert here since this is the right behavior, we should never
357 // return back to DxeCore.