]> git.proxmox.com Git - mirror_edk2.git/blob - EdkCompatibilityPkg/Compatibility/FrameworkHiiToUefiHiiThunk/Package.c
Add support to map more Framework Opcode (such as OrderedList, OneOf, etc) to Uefi...
[mirror_edk2.git] / EdkCompatibilityPkg / Compatibility / FrameworkHiiToUefiHiiThunk / Package.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
20 EFI_STATUS
21 GetIfrAndStringPackNum (
22 IN CONST EFI_HII_PACKAGES *Packages,
23 UINTN *IfrPackNum,
24 UINTN *StringPackNum
25 )
26 {
27 UINTN Index;
28 TIANO_AUTOGEN_PACKAGES_HEADER **TianoAutogenPackageHdrArray;
29
30 ASSERT (Packages != NULL);
31 ASSERT (IfrPackNum != NULL);
32 ASSERT (StringPackNum != NULL);
33
34 *IfrPackNum = 0;
35 *StringPackNum = 0;
36
37 TianoAutogenPackageHdrArray = (TIANO_AUTOGEN_PACKAGES_HEADER **) (((UINT8 *) &Packages->GuidId) + sizeof (Packages->GuidId));
38 for (Index = 0; Index < Packages->NumberOfPackages; Index++) {
39 //
40 // BugBug: The current UEFI HII build tool generate a binary in the format defined in:
41 // TIANO_AUTOGEN_PACKAGES_HEADER. We assume that all packages generated in
42 // this binary is with same package type. So the returned IfrPackNum and StringPackNum
43 // may not be the exact number of valid package number in the binary generated
44 // by HII Build tool.
45 //
46 switch (TianoAutogenPackageHdrArray[Index]->PackageHeader.Type) {
47 case EFI_HII_PACKAGE_FORM:
48 *IfrPackNum += 1;
49 break;
50 case EFI_HII_PACKAGE_STRINGS:
51 *StringPackNum += 1;
52 break;
53
54 case EFI_HII_PACKAGE_SIMPLE_FONTS:
55 break;
56
57 //
58 // The following fonts are invalid for a module that using Framework to UEFI thunk layer.
59 //
60 case EFI_HII_PACKAGE_KEYBOARD_LAYOUT:
61 case EFI_HII_PACKAGE_FONTS:
62 case EFI_HII_PACKAGE_IMAGES:
63 default:
64 ASSERT (FALSE);
65 return EFI_INVALID_PARAMETER;
66 break;
67 }
68 }
69
70 return EFI_SUCCESS;
71 }
72
73 EFI_STATUS
74 LibExportPackageLists (
75 IN EFI_HII_HANDLE UefiHiiHandle,
76 OUT EFI_HII_PACKAGE_LIST_HEADER **PackageListHeader,
77 OUT UINTN *PackageListSize
78 )
79 {
80 EFI_STATUS Status;
81 UINTN Size;
82 EFI_HII_PACKAGE_LIST_HEADER *PackageListHdr;
83
84 ASSERT (PackageListSize != NULL);
85 ASSERT (PackageListHeader != NULL);
86
87 Size = 0;
88 PackageListHdr = NULL;
89 Status = mHiiDatabase->ExportPackageLists (
90 mHiiDatabase,
91 UefiHiiHandle,
92 &Size,
93 PackageListHdr
94 );
95 ASSERT_EFI_ERROR (Status == EFI_BUFFER_TOO_SMALL);
96 if (Status == EFI_BUFFER_TOO_SMALL) {
97 PackageListHdr = AllocateZeroPool (Size);
98 ASSERT (PackageListHdr != NULL);
99
100 if (PackageListHeader == NULL) {
101 return EFI_OUT_OF_RESOURCES;
102 } else {
103 Status = mHiiDatabase->ExportPackageLists (
104 mHiiDatabase,
105 UefiHiiHandle,
106 &Size,
107 PackageListHdr
108 );
109 ASSERT_EFI_ERROR (Status);
110 }
111 }
112
113 if (!EFI_ERROR (Status)) {
114 *PackageListHeader = PackageListHdr;
115 *PackageListSize = Size;
116 }
117
118 return Status;
119 }
120
121 BOOLEAN
122 IsOnlyStringPackagesInPackageList (
123 IN CONST EFI_HII_PACKAGE_LIST_HEADER *StringPackageListHeader
124 )
125 {
126 EFI_HII_PACKAGE_HEADER *PackageHeader;
127
128 PackageHeader = (EFI_HII_PACKAGE_HEADER *) (StringPackageListHeader + 1);
129
130 while (PackageHeader->Type != EFI_HII_PACKAGE_END) {
131 PackageHeader = (EFI_HII_PACKAGE_HEADER *) (PackageHeader );
132 }
133 }
134
135
136 EFI_STATUS
137 InsertStringPackagesToIfrPackageList (
138 IN CONST EFI_HII_PACKAGE_LIST_HEADER *StringPackageListHeader,
139 IN EFI_HII_HANDLE UefiHiiHandle
140 )
141 {
142 EFI_STATUS Status;
143 Status = mHiiDatabase->UpdatePackageList (
144 mHiiDatabase,
145 UefiHiiHandle,
146 StringPackageListHeader
147 );
148
149 return Status;
150 }
151
152
153 /**
154 Removes a node from a doubly linked list, and returns the node that follows
155 the removed node.
156
157 Removes the node Entry from a doubly linked list. It is up to the caller of
158 this function to release the memory used by this node if that is required. On
159 exit, the node following Entry in the doubly linked list is returned. If
160 Entry is the only node in the linked list, then the head node of the linked
161 list is returned.
162
163 If Entry is NULL, then ASSERT().
164 If Entry is the head node of an empty list, then ASSERT().
165 If PcdMaximumLinkedListLength is not zero, and the number of nodes in the
166 linked list containing Entry, including the Entry node, is greater than
167 or equal to PcdMaximumLinkedListLength, then ASSERT().
168
169 @param Entry A pointer to a node in a linked list
170
171 @return Entry
172
173 **/
174 EFI_STATUS
175 AddStringPackagesToMatchingIfrPackageList (
176 IN EFI_HII_THUNK_PRIVATE_DATA *Private,
177 IN CONST EFI_HII_PACKAGE_LIST_HEADER *StringPackageListHeader
178 )
179 {
180 EFI_STATUS Status;
181 LIST_ENTRY *ListEntry;
182 HII_TRHUNK_HANDLE_MAPPING_DATABASE_ENTRY *HandleMapEntry;
183
184 for (ListEntry = Private->HiiThunkHandleMappingDBListHead.ForwardLink;
185 ListEntry != &Private->HiiThunkHandleMappingDBListHead;
186 ListEntry = ListEntry->ForwardLink
187 ) {
188 HandleMapEntry = HII_TRHUNK_HANDLE_MAPPING_DATABASE_ENTRY_FROM_LISTENTRY (ListEntry);
189 if (CompareGuid (&StringPackageListHeader->PackageListGuid, &HandleMapEntry->TagGuid)) {
190 Status = InsertStringPackagesToIfrPackageList (StringPackageListHeader, HandleMapEntry->UefiHiiHandle);
191 }
192 }
193
194 return EFI_NOT_FOUND;
195 }
196 EFI_HII_PACKAGE_LIST_HEADER *
197 PrepareUefiPackageListFromFrameworkHiiPackages (
198 IN CONST EFI_HII_PACKAGES *Packages,
199 IN CONST EFI_GUID *GuidId OPTIONAL
200 )
201 {
202 UINTN NumberOfPackages;
203 EFI_HII_PACKAGE_LIST_HEADER *PackageListHeader;
204 UINT8 *PackageListData;
205 UINT32 PackageListLength;
206 UINT32 PackageLength;
207 EFI_HII_PACKAGE_HEADER PackageHeader;
208 UINTN Index;
209 TIANO_AUTOGEN_PACKAGES_HEADER **TianoAutogenPackageHdrArray;
210
211 TianoAutogenPackageHdrArray = (TIANO_AUTOGEN_PACKAGES_HEADER **) ((UINT8 *) &Packages->GuidId + sizeof (Packages->GuidId));
212 NumberOfPackages = Packages->NumberOfPackages;
213
214 PackageListLength = sizeof (EFI_HII_PACKAGE_LIST_HEADER);
215
216 for (Index = 0; Index < NumberOfPackages; Index++) {
217 CopyMem (&PackageLength, &TianoAutogenPackageHdrArray[Index]->BinaryLength, sizeof (UINT32));
218 //
219 //TIANO_AUTOGEN_PACKAGES_HEADER.BinaryLength include the BinaryLength itself.
220 //
221 PackageListLength += (PackageLength - sizeof(UINT32));
222 }
223
224 //
225 // Include the lenght of EFI_HII_PACKAGE_END
226 //
227 PackageListLength += sizeof (EFI_HII_PACKAGE_HEADER);
228 PackageListHeader = AllocateZeroPool (PackageListLength);
229 ASSERT (PackageListHeader != NULL);
230 if (GuidId == NULL) {
231 CopyMem (&PackageListHeader->PackageListGuid, Packages->GuidId, sizeof (EFI_GUID));
232 } else {
233 CopyMem (&PackageListHeader->PackageListGuid, GuidId, sizeof (EFI_GUID));
234 }
235 PackageListHeader->PackageLength = PackageListLength;
236
237 PackageListData = ((UINT8 *) PackageListHeader) + sizeof (EFI_HII_PACKAGE_LIST_HEADER);
238
239 for (Index = 0; Index < NumberOfPackages; Index++) {
240 CopyMem (&PackageLength, &(TianoAutogenPackageHdrArray[Index]->BinaryLength), sizeof (UINT32));
241 PackageLength -= sizeof (UINT32);
242 CopyMem (PackageListData, &(TianoAutogenPackageHdrArray[Index]->PackageHeader), PackageLength);
243 PackageListData += PackageLength;
244 }
245
246 //
247 // Append EFI_HII_PACKAGE_END
248 //
249 PackageHeader.Type = EFI_HII_PACKAGE_END;
250 PackageHeader.Length = sizeof (EFI_HII_PACKAGE_HEADER);
251 CopyMem (PackageListData, &PackageHeader, PackageHeader.Length);
252
253 return PackageListHeader;
254 }
255
256 VOID
257 GenerateGuidId (
258 IN CONST EFI_GUID * InGuid,
259 OUT EFI_GUID * OutGuid
260 )
261 {
262 UINT64 MonotonicCount;
263
264 CopyMem (OutGuid, InGuid, sizeof (EFI_GUID));
265
266 gBS->GetNextMonotonicCount (&MonotonicCount);
267 //
268 // Use Monotonic Count as a psedo random number generator.
269 //
270 *((UINT64 *) OutGuid) = *((UINT64 *) OutGuid) + MonotonicCount;
271 }
272
273 EFI_STATUS
274 FindAndAddStringPackageToIfrPackageList(
275 EFI_HII_THUNK_PRIVATE_DATA *Private,
276 EFI_GUID *GuidId,
277 EFI_HII_HANDLE UefiIfrHiiHandle
278 )
279 {
280 EFI_STATUS Status;
281 LIST_ENTRY *ListEntry;
282 HII_TRHUNK_HANDLE_MAPPING_DATABASE_ENTRY *HandleMapEntry;
283 EFI_HII_PACKAGE_LIST_HEADER *StringPackageListHeader;
284 UINTN Size;
285
286 for (ListEntry = Private->HiiThunkHandleMappingDBListHead.ForwardLink;
287 ListEntry != &Private->HiiThunkHandleMappingDBListHead;
288 ListEntry = ListEntry->ForwardLink
289 ) {
290 HandleMapEntry = HII_TRHUNK_HANDLE_MAPPING_DATABASE_ENTRY_FROM_LISTENTRY (ListEntry);
291 if (CompareGuid (GuidId, &HandleMapEntry->TagGuid) && (!HandleMapEntry->DoesPackageListImportStringPackages)) {
292 Status = LibExportPackageLists (HandleMapEntry->UefiHiiHandle, &StringPackageListHeader, &Size);
293 ASSERT_EFI_ERROR (Status);
294
295 //
296 // Add Function to only get only String Packages from the Package List
297 //
298
299 Status = InsertStringPackagesToIfrPackageList (StringPackageListHeader, UefiIfrHiiHandle);
300 ASSERT_EFI_ERROR (Status);
301
302 FreePool (StringPackageListHeader);
303 return EFI_SUCCESS;
304 }
305 }
306
307 return EFI_NOT_FOUND;
308
309 }
310
311 CONST EFI_GUID mAGuid =
312 { 0x14f95e01, 0xd562, 0x432e, { 0x84, 0x4a, 0x95, 0xa4, 0x39, 0x5, 0x10, 0x7e } };
313
314 EFI_STATUS
315 UefiRegisterPackageList(
316 EFI_HII_THUNK_PRIVATE_DATA *Private,
317 EFI_HII_PACKAGES *Packages,
318 FRAMEWORK_EFI_HII_HANDLE *Handle
319 )
320 {
321 EFI_STATUS Status;
322 UINTN StringPackNum;
323 UINTN IfrPackNum;
324 EFI_HII_PACKAGE_LIST_HEADER *UefiPackageListHeader;
325 HII_TRHUNK_HANDLE_MAPPING_DATABASE_ENTRY *HandleMappingEntry;
326 EFI_GUID GuidId;
327 EFI_HANDLE UefiHiiDriverHandle;
328
329 UefiHiiDriverHandle = NULL;
330
331 Status = GetIfrAndStringPackNum (Packages, &IfrPackNum, &StringPackNum);
332 ASSERT_EFI_ERROR (Status);
333 //
334 // Thunk Layer only handle the following combinations of IfrPack, StringPkg and FontPack.
335 // Thunk Layer only allow zero or one IfrPack in the Package List.
336 //
337 if (IfrPackNum > 1) {
338 return EFI_UNSUPPORTED;
339 }
340
341 HandleMappingEntry = AllocateZeroPool (sizeof (*HandleMappingEntry));
342 ASSERT (HandleMappingEntry != NULL);
343
344 HandleMappingEntry->Signature = HII_TRHUNK_HANDLE_MAPPING_DATABASE_ENTRY_SIGNATURE;
345 HandleMappingEntry->FrameworkHiiHandle = Private->StaticHiiHandle++;
346
347 //
348 // Packages->GuidId may be NULL. In such case, caller of FramworkHii->NewPack is registering
349 // package with StringPack and IfrPack.
350 //
351 if (Packages->GuidId == NULL) {
352 Packages->GuidId = &GuidId;
353 GenerateGuidId (&mAGuid, Packages->GuidId);
354 }
355
356 CopyGuid (&HandleMappingEntry->TagGuid, Packages->GuidId);
357
358 if ((StringPackNum == 0) && (IfrPackNum != 0)) {
359 //
360 // UEFI HII database does not allow two package list with the same GUID.
361 // In Framework HII implementation, Packages->GuidId is used as an identifier to associate
362 // a PackageList with only IFR to a Package list the with String package.
363 //
364 GenerateGuidId (Packages->GuidId, &GuidId);
365 }
366
367 //
368 // UEFI HII require EFI_HII_CONFIG_ACCESS_PROTOCOL to be installed on a EFI_HANDLE, so
369 // that Setup Utility can load the Buffer Storage using this protocol.
370 //
371 if (IfrPackNum != 0) {
372 InstallDefaultUefiConfigAccessProtocol (Packages, &UefiHiiDriverHandle, HandleMappingEntry);
373 }
374 UefiPackageListHeader = PrepareUefiPackageListFromFrameworkHiiPackages (Packages, &GuidId);
375 Status = mHiiDatabase->NewPackageList (
376 mHiiDatabase,
377 UefiPackageListHeader,
378 UefiHiiDriverHandle,
379 &HandleMappingEntry->UefiHiiHandle
380 );
381 ASSERT_EFI_ERROR (Status);
382 if (EFI_ERROR (Status)) {
383 goto Done;
384 }
385
386 if (IfrPackNum == 0) {
387 if (StringPackNum != 0) {
388 //
389 // Look for a package list with IFR Pack which has already registed with HII Database
390 //
391 HandleMappingEntry->IsPackageListWithOnlyStringPackages = TRUE;
392 Status = AddStringPackagesToMatchingIfrPackageList (
393 Private,
394 UefiPackageListHeader
395 );
396
397 if (!EFI_ERROR (Status) || Status == EFI_NOT_FOUND) {
398
399 if (Status == EFI_NOT_FOUND) {
400 Status = EFI_SUCCESS;
401 }
402 }
403 }
404 } else {
405 if (StringPackNum == 0) {
406 //
407 // Register the Package List to UEFI HII first.
408 //
409 Status = FindAndAddStringPackageToIfrPackageList (
410 Private,
411 Packages->GuidId,
412 HandleMappingEntry->UefiHiiHandle
413 );
414 ASSERT_EFI_ERROR (Status);
415 if (!EFI_ERROR (Status)) {
416 HandleMappingEntry->DoesPackageListImportStringPackages = TRUE;
417 }
418 }
419 }
420
421 if (!EFI_ERROR (Status)) {
422 InsertTailList (&Private->HiiThunkHandleMappingDBListHead, &HandleMappingEntry->List);
423 }
424
425 Done:
426 if (EFI_ERROR (Status)) {
427 FreePool (HandleMappingEntry);
428 } else {
429 *Handle = HandleMappingEntry->FrameworkHiiHandle;
430 }
431
432 FreePool (UefiPackageListHeader);
433
434 return Status;
435 }
436
437 EFI_STATUS
438 EFIAPI
439 HiiNewPack (
440 IN EFI_HII_PROTOCOL *This,
441 IN EFI_HII_PACKAGES *Packages,
442 OUT FRAMEWORK_EFI_HII_HANDLE *Handle
443 )
444 /*++
445
446 Routine Description:
447
448 Extracts the various packs from a package list.
449
450 Arguments:
451
452 This - Pointer of HII protocol.
453 Packages - Pointer of HII packages.
454 Handle - Handle value to be returned.
455
456 Returns:
457
458 EFI_SUCCESS - Pacakges has added to HII database successfully.
459 EFI_INVALID_PARAMETER - Invalid parameter.
460
461 --*/
462 {
463 EFI_STATUS Status;
464 EFI_HII_THUNK_PRIVATE_DATA *Private;
465
466 if (Handle == NULL) {
467 return EFI_INVALID_PARAMETER;
468 }
469
470 if (Packages == NULL) {
471 return EFI_INVALID_PARAMETER;
472 }
473
474 Private = EFI_HII_THUNK_PRIVATE_DATA_FROM_THIS(This);
475
476 Status = UefiRegisterPackageList (
477 Private,
478 Packages,
479 Handle
480 );
481
482 return Status;
483 }
484
485 EFI_STATUS
486 EFIAPI
487 HiiRemovePack (
488 IN EFI_HII_PROTOCOL *This,
489 IN FRAMEWORK_EFI_HII_HANDLE Handle
490 )
491 /*++
492
493 Routine Description:
494 Removes the various packs from a Handle
495
496 Arguments:
497
498 Returns:
499
500 --*/
501 {
502 EFI_STATUS Status;
503 EFI_HII_THUNK_PRIVATE_DATA *Private;
504 HII_TRHUNK_HANDLE_MAPPING_DATABASE_ENTRY *HandleMapEntry;
505 EFI_DEVICE_PATH_PROTOCOL *Path;
506
507 Private = EFI_HII_THUNK_PRIVATE_DATA_FROM_THIS(This);
508
509 HandleMapEntry = FrameworkHiiHandleToMapDatabaseEntry (Private, Handle);
510
511 if (HandleMapEntry->UefiHiiHandle != NULL) {
512 Status = mHiiDatabase->RemovePackageList (
513 mHiiDatabase,
514 HandleMapEntry->UefiHiiHandle
515 );
516 ASSERT_EFI_ERROR (Status);
517
518 Status = gBS->HandleProtocol (
519 HandleMapEntry->UefiHiiHandle,
520 &gEfiDevicePathProtocolGuid,
521 &Path
522 );
523
524 if (!EFI_ERROR (Status)) {
525 Status = gBS->UninstallProtocolInterface (
526 HandleMapEntry->UefiHiiHandle,
527 &gEfiDevicePathProtocolGuid,
528 Path
529 );
530 if (!EFI_ERROR (Status)) {
531 FreePool (Path);
532 }
533 }
534
535 RemoveEntryList (&HandleMapEntry->List);
536
537 FreePool (HandleMapEntry);
538 return Status;
539 }
540
541 return EFI_NOT_FOUND;
542 }