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
;
43 extern EFI_STATUS
BdsMemoryTest (EXTENDMEM_COVERAGE_LEVEL Level
);
44 extern EFI_STATUS
ProcessCapsules (EFI_BOOT_MODE BootMode
);
48 Install Boot Device Selection Protocol
50 @param ImageHandle The image handle.
51 @param SystemTable The system table.
53 @retval EFI_SUCEESS BDS has finished initializing.
54 Return the dispatcher and recall BDS.Entry
55 @retval Other Return status from AllocatePool() or gBS->InstallProtocolInterface
61 IN EFI_HANDLE ImageHandle
,
62 IN EFI_SYSTEM_TABLE
*SystemTable
67 mBdsImageHandle
= ImageHandle
;
70 // Install protocol interface
72 Status
= gBS
->InstallMultipleProtocolInterfaces (
74 &gEfiBdsArchProtocolGuid
, &gBds
,
77 ASSERT_EFI_ERROR (Status
);
84 This function attempts to boot for the boot order specified
95 BDS_COMMON_OPTION
*BootOption
;
101 BOOLEAN BootNextExist
;
102 LIST_ENTRY
*LinkBootNext
;
105 // Got the latest boot option
107 BootNextExist
= FALSE
;
109 InitializeListHead (&BootLists
);
112 // First check the boot next option
114 ZeroMem (Buffer
, sizeof (Buffer
));
116 if (mBootNext
!= NULL
) {
118 // Indicate we have the boot next variable, so this time
119 // boot will always have this boot option
121 BootNextExist
= TRUE
;
124 // Clear the this variable so it's only exist in this time boot
128 &gEfiGlobalVariableGuid
,
129 EFI_VARIABLE_BOOTSERVICE_ACCESS
| EFI_VARIABLE_RUNTIME_ACCESS
| EFI_VARIABLE_NON_VOLATILE
,
135 // Add the boot next boot option
137 UnicodeSPrint (Buffer
, sizeof (Buffer
), L
"Boot%04x", *mBootNext
);
138 BootOption
= BdsLibVariableToOption (&BootLists
, Buffer
);
141 // If fail to get boot option from variable, just return and do nothing.
143 if (BootOption
== NULL
) {
147 BootOption
->BootCurrent
= *mBootNext
;
150 // Parse the boot order to get boot option
152 BdsLibBuildOptionFromVar (&BootLists
, L
"BootOrder");
153 Link
= BootLists
.ForwardLink
;
156 // Parameter check, make sure the loop will be valid
162 // Here we make the boot in a loop, every boot success will
163 // return to the front page
167 // Check the boot option list first
169 if (Link
== &BootLists
) {
171 // There are two ways to enter here:
172 // 1. There is no active boot option, give user chance to
173 // add new boot option
174 // 2. All the active boot option processed, and there is no
175 // one is success to boot, then we back here to allow user
176 // add new active boot option
179 PlatformBdsEnterFrontPage (Timeout
, FALSE
);
180 InitializeListHead (&BootLists
);
181 BdsLibBuildOptionFromVar (&BootLists
, L
"BootOrder");
182 Link
= BootLists
.ForwardLink
;
186 // Get the boot option from the link list
188 BootOption
= CR (Link
, BDS_COMMON_OPTION
, Link
, BDS_LOAD_OPTION_SIGNATURE
);
191 // According to EFI Specification, if a load option is not marked
192 // as LOAD_OPTION_ACTIVE, the boot manager will not automatically
195 if (!IS_LOAD_OPTION_TYPE (BootOption
->Attribute
, LOAD_OPTION_ACTIVE
)) {
197 // skip the header of the link list, becuase it has no boot option
199 Link
= Link
->ForwardLink
;
203 // Make sure the boot option device path connected,
204 // but ignore the BBS device path
206 if (DevicePathType (BootOption
->DevicePath
) != BBS_DEVICE_PATH
) {
208 // Notes: the internal shell can not been connected with device path
209 // so we do not check the status here
211 BdsLibConnectDevicePath (BootOption
->DevicePath
);
214 // All the driver options should have been processed since
215 // now boot will be performed.
217 Status
= BdsLibBootViaBootOption (BootOption
, BootOption
->DevicePath
, &ExitDataSize
, &ExitData
);
218 if (EFI_ERROR (Status
)) {
220 // Call platform action to indicate the boot fail
222 BootOption
->StatusString
= GetStringById (STRING_TOKEN (STR_BOOT_FAILED
));
223 PlatformBdsBootFail (BootOption
, Status
, ExitData
, ExitDataSize
);
226 // Check the next boot option
228 Link
= Link
->ForwardLink
;
232 // Call platform action to indicate the boot success
234 BootOption
->StatusString
= GetStringById (STRING_TOKEN (STR_BOOT_SUCCEEDED
));
235 PlatformBdsBootSuccess (BootOption
);
238 // Boot success, then stop process the boot order, and
239 // present the boot manager menu, front page
242 PlatformBdsEnterFrontPage (Timeout
, FALSE
);
245 // Rescan the boot option list, avoid pertential risk of the boot
246 // option change in front page
249 LinkBootNext
= BootLists
.ForwardLink
;
252 InitializeListHead (&BootLists
);
253 if (LinkBootNext
!= NULL
) {
255 // Reserve the boot next option
257 InsertTailList (&BootLists
, LinkBootNext
);
260 BdsLibBuildOptionFromVar (&BootLists
, L
"BootOrder");
261 Link
= BootLists
.ForwardLink
;
269 Service routine for BdsInstance->Entry(). Devices are connected, the
270 consoles are initialized, and the boot options are tried.
272 @param This Protocol Instance structure.
278 IN EFI_BDS_ARCH_PROTOCOL
*This
281 LIST_ENTRY DriverOptionList
;
282 LIST_ENTRY BootOptionList
;
284 CHAR16
*FirmwareVendor
;
287 // Insert the performance probe
289 PERF_END (NULL
, "DXE", NULL
, 0);
290 PERF_START (NULL
, "BDS", NULL
, 0);
293 // Initialize the global system boot option and driver option
295 InitializeListHead (&DriverOptionList
);
296 InitializeListHead (&BootOptionList
);
299 // Initialize hotkey service
301 InitializeHotkeyService ();
304 // Fill in FirmwareVendor and FirmwareRevision from PCDs
306 FirmwareVendor
= (CHAR16
*)PcdGetPtr (PcdFirmwareVendor
);
307 gST
->FirmwareVendor
= AllocateRuntimeCopyPool (StrSize (FirmwareVendor
), FirmwareVendor
);
308 ASSERT (gST
->FirmwareVendor
!= NULL
);
309 gST
->FirmwareRevision
= PcdGet32 (PcdFirmwareRevision
);
312 // Fixup Tasble CRC after we updated Firmware Vendor and Revision
314 gBS
->CalculateCrc32 ((VOID
*)gST
, sizeof(EFI_SYSTEM_TABLE
), &gST
->Hdr
.CRC32
);
317 // Do the platform init, can be customized by OEM/IBV
319 PERF_START (NULL
, "PlatformBds", "BDS", 0);
322 InitializeHwErrRecSupport();
325 // bugbug: platform specific code
326 // Initialize the platform specific string and language
328 InitializeStringSupport ();
329 InitializeLanguage (TRUE
);
330 InitializeFrontPage (TRUE
);
333 // Set up the device list based on EFI 1.1 variables
334 // process Driver#### and Load the driver's in the
335 // driver option list
337 BdsLibBuildOptionFromVar (&DriverOptionList
, L
"DriverOrder");
338 if (!IsListEmpty (&DriverOptionList
)) {
339 BdsLibLoadDrivers (&DriverOptionList
);
342 // Check if we have the boot next option
344 mBootNext
= BdsLibGetVariableAndSize (
346 &gEfiGlobalVariableGuid
,
351 // Setup some platform policy here
353 PlatformBdsPolicyBehavior (&DriverOptionList
, &BootOptionList
, ProcessCapsules
, BdsMemoryTest
);
354 PERF_END (NULL
, "PlatformBds", "BDS", 0);
357 // BDS select the boot device to load OS
359 BdsBootDeviceSelect ();
362 // Only assert here since this is the right behavior, we should never
363 // return back to DxeCore.