]> git.proxmox.com Git - mirror_edk2.git/blob - EdkCompatibilityPkg/Compatibility/FrameworkHiiToUefiHiiThunk/Package.c
6e2c9dfd34ca8625fd24fea853bec8e08fadf2d6
[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_FORM:
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 HII_THUNK_PRIVATE_DATA *Private,
252 IN EFI_HII_PACKAGES *Packages,
253 OUT FRAMEWORK_EFI_HII_HANDLE *Handle
254 )
255 {
256 EFI_STATUS Status;
257 UINTN StringPackageCount;
258 UINTN IfrPackageCount;
259 EFI_HII_PACKAGE_LIST_HEADER *PackageListHeader;
260 HII_THUNK_CONTEXT *ThunkContext;
261 EFI_GUID GuidId;
262
263 PackageListHeader = NULL;
264
265 Status = GetPackageCount (Packages, &IfrPackageCount, &StringPackageCount);
266 ASSERT_EFI_ERROR (Status);
267
268 if (IfrPackageCount > 1) {
269 //
270 // HII Thunk only handle package with 0 or 1 IFR package.
271 //
272 ASSERT (FALSE);
273 return EFI_UNSUPPORTED;
274 }
275
276 ThunkContext = CreateThunkContext (Private, StringPackageCount, IfrPackageCount);
277 if (ThunkContext == NULL) {
278 return EFI_OUT_OF_RESOURCES;
279 }
280 ThunkContext->ByFrameworkHiiNewPack = TRUE;
281
282 if (Packages->GuidId == NULL) {
283 //
284 // UEFI HII Database require Package List GUID must be unique.
285 //
286 // If Packages->GuidId is NULL, the caller of FramworkHii->NewPack is registering
287 // packages with at least 1 StringPack and 1 IfrPack. Therefore, Packages->GuidId is
288 // not used as the name of the package list. A GUID is generated as a Package List
289 // GUID.
290 //
291 ASSERT (StringPackageCount >=1 && IfrPackageCount == 1);
292 GenerateRandomGuid (&GuidId);
293 } else {
294 CopyGuid (&GuidId, Packages->GuidId);
295 }
296
297 //
298 // Record the Package List GUID, it is used as a name for the package list by Framework HII.
299 //
300 CopyGuid (&ThunkContext->TagGuid, &GuidId);
301
302 if ((StringPackageCount == 0) && (IfrPackageCount != 0)) {
303 //
304 // UEFI HII database does not allow two package list with the same GUID.
305 // In Framework HII implementation, Packages->GuidId is used as an identifier to associate
306 // a PackageList with only IFR to a Package list the with String package.
307 //
308 GenerateRandomGuid (&GuidId);
309 }
310
311 //
312 // UEFI HII require EFI_HII_CONFIG_ACCESS_PROTOCOL to be installed on a EFI_HANDLE, so
313 // that Setup Utility can load the Buffer Storage using this protocol.
314 //
315 if (IfrPackageCount != 0) {
316 InstallDefaultConfigAccessProtocol (Packages, ThunkContext);
317 }
318 PackageListHeader = PrepareUefiPackageListFromFrameworkHiiPackages (Packages, &GuidId);
319 Status = mHiiDatabase->NewPackageList (
320 mHiiDatabase,
321 PackageListHeader,
322 ThunkContext->UefiHiiDriverHandle,
323 &ThunkContext->UefiHiiHandle
324 );
325
326 //
327 // BUGBUG: Remove when development is done
328 //
329 ASSERT_EFI_ERROR (Status);
330 if (EFI_ERROR (Status)) {
331 goto Done;
332 }
333
334 if (IfrPackageCount == 0) {
335 if (StringPackageCount != 0) {
336 //
337 // Look for a Package List with only IFR Package with the same GUID name.
338 // If found one, add the String Packages to it.
339 //
340 UpdatePackListWithOnlyIfrPack (
341 Private,
342 ThunkContext,
343 PackageListHeader
344 );
345 }
346 } else {
347 CreateQuestionIdMap (ThunkContext);
348
349 if (StringPackageCount == 0) {
350 //
351 // Register the Package List to UEFI HII first.
352 //
353 Status = FindStringPackAndUpdatePackListWithOnlyIfrPack (
354 Private,
355 ThunkContext
356 );
357
358 if (EFI_ERROR (Status)) {
359 goto Done;
360 }
361 }
362 }
363
364 Done:
365 if (EFI_ERROR (Status)) {
366 DestroyThunkContext (ThunkContext);
367 } else {
368 InsertTailList (&Private->ThunkContextListHead, &ThunkContext->Link);
369 *Handle = ThunkContext->FwHiiHandle;
370 }
371
372 SafeFreePool (PackageListHeader);
373
374 return Status;
375 }
376
377
378 EFI_STATUS
379 EFIAPI
380 HiiNewPack (
381 IN EFI_HII_PROTOCOL *This,
382 IN EFI_HII_PACKAGES *Packages,
383 OUT FRAMEWORK_EFI_HII_HANDLE *Handle
384 )
385 /*++
386
387 Routine Description:
388
389 Extracts the various packs from a package list.
390
391 Arguments:
392
393 This - Pointer of HII protocol.
394 Packages - Pointer of HII packages.
395 Handle - Handle value to be returned.
396
397 Returns:
398
399 EFI_SUCCESS - Pacakges has added to HII database successfully.
400 EFI_INVALID_PARAMETER - Invalid parameter.
401
402 --*/
403 {
404 EFI_STATUS Status;
405 HII_THUNK_PRIVATE_DATA *Private;
406 EFI_TPL OldTpl;
407
408 if (Handle == NULL) {
409 return EFI_INVALID_PARAMETER;
410 }
411
412 if (Packages == NULL) {
413 return EFI_INVALID_PARAMETER;
414 }
415
416 OldTpl = gBS->RaiseTPL (TPL_NOTIFY);
417
418 //
419 // We use a simple Global variable to inform NewPackNotify
420 // that the package list registered here is already registered
421 // in the HII Thunk Layer. So NewPackNotify does not need to
422 // call RegisterUefiHiiHandle () to registered it.
423 //
424 mInFrameworkHiiNewPack = TRUE;
425
426 Private = HII_THUNK_PRIVATE_DATA_FROM_THIS(This);
427
428 Status = UefiRegisterPackageList (
429 Private,
430 Packages,
431 Handle
432 );
433
434 mInFrameworkHiiNewPack = FALSE;
435
436 gBS->RestoreTPL (OldTpl);
437
438 return Status;
439 }
440
441 EFI_STATUS
442 EFIAPI
443 HiiRemovePack (
444 IN EFI_HII_PROTOCOL *This,
445 IN FRAMEWORK_EFI_HII_HANDLE Handle
446 )
447 /*++
448
449 Routine Description:
450 Removes the various packs from a Handle
451
452 Arguments:
453
454 Returns:
455
456 --*/
457 {
458 EFI_STATUS Status;
459 HII_THUNK_PRIVATE_DATA *Private;
460 HII_THUNK_CONTEXT *ThunkContext;
461 EFI_TPL OldTpl;
462
463 OldTpl = gBS->RaiseTPL (TPL_NOTIFY);
464
465 mInFrameworkHiiRemovePack = TRUE;
466
467 Private = HII_THUNK_PRIVATE_DATA_FROM_THIS(This);
468
469 ThunkContext = FwHiiHandleToThunkContext (Private, Handle);
470
471 if (ThunkContext != NULL) {
472 Status = mHiiDatabase->RemovePackageList (
473 mHiiDatabase,
474 ThunkContext->UefiHiiHandle
475 );
476 ASSERT_EFI_ERROR (Status);
477
478 if (ThunkContext->IfrPackageCount != 0) {
479 UninstallDefaultConfigAccessProtocol (ThunkContext);
480 }
481
482 RemoveEntryList (&ThunkContext->Link);
483 DestroyThunkContext (ThunkContext);
484 }else {
485 Status = EFI_NOT_FOUND;
486 }
487
488 mInFrameworkHiiRemovePack = FALSE;
489 gBS->RestoreTPL (OldTpl);
490
491 return Status;
492 }
493
494 EFI_STATUS
495 EFIAPI
496 NewOrAddPackNotify (
497 IN UINT8 PackageType,
498 IN CONST EFI_GUID *PackageGuid,
499 IN CONST EFI_HII_PACKAGE_HEADER *Package,
500 IN EFI_HII_HANDLE Handle,
501 IN EFI_HII_DATABASE_NOTIFY_TYPE NotifyType
502 )
503 {
504 EFI_STATUS Status;
505 HII_THUNK_PRIVATE_DATA *Private;
506 HII_THUNK_CONTEXT *ThunkContext;
507
508 ASSERT (PackageType == EFI_HII_PACKAGE_STRINGS || PackageType == EFI_HII_PACKAGE_FORM);
509 ASSERT (NotifyType == EFI_HII_DATABASE_NOTIFY_ADD_PACK || NotifyType == EFI_HII_DATABASE_NOTIFY_NEW_PACK);
510
511 Status = EFI_SUCCESS;
512 Private = mHiiThunkPrivateData;
513
514 if (mInFrameworkHiiNewPack || mInFrameworkUpdatePakcage) {
515 return EFI_SUCCESS;
516 }
517
518 //
519 // We only create a ThunkContext if the Uefi Hii Handle is only already registered
520 // by the HII Thunk Layer.
521 //
522 ThunkContext = UefiHiiHandleToThunkContext (Private, Handle);
523 if (ThunkContext == NULL) {
524 ThunkContext = CreateThunkContextForUefiHiiHandle (Handle);
525 ASSERT (ThunkContext != NULL);
526
527 InsertTailList (&Private->ThunkContextListHead, &ThunkContext->Link);
528 }
529
530 if (PackageType == EFI_HII_PACKAGE_FORM) {
531 GetAttributesOfFirstFormSet (ThunkContext);
532 }
533
534 return Status;
535 }
536
537 //
538 // Framework HII module may cache a GUID as the name of the package list.
539 // Then search for the Framework HII handle database for the handle matching
540 // this GUID
541
542 EFI_STATUS
543 EFIAPI
544 RemovePackNotify (
545 IN UINT8 PackageType,
546 IN CONST EFI_GUID *PackageGuid,
547 IN CONST EFI_HII_PACKAGE_HEADER *Package,
548 IN EFI_HII_HANDLE Handle,
549 IN EFI_HII_DATABASE_NOTIFY_TYPE NotifyType
550 )
551 {
552 EFI_STATUS Status;
553 HII_THUNK_PRIVATE_DATA *Private;
554 HII_THUNK_CONTEXT *ThunkContext;
555 EFI_HII_PACKAGE_LIST_HEADER *HiiPackageList;
556 UINTN BufferSize;
557
558 Status = EFI_SUCCESS;
559
560 ASSERT (PackageType == EFI_HII_PACKAGE_STRINGS);
561 ASSERT (NotifyType == EFI_HII_DATABASE_NOTIFY_REMOVE_PACK);
562
563 if (mInFrameworkHiiRemovePack || mInFrameworkUpdatePakcage) {
564 return EFI_SUCCESS;
565 }
566
567 Private = mHiiThunkPrivateData;
568
569 ThunkContext = UefiHiiHandleToThunkContext (Private, Handle);
570
571 if (!ThunkContext->ByFrameworkHiiNewPack) {
572 Status = HiiLibExportPackageLists (Handle, &HiiPackageList, &BufferSize);
573 ASSERT_EFI_ERROR (Status);
574
575 if (GetPackageCountByType (HiiPackageList, EFI_HII_PACKAGE_STRINGS) == 1) {
576 //
577 // If the string package will be removed is the last string package
578 // in the package list, we will remove the HII Thunk entry from the
579 // database.
580 //
581 DestroyThunkContextForUefiHiiHandle (Private, Handle);
582 }
583
584 FreePool (HiiPackageList);
585 }
586
587 return Status;
588 }
589
590
591