]> git.proxmox.com Git - mirror_edk2.git/blame - EdkCompatibilityPkg/Compatibility/FrameworkHiiToUefiHiiThunk/Utility.c
Bug fixes for FrameworkHiiToUefiHiiThunk;
[mirror_edk2.git] / EdkCompatibilityPkg / Compatibility / FrameworkHiiToUefiHiiThunk / Utility.c
CommitLineData
4259256b 1/**@file\r
2\r
3 This file contains the keyboard processing code to the HII database.\r
4\r
5Copyright (c) 2006 - 2008, Intel Corporation\r
6All rights reserved. This program and the accompanying materials\r
7are licensed and made available under the terms and conditions of the BSD License\r
8which accompanies this distribution. The full text of the license may be found at\r
9http://opensource.org/licenses/bsd-license.php\r
10\r
11THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
12WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
13\r
14**/\r
15\r
16\r
17#include "HiiDatabase.h"\r
18\r
0368663f 19EFI_GUID gFrameworkHiiCompatbilityGuid = EFI_IFR_FRAMEWORK_GUID;\r
20EFI_GUID gTianoHiiIfrGuid = EFI_IFR_TIANO_GUID;\r
21\r
22\r
4259256b 23EFI_GUID *\r
24GetGuidOfFirstFormset (\r
25 CONST EFI_HII_FORM_PACKAGE * FormPackage\r
26) \r
27{\r
0368663f 28 UINT8 *StartOfNextPackage;\r
29 EFI_IFR_OP_HEADER *OpCodeData;\r
4259256b 30\r
31 StartOfNextPackage = (UINT8 *) FormPackage + FormPackage->Header.Length;\r
32 OpCodeData = (EFI_IFR_OP_HEADER *) (FormPackage + 1);\r
33\r
34 while ((UINT8 *) OpCodeData < StartOfNextPackage) {\r
35 if (OpCodeData->OpCode == EFI_IFR_FORM_SET_OP) {\r
3711f8f8 36 return AllocateCopyPool (sizeof(EFI_GUID), &(((EFI_IFR_FORM_SET *) OpCodeData)->Guid));\r
4259256b 37 }\r
38 OpCodeData = (EFI_IFR_OP_HEADER *) ((UINT8 *) OpCodeData + OpCodeData->Length);\r
39 }\r
40\r
41 ASSERT (FALSE);\r
42\r
43 return NULL;\r
44}\r
45\r
ee3428bb 46EFI_HII_HANDLE\r
0368663f 47FwHiiHandleToUefiHiiHandle (\r
48 IN CONST HII_THUNK_PRIVATE_DATA *Private,\r
49 IN FRAMEWORK_EFI_HII_HANDLE FwHiiHandle\r
ee3428bb 50 )\r
51{\r
0368663f 52 HII_THUNK_CONTEXT *ThunkContext;\r
ee3428bb 53\r
0368663f 54 ASSERT (FwHiiHandle != (FRAMEWORK_EFI_HII_HANDLE) 0);\r
ee3428bb 55 ASSERT (Private != NULL);\r
56\r
0368663f 57 ThunkContext = FwHiiHandleToThunkContext (Private, FwHiiHandle);\r
ee3428bb 58\r
0368663f 59 if (ThunkContext != NULL) {\r
60 return ThunkContext->UefiHiiHandle;\r
ee3428bb 61 }\r
62 \r
63 return (EFI_HII_HANDLE) NULL;\r
64}\r
65\r
ebbd2793 66\r
0368663f 67HII_THUNK_CONTEXT *\r
68FwHiiHandleToThunkContext (\r
69 IN CONST HII_THUNK_PRIVATE_DATA *Private,\r
70 IN FRAMEWORK_EFI_HII_HANDLE FwHiiHandle\r
ebbd2793 71 )\r
72{\r
0368663f 73 LIST_ENTRY *Link;\r
74 HII_THUNK_CONTEXT *ThunkContext;\r
75\r
ebbd2793 76\r
0368663f 77 Link = GetFirstNode (&Private->ThunkContextListHead);\r
ebbd2793 78\r
0368663f 79 while (!IsNull (&Private->ThunkContextListHead, Link)) {\r
80 ThunkContext = HII_THUNK_CONTEXT_FROM_LINK (Link);\r
81\r
82 if (FwHiiHandle == ThunkContext->FwHiiHandle) {\r
83 return ThunkContext;\r
ebbd2793 84 }\r
0368663f 85\r
86 Link = GetNextNode (&Private->ThunkContextListHead, Link);\r
ebbd2793 87 }\r
88\r
0368663f 89 return NULL;\r
ebbd2793 90}\r
91\r
0368663f 92HII_THUNK_CONTEXT *\r
93UefiHiiHandleToThunkContext (\r
94 IN CONST HII_THUNK_PRIVATE_DATA *Private,\r
ea58467b 95 IN EFI_HII_HANDLE UefiHiiHandle\r
96 )\r
97{\r
0368663f 98 LIST_ENTRY *Link;\r
99 HII_THUNK_CONTEXT *ThunkContext;\r
ea58467b 100\r
0368663f 101 Link = GetFirstNode (&Private->ThunkContextListHead);\r
ea58467b 102\r
0368663f 103 while (!IsNull (&Private->ThunkContextListHead, Link)) {\r
104 ThunkContext = HII_THUNK_CONTEXT_FROM_LINK (Link);\r
105\r
106 if (UefiHiiHandle == ThunkContext->UefiHiiHandle) {\r
107 return ThunkContext;\r
ea58467b 108 }\r
0368663f 109 Link = GetNextNode (&Private->ThunkContextListHead, Link);\r
ea58467b 110 }\r
111\r
0368663f 112 return NULL;\r
ea58467b 113}\r
99a83b4c 114\r
115EFI_HII_HANDLE *\r
0368663f 116TagGuidToUefiHiiHandle (\r
117 IN CONST HII_THUNK_PRIVATE_DATA *Private,\r
99a83b4c 118 IN CONST EFI_GUID *Guid\r
119 )\r
120{\r
0368663f 121 LIST_ENTRY *Link;\r
122 HII_THUNK_CONTEXT *ThunkContext;\r
123\r
124 Link = GetFirstNode (&Private->ThunkContextListHead);\r
99a83b4c 125\r
0368663f 126 while (!IsNull (&Private->ThunkContextListHead, Link)) {\r
127 ThunkContext = HII_THUNK_CONTEXT_FROM_LINK (Link);\r
99a83b4c 128\r
0368663f 129 if (CompareGuid (Guid, &ThunkContext->TagGuid) && (ThunkContext->IfrPackageCount != 0)) {\r
130 return ThunkContext->UefiHiiHandle;\r
99a83b4c 131 }\r
0368663f 132\r
133 Link = GetNextNode (&Private->ThunkContextListHead, Link);\r
99a83b4c 134 }\r
135\r
0368663f 136 return NULL;\r
99a83b4c 137 \r
138}\r
139\r
ea58467b 140BOOLEAN\r
141IsFrameworkHiiDatabaseHandleDepleted (\r
0368663f 142 IN CONST HII_THUNK_PRIVATE_DATA *Private\r
ea58467b 143 )\r
144{\r
145 return (BOOLEAN) (Private->StaticHiiHandle == (UINTN) Private->StaticPureUefiHiiHandle);\r
146}\r
147\r
148EFI_STATUS\r
0368663f 149AssignFrameworkHiiHandle (\r
150 IN OUT HII_THUNK_PRIVATE_DATA *Private,\r
151 IN BOOLEAN FromFwHiiNewPack,\r
ea58467b 152 OUT FRAMEWORK_EFI_HII_HANDLE *Handle\r
153 )\r
154{\r
155 ASSERT (Handle != NULL);\r
156\r
0368663f 157 if (FromFwHiiNewPack) {\r
158\r
159 *Handle = Private->StaticHiiHandle;\r
160 Private->StaticHiiHandle += 1;\r
161\r
162 if (IsFrameworkHiiDatabaseHandleDepleted (Private)) {\r
163 return EFI_OUT_OF_RESOURCES;\r
164 }\r
165\r
166 } else {\r
167\r
168 *Handle = Private->StaticPureUefiHiiHandle;\r
169 Private->StaticPureUefiHiiHandle -= 1;\r
170 \r
171 if (IsFrameworkHiiDatabaseHandleDepleted (Private)) {\r
172 return EFI_OUT_OF_RESOURCES;\r
173 }\r
ea58467b 174\r
ea58467b 175 }\r
176\r
177 return EFI_SUCCESS;\r
178}\r
179\r
180EFI_STATUS\r
0368663f 181DestroyThunkContextForUefiHiiHandle (\r
182 IN HII_THUNK_PRIVATE_DATA *Private,\r
183 IN EFI_HII_HANDLE UefiHiiHandle\r
184 )\r
185{\r
186 HII_THUNK_CONTEXT *ThunkContext;\r
187\r
188 ThunkContext = UefiHiiHandleToThunkContext (Private, UefiHiiHandle);\r
189 ASSERT (ThunkContext != NULL);\r
190\r
191 ASSERT (IsListEmpty (&ThunkContext->OneOfOptionMapListHead));\r
192 ASSERT (IsListEmpty (&ThunkContext->QuestionIdMapListHead));\r
193 \r
194 RemoveEntryList (&ThunkContext->Link);\r
195\r
196 FreePool (ThunkContext);\r
197 \r
198 return EFI_SUCCESS;\r
199}\r
200\r
201\r
202/**\r
203 This function create a HII_THUNK_CONTEXT for a package list registered\r
204 by a module calling EFI_HII_DATABASE_PROTOCOL.NewPackageList. It records\r
205 the PackageListGuid in EFI_HII_PACKAGE_LIST_HEADER in the TagGuid in \r
206 HII_THUNK_CONTEXT created. This TagGuid will be used as a key to s\r
207\r
208**/\r
209HII_THUNK_CONTEXT *\r
210CreateThunkContextForUefiHiiHandle (\r
211 IN HII_THUNK_PRIVATE_DATA *Private,\r
212 IN EFI_HII_HANDLE UefiHiiHandle\r
213 )\r
214{\r
215 EFI_STATUS Status;\r
216 EFI_GUID PackageGuid;\r
217 HII_THUNK_CONTEXT *ThunkContext;\r
218\r
219 ThunkContext = AllocateZeroPool (sizeof (*ThunkContext));\r
220 ASSERT (ThunkContext != NULL);\r
221 \r
222 ThunkContext->Signature = HII_THUNK_CONTEXT_SIGNATURE;\r
223\r
224 Status = AssignFrameworkHiiHandle (Private, FALSE, &ThunkContext->FwHiiHandle);\r
225 if (EFI_ERROR (Status)) {\r
226 return NULL;\r
227 }\r
228 \r
229 ThunkContext->UefiHiiHandle = UefiHiiHandle;\r
230 \r
231 Status = HiiLibExtractGuidFromHiiHandle (UefiHiiHandle, &PackageGuid);\r
232 ASSERT_EFI_ERROR (Status);\r
233 \r
234 CopyGuid(&ThunkContext->TagGuid, &PackageGuid);\r
235\r
236 InitializeListHead (&ThunkContext->QuestionIdMapListHead);\r
237 InitializeListHead (&ThunkContext->OneOfOptionMapListHead);\r
238 \r
239 InsertTailList (&Private->ThunkContextListHead, &ThunkContext->Link);\r
240\r
241 return ThunkContext;\r
242}\r
243\r
244\r
245UINTN\r
246GetPackageCountByType (\r
247 IN CONST EFI_HII_PACKAGE_LIST_HEADER *PackageListHeader,\r
248 IN UINT8 PackageType\r
ea58467b 249 )\r
250{\r
0368663f 251 UINTN Count;\r
252 EFI_HII_PACKAGE_HEADER *PackageHeader;\r
253\r
254 PackageHeader = (EFI_HII_PACKAGE_HEADER *) ((UINT8 *) PackageListHeader + sizeof (EFI_HII_PACKAGE_LIST_HEADER));\r
255 Count = 0;\r
256 \r
257 while (PackageHeader->Type != EFI_HII_PACKAGE_END) {\r
258 if (PackageHeader->Type == PackageType ) {\r
259 Count++;\r
260 }\r
261 PackageHeader = (EFI_HII_PACKAGE_HEADER *) ((UINT8 *) PackageHeader + PackageHeader->Length);\r
262 }\r
263 \r
264 \r
265 return Count;\r
266}\r
267\r
268LIST_ENTRY *\r
269GetOneOfOptionMapEntryListHead (\r
270 IN CONST HII_THUNK_CONTEXT *ThunkContext,\r
271 IN UINT16 QuestionId\r
272 )\r
273{\r
274 LIST_ENTRY *Link;\r
275 ONE_OF_OPTION_MAP *Map;\r
276\r
277 Link = GetFirstNode (&ThunkContext->OneOfOptionMapListHead);\r
278\r
279 while (!IsNull (&ThunkContext->OneOfOptionMapListHead, Link)) {\r
280 Map = ONE_OF_OPTION_MAP_FROM_LINK (Link);\r
281 if (QuestionId == Map->QuestionId) {\r
282 return &Map->OneOfOptionMapEntryListHead;\r
283 }\r
284 Link = GetNextNode (&ThunkContext->OneOfOptionMapListHead, Link);\r
285 }\r
286 \r
287 return NULL;\r
288}\r
99a83b4c 289\r
290\r
0368663f 291EFI_STATUS\r
292CreateQuestionIdMap (\r
293 IN OUT HII_THUNK_CONTEXT *ThunkContext\r
294 )\r
295{\r
296 EFI_STATUS Status;\r
297 EFI_HII_PACKAGE_LIST_HEADER *List;\r
298 EFI_HII_PACKAGE_HEADER *Package;\r
299 UINTN Size;\r
300 EFI_IFR_OP_HEADER *OpCode;\r
301 UINTN Offset;\r
302 QUESTION_ID_MAP *IdMap;\r
303 EFI_IFR_VARSTORE *VarStore;\r
304 EFI_IFR_FORM_SET *FormSet;\r
305 EFI_IFR_QUESTION_HEADER *Question;\r
306 LIST_ENTRY *QuestionIdMapEntryListHead;\r
307 LIST_ENTRY *OneOfOptinMapEntryListHead;\r
308 QUESTION_ID_MAP_ENTRY *IdMapEntry;\r
309 EFI_IFR_GUID_OPTIONKEY *OptionMap;\r
310 ONE_OF_OPTION_MAP *OneOfOptionMap;\r
311 ONE_OF_OPTION_MAP_ENTRY *OneOfOptionMapEntry;\r
312 EFI_IFR_GUID_CLASS *Class;\r
313 \r
314\r
315 Status = HiiLibExportPackageLists (ThunkContext->UefiHiiHandle, &List, &Size);\r
316 if (EFI_ERROR (Status)) {\r
317 return Status;\r
ea58467b 318 }\r
99a83b4c 319\r
0368663f 320 //\r
321 // Get all VarStoreId and build the the QuestionId map.\r
322 // EFI_IFR_QUESTION_HEADER.VarStoreInfo.VarOffset -> Framework Question ID\r
323 // EFI_IFR_QUESTION_HEADER.QuestionId -> UEFI Question ID\r
324 //\r
325\r
326 //\r
327 // Skip the package list header.\r
328 //\r
329 Package = (EFI_HII_PACKAGE_HEADER *) (List + 1);\r
330\r
331 while (Package->Type != EFI_HII_PACKAGE_END) {\r
332\r
333 if (Package->Type == EFI_HII_PACKAGE_FORM) {\r
334\r
335 //\r
336 // Skip the package header\r
337 //\r
338 Offset = sizeof (EFI_HII_PACKAGE_HEADER);\r
339 while (Offset < Package->Length) {\r
340 OpCode = (EFI_IFR_OP_HEADER *)((UINT8 *) Package + Offset);\r
341\r
342 switch (OpCode->OpCode) {\r
343 case EFI_IFR_FORM_SET_OP:\r
344 FormSet = (EFI_IFR_FORM_SET *) OpCode;\r
345 ThunkContext->FormSetTitle = FormSet->FormSetTitle;\r
346 ThunkContext->FormSetHelp = FormSet->Help;\r
347 break;\r
348 \r
349 case EFI_IFR_VARSTORE_OP:\r
350 //\r
351 // IFR built from Framework VFR only has UEFI Buffer Type Storage\r
352 //\r
353 VarStore = (EFI_IFR_VARSTORE *) OpCode;\r
354 IdMap = AllocateZeroPool (sizeof (QUESTION_ID_MAP));\r
355 ASSERT (IdMap != NULL);\r
356 \r
357 IdMap->Signature = QUESTION_ID_MAP_SIGNATURE;\r
358 IdMap->VarStoreId = VarStore->VarStoreId;\r
359 IdMap->VarSize = VarStore->Size;\r
360 InitializeListHead (&IdMap->MapEntryListHead);\r
361 InsertTailList (&ThunkContext->QuestionIdMapListHead, &IdMap->Link);\r
362 break;\r
363\r
364 case EFI_IFR_NUMERIC_OP:\r
365 case EFI_IFR_CHECKBOX_OP:\r
366 case EFI_IFR_ONE_OF_OP:\r
367 case EFI_IFR_ORDERED_LIST_OP:\r
368 case EFI_IFR_STRING_OP:\r
369 //case EFI_IFR_PASSWORD_OP:\r
370 Question = (EFI_IFR_QUESTION_HEADER *)(OpCode + 1);\r
371 QuestionIdMapEntryListHead = GetMapEntryListHead (ThunkContext, Question->VarStoreId);\r
372\r
373 if (QuestionIdMapEntryListHead != NULL) {\r
374 //\r
375 // If the Question is using Buffer (EFI_IFR_VARSTORE_OP) type VarStore.\r
376 //\r
377 IdMapEntry = AllocateZeroPool (sizeof (QUESTION_ID_MAP_ENTRY));\r
378 ASSERT (IdMapEntry != NULL);\r
379\r
380 IdMapEntry->FwQId = Question->VarStoreInfo.VarOffset;\r
381 IdMapEntry->UefiQid = Question->QuestionId;\r
382 IdMapEntry->Signature = QUESTION_ID_MAP_ENTRY_SIGNATURE;\r
383\r
384 InsertTailList (QuestionIdMapEntryListHead, &IdMapEntry->Link);\r
385 }\r
386\r
387 break;\r
388 \r
389 case EFI_IFR_GUID_OP:\r
390 OptionMap = (EFI_IFR_GUID_OPTIONKEY *) OpCode;\r
391 if (CompareGuid (&OptionMap->Guid, &gFrameworkHiiCompatbilityGuid)) {\r
392 if (OptionMap->ExtendOpCode == EFI_IFR_EXTEND_OP_OPTIONKEY) {\r
393 OneOfOptinMapEntryListHead = GetOneOfOptionMapEntryListHead (ThunkContext, OptionMap->QuestionId);\r
394 if (OneOfOptinMapEntryListHead == NULL) {\r
395 OneOfOptionMap = AllocateZeroPool (sizeof (ONE_OF_OPTION_MAP));\r
396 ASSERT (OneOfOptionMap != NULL);\r
397\r
398 OneOfOptionMap->Signature = ONE_OF_OPTION_MAP_SIGNATURE;\r
399 OneOfOptionMap->QuestionId = OptionMap->QuestionId;\r
400 OneOfOptionMap->ValueType = EFI_IFR_TYPE_NUM_SIZE_8;\r
401 InitializeListHead (&OneOfOptionMap->OneOfOptionMapEntryListHead);\r
402 OneOfOptinMapEntryListHead = &OneOfOptionMap->OneOfOptionMapEntryListHead;\r
403 InsertTailList (&ThunkContext->OneOfOptionMapListHead, &OneOfOptionMap->Link);\r
404 }\r
405 OneOfOptionMapEntry = AllocateZeroPool (sizeof (ONE_OF_OPTION_MAP_ENTRY));\r
406 ASSERT (OneOfOptionMapEntry != NULL);\r
407\r
408 OneOfOptionMapEntry->Signature = ONE_OF_OPTION_MAP_ENTRY_SIGNATURE;\r
409 OneOfOptionMapEntry->FwKey = OptionMap->KeyValue;\r
410 CopyMem (&OneOfOptionMapEntry->Value, &OptionMap->OptionValue, sizeof (EFI_IFR_TYPE_VALUE));\r
411 \r
412 InsertTailList (OneOfOptinMapEntryListHead, &OneOfOptionMapEntry->Link);\r
413 }\r
414 }else if (CompareGuid (&OptionMap->Guid, &gTianoHiiIfrGuid)) {\r
415 Class = (EFI_IFR_GUID_CLASS *) OpCode;\r
416\r
417 switch (Class->ExtendOpCode) {\r
418 case EFI_IFR_EXTEND_OP_CLASS:\r
419 ThunkContext->FormSetClass = Class->Class;\r
420 break;\r
421 case EFI_IFR_EXTEND_OP_SUBCLASS:\r
422 ThunkContext->FormSetSubClass = ((EFI_IFR_GUID_SUBCLASS *) Class)->SubClass;\r
423 break;\r
424\r
425 default:\r
426 break;\r
427 }\r
428 }\r
429 break;\r
430 \r
431 default:\r
432 break;\r
433 \r
434 }\r
435\r
436 Offset += OpCode->Length;\r
437 }\r
438 //\r
439 // Only Form Package is in a Package List.\r
440 //\r
441 break;\r
442 }\r
443\r
444 Package = (EFI_HII_PACKAGE_HEADER *) (UINT8 *) Package + Package->Length;\r
445 }\r
446\r
447 FreePool (List);\r
ea58467b 448 return EFI_SUCCESS;\r
449}\r
99a83b4c 450\r
0368663f 451\r
452LIST_ENTRY *\r
453GetMapEntryListHead (\r
454 IN CONST HII_THUNK_CONTEXT *ThunkContext,\r
455 IN UINT16 VarStoreId\r
456 )\r
457{\r
458 LIST_ENTRY *Link;\r
459 QUESTION_ID_MAP *Map;\r
460\r
461 Link = GetFirstNode (&ThunkContext->QuestionIdMapListHead);\r
462\r
463 while (!IsNull (&ThunkContext->QuestionIdMapListHead, Link)) {\r
464 Map = QUESTION_ID_MAP_FROM_LINK (Link);\r
465 if (VarStoreId == Map->VarStoreId) {\r
466 return &Map->MapEntryListHead;\r
467 }\r
468 Link = GetNextNode (&ThunkContext->QuestionIdMapListHead, Link);\r
469 }\r
470 return NULL;\r
471}\r
472\r
473\r