]> git.proxmox.com Git - mirror_edk2.git/blob - EdkCompatibilityPkg/Compatiblity/FrameworkHiiToUefiHiiThunk/Package.c
Add in FrameworkHiiToUefiHiiThunk module.
[mirror_edk2.git] / EdkCompatibilityPkg / Compatiblity / 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 = mUefiHiiDatabaseProtocol->ExportPackageLists (
90 mUefiHiiDatabaseProtocol,
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 = mUefiHiiDatabaseProtocol->ExportPackageLists (
104 mUefiHiiDatabaseProtocol,
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 = mUefiHiiDatabaseProtocol->UpdatePackageList (
144 mUefiHiiDatabaseProtocol,
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 PackageListLength += PackageLength;
219 }
220
221 //
222 // Include the lenght of EFI_HII_PACKAGE_END
223 //
224 PackageListLength += sizeof (EFI_HII_PACKAGE_HEADER);
225 PackageListHeader = AllocateZeroPool (PackageListLength);
226 ASSERT (PackageListHeader != NULL);
227 if (GuidId == NULL) {
228 CopyMem (&PackageListHeader->PackageListGuid, Packages->GuidId, sizeof (EFI_GUID));
229 } else {
230 CopyMem (&PackageListHeader->PackageListGuid, GuidId, sizeof (EFI_GUID));
231 }
232 PackageListHeader->PackageLength = PackageListLength;
233
234 PackageListData = ((UINT8 *) PackageListHeader) + sizeof (EFI_HII_PACKAGE_LIST_HEADER);
235
236 for (Index = 0; Index < NumberOfPackages; Index++) {
237 CopyMem (&PackageLength, &(TianoAutogenPackageHdrArray[Index]->BinaryLength), sizeof (UINT32));
238 PackageLength -= sizeof (UINT32);
239 CopyMem (PackageListData, &(TianoAutogenPackageHdrArray[Index]->PackageHeader), PackageLength);
240 PackageListData += PackageLength;
241 }
242
243 //
244 // Append EFI_HII_PACKAGE_END
245 //
246 PackageHeader.Type = EFI_HII_PACKAGE_END;
247 PackageHeader.Length = sizeof (EFI_HII_PACKAGE_HEADER);
248 CopyMem (PackageListData, &PackageHeader, PackageHeader.Length);
249
250 return PackageListHeader;
251 }
252
253 EFI_GUID *
254 UefiGeneratePackageListGuidId (
255 IN CONST EFI_HII_PACKAGES * Packages
256 )
257 {
258 EFI_GUID *Guid;
259 UINT64 MonotonicCount;
260
261 Guid = AllocateCopyPool (sizeof (EFI_GUID), Packages->GuidId);
262
263 gBS->GetNextMonotonicCount (&MonotonicCount);
264 //
265 // Use Monotonic Count as a psedo random number generator.
266 //
267 *((UINT64 *) Guid) = *((UINT64 *) Guid) + MonotonicCount;
268
269 return Guid;
270 }
271
272 EFI_STATUS
273 FindAndAddStringPackageToIfrPackageList(
274 EFI_HII_THUNK_PRIVATE_DATA *Private,
275 EFI_GUID *GuidId,
276 EFI_HII_HANDLE UefiIfrHiiHandle
277 )
278 {
279 EFI_STATUS Status;
280 LIST_ENTRY *ListEntry;
281 HII_TRHUNK_HANDLE_MAPPING_DATABASE_ENTRY *HandleMapEntry;
282 EFI_HII_PACKAGE_LIST_HEADER *StringPackageListHeader;
283 UINTN Size;
284
285 for (ListEntry = Private->HiiThunkHandleMappingDBListHead.ForwardLink;
286 ListEntry != &Private->HiiThunkHandleMappingDBListHead;
287 ListEntry = ListEntry->ForwardLink
288 ) {
289 HandleMapEntry = HII_TRHUNK_HANDLE_MAPPING_DATABASE_ENTRY_FROM_LISTENTRY (ListEntry);
290 if (CompareGuid (GuidId, &HandleMapEntry->TagGuid) && (!HandleMapEntry->DoesPackageListImportStringPackages)) {
291 Status = LibExportPackageLists (HandleMapEntry->UefiHiiHandle, &StringPackageListHeader, &Size);
292 ASSERT_EFI_ERROR (Status);
293
294 //
295 // Add Function to only get only String Packages from the Package List
296 //
297
298 Status = InsertStringPackagesToIfrPackageList (StringPackageListHeader, UefiIfrHiiHandle);
299 ASSERT_EFI_ERROR (Status);
300
301 FreePool (StringPackageListHeader);
302 return EFI_SUCCESS;
303 }
304 }
305
306 return EFI_NOT_FOUND;
307
308 }
309
310 EFI_STATUS
311 InstallDefaultUefiConfigAccessProtocol (
312 IN EFI_HII_PACKAGES *Packages,
313 OUT EFI_HANDLE *Handle
314 )
315 {
316 return EFI_SUCCESS;
317 }
318
319 EFI_STATUS
320 UefiRegisterPackageList(
321 EFI_HII_THUNK_PRIVATE_DATA *Private,
322 EFI_HII_PACKAGES *Packages,
323 FRAMEWORK_EFI_HII_HANDLE *Handle
324 )
325 {
326 EFI_STATUS Status;
327 UINTN StringPackNum;
328 UINTN IfrPackNum;
329 EFI_HII_PACKAGE_LIST_HEADER *UefiPackageListHeader;
330 HII_TRHUNK_HANDLE_MAPPING_DATABASE_ENTRY *HandleMappingEntry;
331 EFI_GUID *GuidId;
332 EFI_HANDLE UefiHiiDriverHandle;
333
334 GuidId = NULL;
335 UefiHiiDriverHandle = NULL;
336
337 Status = GetIfrAndStringPackNum (Packages, &IfrPackNum, &StringPackNum);
338 ASSERT_EFI_ERROR (Status);
339
340 HandleMappingEntry = AllocateZeroPool (sizeof (*HandleMappingEntry));
341 ASSERT (HandleMappingEntry != NULL);
342
343 HandleMappingEntry->Signature = HII_TRHUNK_HANDLE_MAPPING_DATABASE_ENTRY_SIGNATURE;
344 HandleMappingEntry->FrameworkHiiHandle = Private->StaticHiiHandle++;
345 CopyGuid (&HandleMappingEntry->TagGuid, Packages->GuidId);
346
347 if ((StringPackNum == 0) && (IfrPackNum != 0)) {
348 //
349 // UEFI HII database does not allow two package list with the same GUID.
350 // In Framework HII implementation, Packages->GuidId is used as an identifier to associate
351 // a PackageList with only IFR to a Package list the with String package.
352 //
353 GuidId = UefiGeneratePackageListGuidId (Packages);
354 }
355
356 //
357 // UEFI HII require EFI_HII_CONFIG_ACCESS_PROTOCOL to be installed on a EFI_HANDLE, so
358 // that Setup Utility will load the Buffer Storage
359 //
360 if (IfrPackNum != 0) {
361 InstallDefaultUefiConfigAccessProtocol (Packages, &UefiHiiDriverHandle);
362 }
363 UefiPackageListHeader = PrepareUefiPackageListFromFrameworkHiiPackages (Packages, GuidId);
364 Status = mUefiHiiDatabaseProtocol->NewPackageList (
365 mUefiHiiDatabaseProtocol,
366 UefiPackageListHeader,
367 UefiHiiDriverHandle,
368 &HandleMappingEntry->UefiHiiHandle
369 );
370 ASSERT_EFI_ERROR (Status);
371 if (EFI_ERROR (Status)) {
372 goto Done;
373 }
374
375 if (IfrPackNum == 0) {
376 if (StringPackNum != 0) {
377 //
378 // Look for a package list with IFR Pack which has already registed with HII Database
379 //
380 HandleMappingEntry->IsPackageListWithOnlyStringPackages = TRUE;
381 Status = AddStringPackagesToMatchingIfrPackageList (
382 Private,
383 UefiPackageListHeader
384 );
385
386 if (!EFI_ERROR (Status) || Status == EFI_NOT_FOUND) {
387
388 if (Status == EFI_NOT_FOUND) {
389 Status = EFI_SUCCESS;
390 }
391 }
392 }
393 } else {
394 if (StringPackNum == 0) {
395 //
396 // Register the Package List to UEFI HII first.
397 //
398 Status = FindAndAddStringPackageToIfrPackageList (
399 Private,
400 Packages->GuidId,
401 HandleMappingEntry->UefiHiiHandle
402 );
403 ASSERT_EFI_ERROR (Status);
404 if (!EFI_ERROR (Status)) {
405 HandleMappingEntry->DoesPackageListImportStringPackages = TRUE;
406 }
407 }
408 }
409
410 if (!EFI_ERROR (Status)) {
411 InsertTailList (&Private->HiiThunkHandleMappingDBListHead, &HandleMappingEntry->List);
412 }
413
414 Done:
415 if (EFI_ERROR (Status)) {
416 FreePool (HandleMappingEntry);
417 } else {
418 *Handle = HandleMappingEntry->FrameworkHiiHandle;
419 }
420
421 FreePool (UefiPackageListHeader);
422 SafeFreePool (GuidId);
423
424 return Status;
425 }
426
427 EFI_STATUS
428 EFIAPI
429 HiiNewPack (
430 IN EFI_HII_PROTOCOL *This,
431 IN EFI_HII_PACKAGES *Packages,
432 OUT FRAMEWORK_EFI_HII_HANDLE *Handle
433 )
434 /*++
435
436 Routine Description:
437
438 Extracts the various packs from a package list.
439
440 Arguments:
441
442 This - Pointer of HII protocol.
443 Packages - Pointer of HII packages.
444 Handle - Handle value to be returned.
445
446 Returns:
447
448 EFI_SUCCESS - Pacakges has added to HII database successfully.
449 EFI_INVALID_PARAMETER - Invalid parameter.
450
451 --*/
452 {
453 EFI_STATUS Status;
454 EFI_HII_THUNK_PRIVATE_DATA *Private;
455
456 if (Handle == NULL) {
457 return EFI_INVALID_PARAMETER;
458 }
459
460 if (Packages == NULL) {
461 return EFI_INVALID_PARAMETER;
462 }
463
464 Private = EFI_HII_THUNK_PRIVATE_DATA_FROM_THIS(This);
465
466 Status = UefiRegisterPackageList (
467 Private,
468 Packages,
469 Handle
470 );
471
472 return Status;
473 }
474
475 EFI_STATUS
476 EFIAPI
477 HiiRemovePack (
478 IN EFI_HII_PROTOCOL *This,
479 IN FRAMEWORK_EFI_HII_HANDLE Handle
480 )
481 /*++
482
483 Routine Description:
484 Removes the various packs from a Handle
485
486 Arguments:
487
488 Returns:
489
490 --*/
491 {
492 EFI_STATUS Status;
493 EFI_HII_THUNK_PRIVATE_DATA *Private;
494 LIST_ENTRY *ListEntry;
495 HII_TRHUNK_HANDLE_MAPPING_DATABASE_ENTRY *HandleMapEntry;
496
497 Private = EFI_HII_THUNK_PRIVATE_DATA_FROM_THIS(This);
498
499 for (ListEntry = Private->HiiThunkHandleMappingDBListHead.ForwardLink;
500 ListEntry != &Private->HiiThunkHandleMappingDBListHead;
501 ListEntry = ListEntry->ForwardLink
502 ) {
503 HandleMapEntry = HII_TRHUNK_HANDLE_MAPPING_DATABASE_ENTRY_FROM_LISTENTRY (ListEntry);
504
505 if (Handle == HandleMapEntry->FrameworkHiiHandle) {
506 Status = mUefiHiiDatabaseProtocol->RemovePackageList (
507 mUefiHiiDatabaseProtocol,
508 HandleMapEntry->UefiHiiHandle
509 );
510 ASSERT_EFI_ERROR (Status);
511
512 RemoveEntryList (ListEntry);
513 return Status;
514 }
515 }
516
517 return EFI_NOT_FOUND;
518 }