1. Sync definition of EFI_DEBUG_IMAGE_INFO with UEFI spec
[mirror_edk2.git] / EdkNt32Pkg / Dxe / PlatformBds / Generic / BdsEntry.c
1 /*++
2
3 Copyright (c) 2006, 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 "BdsPlatform.h"
24 #include "FrontPage.h"
25
26 EFI_BDS_ARCH_PROTOCOL_INSTANCE gBdsInstanceTemplate = {
27 EFI_BDS_ARCH_PROTOCOL_INSTANCE_SIGNATURE,
28 NULL,
29 BdsEntry,
30 0xFFFF,
31 TRUE,
32 EXTENSIVE
33 };
34
35 UINT16 *mBootNext = NULL;
36
37 EFI_HANDLE mBdsImageHandle;
38
39 EFI_STATUS
40 EFIAPI
41 BdsInitialize (
42 IN EFI_HANDLE ImageHandle,
43 IN EFI_SYSTEM_TABLE *SystemTable
44 )
45 /*++
46
47 Routine Description:
48
49 Install Boot Device Selection Protocol
50
51 Arguments:
52
53 (Standard EFI Image entry - EFI_IMAGE_ENTRY_POINT)
54
55 Returns:
56
57 EFI_SUCEESS - BDS has finished initializing.
58 Rerun the
59 dispatcher and recall BDS.Entry
60
61 Other - Return value from EfiLibAllocatePool()
62 or gBS->InstallProtocolInterface
63
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 VOID
85 BdsBootDeviceSelect (
86 VOID
87 )
88 /*++
89
90 Routine Description:
91
92 In the loop of attempt to boot for the boot order
93
94 Arguments:
95
96 None.
97
98 Returns:
99
100 None.
101
102 --*/
103 {
104 EFI_STATUS Status;
105 LIST_ENTRY *Link;
106 BDS_COMMON_OPTION *BootOption;
107 UINTN ExitDataSize;
108 CHAR16 *ExitData;
109 UINT16 Timeout;
110 LIST_ENTRY BootLists;
111 CHAR16 Buffer[20];
112 BOOLEAN BootNextExist;
113 LIST_ENTRY *LinkBootNext;
114
115 //
116 // Got the latest boot option
117 //
118 BootNextExist = FALSE;
119 LinkBootNext = NULL;
120 InitializeListHead (&BootLists);
121
122 //
123 // First check the boot next option
124 //
125 ZeroMem (Buffer, sizeof (Buffer));
126
127 if (mBootNext != NULL) {
128 //
129 // Indicate we have the boot next variable, so this time
130 // boot will always have this boot option
131 //
132 BootNextExist = TRUE;
133
134 //
135 // Clear the this variable so it's only exist in this time boot
136 //
137 gRT->SetVariable (
138 L"BootNext",
139 &gEfiGlobalVariableGuid,
140 EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS | EFI_VARIABLE_NON_VOLATILE,
141 0,
142 mBootNext
143 );
144
145 //
146 // Add the boot next boot option
147 //
148 UnicodeSPrint (Buffer, sizeof (Buffer), L"Boot%04x", *mBootNext);
149 BootOption = BdsLibVariableToOption (&BootLists, Buffer);
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 PlatformBdsBootFail (BootOption, Status, ExitData, ExitDataSize);
225
226 //
227 // Check the next boot option
228 //
229 Link = Link->ForwardLink;
230
231 } else {
232 //
233 // Call platform action to indicate the boot success
234 //
235 PlatformBdsBootSuccess (BootOption);
236
237 //
238 // Boot success, then stop process the boot order, and
239 // present the boot manager menu, front page
240 //
241 Timeout = 0xffff;
242 PlatformBdsEnterFrontPage (Timeout, FALSE);
243
244 //
245 // Rescan the boot option list, avoid pertential risk of the boot
246 // option change in front page
247 //
248 if (BootNextExist) {
249 LinkBootNext = BootLists.ForwardLink;
250 }
251
252 InitializeListHead (&BootLists);
253 if (LinkBootNext != NULL) {
254 //
255 // Reserve the boot next option
256 //
257 InsertTailList (&BootLists, LinkBootNext);
258 }
259
260 BdsLibBuildOptionFromVar (&BootLists, L"BootOrder");
261 Link = BootLists.ForwardLink;
262 }
263 }
264
265 return ;
266
267 }
268
269 EFI_STATUS
270 EFIAPI
271 BdsEntry (
272 IN EFI_BDS_ARCH_PROTOCOL *This
273 )
274 /*++
275
276 Routine Description:
277
278 Service routine for BdsInstance->Entry(). Devices are connected, the
279 consoles are initialized, and the boot options are tried.
280
281 Arguments:
282
283 This - Protocol Instance structure.
284
285 Returns:
286
287 EFI_SUCEESS - BDS->Entry has finished executing.
288
289 --*/
290 {
291 EFI_BDS_ARCH_PROTOCOL_INSTANCE *PrivateData;
292 LIST_ENTRY DriverOptionList;
293 LIST_ENTRY BootOptionList;
294 UINTN BootNextSize;
295
296 //
297 // Insert the performance probe
298 //
299 PERF_END (0, DXE_TOK, NULL, 0);
300 PERF_START (0, BDS_TOK, NULL, 0);
301
302 //
303 // Initialize the global system boot option and driver option
304 //
305 InitializeListHead (&DriverOptionList);
306 InitializeListHead (&BootOptionList);
307
308 //
309 // Get the BDS private data
310 //
311 PrivateData = EFI_BDS_ARCH_PROTOCOL_INSTANCE_FROM_THIS (This);
312
313 //
314 // Do the platform init, can be customized by OEM/IBV
315 //
316 PERF_START (0, "PlatformBds", "BDS", 0);
317 PlatformBdsInit (PrivateData);
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 EFI_SUCCESS;
355 }