]> git.proxmox.com Git - mirror_edk2.git/blob - IntelFrameworkModulePkg/Universal/BdsDxe/BdsEntry.c
Reviewed the code comments in the Include/Protocol directory for typos, grammar issue...
[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_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
142 //
143 // If fail to get boot option from variable, just return and do nothing.
144 //
145 if (BootOption == NULL) {
146 return;
147 }
148
149 BootOption->BootCurrent = *mBootNext;
150 }
151 //
152 // Parse the boot order to get boot option
153 //
154 BdsLibBuildOptionFromVar (&BootLists, L"BootOrder");
155 Link = BootLists.ForwardLink;
156
157 //
158 // Parameter check, make sure the loop will be valid
159 //
160 if (Link == NULL) {
161 return ;
162 }
163 //
164 // Here we make the boot in a loop, every boot success will
165 // return to the front page
166 //
167 for (;;) {
168 //
169 // Check the boot option list first
170 //
171 if (Link == &BootLists) {
172 //
173 // There are two ways to enter here:
174 // 1. There is no active boot option, give user chance to
175 // add new boot option
176 // 2. All the active boot option processed, and there is no
177 // one is success to boot, then we back here to allow user
178 // add new active boot option
179 //
180 Timeout = 0xffff;
181 PlatformBdsEnterFrontPage (Timeout, FALSE);
182 InitializeListHead (&BootLists);
183 BdsLibBuildOptionFromVar (&BootLists, L"BootOrder");
184 Link = BootLists.ForwardLink;
185 continue;
186 }
187 //
188 // Get the boot option from the link list
189 //
190 BootOption = CR (Link, BDS_COMMON_OPTION, Link, BDS_LOAD_OPTION_SIGNATURE);
191
192 //
193 // According to EFI Specification, if a load option is not marked
194 // as LOAD_OPTION_ACTIVE, the boot manager will not automatically
195 // load the option.
196 //
197 if (!IS_LOAD_OPTION_TYPE (BootOption->Attribute, LOAD_OPTION_ACTIVE)) {
198 //
199 // skip the header of the link list, becuase it has no boot option
200 //
201 Link = Link->ForwardLink;
202 continue;
203 }
204 //
205 // Make sure the boot option device path connected,
206 // but ignore the BBS device path
207 //
208 if (DevicePathType (BootOption->DevicePath) != BBS_DEVICE_PATH) {
209 //
210 // Notes: the internal shell can not been connected with device path
211 // so we do not check the status here
212 //
213 BdsLibConnectDevicePath (BootOption->DevicePath);
214 }
215 //
216 // All the driver options should have been processed since
217 // now boot will be performed.
218 //
219 Status = BdsLibBootViaBootOption (BootOption, BootOption->DevicePath, &ExitDataSize, &ExitData);
220 if (EFI_ERROR (Status)) {
221 //
222 // Call platform action to indicate the boot fail
223 //
224 BootOption->StatusString = GetStringById (STRING_TOKEN (STR_BOOT_FAILED));
225 PlatformBdsBootFail (BootOption, Status, ExitData, ExitDataSize);
226
227 //
228 // Check the next boot option
229 //
230 Link = Link->ForwardLink;
231
232 } else {
233 //
234 // Call platform action to indicate the boot success
235 //
236 BootOption->StatusString = GetStringById (STRING_TOKEN (STR_BOOT_SUCCEEDED));
237 PlatformBdsBootSuccess (BootOption);
238
239 //
240 // Boot success, then stop process the boot order, and
241 // present the boot manager menu, front page
242 //
243 Timeout = 0xffff;
244 PlatformBdsEnterFrontPage (Timeout, FALSE);
245
246 //
247 // Rescan the boot option list, avoid pertential risk of the boot
248 // option change in front page
249 //
250 if (BootNextExist) {
251 LinkBootNext = BootLists.ForwardLink;
252 }
253
254 InitializeListHead (&BootLists);
255 if (LinkBootNext != NULL) {
256 //
257 // Reserve the boot next option
258 //
259 InsertTailList (&BootLists, LinkBootNext);
260 }
261
262 BdsLibBuildOptionFromVar (&BootLists, L"BootOrder");
263 Link = BootLists.ForwardLink;
264 }
265 }
266
267 }
268
269 /**
270
271 Service routine for BdsInstance->Entry(). Devices are connected, the
272 consoles are initialized, and the boot options are tried.
273
274 @param This Protocol Instance structure.
275
276 **/
277 VOID
278 EFIAPI
279 BdsEntry (
280 IN EFI_BDS_ARCH_PROTOCOL *This
281 )
282 {
283 EFI_BDS_ARCH_PROTOCOL_INSTANCE *PrivateData;
284 LIST_ENTRY DriverOptionList;
285 LIST_ENTRY BootOptionList;
286 UINTN BootNextSize;
287
288 //
289 // Insert the performance probe
290 //
291 PERF_END (0, "DXE", NULL, 0);
292 PERF_START (0, "BDS", NULL, 0);
293
294 //
295 // Initialize the global system boot option and driver option
296 //
297 InitializeListHead (&DriverOptionList);
298 InitializeListHead (&BootOptionList);
299
300 //
301 // Initialize hotkey service
302 //
303 InitializeHotkeyService ();
304
305 //
306 // Get the BDS private data
307 //
308 PrivateData = EFI_BDS_ARCH_PROTOCOL_INSTANCE_FROM_THIS (This);
309
310 //
311 // Do the platform init, can be customized by OEM/IBV
312 //
313 PERF_START (0, "PlatformBds", "BDS", 0);
314 PlatformBdsInit (PrivateData);
315
316 InitializeHwErrRecSupport();
317
318 //
319 // bugbug: platform specific code
320 // Initialize the platform specific string and language
321 //
322 InitializeStringSupport ();
323 InitializeLanguage (TRUE);
324 InitializeFrontPage (TRUE);
325
326 //
327 // Set up the device list based on EFI 1.1 variables
328 // process Driver#### and Load the driver's in the
329 // driver option list
330 //
331 BdsLibBuildOptionFromVar (&DriverOptionList, L"DriverOrder");
332 if (!IsListEmpty (&DriverOptionList)) {
333 BdsLibLoadDrivers (&DriverOptionList);
334 }
335 //
336 // Check if we have the boot next option
337 //
338 mBootNext = BdsLibGetVariableAndSize (
339 L"BootNext",
340 &gEfiGlobalVariableGuid,
341 &BootNextSize
342 );
343
344 //
345 // Setup some platform policy here
346 //
347 PlatformBdsPolicyBehavior (PrivateData, &DriverOptionList, &BootOptionList);
348 PERF_END (0, "PlatformBds", "BDS", 0);
349
350 //
351 // BDS select the boot device to load OS
352 //
353 BdsBootDeviceSelect ();
354
355 //
356 // Only assert here since this is the right behavior, we should never
357 // return back to DxeCore.
358 //
359 ASSERT (FALSE);
360
361 return ;
362 }