]> git.proxmox.com Git - mirror_edk2.git/blob - MdeModulePkg/Universal/BdsDxe/BootMngr/BootManager.c
5dd1e31eb94d66df9f6a8fba7b2e00e5f3c4ba96
[mirror_edk2.git] / MdeModulePkg / Universal / BdsDxe / BootMngr / BootManager.c
1 /** @file
2 The platform boot manager reference implement
3
4 Copyright (c) 2004 - 2008, Intel Corporation. <BR>
5 All rights reserved. This program and the accompanying materials
6 are licensed and made available under the terms and conditions of the BSD License
7 which accompanies this distribution. The full text of the license may be found at
8 http://opensource.org/licenses/bsd-license.php
9
10 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
11 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
12
13 **/
14
15 #include "BootManager.h"
16
17 UINT16 mKeyInput;
18 EFI_GUID mBootManagerGuid = BOOT_MANAGER_FORMSET_GUID;
19 LIST_ENTRY *mBootOptionsList;
20 BDS_COMMON_OPTION *gOption;
21
22 BOOT_MANAGER_CALLBACK_DATA gBootManagerPrivate = {
23 BOOT_MANAGER_CALLBACK_DATA_SIGNATURE,
24 NULL,
25 NULL,
26 {
27 FakeExtractConfig,
28 FakeRouteConfig,
29 BootManagerCallback
30 }
31 };
32
33 /**
34 This call back funtion is registered with Boot Manager formset.
35 When user selects a boot option, this call back function will
36 be triggered. The boot option is saved for later processing.
37
38
39 @param This Points to the EFI_HII_CONFIG_ACCESS_PROTOCOL.
40 @param Action Specifies the type of action taken by the browser.
41 @param QuestionId A unique value which is sent to the original exporting driver
42 so that it can identify the type of data to expect.
43 @param Type The type of value for the question.
44 @param Value A pointer to the data being sent to the original exporting driver.
45 @param ActionRequest On return, points to the action requested by the callback function.
46
47 @retval EFI_SUCCESS The callback successfully handled the action.
48 @retval EFI_INVALID_PARAMETER The setup browser call this function with invalid parameters.
49
50 **/
51 EFI_STATUS
52 EFIAPI
53 BootManagerCallback (
54 IN CONST EFI_HII_CONFIG_ACCESS_PROTOCOL *This,
55 IN EFI_BROWSER_ACTION Action,
56 IN EFI_QUESTION_ID QuestionId,
57 IN UINT8 Type,
58 IN EFI_IFR_TYPE_VALUE *Value,
59 OUT EFI_BROWSER_ACTION_REQUEST *ActionRequest
60 )
61 {
62 BDS_COMMON_OPTION *Option;
63 LIST_ENTRY *Link;
64 UINT16 KeyCount;
65
66 if ((Value == NULL) || (ActionRequest == NULL)) {
67 return EFI_INVALID_PARAMETER;
68 }
69
70 //
71 // Initialize the key count
72 //
73 KeyCount = 0;
74
75 for (Link = mBootOptionsList->ForwardLink; Link != mBootOptionsList; Link = Link->ForwardLink) {
76 Option = CR (Link, BDS_COMMON_OPTION, Link, BDS_LOAD_OPTION_SIGNATURE);
77
78 KeyCount++;
79
80 gOption = Option;
81
82 //
83 // Is this device the one chosen?
84 //
85 if (KeyCount == QuestionId) {
86 //
87 // Assigning the returned Key to a global allows the original routine to know what was chosen
88 //
89 mKeyInput = QuestionId;
90
91 //
92 // Request to exit SendForm(), so that we could boot the selected option
93 //
94 *ActionRequest = EFI_BROWSER_ACTION_REQUEST_EXIT;
95 break;
96 }
97 }
98
99 return EFI_SUCCESS;
100 }
101
102 /**
103
104 Registers HII packages for the Boot Manger to HII Database.
105 It also registers the browser call back function.
106
107
108 @return EDES_TODO: Add description for return value
109
110 **/
111 EFI_STATUS
112 InitializeBootManager (
113 VOID
114 )
115 {
116 EFI_STATUS Status;
117 EFI_HII_PACKAGE_LIST_HEADER *PackageList;
118
119 //
120 // Create driver handle used by HII database
121 //
122 Status = HiiLibCreateHiiDriverHandle (&gBootManagerPrivate.DriverHandle);
123 if (EFI_ERROR (Status)) {
124 return Status;
125 }
126
127 //
128 // Install Config Access protocol to driver handle
129 //
130 Status = gBS->InstallProtocolInterface (
131 &gBootManagerPrivate.DriverHandle,
132 &gEfiHiiConfigAccessProtocolGuid,
133 EFI_NATIVE_INTERFACE,
134 &gBootManagerPrivate.ConfigAccess
135 );
136 ASSERT_EFI_ERROR (Status);
137
138 //
139 // Publish our HII data
140 //
141 PackageList = HiiLibPreparePackageList (2, &mBootManagerGuid, BootManagerVfrBin, BdsDxeStrings);
142 ASSERT (PackageList != NULL);
143
144 Status = gHiiDatabase->NewPackageList (
145 gHiiDatabase,
146 PackageList,
147 gBootManagerPrivate.DriverHandle,
148 &gBootManagerPrivate.HiiHandle
149 );
150 FreePool (PackageList);
151
152 return Status;
153 }
154
155 /**
156 This funtion invokees Boot Manager. If all devices have not a chance to be connected,
157 the connect all will be triggered. It then enumerate all boot options. If
158 a boot option from the Boot Manager page is selected, Boot Manager will boot
159 from this boot option.
160
161 **/
162 VOID
163 CallBootManager (
164 VOID
165 )
166 {
167 EFI_STATUS Status;
168 BDS_COMMON_OPTION *Option;
169 LIST_ENTRY *Link;
170 EFI_HII_UPDATE_DATA UpdateData;
171 CHAR16 *ExitData;
172 UINTN ExitDataSize;
173 EFI_STRING_ID Token;
174 EFI_INPUT_KEY Key;
175 LIST_ENTRY BdsBootOptionList;
176 CHAR16 *HelpString;
177 EFI_STRING_ID HelpToken;
178 UINT16 *TempStr;
179 EFI_HII_HANDLE HiiHandle;
180 EFI_BROWSER_ACTION_REQUEST ActionRequest;
181 UINTN TempSize;
182
183 gOption = NULL;
184 InitializeListHead (&BdsBootOptionList);
185
186 //
187 // Connect all prior to entering the platform setup menu.
188 //
189 if (!gConnectAllHappened) {
190 BdsLibConnectAllDriversToAllControllers ();
191 gConnectAllHappened = TRUE;
192 }
193 //
194 // BugBug: Here we can not remove the legacy refresh macro, so we need
195 // get the boot order every time from "BootOrder" variable.
196 // Recreate the boot option list base on the BootOrder variable
197 //
198 BdsLibEnumerateAllBootOption (&BdsBootOptionList);
199
200 mBootOptionsList = &BdsBootOptionList;
201
202 HiiHandle = gBootManagerPrivate.HiiHandle;
203
204 //
205 // Allocate space for creation of UpdateData Buffer
206 //
207 UpdateData.BufferSize = 0x1000;
208 UpdateData.Offset = 0;
209 UpdateData.Data = AllocateZeroPool (0x1000);
210 ASSERT (UpdateData.Data != NULL);
211
212 mKeyInput = 0;
213
214 for (Link = BdsBootOptionList.ForwardLink; Link != &BdsBootOptionList; Link = Link->ForwardLink) {
215 Option = CR (Link, BDS_COMMON_OPTION, Link, BDS_LOAD_OPTION_SIGNATURE);
216
217 //
218 // At this stage we are creating a menu entry, thus the Keys are reproduceable
219 //
220 mKeyInput++;
221
222 //
223 // Don't display the boot option marked as LOAD_OPTION_HIDDEN
224 //
225 if (Option->Attribute & LOAD_OPTION_HIDDEN) {
226 continue;
227 }
228
229 HiiLibNewString (HiiHandle, &Token, Option->Description);
230
231 TempStr = DevicePathToStr (Option->DevicePath);
232 TempSize = StrSize (TempStr);
233 HelpString = AllocateZeroPool (TempSize + StrSize (L"Device Path : "));
234 StrCat (HelpString, L"Device Path : ");
235 StrCat (HelpString, TempStr);
236
237 HiiLibNewString (HiiHandle, &HelpToken, HelpString);
238
239 CreateActionOpCode (
240 mKeyInput,
241 Token,
242 HelpToken,
243 EFI_IFR_FLAG_CALLBACK,
244 0,
245 &UpdateData
246 );
247 }
248
249 IfrLibUpdateForm (
250 HiiHandle,
251 &mBootManagerGuid,
252 BOOT_MANAGER_FORM_ID,
253 LABEL_BOOT_OPTION,
254 FALSE,
255 &UpdateData
256 );
257 FreePool (UpdateData.Data);
258
259 //
260 // Drop the TPL level from TPL_APPLICATION to TPL_APPLICATION
261 //
262 gBS->RestoreTPL (TPL_APPLICATION);
263
264 ActionRequest = EFI_BROWSER_ACTION_REQUEST_NONE;
265 Status = gFormBrowser2->SendForm (
266 gFormBrowser2,
267 &HiiHandle,
268 1,
269 NULL,
270 0,
271 NULL,
272 &ActionRequest
273 );
274 if (ActionRequest == EFI_BROWSER_ACTION_REQUEST_RESET) {
275 EnableResetRequired ();
276 }
277
278 if (gOption == NULL) {
279 gBS->RaiseTPL (TPL_APPLICATION);
280 return ;
281 }
282
283 //
284 //Will leave browser, check any reset required change is applied? if yes, reset system
285 //
286 SetupResetReminder ();
287
288 //
289 // Raise the TPL level back to TPL_APPLICATION
290 //
291 gBS->RaiseTPL (TPL_APPLICATION);
292
293 //
294 // parse the selected option
295 //
296 Status = BdsLibBootViaBootOption (gOption, gOption->DevicePath, &ExitDataSize, &ExitData);
297
298 if (!EFI_ERROR (Status)) {
299 gOption->StatusString = GetStringById (STRING_TOKEN (STR_BOOT_SUCCEEDED));
300 PlatformBdsBootSuccess (gOption);
301 } else {
302 gOption->StatusString = GetStringById (STRING_TOKEN (STR_BOOT_FAILED));
303 PlatformBdsBootFail (gOption, Status, ExitData, ExitDataSize);
304 gST->ConOut->OutputString (
305 gST->ConOut,
306 GetStringById (STRING_TOKEN (STR_ANY_KEY_CONTINUE))
307 );
308 gBS->RestoreTPL (TPL_APPLICATION);
309 //
310 // BdsLibUiWaitForSingleEvent (gST->ConIn->WaitForKey, 0);
311 //
312 gBS->RaiseTPL (TPL_APPLICATION);
313 gST->ConIn->ReadKeyStroke (gST->ConIn, &Key);
314 }
315 }