]> git.proxmox.com Git - mirror_edk2.git/blob - MdeModulePkg/Universal/BdsDxe/BdsEntry.c
Initialize the timeout value to 0, the original template is not proper initialized.
[mirror_edk2.git] / MdeModulePkg / Universal / BdsDxe / BdsEntry.c
1 /** @file
2 The entry of the bds
3
4 Copyright (c) 2004 - 2008, Intel Corporation. <BR>
5 All rights reserved. This program and the accompanying materials
6 are licensed and made available under the terms and conditions of the BSD License
7 which accompanies this distribution. The full text of the license may be found at
8 http://opensource.org/licenses/bsd-license.php
9
10 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
11 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
12
13 **/
14
15 #include "Bds.h"
16 #include "Language.h"
17 #include "FrontPage.h"
18 #include "Hotkey.h"
19 #include "HwErrRecSupport.h"
20
21 //
22 // BDS arch protocol instance initial value.
23 //
24 // Note: Current BDS not directly get the BootMode, DefaultBoot,
25 // TimeoutDefault, MemoryTestLevel value from the BDS arch protocol.
26 // Please refer to the library useage of BdsLibGetBootMode, BdsLibGetTimeout
27 // and PlatformBdsDiagnostics in BdsPlatform.c
28 //
29 EFI_BDS_ARCH_PROTOCOL_INSTANCE gBdsInstanceTemplate = {
30 EFI_BDS_ARCH_PROTOCOL_INSTANCE_SIGNATURE,
31 NULL,
32 {BdsEntry},
33 0xFFFF,
34 TRUE,
35 0,
36 EXTENSIVE
37 };
38
39 UINT16 *mBootNext = NULL;
40
41 EFI_HANDLE mBdsImageHandle;
42
43 /**
44
45 Install Boot Device Selection Protocol
46
47
48 @param ImageHandle The image handle.
49 @param SystemTable The system table.
50
51 @retval EFI_SUCEESS BDS has finished initializing.
52 Rerun the
53 dispatcher and recall BDS.Entry
54 @retval Other Return value from AllocatePool()
55 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->InstallProtocolInterface (
73 &gBdsInstanceTemplate.Handle,
74 &gEfiBdsArchProtocolGuid,
75 EFI_NATIVE_INTERFACE,
76 &gBdsInstanceTemplate.Bds
77 );
78 ASSERT_EFI_ERROR (Status);
79
80 return Status;
81 }
82
83 /**
84
85 This function attempts to boot for the boot order specified
86 by platform policy.
87
88 **/
89 VOID
90 BdsBootDeviceSelect (
91 VOID
92 )
93 {
94 EFI_STATUS Status;
95 LIST_ENTRY *Link;
96 BDS_COMMON_OPTION *BootOption;
97 UINTN ExitDataSize;
98 CHAR16 *ExitData;
99 UINT16 Timeout;
100 LIST_ENTRY BootLists;
101 CHAR16 Buffer[20];
102 BOOLEAN BootNextExist;
103 LIST_ENTRY *LinkBootNext;
104
105 //
106 // Got the latest boot option
107 //
108 BootNextExist = FALSE;
109 LinkBootNext = NULL;
110 InitializeListHead (&BootLists);
111
112 //
113 // First check the boot next option
114 //
115 ZeroMem (Buffer, sizeof (Buffer));
116
117 if (mBootNext != NULL) {
118 //
119 // Indicate we have the boot next variable, so this time
120 // boot will always have this boot option
121 //
122 BootNextExist = TRUE;
123
124 //
125 // Clear the this variable so it's only exist in this time boot
126 //
127 gRT->SetVariable (
128 L"BootNext",
129 &gEfiGlobalVariableGuid,
130 EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS | EFI_VARIABLE_NON_VOLATILE,
131 0,
132 mBootNext
133 );
134
135 //
136 // Add the boot next boot option
137 //
138 UnicodeSPrint (Buffer, sizeof (Buffer), L"Boot%04x", *mBootNext);
139 BootOption = BdsLibVariableToOption (&BootLists, Buffer);
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, becuase 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 pertential 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
266 @param This - Protocol Instance structure.
267
268 @retval EFI_SUCEESS BDS->Entry has finished executing.
269
270 **/
271 VOID
272 EFIAPI
273 BdsEntry (
274 IN EFI_BDS_ARCH_PROTOCOL *This
275 )
276 {
277 EFI_BDS_ARCH_PROTOCOL_INSTANCE *PrivateData;
278 LIST_ENTRY DriverOptionList;
279 LIST_ENTRY BootOptionList;
280 UINTN BootNextSize;
281
282 //
283 // Insert the performance probe
284 //
285 PERF_END (0, DXE_TOK, NULL, 0);
286 PERF_START (0, BDS_TOK, NULL, 0);
287
288 //
289 // Initialize the global system boot option and driver option
290 //
291 InitializeListHead (&DriverOptionList);
292 InitializeListHead (&BootOptionList);
293
294 //
295 // Initialize hotkey service
296 //
297 InitializeHotkeyService ();
298
299 //
300 // Get the BDS private data
301 //
302 PrivateData = EFI_BDS_ARCH_PROTOCOL_INSTANCE_FROM_THIS (This);
303
304 //
305 // Do the platform init, can be customized by OEM/IBV
306 //
307 PERF_START (0, "PlatformBds", "BDS", 0);
308 PlatformBdsInit (PrivateData);
309
310 if (FeaturePcdGet (PcdSupportHardwareErrorRecord)) {
311 InitializeHwErrRecSupport (PcdGet16 (PcdHardwareErrorRecordLevel));
312 }
313 //
314 // bugbug: platform specific code
315 // Initialize the platform specific string and language
316 //
317 InitializeStringSupport ();
318 InitializeLanguage (TRUE);
319 InitializeFrontPage (TRUE);
320
321 //
322 // Set up the device list based on EFI 1.1 variables
323 // process Driver#### and Load the driver's in the
324 // driver option list
325 //
326 BdsLibBuildOptionFromVar (&DriverOptionList, L"DriverOrder");
327 if (!IsListEmpty (&DriverOptionList)) {
328 BdsLibLoadDrivers (&DriverOptionList);
329 }
330 //
331 // Check if we have the boot next option
332 //
333 mBootNext = BdsLibGetVariableAndSize (
334 L"BootNext",
335 &gEfiGlobalVariableGuid,
336 &BootNextSize
337 );
338
339 //
340 // Setup some platform policy here
341 //
342 PlatformBdsPolicyBehavior (PrivateData, &DriverOptionList, &BootOptionList);
343 PERF_END (0, "PlatformBds", "BDS", 0);
344
345 //
346 // BDS select the boot device to load OS
347 //
348 BdsBootDeviceSelect ();
349
350 //
351 // Only assert here since this is the right behavior, we should never
352 // return back to DxeCore.
353 //
354 ASSERT (FALSE);
355
356 return ;
357 }