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