]> git.proxmox.com Git - mirror_edk2.git/blob - IntelFrameworkModulePkg/Universal/BdsDxe/BdsEntry.c
774049c8c103f736f74ce745ac22ccbfad4c3a31
[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 - 2011, Intel Corporation. All rights reserved.<BR>
9 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 /**
42
43 Install Boot Device Selection Protocol
44
45 @param ImageHandle The image handle.
46 @param SystemTable The system table.
47
48 @retval EFI_SUCEESS BDS has finished initializing.
49 Return the dispatcher and recall BDS.Entry
50 @retval Other Return status from AllocatePool() or gBS->InstallProtocolInterface
51
52 **/
53 EFI_STATUS
54 EFIAPI
55 BdsInitialize (
56 IN EFI_HANDLE ImageHandle,
57 IN EFI_SYSTEM_TABLE *SystemTable
58 )
59 {
60 EFI_STATUS Status;
61
62 //
63 // Install protocol interface
64 //
65 Status = gBS->InstallMultipleProtocolInterfaces (
66 &gBdsHandle,
67 &gEfiBdsArchProtocolGuid, &gBds,
68 NULL
69 );
70 ASSERT_EFI_ERROR (Status);
71
72 return Status;
73 }
74
75 /**
76
77 This function attempts to boot for the boot order specified
78 by platform policy.
79
80 **/
81 VOID
82 BdsBootDeviceSelect (
83 VOID
84 )
85 {
86 EFI_STATUS Status;
87 LIST_ENTRY *Link;
88 BDS_COMMON_OPTION *BootOption;
89 UINTN ExitDataSize;
90 CHAR16 *ExitData;
91 UINT16 Timeout;
92 LIST_ENTRY BootLists;
93 CHAR16 Buffer[20];
94 BOOLEAN BootNextExist;
95 LIST_ENTRY *LinkBootNext;
96
97 //
98 // Got the latest boot option
99 //
100 BootNextExist = FALSE;
101 LinkBootNext = NULL;
102 InitializeListHead (&BootLists);
103
104 //
105 // First check the boot next option
106 //
107 ZeroMem (Buffer, sizeof (Buffer));
108
109 if (mBootNext != NULL) {
110 //
111 // Indicate we have the boot next variable, so this time
112 // boot will always have this boot option
113 //
114 BootNextExist = TRUE;
115
116 //
117 // Clear the this variable so it's only exist in this time boot
118 //
119 gRT->SetVariable (
120 L"BootNext",
121 &gEfiGlobalVariableGuid,
122 EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS | EFI_VARIABLE_NON_VOLATILE,
123 0,
124 mBootNext
125 );
126
127 //
128 // Add the boot next boot option
129 //
130 UnicodeSPrint (Buffer, sizeof (Buffer), L"Boot%04x", *mBootNext);
131 BootOption = BdsLibVariableToOption (&BootLists, Buffer);
132
133 //
134 // If fail to get boot option from variable, just return and do nothing.
135 //
136 if (BootOption == NULL) {
137 return;
138 }
139
140 BootOption->BootCurrent = *mBootNext;
141 }
142 //
143 // Parse the boot order to get boot option
144 //
145 BdsLibBuildOptionFromVar (&BootLists, L"BootOrder");
146
147 //
148 // When we didn't have chance to build boot option variables in the first
149 // full configuration boot (e.g.: Reset in the first page or in Device Manager),
150 // we have no boot options in the following mini configuration boot.
151 // Give the last chance to enumerate the boot options.
152 //
153 if (IsListEmpty (&BootLists)) {
154 BdsLibEnumerateAllBootOption (&BootLists);
155 }
156
157 Link = BootLists.ForwardLink;
158
159 //
160 // Parameter check, make sure the loop will be valid
161 //
162 if (Link == NULL) {
163 return ;
164 }
165 //
166 // Here we make the boot in a loop, every boot success will
167 // return to the front page
168 //
169 for (;;) {
170 //
171 // Check the boot option list first
172 //
173 if (Link == &BootLists) {
174 //
175 // There are two ways to enter here:
176 // 1. There is no active boot option, give user chance to
177 // add new boot option
178 // 2. All the active boot option processed, and there is no
179 // one is success to boot, then we back here to allow user
180 // add new active boot option
181 //
182 Timeout = 0xffff;
183 PlatformBdsEnterFrontPage (Timeout, FALSE);
184 InitializeListHead (&BootLists);
185 BdsLibBuildOptionFromVar (&BootLists, L"BootOrder");
186 Link = BootLists.ForwardLink;
187 continue;
188 }
189 //
190 // Get the boot option from the link list
191 //
192 BootOption = CR (Link, BDS_COMMON_OPTION, Link, BDS_LOAD_OPTION_SIGNATURE);
193
194 //
195 // According to EFI Specification, if a load option is not marked
196 // as LOAD_OPTION_ACTIVE, the boot manager will not automatically
197 // load the option.
198 //
199 if (!IS_LOAD_OPTION_TYPE (BootOption->Attribute, LOAD_OPTION_ACTIVE)) {
200 //
201 // skip the header of the link list, because it has no boot option
202 //
203 Link = Link->ForwardLink;
204 continue;
205 }
206 //
207 // Make sure the boot option device path connected,
208 // but ignore the BBS device path
209 //
210 if (DevicePathType (BootOption->DevicePath) != BBS_DEVICE_PATH) {
211 //
212 // Notes: the internal shell can not been connected with device path
213 // so we do not check the status here
214 //
215 BdsLibConnectDevicePath (BootOption->DevicePath);
216 }
217 //
218 // All the driver options should have been processed since
219 // now boot will be performed.
220 //
221 Status = BdsLibBootViaBootOption (BootOption, BootOption->DevicePath, &ExitDataSize, &ExitData);
222 if (Status != EFI_SUCCESS) {
223 //
224 // Call platform action to indicate the boot fail
225 //
226 BootOption->StatusString = GetStringById (STRING_TOKEN (STR_BOOT_FAILED));
227 PlatformBdsBootFail (BootOption, Status, ExitData, ExitDataSize);
228
229 //
230 // Check the next boot option
231 //
232 Link = Link->ForwardLink;
233
234 } else {
235 //
236 // Call platform action to indicate the boot success
237 //
238 BootOption->StatusString = GetStringById (STRING_TOKEN (STR_BOOT_SUCCEEDED));
239 PlatformBdsBootSuccess (BootOption);
240
241 //
242 // Boot success, then stop process the boot order, and
243 // present the boot manager menu, front page
244 //
245 Timeout = 0xffff;
246 PlatformBdsEnterFrontPage (Timeout, FALSE);
247
248 //
249 // Rescan the boot option list, avoid potential risk of the boot
250 // option change in front page
251 //
252 if (BootNextExist) {
253 LinkBootNext = BootLists.ForwardLink;
254 }
255
256 InitializeListHead (&BootLists);
257 if (LinkBootNext != NULL) {
258 //
259 // Reserve the boot next option
260 //
261 InsertTailList (&BootLists, LinkBootNext);
262 }
263
264 BdsLibBuildOptionFromVar (&BootLists, L"BootOrder");
265 Link = BootLists.ForwardLink;
266 }
267 }
268
269 }
270
271 /**
272
273 Service routine for BdsInstance->Entry(). Devices are connected, the
274 consoles are initialized, and the boot options are tried.
275
276 @param This Protocol Instance structure.
277
278 **/
279 VOID
280 EFIAPI
281 BdsEntry (
282 IN EFI_BDS_ARCH_PROTOCOL *This
283 )
284 {
285 LIST_ENTRY DriverOptionList;
286 LIST_ENTRY BootOptionList;
287 UINTN BootNextSize;
288 CHAR16 *FirmwareVendor;
289
290 //
291 // Insert the performance probe
292 //
293 PERF_END (NULL, "DXE", NULL, 0);
294 PERF_START (NULL, "BDS", NULL, 0);
295
296 //
297 // Initialize the global system boot option and driver option
298 //
299 InitializeListHead (&DriverOptionList);
300 InitializeListHead (&BootOptionList);
301
302 //
303 // Initialize hotkey service
304 //
305 InitializeHotkeyService ();
306
307 //
308 // Fill in FirmwareVendor and FirmwareRevision from PCDs
309 //
310 FirmwareVendor = (CHAR16 *)PcdGetPtr (PcdFirmwareVendor);
311 gST->FirmwareVendor = AllocateRuntimeCopyPool (StrSize (FirmwareVendor), FirmwareVendor);
312 ASSERT (gST->FirmwareVendor != NULL);
313 gST->FirmwareRevision = PcdGet32 (PcdFirmwareRevision);
314
315 //
316 // Fixup Tasble CRC after we updated Firmware Vendor and Revision
317 //
318 gBS->CalculateCrc32 ((VOID *)gST, sizeof(EFI_SYSTEM_TABLE), &gST->Hdr.CRC32);
319
320 //
321 // Do the platform init, can be customized by OEM/IBV
322 //
323 PERF_START (NULL, "PlatformBds", "BDS", 0);
324 PlatformBdsInit ();
325
326 InitializeHwErrRecSupport();
327
328 //
329 // bugbug: platform specific code
330 // Initialize the platform specific string and language
331 //
332 InitializeStringSupport ();
333 InitializeLanguage (TRUE);
334 InitializeFrontPage (TRUE);
335
336 //
337 // Set up the device list based on EFI 1.1 variables
338 // process Driver#### and Load the driver's in the
339 // driver option list
340 //
341 BdsLibBuildOptionFromVar (&DriverOptionList, L"DriverOrder");
342 if (!IsListEmpty (&DriverOptionList)) {
343 BdsLibLoadDrivers (&DriverOptionList);
344 }
345 //
346 // Check if we have the boot next option
347 //
348 mBootNext = BdsLibGetVariableAndSize (
349 L"BootNext",
350 &gEfiGlobalVariableGuid,
351 &BootNextSize
352 );
353
354 //
355 // Setup some platform policy here
356 //
357 PlatformBdsPolicyBehavior (&DriverOptionList, &BootOptionList, BdsProcessCapsules, BdsMemoryTest);
358 PERF_END (NULL, "PlatformBds", "BDS", 0);
359
360 //
361 // BDS select the boot device to load OS
362 //
363 BdsBootDeviceSelect ();
364
365 //
366 // Only assert here since this is the right behavior, we should never
367 // return back to DxeCore.
368 //
369 ASSERT (FALSE);
370
371 return ;
372 }