]> git.proxmox.com Git - mirror_edk2.git/blob - EdkCompatibilityPkg/Compatibility/FrameworkHiiToUefiHiiThunk/Package.c
9717c2f56e7ec7f66f121d986c56a3a11573d91f
[mirror_edk2.git] / EdkCompatibilityPkg / Compatibility / FrameworkHiiToUefiHiiThunk / Package.c
1 /**@file
2 Implement protocol interface related to package registrations.
3
4 Copyright (c) 2006 - 2008, Intel Corporation
5 All rights reserved. This program and the accompanying materials
6 are licensed and made available under the terms and conditions of the BSD License
7 which accompanies this distribution. The full text of the license may be found at
8 http://opensource.org/licenses/bsd-license.php
9
10 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
11 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
12
13 **/
14
15
16 #include "HiiDatabase.h"
17 #include "HiiHandle.h"
18
19
20 STATIC BOOLEAN mInFrameworkHiiNewPack = FALSE;
21 STATIC BOOLEAN mInFrameworkHiiRemovePack = FALSE;
22 BOOLEAN mInFrameworkUpdatePakcage = FALSE;
23
24
25 EFI_STATUS
26 GetPackageCount (
27 IN CONST EFI_HII_PACKAGES *Packages,
28 UINTN *IfrPackageCount,
29 UINTN *StringPackageCount
30 )
31 {
32 UINTN Index;
33 TIANO_AUTOGEN_PACKAGES_HEADER **TianoAutogenPackageHdrArray;
34
35 ASSERT (Packages != NULL);
36 ASSERT (IfrPackageCount != NULL);
37 ASSERT (StringPackageCount != NULL);
38
39 *IfrPackageCount = 0;
40 *StringPackageCount = 0;
41
42 TianoAutogenPackageHdrArray = (TIANO_AUTOGEN_PACKAGES_HEADER **) (((UINT8 *) &Packages->GuidId) + sizeof (Packages->GuidId));
43
44 for (Index = 0; Index < Packages->NumberOfPackages; Index++) {
45 //
46 // The current UEFI HII build tool generate a binary in the format defined by
47 // TIANO_AUTOGEN_PACKAGES_HEADER. We assume that all packages generated in
48 // this binary is with same package type. So the returned IfrPackageCount and StringPackageCount
49 // may not be the exact number of valid package number in the binary generated
50 // by HII Build tool.
51 //
52 switch (TianoAutogenPackageHdrArray[Index]->PackageHeader.Type) {
53 case EFI_HII_PACKAGE_FORMS:
54 *IfrPackageCount += 1;
55 break;
56 case EFI_HII_PACKAGE_STRINGS:
57 *StringPackageCount += 1;
58 break;
59
60 case EFI_HII_PACKAGE_SIMPLE_FONTS:
61 break;
62
63 //
64 // The following fonts are invalid for a module that using Framework to UEFI thunk layer.
65 //
66 case EFI_HII_PACKAGE_KEYBOARD_LAYOUT:
67 case EFI_HII_PACKAGE_FONTS:
68 case EFI_HII_PACKAGE_IMAGES:
69 default:
70 ASSERT (FALSE);
71 return EFI_INVALID_PARAMETER;
72 break;
73 }
74 }
75
76 return EFI_SUCCESS;
77 }
78
79 VOID
80 UpdatePackListWithOnlyIfrPack (
81 IN HII_THUNK_PRIVATE_DATA *Private,
82 IN HII_THUNK_CONTEXT *StringPackageThunkContext,
83 IN CONST EFI_HII_PACKAGE_LIST_HEADER *StringPackageListHeader
84 )
85 {
86 EFI_STATUS Status;
87 LIST_ENTRY *Link;
88 HII_THUNK_CONTEXT *ThunkContext;
89
90 Link = GetFirstNode (&Private->ThunkContextListHead);
91 while (!IsNull (&Private->ThunkContextListHead, Link)) {
92
93 ThunkContext = HII_THUNK_CONTEXT_FROM_LINK (Link);
94
95 if (StringPackageThunkContext != ThunkContext) {
96 //
97 // Skip the String Package Thunk Entry itself.
98 //
99
100 if (CompareGuid (&StringPackageListHeader->PackageListGuid, &ThunkContext->TagGuid)) {
101
102 ASSERT (ThunkContext->StringPackageCount == 0 && ThunkContext->IfrPackageCount == 1);
103
104 ThunkContext->StringPackageCount = GetPackageCountByType (StringPackageListHeader, EFI_HII_PACKAGE_STRINGS);
105
106 Status = mHiiDatabase->UpdatePackageList (
107 mHiiDatabase,
108 ThunkContext->UefiHiiHandle,
109 StringPackageListHeader
110 );
111 ASSERT_EFI_ERROR (Status);
112
113 }
114 }
115
116 Link = GetNextNode (&Private->ThunkContextListHead, Link);
117 }
118
119 }
120
121
122 EFI_HII_PACKAGE_LIST_HEADER *
123 PrepareUefiPackageListFromFrameworkHiiPackages (
124 IN CONST EFI_HII_PACKAGES *Packages,
125 IN CONST EFI_GUID *PackageListGuid
126 )
127 {
128 UINTN NumberOfPackages;
129 EFI_HII_PACKAGE_LIST_HEADER *PackageListHeader;
130 UINT8 *PackageListData;
131 UINT32 PackageListLength;
132 UINT32 PackageLength;
133 EFI_HII_PACKAGE_HEADER PackageHeader;
134 UINTN Index;
135 TIANO_AUTOGEN_PACKAGES_HEADER **TianoAutogenPackageHdrArray;
136
137 ASSERT (Packages != NULL);
138 ASSERT (PackageListGuid != NULL);
139
140 TianoAutogenPackageHdrArray = (TIANO_AUTOGEN_PACKAGES_HEADER **) ((UINT8 *) &Packages->GuidId + sizeof (Packages->GuidId));
141 NumberOfPackages = Packages->NumberOfPackages;
142
143 PackageListLength = sizeof (EFI_HII_PACKAGE_LIST_HEADER);
144
145 for (Index = 0; Index < NumberOfPackages; Index++) {
146 CopyMem (&PackageLength, &TianoAutogenPackageHdrArray[Index]->BinaryLength, sizeof (UINT32));
147 //
148 //TIANO_AUTOGEN_PACKAGES_HEADER.BinaryLength include the BinaryLength itself.
149 //
150 PackageListLength += (PackageLength - sizeof(UINT32));
151 }
152
153 //
154 // Include the lenght of EFI_HII_PACKAGE_END
155 //
156 PackageListLength += sizeof (EFI_HII_PACKAGE_HEADER);
157 PackageListHeader = AllocateZeroPool (PackageListLength);
158 ASSERT (PackageListHeader != NULL);
159
160 CopyMem (&PackageListHeader->PackageListGuid, PackageListGuid, sizeof (EFI_GUID));
161 PackageListHeader->PackageLength = PackageListLength;
162
163 PackageListData = ((UINT8 *) PackageListHeader) + sizeof (EFI_HII_PACKAGE_LIST_HEADER);
164
165 for (Index = 0; Index < NumberOfPackages; Index++) {
166 CopyMem (&PackageLength, &(TianoAutogenPackageHdrArray[Index]->BinaryLength), sizeof (UINT32));
167 PackageLength -= sizeof (UINT32);
168 CopyMem (PackageListData, &(TianoAutogenPackageHdrArray[Index]->PackageHeader), PackageLength);
169 PackageListData += PackageLength;
170 }
171
172 //
173 // Append EFI_HII_PACKAGE_END
174 //
175 PackageHeader.Type = EFI_HII_PACKAGE_END;
176 PackageHeader.Length = sizeof (EFI_HII_PACKAGE_HEADER);
177 CopyMem (PackageListData, &PackageHeader, PackageHeader.Length);
178
179 return PackageListHeader;
180 }
181
182 VOID
183 GenerateRandomGuid (
184 OUT EFI_GUID * Guid
185 )
186 {
187 EFI_GUID GuidBase = { 0x14f95e01, 0xd562, 0x432e, { 0x84, 0x4a, 0x95, 0xa4, 0x39, 0x5, 0x10, 0x7e }};
188 static UINT64 Count = 0;
189
190 CopyGuid (Guid, &GuidBase);
191
192 Count++;
193 *((UINT64 *) Guid) = *((UINT64 *) Guid) + Count;
194 }
195
196 EFI_STATUS
197 FindStringPackAndUpdatePackListWithOnlyIfrPack (
198 IN HII_THUNK_PRIVATE_DATA *Private,
199 IN HII_THUNK_CONTEXT *IfrThunkContext
200 )
201 {
202 EFI_STATUS Status;
203 LIST_ENTRY *Link;
204 EFI_HII_PACKAGE_LIST_HEADER *StringPackageListHeader;
205 UINTN Size;
206 HII_THUNK_CONTEXT *ThunkContext;
207
208
209 Link = GetFirstNode (&Private->ThunkContextListHead);
210
211 while (!IsNull (&Private->ThunkContextListHead, Link)) {
212
213 ThunkContext = HII_THUNK_CONTEXT_FROM_LINK (Link);
214
215 if (ThunkContext != IfrThunkContext) {
216 if (CompareGuid (&IfrThunkContext->TagGuid, &ThunkContext->TagGuid) && (ThunkContext->IfrPackageCount == 0)) {
217 Status = HiiLibExportPackageLists (ThunkContext->UefiHiiHandle, &StringPackageListHeader, &Size);
218 ASSERT_EFI_ERROR (Status);
219
220 IfrThunkContext->StringPackageCount = GetPackageCountByType (StringPackageListHeader, EFI_HII_PACKAGE_STRINGS);
221 //
222 // Add Function to only get only String Packages from the Package List
223 //
224 Status = mHiiDatabase->UpdatePackageList (
225 mHiiDatabase,
226 IfrThunkContext->UefiHiiHandle,
227 StringPackageListHeader
228 );
229 ASSERT_EFI_ERROR (Status);
230
231 FreePool (StringPackageListHeader);
232 return EFI_SUCCESS;
233
234 }
235 }
236
237 Link = GetNextNode (&Private->ThunkContextListHead, Link);
238 }
239
240 ASSERT (FALSE);
241 return EFI_NOT_FOUND;
242
243 }
244
245
246 //
247 //
248 //
249 EFI_STATUS
250 UefiRegisterPackageList(
251 IN EFI_HII_PROTOCOL *This,
252 IN HII_THUNK_PRIVATE_DATA *Private,
253 IN EFI_HII_PACKAGES *Packages,
254 OUT FRAMEWORK_EFI_HII_HANDLE *Handle
255 )
256 {
257 EFI_STATUS Status;
258 UINTN StringPackageCount;
259 UINTN IfrPackageCount;
260 EFI_HII_PACKAGE_LIST_HEADER *PackageListHeader;
261 HII_THUNK_CONTEXT *ThunkContext;
262 HII_THUNK_CONTEXT *ThunkContextToRemove;
263 EFI_GUID GuidId;
264 EFI_HII_PACKAGE_HEADER *IfrPackage;
265
266 PackageListHeader = NULL;
267
268 Status = GetPackageCount (Packages, &IfrPackageCount, &StringPackageCount);
269 ASSERT_EFI_ERROR (Status);
270
271 if (IfrPackageCount > 1) {
272 //
273 // HII Thunk only handle package with 0 or 1 IFR package.
274 //
275 ASSERT (FALSE);
276 return EFI_UNSUPPORTED;
277 }
278
279 ThunkContext = CreateThunkContext (Private, StringPackageCount, IfrPackageCount);
280 if (ThunkContext == NULL) {
281 return EFI_OUT_OF_RESOURCES;
282 }
283 ThunkContext->ByFrameworkHiiNewPack = TRUE;
284
285 if (Packages->GuidId == NULL) {
286 //
287 // UEFI HII Database require Package List GUID must be unique.
288 //
289 // If Packages->GuidId is NULL, the caller of FramworkHii->NewPack is registering
290 // packages with at least 1 StringPack and 1 IfrPack. Therefore, Packages->GuidId is
291 // not used as the name of the package list. A GUID is generated as a Package List
292 // GUID.
293 //
294 ASSERT (StringPackageCount >=1 && IfrPackageCount == 1);
295 IfrPackage = GetIfrPackage (Packages);
296 GetFormSetGuid (IfrPackage, &ThunkContext->TagGuid);
297 } else {
298 ThunkContextToRemove = TagGuidToIfrPackThunkContext (Private, Packages->GuidId);
299
300 if (IfrPackageCount > 0 &&
301 StringPackageCount > 0 &&
302 (ThunkContextToRemove!= NULL)) {
303 DEBUG((EFI_D_WARN, "Framework code registers HII package list with the same GUID more than once.\n"));
304 DEBUG((EFI_D_WARN, "This package list should be already registered. Just return successfully.\n"));
305 HiiRemovePack (This, ThunkContextToRemove->FwHiiHandle);
306 }
307 CopyGuid (&ThunkContext->TagGuid, Packages->GuidId);
308 }
309
310 //
311 // UEFI HII require EFI_HII_CONFIG_ACCESS_PROTOCOL to be installed on a EFI_HANDLE, so
312 // that Setup Utility can load the Buffer Storage using this protocol.
313 //
314 if (IfrPackageCount != 0) {
315 InstallDefaultConfigAccessProtocol (Packages, ThunkContext);
316 }
317 PackageListHeader = PrepareUefiPackageListFromFrameworkHiiPackages (Packages, &ThunkContext->TagGuid);
318 Status = mHiiDatabase->NewPackageList (
319 mHiiDatabase,
320 PackageListHeader,
321 ThunkContext->UefiHiiDriverHandle,
322 &ThunkContext->UefiHiiHandle
323 );
324 if (Status == EFI_INVALID_PARAMETER) {
325 FreePool (PackageListHeader);
326
327 //
328 // UEFI HII database does not allow two package list with the same GUID.
329 // In Framework HII implementation, Packages->GuidId is used as an identifier to associate
330 // a PackageList with only IFR to a Package list the with String package.
331 //
332 GenerateRandomGuid (&GuidId);
333
334 PackageListHeader = PrepareUefiPackageListFromFrameworkHiiPackages (Packages, &GuidId);
335 Status = mHiiDatabase->NewPackageList (
336 mHiiDatabase,
337 PackageListHeader,
338 ThunkContext->UefiHiiDriverHandle,
339 &ThunkContext->UefiHiiHandle
340 );
341 }
342
343 //
344 // BUGBUG: Remove when development is done
345 //
346 ASSERT_EFI_ERROR (Status);
347 if (EFI_ERROR (Status)) {
348 goto Done;
349 }
350
351 if (IfrPackageCount == 0) {
352 if (StringPackageCount != 0) {
353 //
354 // Look for a Package List with only IFR Package with the same GUID name.
355 // If found one, add the String Packages to it.
356 //
357 UpdatePackListWithOnlyIfrPack (
358 Private,
359 ThunkContext,
360 PackageListHeader
361 );
362 }
363 } else {
364 CreateQuestionIdMap (ThunkContext);
365
366 if (StringPackageCount == 0) {
367 //
368 // Register the Package List to UEFI HII first.
369 //
370 Status = FindStringPackAndUpdatePackListWithOnlyIfrPack (
371 Private,
372 ThunkContext
373 );
374
375 if (EFI_ERROR (Status)) {
376 goto Done;
377 }
378 }
379 }
380
381 Done:
382 if (EFI_ERROR (Status)) {
383 DestroyThunkContext (ThunkContext);
384 } else {
385 InsertTailList (&Private->ThunkContextListHead, &ThunkContext->Link);
386 *Handle = ThunkContext->FwHiiHandle;
387 }
388
389 if (PackageListHeader != NULL) {
390 FreePool (PackageListHeader);
391 }
392
393 return Status;
394 }
395
396
397 EFI_STATUS
398 EFIAPI
399 HiiNewPack (
400 IN EFI_HII_PROTOCOL *This,
401 IN EFI_HII_PACKAGES *Packages,
402 OUT FRAMEWORK_EFI_HII_HANDLE *Handle
403 )
404 /*++
405
406 Routine Description:
407
408 Extracts the various packs from a package list.
409
410 Arguments:
411
412 This - Pointer of HII protocol.
413 Packages - Pointer of HII packages.
414 Handle - Handle value to be returned.
415
416 Returns:
417
418 EFI_SUCCESS - Pacakges has added to HII database successfully.
419 EFI_INVALID_PARAMETER - Invalid parameter.
420
421 --*/
422 {
423 EFI_STATUS Status;
424 HII_THUNK_PRIVATE_DATA *Private;
425 EFI_TPL OldTpl;
426
427 if (Handle == NULL) {
428 return EFI_INVALID_PARAMETER;
429 }
430
431 if (Packages == NULL) {
432 return EFI_INVALID_PARAMETER;
433 }
434
435 OldTpl = gBS->RaiseTPL (TPL_NOTIFY);
436
437 //
438 // We use a simple Global variable to inform NewPackNotify
439 // that the package list registered here is already registered
440 // in the HII Thunk Layer. So NewPackNotify does not need to
441 // call RegisterUefiHiiHandle () to registered it.
442 //
443 mInFrameworkHiiNewPack = TRUE;
444
445 Private = HII_THUNK_PRIVATE_DATA_FROM_THIS(This);
446
447 Status = UefiRegisterPackageList (
448 This,
449 Private,
450 Packages,
451 Handle
452 );
453
454 mInFrameworkHiiNewPack = FALSE;
455
456 gBS->RestoreTPL (OldTpl);
457
458 return Status;
459 }
460
461 EFI_STATUS
462 EFIAPI
463 HiiRemovePack (
464 IN EFI_HII_PROTOCOL *This,
465 IN FRAMEWORK_EFI_HII_HANDLE Handle
466 )
467 /*++
468
469 Routine Description:
470 Removes the various packs from a Handle
471
472 Arguments:
473
474 Returns:
475
476 --*/
477 {
478 EFI_STATUS Status;
479 HII_THUNK_PRIVATE_DATA *Private;
480 HII_THUNK_CONTEXT *ThunkContext;
481 EFI_TPL OldTpl;
482
483 OldTpl = gBS->RaiseTPL (TPL_NOTIFY);
484
485 mInFrameworkHiiRemovePack = TRUE;
486
487 Private = HII_THUNK_PRIVATE_DATA_FROM_THIS(This);
488
489 ThunkContext = FwHiiHandleToThunkContext (Private, Handle);
490
491 if (ThunkContext != NULL) {
492 Status = mHiiDatabase->RemovePackageList (
493 mHiiDatabase,
494 ThunkContext->UefiHiiHandle
495 );
496 ASSERT_EFI_ERROR (Status);
497
498 if (ThunkContext->IfrPackageCount != 0) {
499 UninstallDefaultConfigAccessProtocol (ThunkContext);
500 }
501
502 DestroyThunkContext (ThunkContext);
503 }else {
504 Status = EFI_NOT_FOUND;
505 }
506
507 mInFrameworkHiiRemovePack = FALSE;
508 gBS->RestoreTPL (OldTpl);
509
510 return Status;
511 }
512
513 EFI_STATUS
514 EFIAPI
515 NewOrAddPackNotify (
516 IN UINT8 PackageType,
517 IN CONST EFI_GUID *PackageGuid,
518 IN CONST EFI_HII_PACKAGE_HEADER *Package,
519 IN EFI_HII_HANDLE Handle,
520 IN EFI_HII_DATABASE_NOTIFY_TYPE NotifyType
521 )
522 {
523 EFI_STATUS Status;
524 HII_THUNK_PRIVATE_DATA *Private;
525 HII_THUNK_CONTEXT *ThunkContext;
526
527 ASSERT (PackageType == EFI_HII_PACKAGE_STRINGS || PackageType == EFI_HII_PACKAGE_FORMS);
528 ASSERT (NotifyType == EFI_HII_DATABASE_NOTIFY_ADD_PACK || NotifyType == EFI_HII_DATABASE_NOTIFY_NEW_PACK);
529
530 Status = EFI_SUCCESS;
531 Private = mHiiThunkPrivateData;
532
533 if (mInFrameworkHiiNewPack || mInFrameworkUpdatePakcage) {
534 return EFI_SUCCESS;
535 }
536
537 //
538 // We only create a ThunkContext if the Uefi Hii Handle is only already registered
539 // by the HII Thunk Layer.
540 //
541 ThunkContext = UefiHiiHandleToThunkContext (Private, Handle);
542 if (ThunkContext == NULL) {
543 ThunkContext = CreateThunkContextForUefiHiiHandle (Handle);
544 ASSERT (ThunkContext != NULL);
545
546 InsertTailList (&Private->ThunkContextListHead, &ThunkContext->Link);
547 }
548
549 if (PackageType == EFI_HII_PACKAGE_FORMS) {
550 GetAttributesOfFirstFormSet (ThunkContext);
551 }
552
553 return Status;
554 }
555
556 //
557 // Framework HII module may cache a GUID as the name of the package list.
558 // Then search for the Framework HII handle database for the handle matching
559 // this GUID
560
561 EFI_STATUS
562 EFIAPI
563 RemovePackNotify (
564 IN UINT8 PackageType,
565 IN CONST EFI_GUID *PackageGuid,
566 IN CONST EFI_HII_PACKAGE_HEADER *Package,
567 IN EFI_HII_HANDLE Handle,
568 IN EFI_HII_DATABASE_NOTIFY_TYPE NotifyType
569 )
570 {
571 EFI_STATUS Status;
572 HII_THUNK_PRIVATE_DATA *Private;
573 HII_THUNK_CONTEXT *ThunkContext;
574 EFI_HII_PACKAGE_LIST_HEADER *HiiPackageList;
575 UINTN BufferSize;
576
577 Status = EFI_SUCCESS;
578
579 ASSERT (PackageType == EFI_HII_PACKAGE_STRINGS);
580 ASSERT (NotifyType == EFI_HII_DATABASE_NOTIFY_REMOVE_PACK);
581
582 if (mInFrameworkHiiRemovePack || mInFrameworkUpdatePakcage) {
583 return EFI_SUCCESS;
584 }
585
586 Private = mHiiThunkPrivateData;
587
588 ThunkContext = UefiHiiHandleToThunkContext (Private, Handle);
589
590 //
591 // BugBug: Change to ASSERT if HII Database fix the bug and to also invoke
592 // NEW_PACK_NOTIFY for package (String Package) created internally.
593 //
594 if (ThunkContext != NULL) {
595 if (!ThunkContext->ByFrameworkHiiNewPack) {
596 Status = HiiLibExportPackageLists (Handle, &HiiPackageList, &BufferSize);
597 ASSERT_EFI_ERROR (Status);
598
599 if (GetPackageCountByType (HiiPackageList, EFI_HII_PACKAGE_STRINGS) == 1) {
600 //
601 // If the string package will be removed is the last string package
602 // in the package list, we will remove the HII Thunk entry from the
603 // database.
604 //
605 DestroyThunkContextForUefiHiiHandle (Private, Handle);
606 }
607
608 FreePool (HiiPackageList);
609 }
610 }
611
612
613 return Status;
614 }
615
616
617