]> git.proxmox.com Git - mirror_edk2.git/blob - EdkModulePkg/Universal/UserInterface/DriverSample/DriverSample.c
Add missing files in msa file and add module description in msa file, and reorganize...
[mirror_edk2.git] / EdkModulePkg / Universal / UserInterface / DriverSample / DriverSample.c
1 /*++
2 Copyright (c) 2006, Intel Corporation
3 All rights reserved. This program and the accompanying materials
4 are licensed and made available under the terms and conditions of the BSD License
5 which accompanies this distribution. The full text of the license may be found at
6 http://opensource.org/licenses/bsd-license.php
7
8 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
9 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
10
11 Module Name:
12 DriverSample.c
13
14 Abstract:
15
16 This is an example of how a driver might export data to the HII protocol to be
17 later utilized by the Setup Protocol
18
19 --*/
20
21 #include "DriverSample.h"
22
23 #define DISPLAY_ONLY_MY_ITEM 0x0001
24
25 #define STRING_PACK_GUID \
26 { \
27 0x8160a85f, 0x934d, 0x468b, { 0xa2, 0x35, 0x72, 0x89, 0x59, 0x14, 0xf6, 0xfc } \
28 }
29
30 EFI_GUID mFormSetGuid = FORMSET_GUID;
31 EFI_GUID mStringPackGuid = STRING_PACK_GUID;
32
33 EFI_STATUS
34 EFIAPI
35 DriverCallback (
36 IN EFI_FORM_CALLBACK_PROTOCOL *This,
37 IN UINT16 KeyValue,
38 IN EFI_IFR_DATA_ARRAY *Data,
39 OUT EFI_HII_CALLBACK_PACKET **Packet
40 )
41 /*++
42
43 Routine Description:
44
45 This is the function that is called to provide results data to the driver. This data
46 consists of a unique key which is used to identify what data is either being passed back
47 or being asked for.
48
49 Arguments:
50
51 KeyValue - A unique value which is sent to the original exporting driver so that it
52 can identify the type of data to expect. The format of the data tends to
53 vary based on the op-code that geerated the callback.
54
55 Data - A pointer to the data being sent to the original exporting driver.
56
57 Returns:
58
59 --*/
60 {
61 EFI_CALLBACK_INFO *Private;
62 EFI_HII_UPDATE_DATA *UpdateData;
63 EFI_STATUS Status;
64 UINT8 *Location;
65 EFI_HII_CALLBACK_PACKET *DataPacket;
66 UINT16 Value;
67 CHAR16 VariableName[40];
68 STATIC UINT16 QuestionId = 0;
69 IFR_OPTION *OptionList;
70 UINTN Index;
71 MyIfrNVData NVStruc;
72
73 Private = EFI_CALLBACK_INFO_FROM_THIS (This);
74
75 //
76 // This should tell me the first offset AFTER the end of the compiled NV map
77 // If op-code results are not going to be saved to NV locations ensure the QuestionId
78 // is beyond the end of the NVRAM mapping.
79 //
80 if (QuestionId == 0) {
81 QuestionId = sizeof (MyIfrNVData);
82 }
83
84 ZeroMem (VariableName, (sizeof (CHAR16) * 40));
85
86 switch (KeyValue) {
87 case 0x0001:
88 //
89 // Create a small boot order list
90 //
91 QuestionId = (UINT16) ((UINTN) (&NVStruc.BootOrder) - (UINTN) (&NVStruc));
92
93 //
94 // Need some memory for OptionList. Allow for up to 8 options.
95 //
96 OptionList = AllocateZeroPool (sizeof (IFR_OPTION) * 8);
97
98 //
99 // Allocate space for creation of Buffer
100 //
101 UpdateData = AllocateZeroPool (0x1000);
102
103 //
104 // Remove all the op-codes starting with Label 0x2222 to next Label (second label is for convenience
105 // so we don't have to keep track of how many op-codes we added or subtracted. The rules for removal
106 // of op-codes are simply that the removal will always stop as soon as a label or the end of a form is
107 // encountered. Therefore, giving a large obnoxious count such as below takes care of other complexities.
108 //
109 UpdateData->DataCount = 0xFF;
110
111 //
112 // Delete set of op-codes
113 //
114 Private->Hii->UpdateForm (
115 Private->Hii,
116 Private->RegisteredHandle,
117 (EFI_FORM_LABEL) 0x2222,
118 FALSE, // If we aren't adding, we are deleting
119 UpdateData
120 );
121
122 //
123 // Create 3 options
124 //
125 for (Index = 0; Index < 3; Index++) {
126 OptionList[Index].StringToken = (UINT16) (STR_BOOT_OPTION1 + Index);
127 OptionList[Index].Value = (UINT16) (Index + 1);
128 OptionList[Index].Flags = RESET_REQUIRED;
129 }
130
131 CreateOrderedListOpCode (
132 QuestionId, // Question ID
133 8, // Max Entries
134 (UINT16) STRING_TOKEN (STR_BOOT_OPTIONS), // Token value for the Prompt
135 (UINT16) STRING_TOKEN (STR_NULL_STRING), // Token value for the Help
136 OptionList,
137 3,
138 &UpdateData->Data // Buffer location to place op-codes
139 );
140
141 //
142 // For one-of/ordered lists commands, they really consist of 2 op-codes (a header and a footer)
143 // Each option within a one-of/ordered list is also an op-code
144 // So this example has 5 op-codes it is adding since we have a one-of header + 3 options + one-of footer
145 //
146 UpdateData->DataCount = 0x5;
147
148 //
149 // Add one op-code
150 //
151 Private->Hii->UpdateForm (
152 Private->Hii,
153 Private->RegisteredHandle,
154 (EFI_FORM_LABEL) 0x2222,
155 TRUE,
156 UpdateData
157 );
158
159 gBS->FreePool (UpdateData);
160 gBS->FreePool (OptionList);
161 break;
162
163 case 0x0002:
164 //
165 // Create a large boot order list
166 //
167 QuestionId = (UINT16) ((UINTN) (&NVStruc.BootOrder) - (UINTN) (&NVStruc));
168
169 //
170 // Need some memory for OptionList. Allow for up to 8 options.
171 //
172 OptionList = AllocateZeroPool (sizeof (IFR_OPTION) * 8);
173
174 //
175 // Allocate space for creation of Buffer
176 //
177 UpdateData = AllocateZeroPool (0x1000);
178
179 //
180 // Remove all the op-codes starting with Label 0x2222 to next Label (second label is for convenience
181 // so we don't have to keep track of how many op-codes we added or subtracted
182 //
183 UpdateData->DataCount = 0xFF;
184
185 //
186 // Delete one op-code
187 //
188 Private->Hii->UpdateForm (
189 Private->Hii,
190 Private->RegisteredHandle,
191 (EFI_FORM_LABEL) 0x2222,
192 FALSE,
193 UpdateData
194 );
195
196 //
197 // Create 4 options
198 //
199 for (Index = 0; Index < 4; Index++) {
200 OptionList[Index].StringToken = (UINT16) (STR_BOOT_OPTION1 + Index);
201 OptionList[Index].Value = (UINT16) (Index + 1);
202 OptionList[Index].Flags = RESET_REQUIRED;
203 }
204
205 CreateOrderedListOpCode (
206 QuestionId, // Question ID
207 8, // Max Entries
208 (UINT16) STRING_TOKEN (STR_BOOT_OPTIONS), // Token value for the Prompt
209 (UINT16) STRING_TOKEN (STR_NULL_STRING), // Token value for the Help
210 OptionList,
211 4,
212 &UpdateData->Data // Buffer location to place op-codes
213 );
214
215 //
216 // For one-of commands, they really consist of 2 op-codes (a header and a footer)
217 // Each option within a one-of is also an op-code
218 // So this example has 6 op-codes it is adding since we have a one-of header + 4 options + one-of footer
219 //
220 UpdateData->DataCount = 0x6;
221
222 //
223 // Add one op-code
224 //
225 Private->Hii->UpdateForm (
226 Private->Hii,
227 Private->RegisteredHandle,
228 (EFI_FORM_LABEL) 0x2222,
229 TRUE,
230 UpdateData
231 );
232
233 gBS->FreePool (UpdateData);
234 gBS->FreePool (OptionList);
235 break;
236
237 case 0x1234:
238 //
239 // Allocate space for creation of Buffer
240 //
241 QuestionId = (UINT16) ((UINTN) (&NVStruc.DynamicCheck));
242 Status = gBS->AllocatePool (
243 EfiBootServicesData,
244 0x1000,
245 (VOID **) &UpdateData
246 );
247
248 ZeroMem (UpdateData, 0x1000);
249
250 Location = (UINT8 *) &UpdateData->Data;
251
252 UpdateData->FormSetUpdate = TRUE;
253 UpdateData->FormCallbackHandle = (EFI_PHYSICAL_ADDRESS) (UINTN) Private->CallbackHandle;
254 UpdateData->FormUpdate = FALSE;
255 UpdateData->FormTitle = 0;
256 UpdateData->DataCount = 2;
257
258 CreateGotoOpCode (
259 1,
260 STR_GOTO_FORM1, // Token value for the Prompt
261 0, // Goto Help
262 0, // Flags
263 0, // Key
264 &UpdateData->Data // Buffer location to place op-codes
265 );
266
267 Location = Location + ((EFI_IFR_OP_HEADER *) &UpdateData->Data)->Length;
268
269 CreateCheckBoxOpCode (
270 QuestionId, // Question ID
271 1, // Data width (BOOLEAN = 1)
272 (UINT16) STRING_TOKEN (STR_CHECK_DYNAMIC_PROMPT), // Token value for the Prompt
273 (UINT16) STRING_TOKEN (STR_CHECK_DYNAMIC_HELP), // Token value for the Help
274 EFI_IFR_FLAG_INTERACTIVE, // Flags
275 0x1236, // Key
276 Location // Buffer location to place op-codes
277 );
278
279 Private->Hii->UpdateForm (
280 Private->Hii,
281 Private->RegisteredHandle,
282 (EFI_FORM_LABEL) 0x1234,
283 TRUE,
284 UpdateData
285 );
286
287 gBS->FreePool (UpdateData);
288 QuestionId++;
289 break;
290
291 case 0x1235:
292 //
293 // Allocate space for creation of Buffer
294 //
295 Status = gBS->AllocatePool (
296 EfiBootServicesData,
297 0x1000,
298 (VOID **)&UpdateData
299 );
300
301 ZeroMem (UpdateData, 0x1000);
302
303 //
304 // Initialize DataPacket with information intended to remove all
305 // previously created op-codes in the dynamic page
306 //
307 UpdateData->FormSetUpdate = FALSE;
308 UpdateData->FormCallbackHandle = 0;
309 UpdateData->FormUpdate = FALSE;
310 UpdateData->FormTitle = 0;
311 //
312 // Unlikely to be more than 0xff op-codes in the dynamic page to remove
313 //
314 UpdateData->DataCount = 0xff;
315 UpdateData->Data = NULL;
316
317 //
318 // Remove all op-codes from dynamic page
319 //
320 Private->Hii->UpdateForm (
321 Private->Hii,
322 Private->RegisteredHandle,
323 (EFI_FORM_LABEL) 0x1234, // Label 0x1234
324 FALSE, // Remove Op-codes (will never remove form/endform)
325 UpdateData // Significant value is UpdateData->DataCount
326 );
327
328 UpdateData->FormSetUpdate = FALSE;
329 UpdateData->FormCallbackHandle = 0;
330 UpdateData->FormUpdate = FALSE;
331 UpdateData->FormTitle = 0;
332 UpdateData->DataCount = 1;
333
334 CreateGotoOpCode (
335 1,
336 STR_GOTO_FORM1, // Token value for the Prompt
337 0, // Goto Help
338 0, // Flags
339 0, // Key
340 &UpdateData->Data // Buffer location to place op-codes
341 );
342
343 Private->Hii->UpdateForm (
344 Private->Hii,
345 Private->RegisteredHandle,
346 (EFI_FORM_LABEL) 0x1234,
347 TRUE,
348 UpdateData
349 );
350
351 gBS->FreePool (UpdateData);
352 break;
353
354 case 0x1236:
355 //
356 // If I hit the checkbox, I enter this case statement...
357 //
358 //
359 // Since I am returning an error (for test purposes) I need to pass in the string for the error
360 // I will allocate space for the return value. If an error occurs (which is the case) I can simply return
361 // an error and fill in the string parameter, otherwise, I will return information in the DataArray structure.
362 // The browser will free this packet structure
363 //
364 Status = gBS->AllocatePool (
365 EfiBootServicesData,
366 sizeof (EFI_HII_CALLBACK_PACKET) + sizeof (SAMPLE_STRING) + 2,
367 (VOID **) Packet
368 );
369
370 ZeroMem (*Packet, sizeof (EFI_HII_CALLBACK_PACKET) + sizeof (SAMPLE_STRING) + 2);
371
372 //
373 // Assign the buffer address to DataPacket
374 //
375 DataPacket = *Packet;
376
377 StrCpy (DataPacket->String, (CHAR16 *) SAMPLE_STRING);
378 return EFI_DEVICE_ERROR;
379
380 case 0x1237:
381
382 Status = gBS->AllocatePool (
383 EfiBootServicesData,
384 sizeof (EFI_HII_CALLBACK_PACKET) + 2,
385 (VOID **) Packet
386 );
387
388 ZeroMem (*Packet, sizeof (EFI_HII_CALLBACK_PACKET) + 2);
389
390 //
391 // Assign the buffer address to DataPacket
392 //
393 DataPacket = *Packet;
394
395 DataPacket->DataArray.EntryCount = 1;
396 DataPacket->DataArray.NvRamMap = NULL;
397 ((EFI_IFR_DATA_ENTRY *) (&DataPacket->DataArray + 1))->Flags = EXIT_REQUIRED;
398 break;
399
400 case 0x1555:
401 Value = 0x0001;
402 UnicodeSPrint (VariableName, 0x80, (CHAR16 *) L"%d", VAR_EQ_TEST_NAME);
403
404 Status = gRT->SetVariable (
405 VariableName,
406 &mFormSetGuid,
407 EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS,
408 2,
409 (VOID *) &Value
410 );
411 break;
412
413 case 0x1556:
414 Value = 0x1000;
415 UnicodeSPrint (VariableName, 0x80, (CHAR16 *) L"%d", VAR_EQ_TEST_NAME);
416
417 Status = gRT->SetVariable (
418 VariableName,
419 &mFormSetGuid,
420 EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS,
421 2,
422 (VOID *) &Value
423 );
424 break;
425
426 case 0x1557:
427 Value = 0x0000;
428 UnicodeSPrint (VariableName, 0x80, (CHAR16 *) L"%d", VAR_EQ_TEST_NAME);
429
430 Status = gRT->SetVariable (
431 VariableName,
432 &mFormSetGuid,
433 EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS,
434 2,
435 (VOID *) &Value
436 );
437 break;
438
439 default:
440 break;
441 }
442
443 return EFI_SUCCESS;
444 }
445
446 EFI_STATUS
447 EFIAPI
448 DriverSampleInit (
449 IN EFI_HANDLE ImageHandle,
450 IN EFI_SYSTEM_TABLE *SystemTable
451 )
452 {
453 EFI_STATUS Status;
454 EFI_HII_PROTOCOL *Hii;
455 //
456 // EFI_FORM_BROWSER_PROTOCOL *FormConfig;
457 //
458 EFI_HII_PACKAGES *PackageList;
459 EFI_HII_HANDLE HiiHandle;
460 STRING_REF TokenToUpdate;
461 STRING_REF TokenToUpdate2;
462 STRING_REF TokenToUpdate3;
463 CHAR16 *NewString;
464 EFI_HII_UPDATE_DATA *UpdateData;
465 EFI_CALLBACK_INFO *CallbackInfo;
466 EFI_HANDLE Handle;
467 EFI_SCREEN_DESCRIPTOR Screen;
468
469 ZeroMem (&Screen, sizeof (EFI_SCREEN_DESCRIPTOR));
470
471 gST->ConOut->QueryMode (gST->ConOut, gST->ConOut->Mode->Mode, &Screen.RightColumn, &Screen.BottomRow);
472
473 //
474 // Remove 3 characters from top and bottom
475 //
476 Screen.TopRow = 3;
477 Screen.BottomRow = Screen.BottomRow - 3;
478
479 //
480 // There should only be one HII protocol
481 //
482 Status = gBS->LocateProtocol (
483 &gEfiHiiProtocolGuid,
484 NULL,
485 (VOID **) &Hii
486 );
487 if (EFI_ERROR (Status)) {
488 return Status;;
489 }
490
491 /*
492 //
493 // There should only be one Form Configuration protocol
494 //
495 Status = gBS->LocateProtocol (
496 &gEfiFormBrowserProtocolGuid,
497 NULL,
498 &FormConfig
499 );
500 if (EFI_ERROR (Status)) {
501 return Status;;
502 }
503 */
504 Status = gBS->AllocatePool (
505 EfiBootServicesData,
506 sizeof (EFI_CALLBACK_INFO),
507 (VOID **) &CallbackInfo
508 );
509 if (EFI_ERROR (Status)) {
510 return Status;
511 }
512
513 CallbackInfo->Signature = EFI_CALLBACK_INFO_SIGNATURE;
514 CallbackInfo->Hii = Hii;
515
516 //
517 // This example does not implement worker functions for the NV accessor functions. Only a callback evaluator
518 //
519 CallbackInfo->DriverCallback.NvRead = NULL;
520 CallbackInfo->DriverCallback.NvWrite = NULL;
521 CallbackInfo->DriverCallback.Callback = DriverCallback;
522
523 //
524 // Install protocol interface
525 //
526 Handle = NULL;
527 Status = gBS->InstallProtocolInterface (
528 &Handle,
529 &gEfiFormCallbackProtocolGuid,
530 EFI_NATIVE_INTERFACE,
531 &CallbackInfo->DriverCallback
532 );
533
534 ASSERT_EFI_ERROR (Status);
535
536 CallbackInfo->CallbackHandle = Handle;
537
538 PackageList = PreparePackages (1, &mStringPackGuid, DriverSampleStrings);
539 Status = Hii->NewPack (Hii, PackageList, &HiiHandle);
540 gBS->FreePool (PackageList);
541
542 PackageList = PreparePackages (1, &mStringPackGuid, InventoryBin);
543 Status = Hii->NewPack (Hii, PackageList, &HiiHandle);
544 gBS->FreePool (PackageList);
545
546 PackageList = PreparePackages (1, &mStringPackGuid, VfrBin);
547 Status = Hii->NewPack (Hii, PackageList, &HiiHandle);
548 gBS->FreePool (PackageList);
549
550 CallbackInfo->RegisteredHandle = HiiHandle;
551
552 //
553 // Very simple example of how one would update a string that is already
554 // in the HII database
555 //
556 TokenToUpdate = (STRING_REF) STR_CPU_STRING2;
557 NewString = (CHAR16 *) L"700 Mhz";
558
559 Hii->NewString (Hii, NULL, HiiHandle, &TokenToUpdate, NewString);
560
561 //
562 // Add a string - if 0 will be updated with new Token number
563 //
564 TokenToUpdate = (STRING_REF) 0;
565
566 //
567 // Add a string - if 0 will be updated with new Token number
568 //
569 TokenToUpdate2 = (STRING_REF) 0;
570
571 //
572 // Add a string - if 0 will be updated with new Token number
573 //
574 TokenToUpdate3 = (STRING_REF) 0;
575
576 Hii->NewString (Hii, NULL, HiiHandle, &TokenToUpdate, (CHAR16 *) L"Desired Speed");
577 Hii->NewString (Hii, NULL, HiiHandle, &TokenToUpdate2, (CHAR16 *) L"5 Thz");
578 Hii->NewString (Hii, NULL, HiiHandle, &TokenToUpdate3, (CHAR16 *) L"This is next year's desired speed - right?");
579
580 //
581 // Allocate space for creation of Buffer
582 //
583 Status = gBS->AllocatePool (
584 EfiBootServicesData,
585 0x1000,
586 (VOID **) &UpdateData
587 );
588
589 ZeroMem (UpdateData, 0x1000);
590
591 //
592 // Flag update pending in FormSet
593 //
594 UpdateData->FormSetUpdate = TRUE;
595 //
596 // Register CallbackHandle data for FormSet
597 //
598 UpdateData->FormCallbackHandle = (EFI_PHYSICAL_ADDRESS) (UINTN) CallbackInfo->CallbackHandle;
599 UpdateData->FormUpdate = FALSE;
600 UpdateData->FormTitle = 0;
601 UpdateData->DataCount = 1;
602
603 CreateTextOpCode (TokenToUpdate, TokenToUpdate2, TokenToUpdate3, 0, 0, &UpdateData->Data);
604
605 Hii->UpdateForm (Hii, HiiHandle, (EFI_FORM_LABEL) 100, TRUE, UpdateData);
606
607 gBS->FreePool (UpdateData);
608
609 //
610 // Example of how to display only the item we sent to HII
611 //
612 if (DISPLAY_ONLY_MY_ITEM == 0x0001) {
613 //
614 // Have the browser pull out our copy of the data, and only display our data
615 //
616 // Status = FormConfig->SendForm (FormConfig, TRUE, HiiHandle, NULL, NULL, NULL, &Screen, NULL);
617 //
618 } else {
619 //
620 // Have the browser pull out all the data in the HII Database and display it.
621 //
622 // Status = FormConfig->SendForm (FormConfig, TRUE, 0, NULL, NULL, NULL, NULL, NULL);
623 //
624 }
625
626 if (EFI_ERROR (Status)) {
627 return Status;
628 }
629
630 return EFI_SUCCESS;
631 }