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