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