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