]> git.proxmox.com Git - mirror_edk2.git/blame - EdkCompatibilityPkg/Compatibility/FrameworkHiiToUefiHiiThunk/Package.c
Fixed a NULL library instance issue
[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
310EFI_STATUS\r
311InstallDefaultUefiConfigAccessProtocol (\r
312 IN EFI_HII_PACKAGES *Packages,\r
313 OUT EFI_HANDLE *Handle\r
314 )\r
315{\r
316 return EFI_SUCCESS;\r
317}\r
318\r
319EFI_STATUS\r
320UefiRegisterPackageList(\r
321 EFI_HII_THUNK_PRIVATE_DATA *Private,\r
322 EFI_HII_PACKAGES *Packages,\r
323 FRAMEWORK_EFI_HII_HANDLE *Handle\r
324 )\r
325{\r
326 EFI_STATUS Status;\r
327 UINTN StringPackNum;\r
328 UINTN IfrPackNum;\r
329 EFI_HII_PACKAGE_LIST_HEADER *UefiPackageListHeader;\r
330 HII_TRHUNK_HANDLE_MAPPING_DATABASE_ENTRY *HandleMappingEntry;\r
331 EFI_GUID *GuidId;\r
332 EFI_HANDLE UefiHiiDriverHandle;\r
333\r
334 GuidId = NULL;\r
335 UefiHiiDriverHandle = NULL;\r
336\r
337 Status = GetIfrAndStringPackNum (Packages, &IfrPackNum, &StringPackNum);\r
338 ASSERT_EFI_ERROR (Status);\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 CopyGuid (&HandleMappingEntry->TagGuid, Packages->GuidId);\r
346\r
347 if ((StringPackNum == 0) && (IfrPackNum != 0)) {\r
348 //\r
349 // UEFI HII database does not allow two package list with the same GUID.\r
350 // In Framework HII implementation, Packages->GuidId is used as an identifier to associate \r
351 // a PackageList with only IFR to a Package list the with String package.\r
352 //\r
353 GuidId = UefiGeneratePackageListGuidId (Packages);\r
354 }\r
355\r
356 //\r
357 // UEFI HII require EFI_HII_CONFIG_ACCESS_PROTOCOL to be installed on a EFI_HANDLE, so\r
358 // that Setup Utility will load the Buffer Storage\r
359 //\r
360 if (IfrPackNum != 0) {\r
361 InstallDefaultUefiConfigAccessProtocol (Packages, &UefiHiiDriverHandle);\r
362 }\r
363 UefiPackageListHeader = PrepareUefiPackageListFromFrameworkHiiPackages (Packages, GuidId);\r
364 Status = mUefiHiiDatabaseProtocol->NewPackageList (\r
365 mUefiHiiDatabaseProtocol,\r
366 UefiPackageListHeader, \r
367 UefiHiiDriverHandle,\r
368 &HandleMappingEntry->UefiHiiHandle\r
369 );\r
370 ASSERT_EFI_ERROR (Status);\r
371 if (EFI_ERROR (Status)) {\r
372 goto Done;\r
373 }\r
374 \r
375 if (IfrPackNum == 0) {\r
376 if (StringPackNum != 0) {\r
377 //\r
378 // Look for a package list with IFR Pack which has already registed with HII Database\r
379 //\r
380 HandleMappingEntry->IsPackageListWithOnlyStringPackages = TRUE;\r
381 Status = AddStringPackagesToMatchingIfrPackageList (\r
382 Private,\r
383 UefiPackageListHeader\r
384 );\r
385\r
386 if (!EFI_ERROR (Status) || Status == EFI_NOT_FOUND) {\r
387\r
388 if (Status == EFI_NOT_FOUND) {\r
389 Status = EFI_SUCCESS;\r
390 }\r
391 }\r
392 }\r
393 } else {\r
394 if (StringPackNum == 0) {\r
395 //\r
396 // Register the Package List to UEFI HII first.\r
397 //\r
398 Status = FindAndAddStringPackageToIfrPackageList (\r
399 Private,\r
400 Packages->GuidId,\r
401 HandleMappingEntry->UefiHiiHandle\r
402 );\r
403 ASSERT_EFI_ERROR (Status);\r
404 if (!EFI_ERROR (Status)) {\r
405 HandleMappingEntry->DoesPackageListImportStringPackages = TRUE;\r
406 }\r
407 }\r
408 }\r
409\r
410 if (!EFI_ERROR (Status)) {\r
411 InsertTailList (&Private->HiiThunkHandleMappingDBListHead, &HandleMappingEntry->List);\r
412 }\r
413\r
414Done:\r
415 if (EFI_ERROR (Status)) {\r
416 FreePool (HandleMappingEntry);\r
417 } else {\r
418 *Handle = HandleMappingEntry->FrameworkHiiHandle;\r
419 }\r
420\r
421 FreePool (UefiPackageListHeader);\r
422 SafeFreePool (GuidId);\r
423 \r
424 return Status;\r
425}\r
426\r
427EFI_STATUS\r
428EFIAPI\r
429HiiNewPack (\r
430 IN EFI_HII_PROTOCOL *This,\r
431 IN EFI_HII_PACKAGES *Packages,\r
432 OUT FRAMEWORK_EFI_HII_HANDLE *Handle\r
433 )\r
434/*++\r
435\r
436Routine Description:\r
437\r
438 Extracts the various packs from a package list.\r
439\r
440Arguments:\r
441\r
442 This - Pointer of HII protocol.\r
443 Packages - Pointer of HII packages.\r
444 Handle - Handle value to be returned.\r
445\r
446Returns:\r
447\r
448 EFI_SUCCESS - Pacakges has added to HII database successfully.\r
449 EFI_INVALID_PARAMETER - Invalid parameter.\r
450\r
451--*/\r
452{\r
453 EFI_STATUS Status;\r
454 EFI_HII_THUNK_PRIVATE_DATA *Private;\r
455\r
456 if (Handle == NULL) {\r
457 return EFI_INVALID_PARAMETER;\r
458 }\r
459\r
460 if (Packages == NULL) {\r
461 return EFI_INVALID_PARAMETER;\r
462 }\r
463\r
464 Private = EFI_HII_THUNK_PRIVATE_DATA_FROM_THIS(This);\r
465\r
466 Status = UefiRegisterPackageList (\r
467 Private,\r
468 Packages,\r
469 Handle\r
470 );\r
471\r
472 return Status;\r
473}\r
474\r
475EFI_STATUS\r
476EFIAPI\r
477HiiRemovePack (\r
478 IN EFI_HII_PROTOCOL *This,\r
479 IN FRAMEWORK_EFI_HII_HANDLE Handle\r
480 )\r
481/*++\r
482\r
483Routine Description:\r
484 Removes the various packs from a Handle\r
485\r
486Arguments:\r
487\r
488Returns:\r
489\r
490--*/\r
491{\r
492 EFI_STATUS Status;\r
493 EFI_HII_THUNK_PRIVATE_DATA *Private;\r
494 LIST_ENTRY *ListEntry;\r
495 HII_TRHUNK_HANDLE_MAPPING_DATABASE_ENTRY *HandleMapEntry;\r
496\r
497 Private = EFI_HII_THUNK_PRIVATE_DATA_FROM_THIS(This);\r
498\r
499 for (ListEntry = Private->HiiThunkHandleMappingDBListHead.ForwardLink;\r
500 ListEntry != &Private->HiiThunkHandleMappingDBListHead;\r
501 ListEntry = ListEntry->ForwardLink\r
502 ) {\r
503 HandleMapEntry = HII_TRHUNK_HANDLE_MAPPING_DATABASE_ENTRY_FROM_LISTENTRY (ListEntry);\r
504\r
505 if (Handle == HandleMapEntry->FrameworkHiiHandle) {\r
506 Status = mUefiHiiDatabaseProtocol->RemovePackageList (\r
507 mUefiHiiDatabaseProtocol,\r
508 HandleMapEntry->UefiHiiHandle\r
509 );\r
510 ASSERT_EFI_ERROR (Status);\r
511\r
512 RemoveEntryList (ListEntry);\r
513 return Status;\r
514 }\r
515 }\r
516\r
517 return EFI_NOT_FOUND;\r
518}\r