]> git.proxmox.com Git - mirror_edk2.git/blob - EdkCompatibilityPkg/Compatibility/FrameworkHiiOnUefiHiiThunk/SetupBrowser.c
1, Change name of PcdPlatformBootTimeoutDefault to PcdPlatformBootTimeout, now this...
[mirror_edk2.git] / EdkCompatibilityPkg / Compatibility / FrameworkHiiOnUefiHiiThunk / SetupBrowser.c
1 /**@file
2 Framework to UEFI 2.1 Setup Browser Thunk. The file consume EFI_FORM_BROWSER2_PROTOCOL
3 to produce a EFI_FORM_BROWSER_PROTOCOL.
4
5 Copyright (c) 2008, Intel Corporation
6 All rights reserved. This program and the accompanying materials
7 are licensed and made available under the terms and conditions of the BSD License
8 which accompanies this distribution. The full text of the license may be found at
9 http://opensource.org/licenses/bsd-license.php
10
11 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
12 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
13
14 **/
15
16 #include "HiiDatabase.h"
17 #include "SetupBrowser.h"
18
19 EFI_GUID gFrameworkBdsFrontPageFormsetGuid = FRAMEWORK_BDS_FRONTPAGE_FORMSET_GUID;
20 EFI_HII_HANDLE gStringPackHandle = NULL;
21 BOOLEAN mFrontPageDisplayed = FALSE;
22 //
23 // 106F3545-B788-4cb5-9D2A-CE0CDB208DF5
24 //
25 EFI_GUID gEfiHiiThunkProducerGuid = { 0x106f3545, 0xb788, 0x4cb5, { 0x9d, 0x2a, 0xce, 0xc, 0xdb, 0x20, 0x8d, 0xf5 } };
26
27
28 /**
29 Get string by string id from HII Interface
30
31
32 @param Id String ID.
33
34 @retval CHAR16 * String from ID.
35 @retval NULL If error occurs.
36
37 **/
38 CHAR16 *
39 GetStringById (
40 IN EFI_STRING_ID Id
41 )
42 {
43 CHAR16 *String;
44
45 String = NULL;
46 HiiLibGetStringFromHandle (gStringPackHandle, Id, &String);
47
48 return String;
49 }
50 /**
51
52 Show progress bar with title above it. It only works in Graphics mode.
53
54
55 @param TitleForeground Foreground color for Title.
56 @param TitleBackground Background color for Title.
57 @param Title Title above progress bar.
58 @param ProgressColor Progress bar color.
59 @param Progress Progress (0-100)
60 @param PreviousValue The previous value of the progress.
61
62 @retval EFI_STATUS Success update the progress bar
63
64 **/
65 EFI_STATUS
66 PlatformBdsShowProgress (
67 IN EFI_GRAPHICS_OUTPUT_BLT_PIXEL TitleForeground,
68 IN EFI_GRAPHICS_OUTPUT_BLT_PIXEL TitleBackground,
69 IN CHAR16 *Title,
70 IN EFI_GRAPHICS_OUTPUT_BLT_PIXEL ProgressColor,
71 IN UINTN Progress,
72 IN UINTN PreviousValue
73 )
74 {
75 EFI_STATUS Status;
76 EFI_GRAPHICS_OUTPUT_PROTOCOL *GraphicsOutput;
77 EFI_UGA_DRAW_PROTOCOL *UgaDraw;
78 UINT32 SizeOfX;
79 UINT32 SizeOfY;
80 UINT32 ColorDepth;
81 UINT32 RefreshRate;
82 EFI_GRAPHICS_OUTPUT_BLT_PIXEL Color;
83 UINTN BlockHeight;
84 UINTN BlockWidth;
85 UINTN BlockNum;
86 UINTN PosX;
87 UINTN PosY;
88 UINTN Index;
89
90 if (Progress > 100) {
91 return EFI_INVALID_PARAMETER;
92 }
93
94 UgaDraw = NULL;
95 Status = gBS->HandleProtocol (
96 gST->ConsoleOutHandle,
97 &gEfiGraphicsOutputProtocolGuid,
98 (VOID **) &GraphicsOutput
99 );
100 if (EFI_ERROR (Status)) {
101 GraphicsOutput = NULL;
102
103 Status = gBS->HandleProtocol (
104 gST->ConsoleOutHandle,
105 &gEfiUgaDrawProtocolGuid,
106 (VOID **) &UgaDraw
107 );
108 }
109 if (EFI_ERROR (Status)) {
110 return EFI_UNSUPPORTED;
111 }
112
113 SizeOfX = 0;
114 SizeOfY = 0;
115 if (GraphicsOutput != NULL) {
116 SizeOfX = GraphicsOutput->Mode->Info->HorizontalResolution;
117 SizeOfY = GraphicsOutput->Mode->Info->VerticalResolution;
118 } else {
119 Status = UgaDraw->GetMode (
120 UgaDraw,
121 &SizeOfX,
122 &SizeOfY,
123 &ColorDepth,
124 &RefreshRate
125 );
126 if (EFI_ERROR (Status)) {
127 return EFI_UNSUPPORTED;
128 }
129 }
130
131 BlockWidth = SizeOfX / 100;
132 BlockHeight = SizeOfY / 50;
133
134 BlockNum = Progress;
135
136 PosX = 0;
137 PosY = SizeOfY * 48 / 50;
138
139 if (BlockNum == 0) {
140 //
141 // Clear progress area
142 //
143 SetMem (&Color, sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL), 0x0);
144
145 if (GraphicsOutput != NULL) {
146 Status = GraphicsOutput->Blt (
147 GraphicsOutput,
148 &Color,
149 EfiBltVideoFill,
150 0,
151 0,
152 0,
153 PosY - EFI_GLYPH_HEIGHT - 1,
154 SizeOfX,
155 SizeOfY - (PosY - EFI_GLYPH_HEIGHT - 1),
156 SizeOfX * sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL)
157 );
158 } else {
159 Status = UgaDraw->Blt (
160 UgaDraw,
161 (EFI_UGA_PIXEL *) &Color,
162 EfiUgaVideoFill,
163 0,
164 0,
165 0,
166 PosY - EFI_GLYPH_HEIGHT - 1,
167 SizeOfX,
168 SizeOfY - (PosY - EFI_GLYPH_HEIGHT - 1),
169 SizeOfX * sizeof (EFI_UGA_PIXEL)
170 );
171 }
172 }
173 //
174 // Show progress by drawing blocks
175 //
176 for (Index = PreviousValue; Index < BlockNum; Index++) {
177 PosX = Index * BlockWidth;
178 if (GraphicsOutput != NULL) {
179 Status = GraphicsOutput->Blt (
180 GraphicsOutput,
181 &ProgressColor,
182 EfiBltVideoFill,
183 0,
184 0,
185 PosX,
186 PosY,
187 BlockWidth - 1,
188 BlockHeight,
189 (BlockWidth) * sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL)
190 );
191 } else {
192 Status = UgaDraw->Blt (
193 UgaDraw,
194 (EFI_UGA_PIXEL *) &ProgressColor,
195 EfiUgaVideoFill,
196 0,
197 0,
198 PosX,
199 PosY,
200 BlockWidth - 1,
201 BlockHeight,
202 (BlockWidth) * sizeof (EFI_UGA_PIXEL)
203 );
204 }
205 }
206
207 PrintXY (
208 (SizeOfX - StrLen (Title) * EFI_GLYPH_WIDTH) / 2,
209 PosY - EFI_GLYPH_HEIGHT - 1,
210 &TitleForeground,
211 &TitleBackground,
212 Title
213 );
214
215 return EFI_SUCCESS;
216 }
217
218 /**
219 Function waits for a given event to fire, or for an optional timeout to expire.
220
221
222 @param Event The event to wait for
223
224 @param Timeout An optional timeout value in 100 ns units.
225
226 @retval EFI_SUCCESS Event fired before Timeout expired.
227 @retval EFI_TIME_OUT Timout expired before Event fired..
228
229 **/
230 EFI_STATUS
231 WaitForSingleEvent (
232 IN EFI_EVENT Event,
233 IN UINT64 Timeout OPTIONAL
234 )
235 {
236 EFI_STATUS Status;
237 UINTN Index;
238 EFI_EVENT TimerEvent;
239 EFI_EVENT WaitList[2];
240
241 if (Timeout != 0) {
242 //
243 // Create a timer event
244 //
245 Status = gBS->CreateEvent (EVT_TIMER, 0, NULL, NULL, &TimerEvent);
246 if (!EFI_ERROR (Status)) {
247 //
248 // Set the timer event
249 //
250 gBS->SetTimer (
251 TimerEvent,
252 TimerRelative,
253 Timeout
254 );
255
256 //
257 // Wait for the original event or the timer
258 //
259 WaitList[0] = Event;
260 WaitList[1] = TimerEvent;
261 Status = gBS->WaitForEvent (2, WaitList, &Index);
262 gBS->CloseEvent (TimerEvent);
263
264 //
265 // If the timer expired, change the return to timed out
266 //
267 if (!EFI_ERROR (Status) && Index == 1) {
268 Status = EFI_TIMEOUT;
269 }
270 }
271 } else {
272 //
273 // No timeout... just wait on the event
274 //
275 Status = gBS->WaitForEvent (1, &Event, &Index);
276 ASSERT (!EFI_ERROR (Status));
277 ASSERT (Index == 0);
278 }
279
280 return Status;
281 }
282
283 /**
284 Function show progress bar to wait for user input.
285
286
287 @param TimeoutDefault - The fault time out value before the system
288 continue to boot.
289
290 @retval EFI_SUCCESS User pressed some key except "Enter"
291 @retval EFI_TIME_OUT Timout expired or user press "Enter"
292
293 **/
294 EFI_STATUS
295 ShowProgress (
296 IN UINT16 TimeoutDefault
297 )
298 {
299 EFI_STATUS Status;
300 CHAR16 *TmpStr;
301 EFI_GRAPHICS_OUTPUT_BLT_PIXEL Foreground;
302 EFI_GRAPHICS_OUTPUT_BLT_PIXEL Background;
303 EFI_GRAPHICS_OUTPUT_BLT_PIXEL Color;
304 EFI_INPUT_KEY Key;
305 UINT16 TimeoutRemain;
306
307 if (TimeoutDefault == 0) {
308 return EFI_TIMEOUT;
309 }
310
311 DEBUG ((EFI_D_INFO, "\n\nStart showing progress bar... Press any key to stop it! ...Zzz....\n"));
312
313 SetMem (&Foreground, sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL), 0xff);
314 SetMem (&Background, sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL), 0x0);
315 SetMem (&Color, sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL), 0xff);
316
317 //
318 // Clear the progress status bar first
319 //
320 TmpStr = GetStringById (STRING_TOKEN (STR_START_BOOT_OPTION));
321 if (TmpStr != NULL) {
322 PlatformBdsShowProgress (Foreground, Background, TmpStr, Color, 0, 0);
323 }
324
325 TimeoutRemain = TimeoutDefault;
326 while (TimeoutRemain != 0) {
327 DEBUG ((EFI_D_INFO, "Showing progress bar...Remaining %d second!\n", TimeoutRemain));
328
329 Status = WaitForSingleEvent (gST->ConIn->WaitForKey, ONE_SECOND);
330 if (Status != EFI_TIMEOUT) {
331 break;
332 }
333 TimeoutRemain--;
334
335 //
336 // Show progress
337 //
338 if (TmpStr != NULL) {
339 PlatformBdsShowProgress (
340 Foreground,
341 Background,
342 TmpStr,
343 Color,
344 ((TimeoutDefault - TimeoutRemain) * 100 / TimeoutDefault),
345 0
346 );
347 }
348 }
349 gBS->FreePool (TmpStr);
350
351 //
352 // Timeout expired
353 //
354 if (TimeoutRemain == 0) {
355 return EFI_TIMEOUT;
356 }
357
358 //
359 // User pressed some key
360 //
361 Status = gST->ConIn->ReadKeyStroke (gST->ConIn, &Key);
362 if (EFI_ERROR (Status)) {
363 return Status;
364 }
365
366 if (Key.UnicodeChar == CHAR_CARRIAGE_RETURN) {
367 //
368 // User pressed enter, equivalent to select "continue"
369 //
370 return EFI_TIMEOUT;
371 }
372
373 return EFI_SUCCESS;
374 }
375
376 /**
377 Return the default value for system Timeout variable.
378
379 @return Timeout value.
380
381 **/
382 UINT16
383 EFIAPI
384 GetTimeout (
385 VOID
386 )
387 {
388 return PcdGet16 (PcdPlatformBootTimeOut);
389 }
390
391
392 /**
393 This is the Framework Setup Browser interface which displays a FormSet.
394
395 @param This The EFI_FORM_BROWSER_PROTOCOL context.
396 @param UseDatabase TRUE if the FormSet is from HII database. The Thunk implementation
397 only support UseDatabase is TRUE.
398 @param Handle The Handle buffer.
399 @param HandleCount The number of Handle in the Handle Buffer. It must be 1 for this implementation.
400 @param Packet The pointer to data buffer containing IFR and String package. Not supported.
401 @param CallbackHandle Not supported.
402 @param NvMapOverride The buffer is used only when there is no NV variable to define the
403 current settings and the caller needs to provide to the browser the
404 current settings for the the "fake" NV variable. If used, no saving of
405 an NV variable is possbile. This parameter is also ignored if Handle is NULL.
406
407 @retval EFI_SUCCESS If the Formset is displayed correctly.
408 @retval EFI_UNSUPPORTED If UseDatabase is FALSE or HandleCount is not 1.
409 @retval EFI_INVALID_PARAMETER If the *Handle passed in is not found in the database.
410 **/
411
412 EFI_STATUS
413 EFIAPI
414 ThunkSendForm (
415 IN EFI_FORM_BROWSER_PROTOCOL *This,
416 IN BOOLEAN UseDatabase,
417 IN FRAMEWORK_EFI_HII_HANDLE *Handle,
418 IN UINTN HandleCount,
419 IN FRAMEWORK_EFI_IFR_PACKET *Packet, OPTIONAL
420 IN EFI_HANDLE CallbackHandle, OPTIONAL
421 IN UINT8 *NvMapOverride, OPTIONAL
422 IN FRAMEWORK_EFI_SCREEN_DESCRIPTOR *ScreenDimensions, OPTIONAL
423 OUT BOOLEAN *ResetRequired OPTIONAL
424 )
425 {
426 EFI_STATUS Status;
427 EFI_BROWSER_ACTION_REQUEST ActionRequest;
428 HII_THUNK_CONTEXT *ThunkContext;
429 HII_THUNK_PRIVATE_DATA *Private;
430 EFI_FORMBROWSER_THUNK_PRIVATE_DATA *BrowserPrivate;
431
432 if (!UseDatabase) {
433 //
434 // ThunkSendForm only support displays forms registered into the HII database.
435 //
436 return EFI_UNSUPPORTED;
437 }
438
439 if (HandleCount != 1 ) {
440 return EFI_UNSUPPORTED;
441 }
442
443 BrowserPrivate = EFI_FORMBROWSER_THUNK_PRIVATE_DATA_FROM_THIS (This);
444 Private = BrowserPrivate->ThunkPrivate;
445
446 ThunkContext = FwHiiHandleToThunkContext (Private, *Handle);
447 if (ThunkContext == NULL) {
448 return EFI_INVALID_PARAMETER;
449 }
450
451 //
452 // Following UEFI spec to do auto booting after a time-out. This feature is implemented
453 // in Framework Setup Browser and moved to MdeModulePkg/Universal/BdsDxe. The auto booting is
454 // moved here in HII Thunk module.
455 //
456 if (CompareGuid (&gFrameworkBdsFrontPageFormsetGuid, &ThunkContext->FormSet->Guid) && !mFrontPageDisplayed) {
457 //
458 // Send form is called before entering the
459 //
460 mFrontPageDisplayed = TRUE;
461 Status = ShowProgress (GetTimeout ());
462
463 if (EFI_ERROR (Status)) {
464 return Status;
465 }
466 }
467
468 if (NvMapOverride != NULL) {
469 ThunkContext->NvMapOverride = NvMapOverride;
470 }
471
472 Status = mFormBrowser2Protocol->SendForm (
473 mFormBrowser2Protocol,
474 &ThunkContext->UefiHiiHandle,
475 1,
476 NULL,
477 0,
478 (EFI_SCREEN_DESCRIPTOR *) ScreenDimensions,
479 &ActionRequest
480 );
481
482 if (ActionRequest == EFI_BROWSER_ACTION_REQUEST_RESET) {
483 *ResetRequired = TRUE;
484 }
485
486 return Status;
487 }
488
489 /**
490
491 Rountine used to display a generic dialog interface and return
492 the Key or Input from user input.
493
494 @param NumberOfLines The number of lines for the dialog box.
495 @param HotKey Defines if a single character is parsed (TRUE) and returned in KeyValue
496 or if a string is returned in StringBuffer.
497 @param MaximumStringSize The maximum size in bytes of a typed-in string.
498 @param StringBuffer On return contains the typed-in string if HotKey
499 is FALSE.
500 @param KeyValue The EFI_INPUT_KEY value returned if HotKey is TRUE.
501 @param String The pointer to the first string in the list of strings
502 that comprise the dialog box.
503 @param ... A series of NumberOfLines text strings that will be used
504 to construct the dialog box.
505 @retval EFI_SUCCESS The dialog is created successfully and user interaction was received.
506 @retval EFI_DEVICE_ERROR The user typed in an ESC.
507 @retval EFI_INVALID_PARAMETER One of the parameters was invalid.(StringBuffer == NULL && HotKey == FALSE).
508 **/
509 EFI_STATUS
510 EFIAPI
511 ThunkCreatePopUp (
512 IN UINTN NumberOfLines,
513 IN BOOLEAN HotKey,
514 IN UINTN MaximumStringSize,
515 OUT CHAR16 *StringBuffer,
516 OUT EFI_INPUT_KEY *KeyValue,
517 IN CHAR16 *String,
518 ...
519 )
520 {
521 EFI_STATUS Status;
522 VA_LIST Marker;
523
524 if (HotKey != TRUE) {
525 return EFI_UNSUPPORTED;
526 }
527
528 VA_START (Marker, String);
529
530 Status = IfrLibCreatePopUp2 (NumberOfLines, KeyValue, String, Marker);
531
532 VA_END (Marker);
533
534 return Status;
535 }
536
537 /**
538
539 Initialize string packages in HII database.
540
541 **/
542 VOID
543 InitSetBrowserStrings (
544 VOID
545 )
546 {
547 EFI_STATUS Status;
548
549 //
550 // Initialize strings to HII database
551 //
552 Status = HiiLibAddPackages (1, &gEfiHiiThunkProducerGuid, NULL, &gStringPackHandle, STRING_ARRAY_NAME);
553 ASSERT_EFI_ERROR (Status);
554
555 }