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