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