]> git.proxmox.com Git - mirror_edk2.git/blob - IntelFrameworkModulePkg/Universal/BdsDxe/BdsEntry.c
Remove unnecessary mBdsImageHandle.
[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 - 2010, 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 Link = BootLists.ForwardLink;
147
148 //
149 // Parameter check, make sure the loop will be valid
150 //
151 if (Link == NULL) {
152 return ;
153 }
154 //
155 // Here we make the boot in a loop, every boot success will
156 // return to the front page
157 //
158 for (;;) {
159 //
160 // Check the boot option list first
161 //
162 if (Link == &BootLists) {
163 //
164 // There are two ways to enter here:
165 // 1. There is no active boot option, give user chance to
166 // add new boot option
167 // 2. All the active boot option processed, and there is no
168 // one is success to boot, then we back here to allow user
169 // add new active boot option
170 //
171 Timeout = 0xffff;
172 PlatformBdsEnterFrontPage (Timeout, FALSE);
173 InitializeListHead (&BootLists);
174 BdsLibBuildOptionFromVar (&BootLists, L"BootOrder");
175 Link = BootLists.ForwardLink;
176 continue;
177 }
178 //
179 // Get the boot option from the link list
180 //
181 BootOption = CR (Link, BDS_COMMON_OPTION, Link, BDS_LOAD_OPTION_SIGNATURE);
182
183 //
184 // According to EFI Specification, if a load option is not marked
185 // as LOAD_OPTION_ACTIVE, the boot manager will not automatically
186 // load the option.
187 //
188 if (!IS_LOAD_OPTION_TYPE (BootOption->Attribute, LOAD_OPTION_ACTIVE)) {
189 //
190 // skip the header of the link list, because it has no boot option
191 //
192 Link = Link->ForwardLink;
193 continue;
194 }
195 //
196 // Make sure the boot option device path connected,
197 // but ignore the BBS device path
198 //
199 if (DevicePathType (BootOption->DevicePath) != BBS_DEVICE_PATH) {
200 //
201 // Notes: the internal shell can not been connected with device path
202 // so we do not check the status here
203 //
204 BdsLibConnectDevicePath (BootOption->DevicePath);
205 }
206 //
207 // All the driver options should have been processed since
208 // now boot will be performed.
209 //
210 Status = BdsLibBootViaBootOption (BootOption, BootOption->DevicePath, &ExitDataSize, &ExitData);
211 if (EFI_ERROR (Status)) {
212 //
213 // Call platform action to indicate the boot fail
214 //
215 BootOption->StatusString = GetStringById (STRING_TOKEN (STR_BOOT_FAILED));
216 PlatformBdsBootFail (BootOption, Status, ExitData, ExitDataSize);
217
218 //
219 // Check the next boot option
220 //
221 Link = Link->ForwardLink;
222
223 } else {
224 //
225 // Call platform action to indicate the boot success
226 //
227 BootOption->StatusString = GetStringById (STRING_TOKEN (STR_BOOT_SUCCEEDED));
228 PlatformBdsBootSuccess (BootOption);
229
230 //
231 // Boot success, then stop process the boot order, and
232 // present the boot manager menu, front page
233 //
234 Timeout = 0xffff;
235 PlatformBdsEnterFrontPage (Timeout, FALSE);
236
237 //
238 // Rescan the boot option list, avoid potential risk of the boot
239 // option change in front page
240 //
241 if (BootNextExist) {
242 LinkBootNext = BootLists.ForwardLink;
243 }
244
245 InitializeListHead (&BootLists);
246 if (LinkBootNext != NULL) {
247 //
248 // Reserve the boot next option
249 //
250 InsertTailList (&BootLists, LinkBootNext);
251 }
252
253 BdsLibBuildOptionFromVar (&BootLists, L"BootOrder");
254 Link = BootLists.ForwardLink;
255 }
256 }
257
258 }
259
260 /**
261
262 Service routine for BdsInstance->Entry(). Devices are connected, the
263 consoles are initialized, and the boot options are tried.
264
265 @param This Protocol Instance structure.
266
267 **/
268 VOID
269 EFIAPI
270 BdsEntry (
271 IN EFI_BDS_ARCH_PROTOCOL *This
272 )
273 {
274 LIST_ENTRY DriverOptionList;
275 LIST_ENTRY BootOptionList;
276 UINTN BootNextSize;
277 CHAR16 *FirmwareVendor;
278
279 //
280 // Insert the performance probe
281 //
282 PERF_END (NULL, "DXE", NULL, 0);
283 PERF_START (NULL, "BDS", NULL, 0);
284
285 //
286 // Initialize the global system boot option and driver option
287 //
288 InitializeListHead (&DriverOptionList);
289 InitializeListHead (&BootOptionList);
290
291 //
292 // Initialize hotkey service
293 //
294 InitializeHotkeyService ();
295
296 //
297 // Fill in FirmwareVendor and FirmwareRevision from PCDs
298 //
299 FirmwareVendor = (CHAR16 *)PcdGetPtr (PcdFirmwareVendor);
300 gST->FirmwareVendor = AllocateRuntimeCopyPool (StrSize (FirmwareVendor), FirmwareVendor);
301 ASSERT (gST->FirmwareVendor != NULL);
302 gST->FirmwareRevision = PcdGet32 (PcdFirmwareRevision);
303
304 //
305 // Fixup Tasble CRC after we updated Firmware Vendor and Revision
306 //
307 gBS->CalculateCrc32 ((VOID *)gST, sizeof(EFI_SYSTEM_TABLE), &gST->Hdr.CRC32);
308
309 //
310 // Do the platform init, can be customized by OEM/IBV
311 //
312 PERF_START (NULL, "PlatformBds", "BDS", 0);
313 PlatformBdsInit ();
314
315 InitializeHwErrRecSupport();
316
317 //
318 // bugbug: platform specific code
319 // Initialize the platform specific string and language
320 //
321 InitializeStringSupport ();
322 InitializeLanguage (TRUE);
323 InitializeFrontPage (TRUE);
324
325 //
326 // Set up the device list based on EFI 1.1 variables
327 // process Driver#### and Load the driver's in the
328 // driver option list
329 //
330 BdsLibBuildOptionFromVar (&DriverOptionList, L"DriverOrder");
331 if (!IsListEmpty (&DriverOptionList)) {
332 BdsLibLoadDrivers (&DriverOptionList);
333 }
334 //
335 // Check if we have the boot next option
336 //
337 mBootNext = BdsLibGetVariableAndSize (
338 L"BootNext",
339 &gEfiGlobalVariableGuid,
340 &BootNextSize
341 );
342
343 //
344 // Setup some platform policy here
345 //
346 PlatformBdsPolicyBehavior (&DriverOptionList, &BootOptionList, BdsProcessCapsules, BdsMemoryTest);
347 PERF_END (NULL, "PlatformBds", "BDS", 0);
348
349 //
350 // BDS select the boot device to load OS
351 //
352 BdsBootDeviceSelect ();
353
354 //
355 // Only assert here since this is the right behavior, we should never
356 // return back to DxeCore.
357 //
358 ASSERT (FALSE);
359
360 return ;
361 }