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