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