]> git.proxmox.com Git - mirror_edk2.git/blob - EdkModulePkg/Library/EdkGenericPlatformBdsLib/BootMngr/BootManager.c
EdkGenericPlatformBdsLib added
[mirror_edk2.git] / EdkModulePkg / Library / EdkGenericPlatformBdsLib / BootMngr / BootManager.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 BootManager.c
15
16 Abstract:
17
18 The platform boot manager reference implement
19
20 --*/
21 #include "BootManager.h"
22
23 UINT16 mKeyInput;
24 LIST_ENTRY *mBootOptionsList;
25 BDS_COMMON_OPTION *gOption;
26 EFI_HII_HANDLE gBootManagerHandle;
27 EFI_HANDLE BootManagerCallbackHandle;
28 EFI_FORM_CALLBACK_PROTOCOL BootManagerCallback;
29 EFI_GUID gBmGuid = BOOT_MANAGER_GUID;
30
31 extern EFI_FORM_BROWSER_PROTOCOL *gBrowser;
32 extern UINT8 BootManagerVfrBin[];
33 extern UINT8 EdkGenericPlatformBdsLibStrings[];
34 extern BOOLEAN gConnectAllHappened;
35
36 EFI_STATUS
37 EFIAPI
38 BootManagerCallbackRoutine (
39 IN EFI_FORM_CALLBACK_PROTOCOL *This,
40 IN UINT16 KeyValue,
41 IN EFI_IFR_DATA_ARRAY *DataArray,
42 OUT EFI_HII_CALLBACK_PACKET **Packet
43 )
44 /*++
45
46 Routine Description:
47
48 This is the function that is called to provide results data to the driver. This data
49 consists of a unique key which is used to identify what data is either being passed back
50 or being asked for.
51
52 Arguments:
53
54 KeyValue - A unique value which is sent to the original exporting driver so that it
55 can identify the type of data to expect. The format of the data tends to
56 vary based on the op-code that geerated the callback.
57
58 Data - A pointer to the data being sent to the original exporting driver.
59
60 Returns:
61
62 --*/
63 {
64 BDS_COMMON_OPTION *Option;
65 LIST_ENTRY *Link;
66 UINT16 KeyCount;
67 EFI_HII_CALLBACK_PACKET *DataPacket;
68
69 //
70 // Initialize the key count
71 //
72 KeyCount = 0;
73
74 for (Link = mBootOptionsList->ForwardLink; Link != mBootOptionsList; Link = Link->ForwardLink) {
75 Option = CR (Link, BDS_COMMON_OPTION, Link, BDS_LOAD_OPTION_SIGNATURE);
76
77 KeyCount++;
78
79 gOption = Option;
80
81 //
82 // Is this device the one chosen?
83 //
84 if (KeyCount == KeyValue) {
85 //
86 // Assigning the returned Key to a global allows the original routine to know what was chosen
87 //
88 mKeyInput = KeyValue;
89
90 *Packet = AllocateZeroPool (sizeof (EFI_HII_CALLBACK_PACKET) + 2);
91 ASSERT (*Packet != NULL);
92
93 //
94 // Assign the buffer address to DataPacket
95 //
96 DataPacket = *Packet;
97
98 DataPacket->DataArray.EntryCount = 1;
99 DataPacket->DataArray.NvRamMap = NULL;
100 ((EFI_IFR_DATA_ENTRY *) (((EFI_IFR_DATA_ARRAY *)DataPacket) + 1))->Flags = EXIT_REQUIRED | NV_NOT_CHANGED;
101 return EFI_SUCCESS;
102 } else {
103 continue;
104 }
105 }
106
107 return EFI_SUCCESS;
108 }
109
110 VOID
111 CallBootManager (
112 VOID
113 )
114 /*++
115
116 Routine Description:
117 Hook to enable UI timeout override behavior.
118
119 Arguments:
120 BdsDeviceList - Device List that BDS needs to connect.
121
122 Entry - Pointer to current Boot Entry.
123
124 Returns:
125 NONE
126
127 --*/
128 {
129 EFI_STATUS Status;
130 EFI_HII_PACKAGES *PackageList;
131 BDS_COMMON_OPTION *Option;
132 LIST_ENTRY *Link;
133 EFI_HII_UPDATE_DATA *UpdateData;
134 CHAR16 *ExitData;
135 UINTN ExitDataSize;
136 STRING_REF Token;
137 STRING_REF LastToken;
138 EFI_INPUT_KEY Key;
139 UINT8 *Location;
140 EFI_GUID BmGuid;
141 LIST_ENTRY BdsBootOptionList;
142 BOOLEAN BootMngrMenuResetRequired;
143
144 gOption = NULL;
145 InitializeListHead (&BdsBootOptionList);
146
147 //
148 // Connect all prior to entering the platform setup menu.
149 //
150 if (!gConnectAllHappened) {
151 BdsLibConnectAllDriversToAllControllers ();
152 gConnectAllHappened = TRUE;
153 }
154 //
155 // BugBug: Here we can not remove the legacy refresh macro, so we need
156 // get the boot order every time from "BootOrder" variable.
157 // Recreate the boot option list base on the BootOrder variable
158 //
159 BdsLibEnumerateAllBootOption (&BdsBootOptionList);
160
161 //
162 // This GUID must be the same as what is defined in BootManagerVfr.vfr
163 //
164 BmGuid = gBmGuid;
165
166 mBootOptionsList = &BdsBootOptionList;
167
168 //
169 // Post our VFR to the HII database
170 //
171 PackageList = PreparePackages (2, &BmGuid, BootManagerVfrBin, EdkGenericPlatformBdsLibStrings);
172 Status = Hii->NewPack (Hii, PackageList, &gBootManagerHandle);
173 gBS->FreePool (PackageList);
174
175 //
176 // This example does not implement worker functions
177 // for the NV accessor functions. Only a callback evaluator
178 //
179 BootManagerCallback.NvRead = NULL;
180 BootManagerCallback.NvWrite = NULL;
181 BootManagerCallback.Callback = BootManagerCallbackRoutine;
182
183 //
184 // Install protocol interface
185 //
186 BootManagerCallbackHandle = NULL;
187 Status = gBS->InstallProtocolInterface (
188 &BootManagerCallbackHandle,
189 &gEfiFormCallbackProtocolGuid,
190 EFI_NATIVE_INTERFACE,
191 &BootManagerCallback
192 );
193 ASSERT_EFI_ERROR (Status);
194
195 LastToken = 0;
196 Hii->NewString (Hii, NULL, gBootManagerHandle, &LastToken, L" ");
197
198 //
199 // Allocate space for creation of UpdateData Buffer
200 //
201 UpdateData = AllocateZeroPool (0x1000);
202 ASSERT (UpdateData != NULL);
203
204 //
205 // Flag update pending in FormSet
206 //
207 UpdateData->FormSetUpdate = TRUE;
208 //
209 // Register CallbackHandle data for FormSet
210 //
211 UpdateData->FormCallbackHandle = (EFI_PHYSICAL_ADDRESS) (UINTN) BootManagerCallbackHandle;
212 UpdateData->FormUpdate = FALSE;
213 UpdateData->FormTitle = 0;
214 UpdateData->DataCount = 1;
215
216 //
217 // Create blank space. Since when we update the contents of IFR data at a label, it is
218 // inserted at the location of the label. So if you want to add a string with an empty
219 // space afterwards, you need to add the space first and then the string like below.
220 //
221 Status = CreateSubTitleOpCode (
222 LastToken, // Token Value for the string
223 &UpdateData->Data // Buffer containing created op-code
224 );
225
226 Hii->UpdateForm (Hii, gBootManagerHandle, (EFI_FORM_LABEL) 0x0000, TRUE, UpdateData);
227
228 //
229 // Create "Boot Option Menu" title
230 //
231 Status = CreateSubTitleOpCode (
232 STRING_TOKEN (STR_BOOT_OPTION_BANNER), // Token Value for the string
233 &UpdateData->Data // Buffer containing created op-code
234 );
235
236 Hii->UpdateForm (Hii, gBootManagerHandle, (EFI_FORM_LABEL) 0x0000, TRUE, UpdateData);
237
238 Token = LastToken;
239 mKeyInput = 0;
240
241 UpdateData->DataCount = 0;
242 Location = (UINT8 *) &UpdateData->Data;
243
244 for (Link = BdsBootOptionList.ForwardLink; Link != &BdsBootOptionList; Link = Link->ForwardLink) {
245 Option = CR (Link, BDS_COMMON_OPTION, Link, BDS_LOAD_OPTION_SIGNATURE);
246
247 //
248 // At this stage we are creating a menu entry, thus the Keys are reproduceable
249 //
250 mKeyInput++;
251 Token++;
252
253 Status = Hii->NewString (Hii, NULL, gBootManagerHandle, &Token, Option->Description);
254
255 //
256 // If we got an error it is almost certainly due to the token value being invalid.
257 // Therefore we will set the Token to 0 to automatically add a token.
258 //
259 if (EFI_ERROR (Status)) {
260 Token = 0;
261 Status = Hii->NewString (Hii, NULL, gBootManagerHandle, &Token, Option->Description);
262 }
263
264 Status = CreateGotoOpCode (
265 0x1000, // Form ID
266 Token, // Token Value for the string
267 0, // Help String (none)
268 EFI_IFR_FLAG_INTERACTIVE | EFI_IFR_FLAG_NV_ACCESS, // The Op-Code flags
269 mKeyInput, // The Key to get a callback on
270 Location // Buffer containing created op-code
271 );
272
273 UpdateData->DataCount++;
274 Location = Location + ((EFI_IFR_OP_HEADER *) Location)->Length;
275
276 }
277
278 Hii->UpdateForm (Hii, gBootManagerHandle, (EFI_FORM_LABEL) 0x0001, TRUE, UpdateData);
279
280 UpdateData->DataCount = 1;
281
282 //
283 // Create "Boot Option Menu" title
284 //
285 Status = CreateSubTitleOpCode (
286 STRING_TOKEN (STR_HELP_FOOTER), // Token Value for the string
287 &UpdateData->Data // Buffer containing created op-code
288 );
289
290 Hii->UpdateForm (Hii, gBootManagerHandle, (EFI_FORM_LABEL) 0x0002, TRUE, UpdateData);
291
292 Status = CreateSubTitleOpCode (
293 LastToken, // Token Value for the string
294 &UpdateData->Data // Buffer containing created op-code
295 );
296
297 Hii->UpdateForm (Hii, gBootManagerHandle, (EFI_FORM_LABEL) 0x0002, TRUE, UpdateData);
298
299 gBS->FreePool (UpdateData);
300
301 ASSERT (gBrowser);
302
303 BootMngrMenuResetRequired = FALSE;
304 gBrowser->SendForm (
305 gBrowser,
306 TRUE,
307 &gBootManagerHandle,
308 1,
309 NULL,
310 NULL,
311 NULL,
312 NULL,
313 &BootMngrMenuResetRequired
314 );
315
316 if (BootMngrMenuResetRequired) {
317 EnableResetRequired ();
318 }
319
320 Hii->ResetStrings (Hii, gBootManagerHandle);
321
322 if (gOption == NULL) {
323 return ;
324 }
325
326 //
327 //Will leave browser, check any reset required change is applied? if yes, reset system
328 //
329 SetupResetReminder ();
330
331 //
332 // BugBug: This code looks repeated from the BDS. Need to save code space.
333 //
334
335 //
336 // parse the selected option
337 //
338 Status = BdsLibBootViaBootOption (gOption, gOption->DevicePath, &ExitDataSize, &ExitData);
339
340 if (!EFI_ERROR (Status)) {
341 PlatformBdsBootSuccess (gOption);
342 } else {
343 PlatformBdsBootFail (gOption, Status, ExitData, ExitDataSize);
344 gST->ConOut->OutputString (
345 gST->ConOut,
346 GetStringById (STRING_TOKEN (STR_ANY_KEY_CONTINUE))
347 );
348
349 //
350 // BdsLibUiWaitForSingleEvent (gST->ConIn->WaitForKey, 0);
351 //
352
353 gST->ConIn->ReadKeyStroke (gST->ConIn, &Key);
354 }
355 }