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