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