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