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