]> git.proxmox.com Git - mirror_edk2.git/blob - MdeModulePkg/Universal/BdsDxe/BdsEntry.c
UEFI HII: Merge UEFI HII support changes from branch.
[mirror_edk2.git] / MdeModulePkg / Universal / BdsDxe / BdsEntry.c
1 /*++
2
3 Copyright (c) 2004 - 2008, Intel Corporation
4 All rights reserved. This program and the accompanying materials
5 are licensed and made available under the terms and conditions of the BSD License
6 which accompanies this distribution. The full text of the license may be found at
7 http://opensource.org/licenses/bsd-license.php
8
9 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
10 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
11
12 Module Name:
13
14 BdsEntry.c
15
16 Abstract:
17
18 The entry of the bds
19
20 --*/
21
22 #include "Bds.h"
23 #include "Language.h"
24 #include "FrontPage.h"
25 #include "Hotkey.h"
26 #include "HwErrRecSupport.h"
27
28
29 EFI_BDS_ARCH_PROTOCOL_INSTANCE gBdsInstanceTemplate = {
30 EFI_BDS_ARCH_PROTOCOL_INSTANCE_SIGNATURE,
31 NULL,
32 {BdsEntry},
33 0xFFFF,
34 TRUE,
35 EXTENSIVE
36 };
37
38 UINT16 *mBootNext = NULL;
39
40 EFI_HANDLE mBdsImageHandle;
41
42 EFI_STATUS
43 EFIAPI
44 BdsInitialize (
45 IN EFI_HANDLE ImageHandle,
46 IN EFI_SYSTEM_TABLE *SystemTable
47 )
48 /*++
49
50 Routine Description:
51
52 Install Boot Device Selection Protocol
53
54 Arguments:
55
56 (Standard EFI Image entry - EFI_IMAGE_ENTRY_POINT)
57
58 Returns:
59
60 EFI_SUCEESS - BDS has finished initializing.
61 Rerun the
62 dispatcher and recall BDS.Entry
63
64 Other - Return value from AllocatePool()
65 or gBS->InstallProtocolInterface
66
67 --*/
68 {
69 EFI_STATUS Status;
70
71 mBdsImageHandle = ImageHandle;
72
73 //
74 // Install protocol interface
75 //
76 Status = gBS->InstallProtocolInterface (
77 &gBdsInstanceTemplate.Handle,
78 &gEfiBdsArchProtocolGuid,
79 EFI_NATIVE_INTERFACE,
80 &gBdsInstanceTemplate.Bds
81 );
82 ASSERT_EFI_ERROR (Status);
83
84 return Status;
85 }
86
87 VOID
88 BdsBootDeviceSelect (
89 VOID
90 )
91 /*++
92
93 Routine Description:
94
95 In the loop of attempt to boot for the boot order
96
97 Arguments:
98
99 None.
100
101 Returns:
102
103 None.
104
105 --*/
106 {
107 EFI_STATUS Status;
108 LIST_ENTRY *Link;
109 BDS_COMMON_OPTION *BootOption;
110 UINTN ExitDataSize;
111 CHAR16 *ExitData;
112 UINT16 Timeout;
113 LIST_ENTRY BootLists;
114 CHAR16 Buffer[20];
115 BOOLEAN BootNextExist;
116 LIST_ENTRY *LinkBootNext;
117
118 //
119 // Got the latest boot option
120 //
121 BootNextExist = FALSE;
122 LinkBootNext = NULL;
123 InitializeListHead (&BootLists);
124
125 //
126 // First check the boot next option
127 //
128 ZeroMem (Buffer, sizeof (Buffer));
129
130 if (mBootNext != NULL) {
131 //
132 // Indicate we have the boot next variable, so this time
133 // boot will always have this boot option
134 //
135 BootNextExist = TRUE;
136
137 //
138 // Clear the this variable so it's only exist in this time boot
139 //
140 gRT->SetVariable (
141 L"BootNext",
142 &gEfiGlobalVariableGuid,
143 EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS | EFI_VARIABLE_NON_VOLATILE,
144 0,
145 mBootNext
146 );
147
148 //
149 // Add the boot next boot option
150 //
151 UnicodeSPrint (Buffer, sizeof (Buffer), L"Boot%04x", *mBootNext);
152 BootOption = BdsLibVariableToOption (&BootLists, Buffer);
153 BootOption->BootCurrent = *mBootNext;
154 }
155 //
156 // Parse the boot order to get boot option
157 //
158 BdsLibBuildOptionFromVar (&BootLists, L"BootOrder");
159 Link = BootLists.ForwardLink;
160
161 //
162 // Parameter check, make sure the loop will be valid
163 //
164 if (Link == NULL) {
165 return ;
166 }
167 //
168 // Here we make the boot in a loop, every boot success will
169 // return to the front page
170 //
171 for (;;) {
172 //
173 // Check the boot option list first
174 //
175 if (Link == &BootLists) {
176 //
177 // There are two ways to enter here:
178 // 1. There is no active boot option, give user chance to
179 // add new boot option
180 // 2. All the active boot option processed, and there is no
181 // one is success to boot, then we back here to allow user
182 // add new active boot option
183 //
184 Timeout = 0xffff;
185 PlatformBdsEnterFrontPage (Timeout, FALSE);
186 InitializeListHead (&BootLists);
187 BdsLibBuildOptionFromVar (&BootLists, L"BootOrder");
188 Link = BootLists.ForwardLink;
189 continue;
190 }
191 //
192 // Get the boot option from the link list
193 //
194 BootOption = CR (Link, BDS_COMMON_OPTION, Link, BDS_LOAD_OPTION_SIGNATURE);
195
196 //
197 // According to EFI Specification, if a load option is not marked
198 // as LOAD_OPTION_ACTIVE, the boot manager will not automatically
199 // load the option.
200 //
201 if (!IS_LOAD_OPTION_TYPE (BootOption->Attribute, LOAD_OPTION_ACTIVE)) {
202 //
203 // skip the header of the link list, becuase it has no boot option
204 //
205 Link = Link->ForwardLink;
206 continue;
207 }
208 //
209 // Make sure the boot option device path connected,
210 // but ignore the BBS device path
211 //
212 if (DevicePathType (BootOption->DevicePath) != BBS_DEVICE_PATH) {
213 //
214 // Notes: the internal shell can not been connected with device path
215 // so we do not check the status here
216 //
217 BdsLibConnectDevicePath (BootOption->DevicePath);
218 }
219 //
220 // All the driver options should have been processed since
221 // now boot will be performed.
222 //
223 Status = BdsLibBootViaBootOption (BootOption, BootOption->DevicePath, &ExitDataSize, &ExitData);
224 if (EFI_ERROR (Status)) {
225 //
226 // Call platform action to indicate the boot fail
227 //
228 BootOption->StatusString = GetStringById (STRING_TOKEN (STR_BOOT_FAILED));
229 PlatformBdsBootFail (BootOption, Status, ExitData, ExitDataSize);
230
231 //
232 // Check the next boot option
233 //
234 Link = Link->ForwardLink;
235
236 } else {
237 //
238 // Call platform action to indicate the boot success
239 //
240 BootOption->StatusString = GetStringById (STRING_TOKEN (STR_BOOT_SUCCEEDED));
241 PlatformBdsBootSuccess (BootOption);
242
243 //
244 // Boot success, then stop process the boot order, and
245 // present the boot manager menu, front page
246 //
247 Timeout = 0xffff;
248 PlatformBdsEnterFrontPage (Timeout, FALSE);
249
250 //
251 // Rescan the boot option list, avoid pertential risk of the boot
252 // option change in front page
253 //
254 if (BootNextExist) {
255 LinkBootNext = BootLists.ForwardLink;
256 }
257
258 InitializeListHead (&BootLists);
259 if (LinkBootNext != NULL) {
260 //
261 // Reserve the boot next option
262 //
263 InsertTailList (&BootLists, LinkBootNext);
264 }
265
266 BdsLibBuildOptionFromVar (&BootLists, L"BootOrder");
267 Link = BootLists.ForwardLink;
268 }
269 }
270
271 }
272
273 VOID
274 EFIAPI
275 BdsEntry (
276 IN EFI_BDS_ARCH_PROTOCOL *This
277 )
278 /*++
279
280 Routine Description:
281
282 Service routine for BdsInstance->Entry(). Devices are connected, the
283 consoles are initialized, and the boot options are tried.
284
285 Arguments:
286
287 This - Protocol Instance structure.
288
289 Returns:
290
291 EFI_SUCEESS - BDS->Entry has finished executing.
292
293 --*/
294 {
295 EFI_BDS_ARCH_PROTOCOL_INSTANCE *PrivateData;
296 LIST_ENTRY DriverOptionList;
297 LIST_ENTRY BootOptionList;
298 UINTN BootNextSize;
299
300 //
301 // Insert the performance probe
302 //
303 PERF_END (0, DXE_TOK, NULL, 0);
304 PERF_START (0, BDS_TOK, NULL, 0);
305
306 //
307 // Initialize the global system boot option and driver option
308 //
309 InitializeListHead (&DriverOptionList);
310 InitializeListHead (&BootOptionList);
311
312 //
313 // Initialize hotkey service
314 //
315 InitializeHotkeyService ();
316
317 //
318 // Get the BDS private data
319 //
320 PrivateData = EFI_BDS_ARCH_PROTOCOL_INSTANCE_FROM_THIS (This);
321
322 //
323 // Do the platform init, can be customized by OEM/IBV
324 //
325 PERF_START (0, "PlatformBds", "BDS", 0);
326 PlatformBdsInit (PrivateData);
327
328 if (FeaturePcdGet (PcdSupportHardwareErrorRecord)) {
329 InitializeHwErrRecSupport (PcdGet16 (PcdHardwareErrorRecordLevel));
330 }
331 //
332 // bugbug: platform specific code
333 // Initialize the platform specific string and language
334 //
335 InitializeStringSupport ();
336 InitializeLanguage (TRUE);
337 InitializeFrontPage (FALSE);
338
339 //
340 // Set up the device list based on EFI 1.1 variables
341 // process Driver#### and Load the driver's in the
342 // driver option list
343 //
344 BdsLibBuildOptionFromVar (&DriverOptionList, L"DriverOrder");
345 if (!IsListEmpty (&DriverOptionList)) {
346 BdsLibLoadDrivers (&DriverOptionList);
347 }
348 //
349 // Check if we have the boot next option
350 //
351 mBootNext = BdsLibGetVariableAndSize (
352 L"BootNext",
353 &gEfiGlobalVariableGuid,
354 &BootNextSize
355 );
356
357 //
358 // Setup some platform policy here
359 //
360 PlatformBdsPolicyBehavior (PrivateData, &DriverOptionList, &BootOptionList);
361 PERF_END (0, "PlatformBds", "BDS", 0);
362
363 //
364 // BDS select the boot device to load OS
365 //
366 BdsBootDeviceSelect ();
367
368 //
369 // Only assert here since this is the right behavior, we should never
370 // return back to DxeCore.
371 //
372 ASSERT (FALSE);
373
374 return ;
375 }