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_HANDLE gBdsHandle
= NULL
;
35 EFI_BDS_ARCH_PROTOCOL gBds
= {
39 UINT16
*mBootNext
= NULL
;
41 EFI_HANDLE mBdsImageHandle
;
45 Install Boot Device Selection Protocol
47 @param ImageHandle The image handle.
48 @param SystemTable The system table.
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
58 IN EFI_HANDLE ImageHandle
,
59 IN EFI_SYSTEM_TABLE
*SystemTable
64 mBdsImageHandle
= ImageHandle
;
67 // Install protocol interface
69 Status
= gBS
->InstallMultipleProtocolInterfaces (
71 &gEfiBdsArchProtocolGuid
, &gBds
,
74 ASSERT_EFI_ERROR (Status
);
81 This function attempts to boot for the boot order specified
92 BDS_COMMON_OPTION
*BootOption
;
98 BOOLEAN BootNextExist
;
99 LIST_ENTRY
*LinkBootNext
;
102 // Got the latest boot option
104 BootNextExist
= FALSE
;
106 InitializeListHead (&BootLists
);
109 // First check the boot next option
111 ZeroMem (Buffer
, sizeof (Buffer
));
113 if (mBootNext
!= NULL
) {
115 // Indicate we have the boot next variable, so this time
116 // boot will always have this boot option
118 BootNextExist
= TRUE
;
121 // Clear the this variable so it's only exist in this time boot
125 &gEfiGlobalVariableGuid
,
126 EFI_VARIABLE_BOOTSERVICE_ACCESS
| EFI_VARIABLE_RUNTIME_ACCESS
| EFI_VARIABLE_NON_VOLATILE
,
132 // Add the boot next boot option
134 UnicodeSPrint (Buffer
, sizeof (Buffer
), L
"Boot%04x", *mBootNext
);
135 BootOption
= BdsLibVariableToOption (&BootLists
, Buffer
);
138 // If fail to get boot option from variable, just return and do nothing.
140 if (BootOption
== NULL
) {
144 BootOption
->BootCurrent
= *mBootNext
;
147 // Parse the boot order to get boot option
149 BdsLibBuildOptionFromVar (&BootLists
, L
"BootOrder");
150 Link
= BootLists
.ForwardLink
;
153 // Parameter check, make sure the loop will be valid
159 // Here we make the boot in a loop, every boot success will
160 // return to the front page
164 // Check the boot option list first
166 if (Link
== &BootLists
) {
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
176 PlatformBdsEnterFrontPage (Timeout
, FALSE
);
177 InitializeListHead (&BootLists
);
178 BdsLibBuildOptionFromVar (&BootLists
, L
"BootOrder");
179 Link
= BootLists
.ForwardLink
;
183 // Get the boot option from the link list
185 BootOption
= CR (Link
, BDS_COMMON_OPTION
, Link
, BDS_LOAD_OPTION_SIGNATURE
);
188 // According to EFI Specification, if a load option is not marked
189 // as LOAD_OPTION_ACTIVE, the boot manager will not automatically
192 if (!IS_LOAD_OPTION_TYPE (BootOption
->Attribute
, LOAD_OPTION_ACTIVE
)) {
194 // skip the header of the link list, becuase it has no boot option
196 Link
= Link
->ForwardLink
;
200 // Make sure the boot option device path connected,
201 // but ignore the BBS device path
203 if (DevicePathType (BootOption
->DevicePath
) != BBS_DEVICE_PATH
) {
205 // Notes: the internal shell can not been connected with device path
206 // so we do not check the status here
208 BdsLibConnectDevicePath (BootOption
->DevicePath
);
211 // All the driver options should have been processed since
212 // now boot will be performed.
214 Status
= BdsLibBootViaBootOption (BootOption
, BootOption
->DevicePath
, &ExitDataSize
, &ExitData
);
215 if (EFI_ERROR (Status
)) {
217 // Call platform action to indicate the boot fail
219 BootOption
->StatusString
= GetStringById (STRING_TOKEN (STR_BOOT_FAILED
));
220 PlatformBdsBootFail (BootOption
, Status
, ExitData
, ExitDataSize
);
223 // Check the next boot option
225 Link
= Link
->ForwardLink
;
229 // Call platform action to indicate the boot success
231 BootOption
->StatusString
= GetStringById (STRING_TOKEN (STR_BOOT_SUCCEEDED
));
232 PlatformBdsBootSuccess (BootOption
);
235 // Boot success, then stop process the boot order, and
236 // present the boot manager menu, front page
239 PlatformBdsEnterFrontPage (Timeout
, FALSE
);
242 // Rescan the boot option list, avoid pertential risk of the boot
243 // option change in front page
246 LinkBootNext
= BootLists
.ForwardLink
;
249 InitializeListHead (&BootLists
);
250 if (LinkBootNext
!= NULL
) {
252 // Reserve the boot next option
254 InsertTailList (&BootLists
, LinkBootNext
);
257 BdsLibBuildOptionFromVar (&BootLists
, L
"BootOrder");
258 Link
= BootLists
.ForwardLink
;
266 Service routine for BdsInstance->Entry(). Devices are connected, the
267 consoles are initialized, and the boot options are tried.
269 @param This Protocol Instance structure.
275 IN EFI_BDS_ARCH_PROTOCOL
*This
278 LIST_ENTRY DriverOptionList
;
279 LIST_ENTRY BootOptionList
;
281 CHAR16
*FirmwareVendor
;
284 // Insert the performance probe
286 PERF_END (0, "DXE", NULL
, 0);
287 PERF_START (0, "BDS", NULL
, 0);
290 // Initialize the global system boot option and driver option
292 InitializeListHead (&DriverOptionList
);
293 InitializeListHead (&BootOptionList
);
296 // Initialize hotkey service
298 InitializeHotkeyService ();
301 // Fill in FirmwareVendor and FirmwareRevision from PCDs
303 FirmwareVendor
= (CHAR16
*)PcdGetPtr (PcdFirmwareVendor
);
304 gST
->FirmwareVendor
= AllocateRuntimeCopyPool (StrSize (FirmwareVendor
), FirmwareVendor
);
305 ASSERT (gST
->FirmwareVendor
!= NULL
);
306 gST
->FirmwareRevision
= PcdGet32 (PcdFirmwareRevision
);
309 // Fixup Tasble CRC after we updated Firmware Vendor and Revision
311 gBS
->CalculateCrc32 ((VOID
*)gST
, sizeof(EFI_SYSTEM_TABLE
), &gST
->Hdr
.CRC32
);
314 // Do the platform init, can be customized by OEM/IBV
316 PERF_START (0, "PlatformBds", "BDS", 0);
319 InitializeHwErrRecSupport();
322 // bugbug: platform specific code
323 // Initialize the platform specific string and language
325 InitializeStringSupport ();
326 InitializeLanguage (TRUE
);
327 InitializeFrontPage (TRUE
);
330 // Set up the device list based on EFI 1.1 variables
331 // process Driver#### and Load the driver's in the
332 // driver option list
334 BdsLibBuildOptionFromVar (&DriverOptionList
, L
"DriverOrder");
335 if (!IsListEmpty (&DriverOptionList
)) {
336 BdsLibLoadDrivers (&DriverOptionList
);
339 // Check if we have the boot next option
341 mBootNext
= BdsLibGetVariableAndSize (
343 &gEfiGlobalVariableGuid
,
348 // Setup some platform policy here
350 PlatformBdsPolicyBehavior (&DriverOptionList
, &BootOptionList
);
351 PERF_END (0, "PlatformBds", "BDS", 0);
354 // BDS select the boot device to load OS
356 BdsBootDeviceSelect ();
359 // Only assert here since this is the right behavior, we should never
360 // return back to DxeCore.