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