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