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