]> git.proxmox.com Git - mirror_edk2.git/blame - EdkCompatibilityPkg/Compatibility/FrameworkHiiOnUefiHiiThunk/ConfigAccess.c
Fix a bug in HII thunk that ThunkCallback does not support callback for a text tag...
[mirror_edk2.git] / EdkCompatibilityPkg / Compatibility / FrameworkHiiOnUefiHiiThunk / ConfigAccess.c
CommitLineData
ebbd2793 1/**@file\r
a9d85320 2 This file implements functions related to Config Access Protocols installed by\r
3 by HII Thunk Modules. These Config access Protocols are used to thunk UEFI Config \r
4 Access Callback to Framework HII Callback and EFI Variable Set/Get operations.\r
ebbd2793 5 \r
d2f91345 6Copyright (c) 2008 - 2010, Intel Corporation\r
ebbd2793 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
14\r
15**/\r
16\r
17#include "HiiDatabase.h"\r
a9d85320 18#include "UefiIfrParser.h"\r
ebbd2793 19\r
a9d85320 20BOOLEAN mHiiPackageListUpdated = FALSE;\r
0368663f 21\r
f6f910dd 22HII_VENDOR_DEVICE_PATH mUefiHiiVendorDevicePath = {\r
23 {\r
24 {\r
f6f910dd 25 {\r
6d931089
LG
26 HARDWARE_DEVICE_PATH,\r
27 HW_VENDOR_DP,\r
28 {\r
29 (UINT8) (sizeof (HII_VENDOR_DEVICE_PATH_NODE)),\r
30 (UINT8) ((sizeof (HII_VENDOR_DEVICE_PATH_NODE)) >> 8)\r
31 }\r
32 },\r
33 EFI_CALLER_ID_GUID\r
f6f910dd 34 },\r
6d931089
LG
35 0,\r
36 0\r
f6f910dd 37 },\r
38 {\r
39 END_DEVICE_PATH_TYPE,\r
40 END_ENTIRE_DEVICE_PATH_SUBTYPE,\r
41 { \r
6d931089
LG
42 (UINT8) (sizeof (EFI_DEVICE_PATH_PROTOCOL)),\r
43 (UINT8) ((sizeof (EFI_DEVICE_PATH_PROTOCOL)) >> 8)\r
f6f910dd 44 }\r
45 }\r
46};\r
47\r
0368663f 48CONFIG_ACCESS_PRIVATE gConfigAccessPrivateTempate = {\r
49 CONFIG_ACCESS_PRIVATE_SIGNATURE,\r
ebbd2793 50 {\r
51 ThunkExtractConfig,\r
52 ThunkRouteConfig,\r
53 ThunkCallback\r
54 }, //ConfigAccessProtocol\r
0368663f 55 NULL, //FormCallbackProtocol\r
0368663f 56 NULL \r
ebbd2793 57};\r
58\r
1a6cdbd9 59/**\r
a9d85320 60 Get the first EFI_IFR_VARSTORE from the FormSet. \r
61 \r
62 @param FormSet The Form Set.\r
63 \r
64 @retval FORMSET_STORAGE * Return the first EFI_IFR_VARSTORE.\r
65 @retval NULL If the Form Set does not have EFI_IFR_VARSTORE.\r
66**/\r
67FORMSET_STORAGE *\r
68GetFirstStorageOfFormSet (\r
69 IN CONST FORM_BROWSER_FORMSET * FormSet\r
70 ) \r
71{\r
72 LIST_ENTRY *StorageList;\r
73 FORMSET_STORAGE *Storage;\r
74\r
75 StorageList = GetFirstNode (&FormSet->StorageListHead);\r
76\r
77 if (!IsNull (&FormSet->StorageListHead, StorageList)) {\r
78 Storage = FORMSET_STORAGE_FROM_LINK (StorageList);\r
79 return Storage;\r
80 }\r
81 \r
82 return NULL;\r
83}\r
84\r
85/**\r
b6c72071 86 Get the FORM_BROWSER_STATEMENT that matches the Question's value.\r
1a6cdbd9 87 \r
a9d85320 88 @param FormSet The Form Set.\r
b6c72071 89 @param QuestionId QuestionId\r
1a6cdbd9 90 \r
b6c72071
LG
91 @retval FORM_BROWSER_STATEMENT* FORM_BROWSER_STATEMENT that match Question's value.\r
92 @retval NULL If the Form Set does not have EFI_IFR_VARSTORE.\r
1a6cdbd9 93**/\r
b6c72071 94FORM_BROWSER_STATEMENT *\r
a9d85320 95GetStorageFromQuestionId (\r
96 IN CONST FORM_BROWSER_FORMSET * FormSet,\r
97 IN EFI_QUESTION_ID QuestionId\r
ebbd2793 98 )\r
99{\r
a9d85320 100 LIST_ENTRY *FormList;\r
101 LIST_ENTRY *StatementList;\r
102 FORM_BROWSER_FORM *Form;\r
103 FORM_BROWSER_STATEMENT *Statement;\r
104\r
105 FormList = GetFirstNode (&FormSet->FormListHead);\r
106\r
107 while (!IsNull (&FormSet->FormListHead, FormList)) {\r
108 Form = FORM_BROWSER_FORM_FROM_LINK (FormList);\r
109\r
110 StatementList = GetFirstNode (&Form->StatementListHead);\r
111\r
112 while (!IsNull (&Form->StatementListHead, StatementList)) {\r
113 Statement = FORM_BROWSER_STATEMENT_FROM_LINK (StatementList);\r
114 if ((QuestionId == Statement->QuestionId) && (Statement->Storage != NULL)) {\r
115 //\r
116 // UEFI Question ID is unique in a FormSet.\r
117 //\r
118 ASSERT (Statement->Storage->Type == EFI_HII_VARSTORE_BUFFER);\r
b6c72071 119 return Statement;\r
a9d85320 120 }\r
121 StatementList = GetNextNode (&Form->StatementListHead, StatementList);\r
122 }\r
ebbd2793 123\r
a9d85320 124 FormList = GetNextNode (&FormSet->FormListHead, FormList);\r
125 }\r
126 \r
127 return NULL;\r
128}\r
ebbd2793 129\r
a9d85320 130/**\r
131 Get the EFI_IFR_VARSTORE based the ID.\r
132 \r
133 @param FormSet The Form Set.\r
134 \r
135 @retval FORMSET_STORAGE * The EFI_IFR_VARSTORE with the ID.\r
136 @retval NULL If the Form Set does not have EFI_IFR_VARSTORE with such ID.\r
137**/\r
138FORMSET_STORAGE *\r
139GetStorageFromVarStoreId (\r
140 IN CONST FORM_BROWSER_FORMSET * FormSet,\r
141 IN EFI_VARSTORE_ID VarStoreId\r
142 )\r
143{\r
144 LIST_ENTRY *StorageList;\r
145 FORMSET_STORAGE *Storage;\r
ebbd2793 146\r
a9d85320 147 StorageList = GetFirstNode (&FormSet->StorageListHead);\r
ebbd2793 148\r
a9d85320 149 while (!IsNull (&FormSet->StorageListHead, StorageList)) {\r
150 Storage = FORMSET_STORAGE_FROM_LINK (StorageList);\r
ebbd2793 151\r
a9d85320 152 if (VarStoreId == Storage->VarStoreId) {\r
153 return Storage;\r
ebbd2793 154 }\r
ebbd2793 155\r
a9d85320 156 StorageList = GetNextNode (&FormSet->StorageListHead, StorageList);\r
157 }\r
158 \r
159 return NULL;\r
ebbd2793 160}\r
161\r
1a6cdbd9 162/**\r
a9d85320 163 Get the EFI_IFR_VARSTORE based the <ConfigHdr> string in a <ConfigRequest>\r
164 or a <ConfigResp> string.\r
165 \r
166 @param FormSet The Form Set.\r
167 @param ConfigString The Configuration String which is defined by UEFI HII.\r
1a6cdbd9 168 \r
a9d85320 169 @retval FORMSET_STORAGE * The EFI_IFR_VARSTORE where the Question's value is stored.\r
170 @retval NULL If the Form Set does not have EFI_IFR_VARSTORE with such ID.\r
1a6cdbd9 171**/\r
a9d85320 172FORMSET_STORAGE *\r
173GetStorageFromConfigString (\r
174 IN CONST FORM_BROWSER_FORMSET *FormSet,\r
175 IN CONST EFI_STRING ConfigString\r
ebbd2793 176 )\r
177{\r
a9d85320 178 LIST_ENTRY *StorageList;\r
179 FORMSET_STORAGE *Storage;\r
dee207ee 180 CHAR16 *Name;\r
ebbd2793 181\r
a9d85320 182 StorageList = GetFirstNode (&FormSet->StorageListHead);\r
ebbd2793 183\r
a9d85320 184 while (!IsNull (&FormSet->StorageListHead, StorageList)) {\r
185 Storage = FORMSET_STORAGE_FROM_LINK (StorageList);\r
ebbd2793 186\r
dee207ee 187 if ((Storage->VarStoreId == FormSet->DefaultVarStoreId) && (FormSet->OriginalDefaultVarStoreName != NULL)) {\r
188 Name = FormSet->OriginalDefaultVarStoreName;\r
189 } else {\r
190 Name = Storage->Name;\r
191 }\r
192 \r
a5420536 193 if (HiiIsConfigHdrMatch (ConfigString, &Storage->Guid, Name)) {\r
a9d85320 194 return Storage;\r
ebbd2793 195 }\r
a9d85320 196\r
197 StorageList = GetNextNode (&FormSet->StorageListHead, StorageList);\r
ebbd2793 198 }\r
1a6cdbd9 199\r
a9d85320 200 return NULL;\r
ebbd2793 201}\r
0368663f 202\r
1a6cdbd9 203/**\r
204 This function installs a EFI_CONFIG_ACCESS_PROTOCOL instance for a form package registered\r
205 by a module using Framework HII Protocol Interfaces.\r
206\r
a9d85320 207 UEFI HII require EFI_HII_CONFIG_ACCESS_PROTOCOL to be installed on a EFI_HANDLE, so\r
208 that Setup Utility can load the Buffer Storage using this protocol.\r
1a6cdbd9 209 \r
a9d85320 210 @param Packages The Package List.\r
211 @param ThunkContext The Thunk Context.\r
1a6cdbd9 212 \r
a9d85320 213 @retval EFI_SUCCESS The Config Access Protocol is installed successfully.\r
214 @retval EFI_OUT_RESOURCE There is not enough memory.\r
1a6cdbd9 215 \r
216**/\r
ebbd2793 217EFI_STATUS\r
0368663f 218InstallDefaultConfigAccessProtocol (\r
219 IN CONST EFI_HII_PACKAGES *Packages,\r
220 IN OUT HII_THUNK_CONTEXT *ThunkContext\r
ebbd2793 221 )\r
222{\r
ebbd2793 223 EFI_STATUS Status;\r
0368663f 224 CONFIG_ACCESS_PRIVATE *ConfigAccessInstance;\r
6d931089 225 HII_VENDOR_DEVICE_PATH *HiiVendorPath;\r
ebbd2793 226\r
a9d85320 227 ASSERT (ThunkContext->IfrPackageCount != 0);\r
228\r
ebbd2793 229 ConfigAccessInstance = AllocateCopyPool (\r
0368663f 230 sizeof (CONFIG_ACCESS_PRIVATE), \r
231 &gConfigAccessPrivateTempate\r
ebbd2793 232 );\r
1a6cdbd9 233 ASSERT (ConfigAccessInstance != NULL);\r
6d931089
LG
234\r
235 //\r
236 // Use memory address as unique ID to distinguish from different device paths\r
237 // This function may be called multi times by the framework HII driver.\r
238 //\r
239 HiiVendorPath = AllocateCopyPool (\r
240 sizeof (HII_VENDOR_DEVICE_PATH), \r
241 &mUefiHiiVendorDevicePath\r
242 );\r
243 ASSERT (HiiVendorPath != NULL);\r
244\r
245 HiiVendorPath->Node.UniqueId = (UINT64) ((UINTN) HiiVendorPath);\r
246\r
ebbd2793 247 Status = gBS->InstallMultipleProtocolInterfaces (\r
0368663f 248 &ThunkContext->UefiHiiDriverHandle,\r
f6f910dd 249 &gEfiDevicePathProtocolGuid, \r
6d931089 250 HiiVendorPath,\r
ebbd2793 251 &gEfiHiiConfigAccessProtocolGuid,\r
252 &ConfigAccessInstance->ConfigAccessProtocol,\r
253 NULL\r
254 );\r
255 ASSERT_EFI_ERROR (Status);\r
0368663f 256 \r
0368663f 257 ConfigAccessInstance->ThunkContext = ThunkContext;\r
ebbd2793 258 \r
259 return EFI_SUCCESS;\r
260}\r
261\r
a9d85320 262/**\r
263 This function un-installs the EFI_CONFIG_ACCESS_PROTOCOL instance for a form package registered\r
264 by a module using Framework HII Protocol Interfaces.\r
0368663f 265\r
a9d85320 266 ASSERT if no Config Access is found for such pakcage list or failed to uninstall the protocol.\r
0368663f 267\r
a9d85320 268 @param ThunkContext The Thunk Context.\r
269 \r
270**/\r
0368663f 271VOID\r
272UninstallDefaultConfigAccessProtocol (\r
273 IN HII_THUNK_CONTEXT *ThunkContext\r
ebbd2793 274 )\r
275{\r
0368663f 276 EFI_STATUS Status;\r
277 EFI_HII_CONFIG_ACCESS_PROTOCOL *ConfigAccess;\r
647a768d 278 HII_VENDOR_DEVICE_PATH *HiiVendorPath;\r
279\r
0368663f 280 Status = gBS->HandleProtocol (\r
281 ThunkContext->UefiHiiDriverHandle,\r
282 &gEfiHiiConfigAccessProtocolGuid,\r
283 (VOID **) &ConfigAccess\r
284 );\r
0368663f 285 ASSERT_EFI_ERROR (Status);\r
286\r
647a768d 287 Status = gBS->HandleProtocol (\r
288 ThunkContext->UefiHiiDriverHandle,\r
289 &gEfiDevicePathProtocolGuid,\r
290 (VOID **) &HiiVendorPath\r
291 );\r
292 ASSERT_EFI_ERROR (Status);\r
293\r
f6f910dd 294 Status = gBS->UninstallMultipleProtocolInterfaces (\r
0368663f 295 ThunkContext->UefiHiiDriverHandle,\r
f6f910dd 296 &gEfiDevicePathProtocolGuid,\r
647a768d 297 HiiVendorPath,\r
0368663f 298 &gEfiHiiConfigAccessProtocolGuid,\r
f6f910dd 299 ConfigAccess,\r
300 NULL\r
0368663f 301 );\r
302 ASSERT_EFI_ERROR (Status);\r
303\r
ebbd2793 304}\r
0368663f 305 \r
ebbd2793 306\r
1a6cdbd9 307/**\r
308 Wrap the EFI_HII_CONFIG_ACCESS_PROTOCOL.ExtractConfig to a call to EFI_FORM_CALLBACK_PROTOCOL.NvRead.\r
309 \r
0368663f 310 @param BufferStorage The key with all attributes needed to call EFI_FORM_CALLBACK_PROTOCOL.NvRead.\r
311 @param FwFormCallBack The EFI_FORM_CALLBACK_PROTOCOL registered by Framework HII module.\r
312 @param Data The data read.\r
313 @param DataSize The size of data.\r
1a6cdbd9 314 \r
0368663f 315 @retval EFI_STATUS The status returned by the EFI_FORM_CALLBACK_PROTOCOL.NvWrite.\r
1a6cdbd9 316 @retval EFI_INVALID_PARAMETER If the EFI_FORM_CALLBACK_PROTOCOL.NvRead return the size information of the data\r
0368663f 317 does not match what has been recorded early in he BUFFER_STORAGE_ENTRY.\r
1a6cdbd9 318 **/\r
ebbd2793 319EFI_STATUS\r
0368663f 320CallFormCallBack (\r
a9d85320 321 IN FORMSET_STORAGE *BufferStorage,\r
0368663f 322 IN EFI_FORM_CALLBACK_PROTOCOL *FwFormCallBack,\r
ebbd2793 323 OUT VOID **Data,\r
324 OUT UINTN *DataSize\r
325 )\r
326{\r
327 EFI_STATUS Status;\r
328\r
329 *DataSize = 0;\r
330 *Data = NULL;\r
331 \r
0368663f 332 Status = FwFormCallBack->NvRead (\r
333 FwFormCallBack, \r
334 BufferStorage->Name,\r
335 &BufferStorage->Guid,\r
ebbd2793 336 NULL,\r
337 DataSize,\r
338 *Data\r
339 );\r
340 if (Status == EFI_BUFFER_TOO_SMALL) {\r
0368663f 341 if (BufferStorage->Size != *DataSize) {\r
ebbd2793 342 ASSERT (FALSE);\r
343 return EFI_INVALID_PARAMETER;\r
344 }\r
345\r
346 *Data = AllocateZeroPool (*DataSize);\r
e0e51f62 347 if (*Data == NULL) {\r
ebbd2793 348 return EFI_OUT_OF_RESOURCES;\r
349 }\r
350\r
e0e51f62 351 Status = FwFormCallBack->NvRead (\r
0368663f 352 FwFormCallBack, \r
353 BufferStorage->Name,\r
354 &BufferStorage->Guid,\r
ebbd2793 355 NULL,\r
356 DataSize,\r
357 *Data\r
358 );\r
359 }\r
360\r
361 return Status;\r
362}\r
363\r
1a6cdbd9 364\r
365/**\r
366 Wrap the EFI_HII_CONFIG_ACCESS_PROTOCOL.ExtractConfig to a call to UEFI Variable Get Service.\r
367 \r
0368663f 368 @param BufferStorage The key with all attributes needed to call a UEFI Variable Get Service.\r
369 @param Data The data read.\r
370 @param DataSize The size of data.\r
1a6cdbd9 371\r
372 If the UEFI Variable Get Service return the size information of the data\r
0368663f 373 does not match what has been recorded early in he BUFFER_STORAGE_ENTRY.\r
1a6cdbd9 374 then ASSERT.\r
375 \r
0368663f 376 @retval EFI_STATUS The status returned by the UEFI Variable Get Service.\r
1a6cdbd9 377 @retval EFI_INVALID_PARAMETER If the UEFI Variable Get Service return the size information of the data\r
0368663f 378 does not match what has been recorded early in he BUFFER_STORAGE_ENTRY.\r
1a6cdbd9 379 **/\r
380\r
ebbd2793 381EFI_STATUS\r
0368663f 382GetUefiVariable (\r
a9d85320 383 IN FORMSET_STORAGE *BufferStorage,\r
ebbd2793 384 OUT VOID **Data,\r
385 OUT UINTN *DataSize\r
386 )\r
387{\r
388 EFI_STATUS Status;\r
389\r
390 *DataSize = 0;\r
391 *Data = NULL;\r
392 Status = gRT->GetVariable (\r
0368663f 393 BufferStorage->Name,\r
394 &BufferStorage->Guid,\r
ebbd2793 395 NULL,\r
396 DataSize,\r
397 *Data\r
398 );\r
399 if (Status == EFI_BUFFER_TOO_SMALL) {\r
400\r
0368663f 401 if (BufferStorage->Size != *DataSize) {\r
ebbd2793 402 ASSERT (FALSE);\r
403 return EFI_INVALID_PARAMETER;\r
404 }\r
405\r
406 *Data = AllocateZeroPool (*DataSize);\r
e0e51f62 407 if (*Data == NULL) {\r
ebbd2793 408 return EFI_OUT_OF_RESOURCES;\r
409 }\r
410\r
411 Status = gRT->GetVariable (\r
0368663f 412 BufferStorage->Name,\r
413 &BufferStorage->Guid,\r
ebbd2793 414 NULL,\r
415 DataSize,\r
416 *Data\r
417 );\r
418 }\r
419\r
420 return Status;\r
421}\r
422\r
1a6cdbd9 423/**\r
424\r
425 This function implement the EFI_HII_CONFIG_ACCESS_PROTOCOL.ExtractConfig\r
426 so that data can be read from the data storage such as UEFI Variable or module's\r
427 customized storage exposed by EFI_FRAMEWORK_CALLBACK.\r
428\r
0368663f 429 @param This Points to the EFI_HII_CONFIG_ACCESS_PROTOCOL\r
1a6cdbd9 430 @param Request A null-terminated Unicode string in <ConfigRequest> format. Note that this\r
0368663f 431 includes the routing information as well as the configurable name / value pairs. It is\r
432 invalid for this string to be in <MultiConfigRequest> format.\r
1a6cdbd9 433\r
0368663f 434 @param Progress On return, points to a character in the Request string. Points to the string's null\r
435 terminator if request was successful. Points to the most recent '&' before the first\r
436 failing name / value pair (or the beginning of the string if the failure is in the first\r
437 name / value pair) if the request was not successful\r
1a6cdbd9 438 @param Results A null-terminated Unicode string in <ConfigAltResp> format which has all\r
0368663f 439 values filled in for the names in the Request string. String to be allocated by the called\r
440 function.\r
1a6cdbd9 441 \r
442 @retval EFI_INVALID_PARAMETER If there is no Buffer Storage for this Config Access instance.\r
0368663f 443 @retval EFI_SUCCESS The setting is retrived successfully.\r
444 @retval !EFI_SUCCESS The error returned by UEFI Get Variable or Framework Form Callback Nvread.\r
1a6cdbd9 445 **/\r
ebbd2793 446EFI_STATUS\r
447EFIAPI\r
448ThunkExtractConfig (\r
449 IN CONST EFI_HII_CONFIG_ACCESS_PROTOCOL *This,\r
450 IN CONST EFI_STRING Request,\r
451 OUT EFI_STRING *Progress,\r
452 OUT EFI_STRING *Results\r
453 )\r
454{\r
455 EFI_STATUS Status;\r
0368663f 456 CONFIG_ACCESS_PRIVATE *ConfigAccess;\r
a9d85320 457 FORMSET_STORAGE *BufferStorage;\r
ebbd2793 458 VOID *Data;\r
459 UINTN DataSize;\r
460\r
6a179dca 461 if (Request == NULL) {\r
462 return EFI_NOT_FOUND;\r
463 }\r
464\r
ebbd2793 465 Data = NULL;\r
0368663f 466 ConfigAccess = CONFIG_ACCESS_PRIVATE_FROM_PROTOCOL (This);\r
ebbd2793 467\r
a9d85320 468 BufferStorage = GetStorageFromConfigString (ConfigAccess->ThunkContext->FormSet, Request);\r
ebbd2793 469\r
6a179dca 470 if (BufferStorage == NULL) {\r
471 *Progress = (EFI_STRING) Request;\r
472 return EFI_NOT_FOUND;\r
473 }\r
474\r
133a9dfb 475 if (ConfigAccess->ThunkContext->NvMapOverride == NULL) {\r
a9d85320 476 //\r
477 // NvMapOverride is not used. Get the Storage data from EFI Variable or Framework Form Callback.\r
478 //\r
133a9dfb 479 if (ConfigAccess->FormCallbackProtocol == NULL ||\r
480 ConfigAccess->FormCallbackProtocol->NvRead == NULL) {\r
481 Status = GetUefiVariable (\r
482 BufferStorage,\r
483 &Data,\r
484 &DataSize\r
485 );\r
486 } else {\r
487 Status = CallFormCallBack (\r
488 BufferStorage,\r
489 ConfigAccess->FormCallbackProtocol,\r
490 &Data,\r
491 &DataSize\r
492 );\r
493 }\r
ebbd2793 494 } else {\r
a9d85320 495 //\r
496 // Use the NvMapOverride.\r
497 //\r
133a9dfb 498 DataSize = BufferStorage->Size;\r
499 Data = AllocateCopyPool (DataSize, ConfigAccess->ThunkContext->NvMapOverride);\r
500 \r
501 if (Data != NULL) {\r
502 Status = EFI_SUCCESS;\r
503 } else {\r
504 Status = EFI_OUT_OF_RESOURCES;\r
505 }\r
ebbd2793 506 }\r
507 \r
508 if (!EFI_ERROR (Status)) {\r
59336178 509 Status = mHiiConfigRoutingProtocol->BlockToConfig (\r
510 mHiiConfigRoutingProtocol,\r
ebbd2793 511 Request,\r
512 Data,\r
513 DataSize,\r
514 Results,\r
515 Progress\r
516 );\r
517 }\r
518\r
7001eaf8 519 if (Data != NULL) {\r
520 FreePool (Data);\r
521 }\r
ebbd2793 522 return Status;\r
523}\r
524\r
1a6cdbd9 525/**\r
1a6cdbd9 526 This function implement the EFI_HII_CONFIG_ACCESS_PROTOCOL.RouteConfig\r
527 so that data can be written to the data storage such as UEFI Variable or module's\r
528 customized storage exposed by EFI_FRAMEWORK_CALLBACK.\r
529 \r
0368663f 530 @param This Points to the EFI_HII_CONFIG_ACCESS_PROTOCOL\r
531 @param Configuration A null-terminated Unicode string in <ConfigResp> format.\r
fd0d281b 532 @param Progress A pointer to a string filled in with the offset of the most recent '&' before the first\r
0368663f 533 failing name / value pair (or the beginning of the string if the failure is in the first\r
534 name / value pair) or the terminating NULL if all was successful.\r
1a6cdbd9 535 \r
536 @retval EFI_INVALID_PARAMETER If there is no Buffer Storage for this Config Access instance.\r
0368663f 537 @retval EFI_SUCCESS The setting is saved successfully.\r
538 @retval !EFI_SUCCESS The error returned by UEFI Set Variable or Framework Form Callback Nvwrite.\r
1a6cdbd9 539**/ \r
ebbd2793 540EFI_STATUS\r
541EFIAPI\r
542ThunkRouteConfig (\r
543 IN CONST EFI_HII_CONFIG_ACCESS_PROTOCOL *This,\r
544 IN CONST EFI_STRING Configuration,\r
545 OUT EFI_STRING *Progress\r
546 )\r
547{\r
548 EFI_STATUS Status;\r
0368663f 549 CONFIG_ACCESS_PRIVATE *ConfigAccess;\r
a9d85320 550 FORMSET_STORAGE *BufferStorage;\r
98b16b9d 551 VOID *Data;\r
ebbd2793 552 UINTN DataSize;\r
0368663f 553 UINTN DataSize2;\r
ebbd2793 554 UINTN LastModifiedByteIndex;\r
0368663f 555 BOOLEAN ResetRequired;\r
556 BOOLEAN DataAllocated;\r
ebbd2793 557\r
6a179dca 558 if (Configuration == NULL) {\r
559 return EFI_INVALID_PARAMETER;\r
560 }\r
561\r
ebbd2793 562 Data = NULL;\r
0368663f 563 ConfigAccess = CONFIG_ACCESS_PRIVATE_FROM_PROTOCOL (This);\r
ebbd2793 564\r
a9d85320 565 BufferStorage = GetStorageFromConfigString (ConfigAccess->ThunkContext->FormSet, Configuration);\r
ebbd2793 566\r
6a179dca 567 if (BufferStorage == NULL) {\r
568 *Progress = Configuration;\r
569 return EFI_NOT_FOUND;\r
570 }\r
571\r
0368663f 572 DataSize2 = BufferStorage->Size;\r
573 if (ConfigAccess->ThunkContext->NvMapOverride == NULL) {\r
133a9dfb 574 DataAllocated = TRUE;\r
0368663f 575 if (ConfigAccess->FormCallbackProtocol == NULL ||\r
576 ConfigAccess->FormCallbackProtocol->NvRead == NULL) {\r
577 Status = GetUefiVariable (\r
578 BufferStorage,\r
579 &Data,\r
580 &DataSize\r
581 );\r
0368663f 582 } else {\r
583 Status = CallFormCallBack (\r
584 BufferStorage,\r
585 ConfigAccess->FormCallbackProtocol,\r
586 &Data,\r
587 &DataSize\r
588 );\r
0368663f 589 }\r
590 } else {\r
133a9dfb 591 //\r
592 // ConfigToBlock will convert the Config String and update the NvMapOverride accordingly.\r
593 //\r
0368663f 594 Status = EFI_SUCCESS;\r
595 Data = ConfigAccess->ThunkContext->NvMapOverride;\r
596 DataSize = DataSize2;\r
597 DataAllocated = FALSE;\r
598 } \r
133a9dfb 599 if (EFI_ERROR (Status) || (DataSize2 != DataSize)) {\r
600 if (Data == NULL) {\r
601 Data = AllocateZeroPool (DataSize2);\r
602 }\r
ebbd2793 603 }\r
0368663f 604\r
59336178 605 Status = mHiiConfigRoutingProtocol->ConfigToBlock (\r
606 mHiiConfigRoutingProtocol,\r
ebbd2793 607 Configuration,\r
608 Data,\r
609 &LastModifiedByteIndex,\r
610 Progress\r
611 );\r
ebbd2793 612 if (EFI_ERROR (Status)) {\r
613 goto Done;\r
614 }\r
e0e51f62 615 \r
133a9dfb 616 if (ConfigAccess->ThunkContext->NvMapOverride == NULL) {\r
617 if (ConfigAccess->FormCallbackProtocol == NULL ||\r
618 ConfigAccess->FormCallbackProtocol->NvWrite == NULL) {\r
619 Status = gRT->SetVariable (\r
620 BufferStorage->Name,\r
621 &BufferStorage->Guid,\r
622 EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS,\r
623 DataSize2,\r
624 Data\r
625 );\r
626 } else {\r
627 Status = ConfigAccess->FormCallbackProtocol->NvWrite (\r
628 ConfigAccess->FormCallbackProtocol, \r
629 BufferStorage->Name,\r
630 &BufferStorage->Guid,\r
631 EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS,\r
632 DataSize2,\r
633 Data,\r
634 &ResetRequired\r
635 );\r
636 \r
637 }\r
ebbd2793 638 }\r
639\r
0368663f 640Done: \r
641 if (DataAllocated && (Data != NULL)) {\r
642 FreePool (Data);\r
643 }\r
644 \r
ebbd2793 645 return Status;\r
646}\r
647\r
a9d85320 648/**\r
aa2ebe0f
LG
649 Build the EFI_IFR_DATA_ARRAY which will be used to pass to \r
650 EFI_FORM_CALLBACK_PROTOCOL.Callback. Check definition of EFI_IFR_DATA_ARRAY\r
a9d85320 651 for details.\r
652\r
653 ASSERT if the Question Type is not EFI_IFR_TYPE_NUM_SIZE_* or EFI_IFR_TYPE_STRING.\r
654 \r
655 @param This Points to the EFI_HII_CONFIG_ACCESS_PROTOCOL\r
656 @param QuestionId The Question ID.\r
657 @param Type The Question Type.\r
658 @param Value The Question Value.\r
659 @param NvMapAllocated On output indicates if a buffer is allocated for NvMap.\r
660 \r
aa2ebe0f 661 @return A pointer to EFI_IFR_DATA_ARRAY. The caller must free this buffer allocated.\r
a9d85320 662**/ \r
aa2ebe0f 663EFI_IFR_DATA_ARRAY *\r
0368663f 664CreateIfrDataArray (\r
665 IN CONFIG_ACCESS_PRIVATE *ConfigAccess,\r
666 IN EFI_QUESTION_ID QuestionId,\r
667 IN UINT8 Type,\r
668 IN EFI_IFR_TYPE_VALUE *Value,\r
669 OUT BOOLEAN *NvMapAllocated\r
670 )\r
671{\r
aa2ebe0f
LG
672 EFI_IFR_DATA_ARRAY *IfrDataArray;\r
673 EFI_IFR_DATA_ENTRY *IfrDataEntry;\r
0368663f 674 UINTN BrowserDataSize;\r
a5420536 675 FORMSET_STORAGE *BufferStorage;\r
286f0de7 676 UINTN Size;\r
286f0de7 677 EFI_STRING String;\r
b6c72071 678 FORM_BROWSER_STATEMENT *Statement;\r
286f0de7 679\r
a9d85320 680 *NvMapAllocated = FALSE;\r
0368663f 681\r
a9d85320 682 String = NULL;\r
286f0de7 683\r
684 switch (Type) {\r
685 case EFI_IFR_TYPE_NUM_SIZE_8:\r
686 case EFI_IFR_TYPE_NUM_SIZE_16:\r
687 case EFI_IFR_TYPE_NUM_SIZE_32:\r
688 case EFI_IFR_TYPE_NUM_SIZE_64:\r
689 case EFI_IFR_TYPE_BOOLEAN:\r
690 Size = sizeof (*Value);\r
691 break;\r
692\r
693 case EFI_IFR_TYPE_STRING:\r
887c077d 694 if (Value->string == 0) {\r
695 Size = 0;\r
696 } else {\r
697 String = HiiGetString (ConfigAccess->ThunkContext->UefiHiiHandle, Value->string, NULL);\r
698 ASSERT (String != NULL);\r
286f0de7 699\r
887c077d 700 Size = StrSize (String);\r
701 }\r
286f0de7 702 break;\r
d2f91345 703\r
704 case EFI_IFR_TYPE_ACTION:\r
705 Size = 0;\r
706 break;\r
286f0de7 707 \r
708 default:\r
709 ASSERT (FALSE);\r
710 Size = 0;\r
711 break;\r
712 }\r
713\r
aa2ebe0f 714 IfrDataArray = AllocateZeroPool (sizeof (EFI_IFR_DATA_ARRAY) + sizeof (EFI_IFR_DATA_ENTRY) + Size);\r
0368663f 715 ASSERT (IfrDataArray != NULL);\r
b6c72071
LG
716 IfrDataArray->EntryCount = 1;\r
717 IfrDataEntry = (EFI_IFR_DATA_ENTRY *) (IfrDataArray + 1);\r
0368663f 718\r
b6c72071 719 Statement = GetStorageFromQuestionId (ConfigAccess->ThunkContext->FormSet, QuestionId);\r
0368663f 720\r
b6c72071 721 if (Statement == NULL || Statement->Storage == NULL) {\r
a9d85320 722 //\r
723 // The QuestionId is not associated with a Buffer Storage.\r
724 // Try to get the first Buffer Storage then.\r
725 //\r
726 BufferStorage = GetFirstStorageOfFormSet (ConfigAccess->ThunkContext->FormSet);\r
b6c72071
LG
727 } else {\r
728 BufferStorage = Statement->Storage;\r
729 IfrDataEntry->OpCode = Statement->Operand;\r
0368663f 730 }\r
133a9dfb 731 \r
a9d85320 732 if (BufferStorage != NULL) {\r
b6c72071
LG
733 BrowserDataSize = BufferStorage->Size;\r
734 IfrDataEntry->Length = (UINT8) (sizeof (EFI_IFR_DATA_ENTRY) + Size);\r
0368663f 735\r
a9d85320 736 if (ConfigAccess->ThunkContext->NvMapOverride == NULL) {\r
737 *NvMapAllocated = TRUE;\r
738 IfrDataArray->NvRamMap = AllocateZeroPool (BrowserDataSize);\r
739 } else {\r
740 *NvMapAllocated = FALSE;\r
741 IfrDataArray->NvRamMap = ConfigAccess->ThunkContext->NvMapOverride;\r
742 }\r
743 \r
27e87dab 744 ASSERT (HiiGetBrowserData (&BufferStorage->Guid, BufferStorage->Name, BrowserDataSize, (UINT8 *) IfrDataArray->NvRamMap));\r
0368663f 745\r
a9d85320 746 switch (Type) {\r
747 case EFI_IFR_TYPE_NUM_SIZE_8:\r
748 case EFI_IFR_TYPE_NUM_SIZE_16:\r
749 case EFI_IFR_TYPE_NUM_SIZE_32:\r
750 case EFI_IFR_TYPE_NUM_SIZE_64:\r
751 case EFI_IFR_TYPE_BOOLEAN:\r
752 CopyMem (&IfrDataEntry->Data, &(Value->u8), sizeof (*Value));\r
753 break;\r
754\r
755 case EFI_IFR_TYPE_STRING:\r
887c077d 756 if (Size != 0) {\r
757 ASSERT (String != NULL);\r
758 StrCpy ((CHAR16 *) &IfrDataEntry->Data, String);\r
759 FreePool (String);\r
760 }\r
a9d85320 761 break;\r
d2f91345 762\r
763 case EFI_IFR_TYPE_ACTION:\r
764 break;\r
765\r
a9d85320 766 default:\r
767 ASSERT (FALSE);\r
768 break;\r
769 }\r
770\r
771 //\r
aa2ebe0f 772 // Need to fiil in the information for the rest of field for EFI_IFR_DATA_ENTRY.\r
a9d85320 773 // It seems that no implementation is found to use other fields. Leave them uninitialized for now.\r
774 //\r
775 //UINT8 OpCode; // Likely a string, numeric, or one-of\r
aa2ebe0f 776 //UINT8 Length; // Length of the EFI_IFR_DATA_ENTRY packet\r
a9d85320 777 //UINT16 Flags; // Flags settings to determine what behavior is desired from the browser after the callback\r
778 //VOID *Data; // The data in the form based on the op-code type - this is not a pointer to the data, the data follows immediately\r
779 // If the OpCode is a OneOf or Numeric type - Data is a UINT16 value\r
780 // If the OpCode is a String type - Data is a CHAR16[x] type\r
781 // If the OpCode is a Checkbox type - Data is a UINT8 value\r
782 // If the OpCode is a NV Access type - Data is a FRAMEWORK_EFI_IFR_NV_DATA structure\r
0368663f 783 }\r
784\r
785 return IfrDataArray;\r
786}\r
787\r
a9d85320 788/**\r
789 If a NvMapOverride is passed in to EFI_FORM_BROWSER_PROTOCOL.SendForm, the Form Browser\r
790 needs to be informed when data changed in NvMapOverride. This function will invoke\r
791 SetBrowserData () to set internal data of Form Browser.\r
792\r
793 @param ConfigAccess The Config Access Private Context.\r
794 @param QuestionId The Question Id that invokes the callback.\r
795 \r
796\r
797**/\r
133a9dfb 798VOID\r
799SyncBrowserDataForNvMapOverride (\r
a9d85320 800 IN CONST CONFIG_ACCESS_PRIVATE *ConfigAccess,\r
801 IN EFI_QUESTION_ID QuestionId\r
133a9dfb 802 )\r
803{\r
a5420536
LG
804 FORMSET_STORAGE *BufferStorage;\r
805 BOOLEAN CheckFlag;\r
806 UINTN BrowserDataSize;\r
b6c72071 807 FORM_BROWSER_STATEMENT *Statement;\r
133a9dfb 808\r
809 if (ConfigAccess->ThunkContext->NvMapOverride != NULL) {\r
a9d85320 810\r
b6c72071 811 Statement = GetStorageFromQuestionId (ConfigAccess->ThunkContext->FormSet, QuestionId);\r
a9d85320 812\r
b6c72071 813 if (Statement == NULL || Statement->Storage == NULL) {\r
a9d85320 814 //\r
815 // QuestionId is a statement without Storage.\r
816 // 1) It is a Goto. \r
817 // \r
818 //\r
819 BufferStorage = GetFirstStorageOfFormSet (ConfigAccess->ThunkContext->FormSet);\r
b6c72071
LG
820 } else {\r
821 BufferStorage = Statement->Storage;\r
a9d85320 822 }\r
823\r
824 //\r
825 // If NvMapOverride is not NULL, this Form must have at least one Buffer Type Variable Storage.\r
826 //\r
827 ASSERT (BufferStorage != NULL);\r
133a9dfb 828 \r
a9d85320 829 BrowserDataSize = BufferStorage->Size;\r
133a9dfb 830\r
a5420536
LG
831 CheckFlag = HiiSetBrowserData (&BufferStorage->Guid, BufferStorage->Name, BrowserDataSize, ConfigAccess->ThunkContext->NvMapOverride, NULL);\r
832 ASSERT (CheckFlag);\r
133a9dfb 833 }\r
834\r
835}\r
836\r
a9d85320 837/**\r
aa2ebe0f 838 Free up resource allocated for a EFI_IFR_DATA_ARRAY by CreateIfrDataArray ().\r
a9d85320 839\r
aa2ebe0f
LG
840 @param Array The EFI_IFR_DATA_ARRAY allocated.\r
841 @param NvMapAllocated If the NvRamMap is allocated for EFI_IFR_DATA_ARRAY.\r
a9d85320 842\r
843**/\r
0368663f 844VOID\r
845DestroyIfrDataArray (\r
aa2ebe0f 846 IN EFI_IFR_DATA_ARRAY *Array,\r
0368663f 847 IN BOOLEAN NvMapAllocated\r
848 )\r
849{\r
d4775f2a 850 if (Array != NULL) {\r
851 if (NvMapAllocated) {\r
852 FreePool (Array->NvRamMap);\r
853 }\r
0368663f 854\r
d4775f2a 855 FreePool (Array);\r
856 }\r
0368663f 857}\r
858\r
a9d85320 859/**\r
860 Get the ONE_OF_OPTION_MAP_ENTRY for a QuestionId that invokes the \r
861 EFI_FORM_CALLBACK_PROTOCOL.Callback. The information is needed as\r
862 the callback mechanism for EFI_IFR_ONE_OF_OPTION is changed from \r
863 EFI_IFR_ONE_OF_OPTION in Framework IFR. Check EFI_IFR_GUID_OPTIONKEY\r
864 for detailed information.\r
865\r
866 @param ThunkContext The Thunk Context.\r
867 @param QuestionId The Question Id.\r
868 @param Type The Question Type.\r
869 @param Value The One Of Option's value.\r
870\r
871 @return The ONE_OF_OPTION_MAP_ENTRY found.\r
872 @retval NULL If no entry is found.\r
873**/\r
0368663f 874ONE_OF_OPTION_MAP_ENTRY *\r
875GetOneOfOptionMapEntry (\r
876 IN HII_THUNK_CONTEXT *ThunkContext,\r
877 IN EFI_QUESTION_ID QuestionId,\r
878 IN UINT8 Type,\r
879 IN EFI_IFR_TYPE_VALUE *Value\r
880 )\r
881{\r
882 LIST_ENTRY *Link;\r
883 LIST_ENTRY *Link2;\r
884 ONE_OF_OPTION_MAP_ENTRY *OneOfOptionMapEntry;\r
885 ONE_OF_OPTION_MAP *OneOfOptionMap;\r
a9d85320 886 FORM_BROWSER_FORMSET *FormSet;\r
0368663f 887\r
a9d85320 888 FormSet = ThunkContext->FormSet;\r
0368663f 889\r
a9d85320 890 Link = GetFirstNode (&FormSet->OneOfOptionMapListHead);\r
891\r
892 while (!IsNull (&FormSet->OneOfOptionMapListHead, Link)) {\r
0368663f 893 OneOfOptionMap = ONE_OF_OPTION_MAP_FROM_LINK(Link);\r
894 if (OneOfOptionMap->QuestionId == QuestionId) {\r
895 ASSERT (OneOfOptionMap->ValueType == Type);\r
896\r
897 Link2 = GetFirstNode (&OneOfOptionMap->OneOfOptionMapEntryListHead);\r
898\r
899 while (!IsNull (&OneOfOptionMap->OneOfOptionMapEntryListHead, Link2)) {\r
900 OneOfOptionMapEntry = ONE_OF_OPTION_MAP_ENTRY_FROM_LINK (Link2);\r
901\r
902 if (CompareMem (Value, &OneOfOptionMapEntry->Value, sizeof (EFI_IFR_TYPE_VALUE)) == 0) {\r
903 return OneOfOptionMapEntry;\r
904 }\r
905\r
906 Link2 = GetNextNode (&OneOfOptionMap->OneOfOptionMapEntryListHead, Link2);\r
907 }\r
908 }\r
909\r
a9d85320 910 Link = GetNextNode (&FormSet->OneOfOptionMapListHead, Link);\r
0368663f 911 }\r
912\r
913\r
914 return NULL;\r
915}\r
916\r
917/**\r
918 Functions which are registered to receive notification of\r
919 database events have this prototype. The actual event is encoded\r
920 in NotifyType. The following table describes how PackageType,\r
921 PackageGuid, Handle, and Package are used for each of the\r
922 notification types.\r
923\r
a9d85320 924 If any Pakcage List in database is updated, mHiiPackageListUpdated\r
925 will be set. If mHiiPackageListUpdated is set, Framework ThunkCallback()\r
926 will force the UEFI Setup Browser to save the uncommitted data. This\r
927 is needed as Framework's Callback function may dynamically update\r
928 opcode in a Package List. UEFI Setup Browser will quit itself and reparse\r
929 the Package List's IFR and display it. UEFI Config Access's implementation\r
930 is required to save the modified (SetBrowserData or directly save the data\r
931 to NV storage). But Framework HII Modules is not aware of this rule. Therefore,\r
932 we will enforce the rule in ThunkCallback (). The side effect of force saving\r
933 of NV data is the NV flag in browser may not flag a update as data has already\r
934 been saved to NV storage.\r
935\r
0368663f 936 @param PackageType Package type of the notification.\r
937\r
938 @param PackageGuid If PackageType is\r
939 EFI_HII_PACKAGE_TYPE_GUID, then this is\r
940 the pointer to the GUID from the Guid\r
941 field of EFI_HII_PACKAGE_GUID_HEADER.\r
942 Otherwise, it must be NULL.\r
943\r
944 @param Package Points to the package referred to by the\r
945 notification Handle The handle of the package\r
946 list which contains the specified package.\r
947\r
948 @param Handle The HII handle.\r
949\r
950 @param NotifyType The type of change concerning the\r
951 database. See\r
952 EFI_HII_DATABASE_NOTIFY_TYPE.\r
953\r
954**/\r
955EFI_STATUS\r
956EFIAPI\r
957FormUpdateNotify (\r
958 IN UINT8 PackageType,\r
959 IN CONST EFI_GUID *PackageGuid,\r
960 IN CONST EFI_HII_PACKAGE_HEADER *Package,\r
961 IN EFI_HII_HANDLE Handle,\r
962 IN EFI_HII_DATABASE_NOTIFY_TYPE NotifyType\r
963 )\r
964{\r
965 mHiiPackageListUpdated = TRUE;\r
966\r
967 return EFI_SUCCESS;\r
968}\r
969\r
1a6cdbd9 970/**\r
971 Wrap the EFI_HII_CONFIG_ACCESS_PROTOCOL.CallBack to EFI_FORM_CALLBACK_PROTOCOL.Callback. Therefor,\r
a9d85320 972 the framework HII module willl do no porting and work with a UEFI HII SetupBrowser.\r
1a6cdbd9 973 \r
0368663f 974 @param This Points to the EFI_HII_CONFIG_ACCESS_PROTOCOL.\r
975 @param Action Specifies the type of action taken by the browser. See EFI_BROWSER_ACTION_x.\r
1a6cdbd9 976 @param QuestionId A unique value which is sent to the original exporting driver so that it can identify the\r
0368663f 977 type of data to expect. The format of the data tends to vary based on the opcode that\r
978 generated the callback.\r
979 @param Type The type of value for the question. See EFI_IFR_TYPE_x in\r
980 EFI_IFR_ONE_OF_OPTION.\r
981 @param Value A pointer to the data being sent to the original exporting driver. The type is specified\r
982 by Type. Type EFI_IFR_TYPE_VALUE is defined in\r
983 EFI_IFR_ONE_OF_OPTION.\r
1a6cdbd9 984 @param ActionRequest On return, points to the action requested by the callback function. Type\r
0368663f 985 EFI_BROWSER_ACTION_REQUEST is specified in SendForm() in the Form\r
986 Browser Protocol.\r
1a6cdbd9 987 \r
0368663f 988 @retval EFI_UNSUPPORTED If the Framework HII module does not register Callback although it specify the opcode under\r
989 focuse to be INTERRACTIVE.\r
1a6cdbd9 990 @retval EFI_SUCCESS The callback complete successfully.\r
991 @retval !EFI_SUCCESS The error code returned by EFI_FORM_CALLBACK_PROTOCOL.Callback.\r
992 \r
993 **/\r
ebbd2793 994EFI_STATUS\r
995EFIAPI\r
996ThunkCallback (\r
997 IN CONST EFI_HII_CONFIG_ACCESS_PROTOCOL *This,\r
998 IN EFI_BROWSER_ACTION Action,\r
999 IN EFI_QUESTION_ID QuestionId,\r
1000 IN UINT8 Type,\r
1001 IN EFI_IFR_TYPE_VALUE *Value,\r
1002 OUT EFI_BROWSER_ACTION_REQUEST *ActionRequest\r
1003 )\r
1004{\r
1005 EFI_STATUS Status;\r
0368663f 1006 CONFIG_ACCESS_PRIVATE *ConfigAccess;\r
1007 EFI_FORM_CALLBACK_PROTOCOL *FormCallbackProtocol;\r
ebbd2793 1008 EFI_HII_CALLBACK_PACKET *Packet;\r
aa2ebe0f
LG
1009 EFI_IFR_DATA_ARRAY *Data;\r
1010 EFI_IFR_DATA_ENTRY *DataEntry;\r
0368663f 1011 UINT16 KeyValue;\r
1012 ONE_OF_OPTION_MAP_ENTRY *OneOfOptionMapEntry;\r
1013 EFI_HANDLE NotifyHandle;\r
1014 EFI_INPUT_KEY Key; \r
1015 BOOLEAN NvMapAllocated;\r
ebbd2793 1016\r
880ea0e2
LG
1017 if ((Action == EFI_BROWSER_ACTION_FORM_OPEN) || (Action == EFI_BROWSER_ACTION_FORM_CLOSE)) {\r
1018 //\r
1019 // Ignore UEFI OPEN/CLOSE Action for FrameworkCallback\r
1020 //\r
1021 return EFI_SUCCESS;\r
1022 }\r
1023\r
ebbd2793 1024 ASSERT (This != NULL);\r
1025 ASSERT (Value != NULL);\r
1026 ASSERT (ActionRequest != NULL);\r
1027\r
1028 *ActionRequest = EFI_BROWSER_ACTION_REQUEST_NONE;\r
1029\r
0368663f 1030 ConfigAccess = CONFIG_ACCESS_PRIVATE_FROM_PROTOCOL (This);\r
ebbd2793 1031\r
0368663f 1032 FormCallbackProtocol = ConfigAccess->FormCallbackProtocol;\r
1033 if (FormCallbackProtocol == NULL) {\r
1034 ASSERT (FALSE);\r
ebbd2793 1035 return EFI_UNSUPPORTED;\r
1036 }\r
ebbd2793 1037\r
0368663f 1038 //\r
1039 // Check if the QuestionId match a OneOfOption.\r
1040 //\r
1041 OneOfOptionMapEntry = GetOneOfOptionMapEntry (ConfigAccess->ThunkContext, QuestionId, Type, Value);\r
1042\r
1043 if (OneOfOptionMapEntry == NULL) {\r
1044 //\r
1045 // This is not a One-Of-Option opcode. QuestionId is the KeyValue\r
1046 //\r
1047 KeyValue = QuestionId;\r
1048 } else {\r
a9d85320 1049 //\r
1050 // Otherwise, use the original Key specified in One Of Option in the Framework VFR syntax.\r
1051 //\r
0368663f 1052 KeyValue = OneOfOptionMapEntry->FwKey;\r
1053 }\r
1054\r
1055 //\r
aa2ebe0f 1056 // Build the EFI_IFR_DATA_ARRAY\r
0368663f 1057 //\r
1058 Data = CreateIfrDataArray (ConfigAccess, QuestionId, Type, Value, &NvMapAllocated);\r
1059\r
1060 Status = mHiiDatabase->RegisterPackageNotify (\r
1061 mHiiDatabase,\r
4dd76ade 1062 EFI_HII_PACKAGE_FORMS,\r
0368663f 1063 NULL,\r
1064 FormUpdateNotify,\r
1065 EFI_HII_DATABASE_NOTIFY_REMOVE_PACK,\r
1066 &NotifyHandle\r
1067 );\r
1068 //\r
a9d85320 1069 //Call the Framework Callback function.\r
0368663f 1070 //\r
1071 Packet = NULL;\r
1072 Status = FormCallbackProtocol->Callback (\r
1073 FormCallbackProtocol,\r
1074 KeyValue,\r
1075 Data,\r
ebbd2793 1076 &Packet\r
1077 );\r
a9d85320 1078 SyncBrowserDataForNvMapOverride (ConfigAccess, QuestionId);\r
ebbd2793 1079\r
1080 //\r
1081 // Callback require browser to perform action\r
1082 //\r
0368663f 1083 if (EFI_ERROR (Status)) {\r
1084 if (Packet != NULL) {\r
0368663f 1085 do {\r
a5420536 1086 CreatePopUp (EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE, &Key, Packet->String, NULL);\r
0368663f 1087 } while (Key.UnicodeChar != CHAR_CARRIAGE_RETURN);\r
ebbd2793 1088 }\r
0368663f 1089 //\r
1090 // Error Code in Status is discarded.\r
1091 //\r
1092 } else {\r
1093 if (Packet != NULL) {\r
1094 if (Packet->DataArray.EntryCount == 1 && Packet->DataArray.NvRamMap == NULL) {\r
aa2ebe0f 1095 DataEntry = (EFI_IFR_DATA_ENTRY *) ((UINT8 *) Packet + sizeof (EFI_IFR_DATA_ARRAY));\r
0368663f 1096 if ((DataEntry->Flags & EXIT_REQUIRED) == EXIT_REQUIRED) {\r
1097 *ActionRequest = EFI_BROWSER_ACTION_REQUEST_EXIT;\r
1098 }\r
1099\r
1100 if ((DataEntry->Flags & SAVE_REQUIRED) == SAVE_REQUIRED) {\r
1101 Status = ConfigAccess->ConfigAccessProtocol.RouteConfig (\r
1102 &ConfigAccess->ConfigAccessProtocol,\r
1103 NULL,\r
1104 NULL\r
1105 );\r
1106 }\r
1107 }\r
1108 FreePool (Packet);\r
1109 }\r
1110 }\r
1111\r
1112 //\r
1113 // Unregister notify for Form package update\r
1114 //\r
1115 Status = mHiiDatabase->UnregisterPackageNotify (\r
1116 mHiiDatabase,\r
1117 NotifyHandle\r
1118 );\r
1119 //\r
a3318eaf 1120 // UEFI SetupBrowser behaves differently with Framework SetupBrowser when call back function \r
0368663f 1121 // update any forms in HII database. UEFI SetupBrowser will re-parse the displaying form package and load\r
1122 // the values from variable storages. Framework SetupBrowser will only re-parse the displaying form packages.\r
1123 // To make sure customer's previous changes is saved and the changing question behaves as expected, we\r
1124 // issue a EFI_BROWSER_ACTION_REQUEST_SUBMIT to ask UEFI SetupBrowser to save the changes proceed to re-parse\r
1125 // the form and load all the variable storages.\r
1126 //\r
1127 if (*ActionRequest == EFI_BROWSER_ACTION_REQUEST_NONE && mHiiPackageListUpdated) {\r
a9d85320 1128 mHiiPackageListUpdated= FALSE;\r
0368663f 1129 *ActionRequest = EFI_BROWSER_ACTION_REQUEST_SUBMIT;\r
fed39e58 1130 } else {\r
a9d85320 1131 if (ConfigAccess->ThunkContext->FormSet->SubClass == EFI_FRONT_PAGE_SUBCLASS ||\r
1132 ConfigAccess->ThunkContext->FormSet->SubClass == EFI_SINGLE_USE_SUBCLASS) {\r
fed39e58 1133 *ActionRequest = EFI_BROWSER_ACTION_REQUEST_EXIT;\r
1134 }\r
ebbd2793 1135 }\r
0368663f 1136\r
d4775f2a 1137\r
a9d85320 1138 //\r
1139 // Clean up.\r
1140 //\r
0368663f 1141 DestroyIfrDataArray (Data, NvMapAllocated);\r
ebbd2793 1142 \r
1143 return Status;\r
1144}\r
1145\r