]> git.proxmox.com Git - mirror_edk2.git/blame_incremental - MdeModulePkg/Universal/HiiDatabaseDxe/Database.c
UefiCpuPkg: Move AsmRelocateApLoopStart from Mpfuncs.nasm to AmdSev.nasm
[mirror_edk2.git] / MdeModulePkg / Universal / HiiDatabaseDxe / Database.c
... / ...
CommitLineData
1/** @file\r
2Implementation for EFI_HII_DATABASE_PROTOCOL.\r
3\r
4Copyright (c) 2007 - 2020, Intel Corporation. All rights reserved.<BR>\r
5SPDX-License-Identifier: BSD-2-Clause-Patent\r
6\r
7**/\r
8\r
9#include "HiiDatabase.h"\r
10\r
11#define BASE_NUMBER 10\r
12\r
13EFI_HII_PACKAGE_LIST_HEADER *gRTDatabaseInfoBuffer = NULL;\r
14EFI_STRING gRTConfigRespBuffer = NULL;\r
15UINTN gDatabaseInfoSize = 0;\r
16UINTN gConfigRespSize = 0;\r
17BOOLEAN gExportConfigResp = FALSE;\r
18UINTN gNvDefaultStoreSize = 0;\r
19SKU_ID gSkuId = 0xFFFFFFFFFFFFFFFF;\r
20LIST_ENTRY gVarStorageList = INITIALIZE_LIST_HEAD_VARIABLE (gVarStorageList);\r
21\r
22//\r
23// HII database lock.\r
24//\r
25EFI_LOCK mHiiDatabaseLock = EFI_INITIALIZE_LOCK_VARIABLE (TPL_NOTIFY);\r
26\r
27/**\r
28 This function generates a HII_DATABASE_RECORD node and adds into hii database.\r
29 This is a internal function.\r
30\r
31 @param Private hii database private structure\r
32 @param DatabaseNode HII_DATABASE_RECORD node which is used to store a\r
33 package list\r
34\r
35 @retval EFI_SUCCESS A database record is generated successfully.\r
36 @retval EFI_OUT_OF_RESOURCES Unable to allocate necessary resources for the new\r
37 database contents.\r
38 @retval EFI_INVALID_PARAMETER Private is NULL or DatabaseRecord is NULL.\r
39\r
40**/\r
41EFI_STATUS\r
42GenerateHiiDatabaseRecord (\r
43 IN HII_DATABASE_PRIVATE_DATA *Private,\r
44 OUT HII_DATABASE_RECORD **DatabaseNode\r
45 )\r
46{\r
47 HII_DATABASE_RECORD *DatabaseRecord;\r
48 HII_DATABASE_PACKAGE_LIST_INSTANCE *PackageList;\r
49 HII_HANDLE *HiiHandle;\r
50\r
51 if ((Private == NULL) || (DatabaseNode == NULL)) {\r
52 return EFI_INVALID_PARAMETER;\r
53 }\r
54\r
55 DatabaseRecord = (HII_DATABASE_RECORD *)AllocateZeroPool (sizeof (HII_DATABASE_RECORD));\r
56 if (DatabaseRecord == NULL) {\r
57 return EFI_OUT_OF_RESOURCES;\r
58 }\r
59\r
60 DatabaseRecord->Signature = HII_DATABASE_RECORD_SIGNATURE;\r
61\r
62 DatabaseRecord->PackageList = AllocateZeroPool (sizeof (HII_DATABASE_PACKAGE_LIST_INSTANCE));\r
63 if (DatabaseRecord->PackageList == NULL) {\r
64 FreePool (DatabaseRecord);\r
65 return EFI_OUT_OF_RESOURCES;\r
66 }\r
67\r
68 PackageList = DatabaseRecord->PackageList;\r
69\r
70 InitializeListHead (&PackageList->GuidPkgHdr);\r
71 InitializeListHead (&PackageList->FormPkgHdr);\r
72 InitializeListHead (&PackageList->KeyboardLayoutHdr);\r
73 InitializeListHead (&PackageList->StringPkgHdr);\r
74 InitializeListHead (&PackageList->FontPkgHdr);\r
75 InitializeListHead (&PackageList->SimpleFontPkgHdr);\r
76 PackageList->ImagePkg = NULL;\r
77 PackageList->DevicePathPkg = NULL;\r
78\r
79 //\r
80 // Create a new hii handle\r
81 //\r
82 HiiHandle = (HII_HANDLE *)AllocateZeroPool (sizeof (HII_HANDLE));\r
83 if (HiiHandle == NULL) {\r
84 FreePool (DatabaseRecord->PackageList);\r
85 FreePool (DatabaseRecord);\r
86 return EFI_OUT_OF_RESOURCES;\r
87 }\r
88\r
89 HiiHandle->Signature = HII_HANDLE_SIGNATURE;\r
90 //\r
91 // Backup the number of Hii handles\r
92 //\r
93 Private->HiiHandleCount++;\r
94 HiiHandle->Key = (UINTN)Private->HiiHandleCount;\r
95 //\r
96 // Insert the handle to hii handle list of the whole database.\r
97 //\r
98 InsertTailList (&Private->HiiHandleList, &HiiHandle->Handle);\r
99\r
100 DatabaseRecord->Handle = (EFI_HII_HANDLE)HiiHandle;\r
101\r
102 //\r
103 // Insert the Package List node to Package List link of the whole database.\r
104 //\r
105 InsertTailList (&Private->DatabaseList, &DatabaseRecord->DatabaseEntry);\r
106\r
107 *DatabaseNode = DatabaseRecord;\r
108\r
109 return EFI_SUCCESS;\r
110}\r
111\r
112/**\r
113 This function checks whether a handle is a valid EFI_HII_HANDLE\r
114 This is a internal function.\r
115\r
116 @param Handle Pointer to a EFI_HII_HANDLE\r
117\r
118 @retval TRUE Valid\r
119 @retval FALSE Invalid\r
120\r
121**/\r
122BOOLEAN\r
123IsHiiHandleValid (\r
124 EFI_HII_HANDLE Handle\r
125 )\r
126{\r
127 HII_HANDLE *HiiHandle;\r
128\r
129 HiiHandle = (HII_HANDLE *)Handle;\r
130\r
131 if (HiiHandle == NULL) {\r
132 return FALSE;\r
133 }\r
134\r
135 if (HiiHandle->Signature != HII_HANDLE_SIGNATURE) {\r
136 return FALSE;\r
137 }\r
138\r
139 return TRUE;\r
140}\r
141\r
142/**\r
143 This function invokes the matching registered function.\r
144 This is a internal function.\r
145\r
146 @param Private HII Database driver private structure.\r
147 @param NotifyType The type of change concerning the database.\r
148 @param PackageInstance Points to the package referred to by the\r
149 notification.\r
150 @param PackageType Package type\r
151 @param Handle The handle of the package list which contains the\r
152 specified package.\r
153\r
154 @retval EFI_SUCCESS Already checked all registered function and\r
155 invoked if matched.\r
156 @retval EFI_INVALID_PARAMETER Any input parameter is not valid.\r
157\r
158**/\r
159EFI_STATUS\r
160InvokeRegisteredFunction (\r
161 IN HII_DATABASE_PRIVATE_DATA *Private,\r
162 IN EFI_HII_DATABASE_NOTIFY_TYPE NotifyType,\r
163 IN VOID *PackageInstance,\r
164 IN UINT8 PackageType,\r
165 IN EFI_HII_HANDLE Handle\r
166 )\r
167{\r
168 HII_DATABASE_NOTIFY *Notify;\r
169 LIST_ENTRY *Link;\r
170 EFI_HII_PACKAGE_HEADER *Package;\r
171 UINT8 *Buffer;\r
172 UINT32 BufferSize;\r
173 UINT32 HeaderSize;\r
174 UINT32 ImageBlockSize;\r
175 UINT32 PaletteInfoSize;\r
176\r
177 if ((Private == NULL) || ((NotifyType & 0xF) == 0) || (PackageInstance == NULL)) {\r
178 return EFI_INVALID_PARAMETER;\r
179 }\r
180\r
181 if (Private->Signature != HII_DATABASE_PRIVATE_DATA_SIGNATURE) {\r
182 return EFI_INVALID_PARAMETER;\r
183 }\r
184\r
185 if (!IsHiiHandleValid (Handle)) {\r
186 return EFI_INVALID_PARAMETER;\r
187 }\r
188\r
189 Buffer = NULL;\r
190 Package = NULL;\r
191\r
192 //\r
193 // Convert the incoming package from hii database storage format to UEFI\r
194 // storage format. e.g. HII_GUID_PACKAGE_INSTANCE to EFI_HII_GUID_PACKAGE_HDR.\r
195 //\r
196 switch (PackageType) {\r
197 case EFI_HII_PACKAGE_TYPE_GUID:\r
198 Package = (EFI_HII_PACKAGE_HEADER *)(((HII_GUID_PACKAGE_INSTANCE *)PackageInstance)->GuidPkg);\r
199 break;\r
200\r
201 case EFI_HII_PACKAGE_FORMS:\r
202 BufferSize = ((HII_IFR_PACKAGE_INSTANCE *)PackageInstance)->FormPkgHdr.Length;\r
203 Buffer = (UINT8 *)AllocateZeroPool (BufferSize);\r
204 ASSERT (Buffer != NULL);\r
205 CopyMem (\r
206 Buffer,\r
207 &((HII_IFR_PACKAGE_INSTANCE *)PackageInstance)->FormPkgHdr,\r
208 sizeof (EFI_HII_PACKAGE_HEADER)\r
209 );\r
210 CopyMem (\r
211 Buffer + sizeof (EFI_HII_PACKAGE_HEADER),\r
212 ((HII_IFR_PACKAGE_INSTANCE *)PackageInstance)->IfrData,\r
213 BufferSize - sizeof (EFI_HII_PACKAGE_HEADER)\r
214 );\r
215 Package = (EFI_HII_PACKAGE_HEADER *)Buffer;\r
216 break;\r
217\r
218 case EFI_HII_PACKAGE_KEYBOARD_LAYOUT:\r
219 Package = (EFI_HII_PACKAGE_HEADER *)(((HII_KEYBOARD_LAYOUT_PACKAGE_INSTANCE *)PackageInstance)->KeyboardPkg);\r
220 break;\r
221\r
222 case EFI_HII_PACKAGE_STRINGS:\r
223 BufferSize = ((HII_STRING_PACKAGE_INSTANCE *)PackageInstance)->StringPkgHdr->Header.Length;\r
224 HeaderSize = ((HII_STRING_PACKAGE_INSTANCE *)PackageInstance)->StringPkgHdr->HdrSize;\r
225 Buffer = (UINT8 *)AllocateZeroPool (BufferSize);\r
226 ASSERT (Buffer != NULL);\r
227 CopyMem (\r
228 Buffer,\r
229 ((HII_STRING_PACKAGE_INSTANCE *)PackageInstance)->StringPkgHdr,\r
230 HeaderSize\r
231 );\r
232 CopyMem (\r
233 Buffer + HeaderSize,\r
234 ((HII_STRING_PACKAGE_INSTANCE *)PackageInstance)->StringBlock,\r
235 BufferSize - HeaderSize\r
236 );\r
237 Package = (EFI_HII_PACKAGE_HEADER *)Buffer;\r
238 break;\r
239\r
240 case EFI_HII_PACKAGE_FONTS:\r
241 BufferSize = ((HII_FONT_PACKAGE_INSTANCE *)PackageInstance)->FontPkgHdr->Header.Length;\r
242 HeaderSize = ((HII_FONT_PACKAGE_INSTANCE *)PackageInstance)->FontPkgHdr->HdrSize;\r
243 Buffer = (UINT8 *)AllocateZeroPool (BufferSize);\r
244 ASSERT (Buffer != NULL);\r
245 CopyMem (\r
246 Buffer,\r
247 ((HII_FONT_PACKAGE_INSTANCE *)PackageInstance)->FontPkgHdr,\r
248 HeaderSize\r
249 );\r
250 CopyMem (\r
251 Buffer + HeaderSize,\r
252 ((HII_FONT_PACKAGE_INSTANCE *)PackageInstance)->GlyphBlock,\r
253 BufferSize - HeaderSize\r
254 );\r
255 Package = (EFI_HII_PACKAGE_HEADER *)Buffer;\r
256 break;\r
257\r
258 case EFI_HII_PACKAGE_IMAGES:\r
259 BufferSize = ((HII_IMAGE_PACKAGE_INSTANCE *)PackageInstance)->ImagePkgHdr.Header.Length;\r
260 HeaderSize = sizeof (EFI_HII_IMAGE_PACKAGE_HDR);\r
261 Buffer = (UINT8 *)AllocateZeroPool (BufferSize);\r
262 ASSERT (Buffer != NULL);\r
263\r
264 CopyMem (\r
265 Buffer,\r
266 &((HII_IMAGE_PACKAGE_INSTANCE *)PackageInstance)->ImagePkgHdr,\r
267 HeaderSize\r
268 );\r
269 CopyMem (\r
270 Buffer + sizeof (EFI_HII_PACKAGE_HEADER),\r
271 &HeaderSize,\r
272 sizeof (UINT32)\r
273 );\r
274\r
275 ImageBlockSize = ((HII_IMAGE_PACKAGE_INSTANCE *)PackageInstance)->ImageBlockSize;\r
276 if (ImageBlockSize != 0) {\r
277 CopyMem (\r
278 Buffer + HeaderSize,\r
279 ((HII_IMAGE_PACKAGE_INSTANCE *)PackageInstance)->ImageBlock,\r
280 ImageBlockSize\r
281 );\r
282 }\r
283\r
284 PaletteInfoSize = ((HII_IMAGE_PACKAGE_INSTANCE *)PackageInstance)->PaletteInfoSize;\r
285 if (PaletteInfoSize != 0) {\r
286 CopyMem (\r
287 Buffer + HeaderSize + ImageBlockSize,\r
288 ((HII_IMAGE_PACKAGE_INSTANCE *)PackageInstance)->PaletteBlock,\r
289 PaletteInfoSize\r
290 );\r
291 HeaderSize += ImageBlockSize;\r
292 CopyMem (\r
293 Buffer + sizeof (EFI_HII_PACKAGE_HEADER) + sizeof (UINT32),\r
294 &HeaderSize,\r
295 sizeof (UINT32)\r
296 );\r
297 }\r
298\r
299 Package = (EFI_HII_PACKAGE_HEADER *)Buffer;\r
300 break;\r
301\r
302 case EFI_HII_PACKAGE_SIMPLE_FONTS:\r
303 BufferSize = ((HII_SIMPLE_FONT_PACKAGE_INSTANCE *)PackageInstance)->SimpleFontPkgHdr->Header.Length;\r
304 Buffer = (UINT8 *)AllocateZeroPool (BufferSize);\r
305 ASSERT (Buffer != NULL);\r
306 CopyMem (\r
307 Buffer,\r
308 ((HII_SIMPLE_FONT_PACKAGE_INSTANCE *)PackageInstance)->SimpleFontPkgHdr,\r
309 BufferSize\r
310 );\r
311 Package = (EFI_HII_PACKAGE_HEADER *)Buffer;\r
312 break;\r
313\r
314 case EFI_HII_PACKAGE_DEVICE_PATH:\r
315 Package = (EFI_HII_PACKAGE_HEADER *)PackageInstance;\r
316 break;\r
317\r
318 default:\r
319 return EFI_INVALID_PARAMETER;\r
320 }\r
321\r
322 for (Link = Private->DatabaseNotifyList.ForwardLink;\r
323 Link != &Private->DatabaseNotifyList;\r
324 Link = Link->ForwardLink\r
325 )\r
326 {\r
327 Notify = CR (Link, HII_DATABASE_NOTIFY, DatabaseNotifyEntry, HII_DATABASE_NOTIFY_SIGNATURE);\r
328 if ((Notify->NotifyType == NotifyType) && (Notify->PackageType == PackageType)) {\r
329 //\r
330 // Check in case PackageGuid is not NULL when Package is GUID package\r
331 //\r
332 if (PackageType != EFI_HII_PACKAGE_TYPE_GUID) {\r
333 Notify->PackageGuid = NULL;\r
334 }\r
335\r
336 //\r
337 // Status of Registered Function is unknown so did not check it\r
338 //\r
339 Notify->PackageNotifyFn (\r
340 Notify->PackageType,\r
341 Notify->PackageGuid,\r
342 Package,\r
343 Handle,\r
344 NotifyType\r
345 );\r
346 }\r
347 }\r
348\r
349 if (Buffer != NULL) {\r
350 FreePool (Buffer);\r
351 }\r
352\r
353 return EFI_SUCCESS;\r
354}\r
355\r
356/**\r
357 This function insert a GUID package to a package list node.\r
358 This is a internal function.\r
359\r
360 @param PackageHdr Pointer to a buffer stored with GUID package\r
361 information.\r
362 @param NotifyType The type of change concerning the database.\r
363 @param PackageList Pointer to a package list which will be inserted\r
364 to.\r
365 @param Package Created GUID package\r
366\r
367 @retval EFI_SUCCESS Guid Package is inserted successfully.\r
368 @retval EFI_OUT_OF_RESOURCES Unable to allocate necessary resources for the new\r
369 Guid package.\r
370 @retval EFI_INVALID_PARAMETER PackageHdr is NULL or PackageList is NULL.\r
371\r
372**/\r
373EFI_STATUS\r
374InsertGuidPackage (\r
375 IN VOID *PackageHdr,\r
376 IN EFI_HII_DATABASE_NOTIFY_TYPE NotifyType,\r
377 IN OUT HII_DATABASE_PACKAGE_LIST_INSTANCE *PackageList,\r
378 OUT HII_GUID_PACKAGE_INSTANCE **Package\r
379 )\r
380{\r
381 HII_GUID_PACKAGE_INSTANCE *GuidPackage;\r
382 EFI_HII_PACKAGE_HEADER PackageHeader;\r
383\r
384 if ((PackageHdr == NULL) || (PackageList == NULL)) {\r
385 return EFI_INVALID_PARAMETER;\r
386 }\r
387\r
388 CopyMem (&PackageHeader, PackageHdr, sizeof (EFI_HII_PACKAGE_HEADER));\r
389\r
390 //\r
391 // Create a GUID package node\r
392 //\r
393 GuidPackage = (HII_GUID_PACKAGE_INSTANCE *)AllocateZeroPool (sizeof (HII_GUID_PACKAGE_INSTANCE));\r
394 if (GuidPackage == NULL) {\r
395 return EFI_OUT_OF_RESOURCES;\r
396 }\r
397\r
398 GuidPackage->GuidPkg = (UINT8 *)AllocateZeroPool (PackageHeader.Length);\r
399 if (GuidPackage->GuidPkg == NULL) {\r
400 FreePool (GuidPackage);\r
401 return EFI_OUT_OF_RESOURCES;\r
402 }\r
403\r
404 GuidPackage->Signature = HII_GUID_PACKAGE_SIGNATURE;\r
405 CopyMem (GuidPackage->GuidPkg, PackageHdr, PackageHeader.Length);\r
406 InsertTailList (&PackageList->GuidPkgHdr, &GuidPackage->GuidEntry);\r
407 *Package = GuidPackage;\r
408\r
409 if (NotifyType == EFI_HII_DATABASE_NOTIFY_ADD_PACK) {\r
410 PackageList->PackageListHdr.PackageLength += PackageHeader.Length;\r
411 }\r
412\r
413 return EFI_SUCCESS;\r
414}\r
415\r
416/**\r
417 This function exports GUID packages to a buffer.\r
418 This is a internal function.\r
419\r
420 @param Private Hii database private structure.\r
421 @param Handle Identification of a package list.\r
422 @param PackageList Pointer to a package list which will be exported.\r
423 @param UsedSize The length of buffer be used.\r
424 @param BufferSize Length of the Buffer.\r
425 @param Buffer Allocated space for storing exported data.\r
426 @param ResultSize The size of the already exported content of this\r
427 package list.\r
428\r
429 @retval EFI_SUCCESS Guid Packages are exported successfully.\r
430 @retval EFI_INVALID_PARAMETER Any input parameter is invalid.\r
431\r
432**/\r
433EFI_STATUS\r
434ExportGuidPackages (\r
435 IN HII_DATABASE_PRIVATE_DATA *Private,\r
436 IN EFI_HII_HANDLE Handle,\r
437 IN HII_DATABASE_PACKAGE_LIST_INSTANCE *PackageList,\r
438 IN UINTN UsedSize,\r
439 IN UINTN BufferSize,\r
440 IN OUT VOID *Buffer,\r
441 IN OUT UINTN *ResultSize\r
442 )\r
443{\r
444 HII_GUID_PACKAGE_INSTANCE *GuidPackage;\r
445 LIST_ENTRY *Link;\r
446 UINTN PackageLength;\r
447 EFI_HII_PACKAGE_HEADER PackageHeader;\r
448 EFI_STATUS Status;\r
449\r
450 if ((PackageList == NULL) || (ResultSize == NULL)) {\r
451 return EFI_INVALID_PARAMETER;\r
452 }\r
453\r
454 if ((BufferSize > 0) && (Buffer == NULL)) {\r
455 return EFI_INVALID_PARAMETER;\r
456 }\r
457\r
458 PackageLength = 0;\r
459 Status = EFI_SUCCESS;\r
460\r
461 for (Link = PackageList->GuidPkgHdr.ForwardLink; Link != &PackageList->GuidPkgHdr; Link = Link->ForwardLink) {\r
462 GuidPackage = CR (Link, HII_GUID_PACKAGE_INSTANCE, GuidEntry, HII_GUID_PACKAGE_SIGNATURE);\r
463 CopyMem (&PackageHeader, GuidPackage->GuidPkg, sizeof (EFI_HII_PACKAGE_HEADER));\r
464 PackageLength += PackageHeader.Length;\r
465 if (PackageLength + *ResultSize + UsedSize <= BufferSize) {\r
466 Status = InvokeRegisteredFunction (\r
467 Private,\r
468 EFI_HII_DATABASE_NOTIFY_EXPORT_PACK,\r
469 (VOID *)GuidPackage,\r
470 EFI_HII_PACKAGE_TYPE_GUID,\r
471 Handle\r
472 );\r
473 ASSERT_EFI_ERROR (Status);\r
474 CopyMem (Buffer, GuidPackage->GuidPkg, PackageHeader.Length);\r
475 Buffer = (UINT8 *)Buffer + PackageHeader.Length;\r
476 }\r
477 }\r
478\r
479 *ResultSize += PackageLength;\r
480 return EFI_SUCCESS;\r
481}\r
482\r
483/**\r
484 This function deletes all GUID packages from a package list node.\r
485 This is a internal function.\r
486\r
487 @param Private Hii database private data.\r
488 @param Handle Handle of the package list which contains the to\r
489 be removed GUID packages.\r
490 @param PackageList Pointer to a package list that contains removing\r
491 packages.\r
492\r
493 @retval EFI_SUCCESS GUID Package(s) is deleted successfully.\r
494 @retval EFI_INVALID_PARAMETER Any input parameter is not valid.\r
495\r
496**/\r
497EFI_STATUS\r
498RemoveGuidPackages (\r
499 IN HII_DATABASE_PRIVATE_DATA *Private,\r
500 IN EFI_HII_HANDLE Handle,\r
501 IN OUT HII_DATABASE_PACKAGE_LIST_INSTANCE *PackageList\r
502 )\r
503{\r
504 LIST_ENTRY *ListHead;\r
505 HII_GUID_PACKAGE_INSTANCE *Package;\r
506 EFI_STATUS Status;\r
507 EFI_HII_PACKAGE_HEADER PackageHeader;\r
508\r
509 ListHead = &PackageList->GuidPkgHdr;\r
510\r
511 while (!IsListEmpty (ListHead)) {\r
512 Package = CR (\r
513 ListHead->ForwardLink,\r
514 HII_GUID_PACKAGE_INSTANCE,\r
515 GuidEntry,\r
516 HII_GUID_PACKAGE_SIGNATURE\r
517 );\r
518 Status = InvokeRegisteredFunction (\r
519 Private,\r
520 EFI_HII_DATABASE_NOTIFY_REMOVE_PACK,\r
521 (VOID *)Package,\r
522 EFI_HII_PACKAGE_TYPE_GUID,\r
523 Handle\r
524 );\r
525 if (EFI_ERROR (Status)) {\r
526 return Status;\r
527 }\r
528\r
529 RemoveEntryList (&Package->GuidEntry);\r
530 CopyMem (&PackageHeader, Package->GuidPkg, sizeof (EFI_HII_PACKAGE_HEADER));\r
531 PackageList->PackageListHdr.PackageLength -= PackageHeader.Length;\r
532 FreePool (Package->GuidPkg);\r
533 FreePool (Package);\r
534 }\r
535\r
536 return EFI_SUCCESS;\r
537}\r
538\r
539/**\r
540 Check the input question related to EFI variable\r
541\r
542 @param IfrQuestionHdr Point to Question header\r
543 @param EfiVarStoreList Point to EFI VarStore List\r
544 @param EfiVarStoreNumber The number of EFI VarStore\r
545\r
546 @retval Index The index of the found EFI varstore in EFI varstore list\r
547 EfiVarStoreNumber will return if no EFI varstore is found.\r
548**/\r
549UINTN\r
550IsEfiVarStoreQuestion (\r
551 EFI_IFR_QUESTION_HEADER *IfrQuestionHdr,\r
552 EFI_IFR_VARSTORE_EFI **EfiVarStoreList,\r
553 UINTN EfiVarStoreNumber\r
554 )\r
555{\r
556 UINTN Index;\r
557\r
558 for (Index = 0; Index < EfiVarStoreNumber; Index++) {\r
559 if (IfrQuestionHdr->VarStoreId == EfiVarStoreList[Index]->VarStoreId) {\r
560 return Index;\r
561 }\r
562 }\r
563\r
564 return EfiVarStoreNumber;\r
565}\r
566\r
567/**\r
568 Find the matched variable from the input variable storage.\r
569\r
570 @param[in] VariableStorage Point to the variable storage header.\r
571 @param[in] VarGuid A unique identifier for the variable.\r
572 @param[in] VarAttribute The attributes bitmask for the variable.\r
573 @param[in] VarName A Null-terminated ascii string that is the name of the variable.\r
574\r
575 @return Pointer to the matched variable header or NULL if not found.\r
576**/\r
577VARIABLE_HEADER *\r
578FindVariableData (\r
579 IN VARIABLE_STORE_HEADER *VariableStorage,\r
580 IN EFI_GUID *VarGuid,\r
581 IN UINT32 VarAttribute,\r
582 IN CHAR16 *VarName\r
583 )\r
584{\r
585 VARIABLE_HEADER *VariableHeader;\r
586 VARIABLE_HEADER *VariableEnd;\r
587\r
588 VariableEnd = (VARIABLE_HEADER *)((UINT8 *)VariableStorage + VariableStorage->Size);\r
589 VariableHeader = (VARIABLE_HEADER *)(VariableStorage + 1);\r
590 VariableHeader = (VARIABLE_HEADER *)HEADER_ALIGN (VariableHeader);\r
591 while (VariableHeader < VariableEnd) {\r
592 if (CompareGuid (&VariableHeader->VendorGuid, VarGuid) &&\r
593 (VariableHeader->Attributes == VarAttribute) &&\r
594 (StrCmp (VarName, (CHAR16 *)(VariableHeader + 1)) == 0))\r
595 {\r
596 return VariableHeader;\r
597 }\r
598\r
599 VariableHeader = (VARIABLE_HEADER *)((UINT8 *)VariableHeader + sizeof (VARIABLE_HEADER) + VariableHeader->NameSize + VariableHeader->DataSize);\r
600 VariableHeader = (VARIABLE_HEADER *)HEADER_ALIGN (VariableHeader);\r
601 }\r
602\r
603 return NULL;\r
604}\r
605\r
606/**\r
607 Find question default value from PcdNvStoreDefaultValueBuffer\r
608\r
609 @param DefaultId Default store ID\r
610 @param EfiVarStore Point to EFI VarStore header\r
611 @param IfrQuestionHdr Point to Question header\r
612 @param ValueBuffer Point to Buffer includes the found default setting\r
613 @param Width Width of the default value\r
614 @param BitFieldQuestion Whether the Question is stored in Bit field.\r
615\r
616 @retval EFI_SUCCESS Question default value is found.\r
617 @retval EFI_NOT_FOUND Question default value is not found.\r
618**/\r
619EFI_STATUS\r
620FindQuestionDefaultSetting (\r
621 IN UINT16 DefaultId,\r
622 IN EFI_IFR_VARSTORE_EFI *EfiVarStore,\r
623 IN EFI_IFR_QUESTION_HEADER *IfrQuestionHdr,\r
624 OUT VOID *ValueBuffer,\r
625 IN UINTN Width,\r
626 IN BOOLEAN BitFieldQuestion\r
627 )\r
628{\r
629 VARIABLE_HEADER *VariableHeader;\r
630 VARIABLE_STORE_HEADER *VariableStorage;\r
631 LIST_ENTRY *Link;\r
632 VARSTORAGE_DEFAULT_DATA *Entry;\r
633 VARIABLE_STORE_HEADER *NvStoreBuffer;\r
634 UINT8 *DataBuffer;\r
635 UINT8 *BufferEnd;\r
636 BOOLEAN IsFound;\r
637 UINTN Index;\r
638 UINT32 BufferValue;\r
639 UINT32 BitFieldVal;\r
640 UINTN BitOffset;\r
641 UINTN ByteOffset;\r
642 UINTN BitWidth;\r
643 UINTN StartBit;\r
644 UINTN EndBit;\r
645 PCD_DEFAULT_DATA *DataHeader;\r
646 PCD_DEFAULT_INFO *DefaultInfo;\r
647 PCD_DATA_DELTA *DeltaData;\r
648\r
649 if (gSkuId == 0xFFFFFFFFFFFFFFFF) {\r
650 gSkuId = LibPcdGetSku ();\r
651 }\r
652\r
653 //\r
654 // Find the DefaultId setting from the full DefaultSetting\r
655 //\r
656 VariableStorage = NULL;\r
657 Link = gVarStorageList.ForwardLink;\r
658 while (Link != &gVarStorageList) {\r
659 Entry = BASE_CR (Link, VARSTORAGE_DEFAULT_DATA, Entry);\r
660 if (Entry->DefaultId == DefaultId) {\r
661 VariableStorage = Entry->VariableStorage;\r
662 break;\r
663 }\r
664\r
665 Link = Link->ForwardLink;\r
666 }\r
667\r
668 if (Link == &gVarStorageList) {\r
669 DataBuffer = (UINT8 *)PcdGetPtr (PcdNvStoreDefaultValueBuffer);\r
670 gNvDefaultStoreSize = ((PCD_NV_STORE_DEFAULT_BUFFER_HEADER *)DataBuffer)->Length;\r
671 //\r
672 // The first section data includes NV storage default setting.\r
673 //\r
674 DataHeader = (PCD_DEFAULT_DATA *)(DataBuffer + sizeof (PCD_NV_STORE_DEFAULT_BUFFER_HEADER));\r
675 NvStoreBuffer = (VARIABLE_STORE_HEADER *)((UINT8 *)DataHeader + sizeof (DataHeader->DataSize) + DataHeader->HeaderSize);\r
676 VariableStorage = AllocatePool (NvStoreBuffer->Size);\r
677 ASSERT (VariableStorage != NULL);\r
678 CopyMem (VariableStorage, NvStoreBuffer, NvStoreBuffer->Size);\r
679\r
680 //\r
681 // Find the matched SkuId and DefaultId in the first section\r
682 //\r
683 IsFound = FALSE;\r
684 DefaultInfo = &(DataHeader->DefaultInfo[0]);\r
685 BufferEnd = (UINT8 *)DataHeader + sizeof (DataHeader->DataSize) + DataHeader->HeaderSize;\r
686 while ((UINT8 *)DefaultInfo < BufferEnd) {\r
687 if ((DefaultInfo->DefaultId == DefaultId) && (DefaultInfo->SkuId == gSkuId)) {\r
688 IsFound = TRUE;\r
689 break;\r
690 }\r
691\r
692 DefaultInfo++;\r
693 }\r
694\r
695 //\r
696 // Find the matched SkuId and DefaultId in the remaining section\r
697 //\r
698 Index = sizeof (PCD_NV_STORE_DEFAULT_BUFFER_HEADER) + ((DataHeader->DataSize + 7) & (~7));\r
699 DataHeader = (PCD_DEFAULT_DATA *)(DataBuffer + Index);\r
700 while (!IsFound && Index < gNvDefaultStoreSize && DataHeader->DataSize != 0xFFFF) {\r
701 DefaultInfo = &(DataHeader->DefaultInfo[0]);\r
702 BufferEnd = (UINT8 *)DataHeader + sizeof (DataHeader->DataSize) + DataHeader->HeaderSize;\r
703 while ((UINT8 *)DefaultInfo < BufferEnd) {\r
704 if ((DefaultInfo->DefaultId == DefaultId) && (DefaultInfo->SkuId == gSkuId)) {\r
705 IsFound = TRUE;\r
706 break;\r
707 }\r
708\r
709 DefaultInfo++;\r
710 }\r
711\r
712 if (IsFound) {\r
713 DeltaData = (PCD_DATA_DELTA *)BufferEnd;\r
714 BufferEnd = (UINT8 *)DataHeader + DataHeader->DataSize;\r
715 while ((UINT8 *)DeltaData < BufferEnd) {\r
716 *((UINT8 *)VariableStorage + DeltaData->Offset) = (UINT8)DeltaData->Value;\r
717 DeltaData++;\r
718 }\r
719\r
720 break;\r
721 }\r
722\r
723 Index = (Index + DataHeader->DataSize + 7) & (~7);\r
724 DataHeader = (PCD_DEFAULT_DATA *)(DataBuffer + Index);\r
725 }\r
726\r
727 //\r
728 // Cache the found result in VarStorageList\r
729 //\r
730 if (!IsFound) {\r
731 FreePool (VariableStorage);\r
732 VariableStorage = NULL;\r
733 }\r
734\r
735 Entry = AllocatePool (sizeof (VARSTORAGE_DEFAULT_DATA));\r
736 if (Entry != NULL) {\r
737 Entry->DefaultId = DefaultId;\r
738 Entry->VariableStorage = VariableStorage;\r
739 InsertTailList (&gVarStorageList, &Entry->Entry);\r
740 } else if (VariableStorage != NULL) {\r
741 FreePool (VariableStorage);\r
742 VariableStorage = NULL;\r
743 }\r
744 }\r
745\r
746 //\r
747 // The matched variable storage is not found.\r
748 //\r
749 if (VariableStorage == NULL) {\r
750 return EFI_NOT_FOUND;\r
751 }\r
752\r
753 //\r
754 // Find the question default value from the variable storage\r
755 //\r
756 VariableHeader = FindVariableData (VariableStorage, &EfiVarStore->Guid, EfiVarStore->Attributes, (CHAR16 *)EfiVarStore->Name);\r
757 if (VariableHeader == NULL) {\r
758 return EFI_NOT_FOUND;\r
759 }\r
760\r
761 StartBit = 0;\r
762 EndBit = 0;\r
763 ByteOffset = IfrQuestionHdr->VarStoreInfo.VarOffset;\r
764 if (BitFieldQuestion) {\r
765 BitOffset = IfrQuestionHdr->VarStoreInfo.VarOffset;\r
766 ByteOffset = BitOffset / 8;\r
767 BitWidth = Width;\r
768 StartBit = BitOffset % 8;\r
769 EndBit = StartBit + BitWidth - 1;\r
770 Width = EndBit / 8 + 1;\r
771 }\r
772\r
773 if (VariableHeader->DataSize < ByteOffset + Width) {\r
774 return EFI_INVALID_PARAMETER;\r
775 }\r
776\r
777 //\r
778 // Copy the question value\r
779 //\r
780 if (ValueBuffer != NULL) {\r
781 if (BitFieldQuestion) {\r
782 CopyMem (&BufferValue, (UINT8 *)VariableHeader + sizeof (VARIABLE_HEADER) + VariableHeader->NameSize + ByteOffset, Width);\r
783 BitFieldVal = BitFieldRead32 (BufferValue, StartBit, EndBit);\r
784 CopyMem (ValueBuffer, &BitFieldVal, Width);\r
785 } else {\r
786 CopyMem (ValueBuffer, (UINT8 *)VariableHeader + sizeof (VARIABLE_HEADER) + VariableHeader->NameSize + IfrQuestionHdr->VarStoreInfo.VarOffset, Width);\r
787 }\r
788 }\r
789\r
790 return EFI_SUCCESS;\r
791}\r
792\r
793/**\r
794 Update IFR default setting in Form Package.\r
795\r
796 @param FormPackage Form Package to be updated\r
797\r
798**/\r
799VOID\r
800UpdateDefaultSettingInFormPackage (\r
801 HII_IFR_PACKAGE_INSTANCE *FormPackage\r
802 )\r
803{\r
804 UINTN IfrOffset;\r
805 UINTN PackageLength;\r
806 EFI_IFR_VARSTORE_EFI *IfrEfiVarStore;\r
807 EFI_IFR_OP_HEADER *IfrOpHdr;\r
808 EFI_IFR_ONE_OF_OPTION *IfrOneOfOption;\r
809 UINT8 IfrQuestionType;\r
810 UINT8 IfrScope;\r
811 EFI_IFR_QUESTION_HEADER *IfrQuestionHdr;\r
812 EFI_IFR_VARSTORE_EFI **EfiVarStoreList;\r
813 UINTN EfiVarStoreMaxNum;\r
814 UINTN EfiVarStoreNumber;\r
815 UINT16 *DefaultIdList;\r
816 UINTN DefaultIdNumber;\r
817 UINTN DefaultIdMaxNum;\r
818 UINTN Index;\r
819 UINTN EfiVarStoreIndex;\r
820 EFI_IFR_TYPE_VALUE IfrValue;\r
821 EFI_IFR_TYPE_VALUE IfrManufactValue;\r
822 BOOLEAN StandardDefaultIsSet;\r
823 BOOLEAN ManufactDefaultIsSet;\r
824 EFI_IFR_CHECKBOX *IfrCheckBox;\r
825 EFI_STATUS Status;\r
826 EFI_IFR_DEFAULT *IfrDefault;\r
827 UINTN Width;\r
828 EFI_IFR_QUESTION_HEADER VarStoreQuestionHeader;\r
829 BOOLEAN QuestionReferBitField;\r
830\r
831 //\r
832 // If no default setting, do nothing\r
833 //\r
834 if (gNvDefaultStoreSize == 0) {\r
835 gNvDefaultStoreSize = PcdGetSize (PcdNvStoreDefaultValueBuffer);\r
836 }\r
837\r
838 if (gNvDefaultStoreSize < sizeof (PCD_NV_STORE_DEFAULT_BUFFER_HEADER)) {\r
839 return;\r
840 }\r
841\r
842 ZeroMem (&VarStoreQuestionHeader, sizeof (VarStoreQuestionHeader));\r
843 PackageLength = FormPackage->FormPkgHdr.Length - sizeof (EFI_HII_PACKAGE_HEADER);\r
844 Width = 0;\r
845 IfrOffset = 0;\r
846 IfrScope = 0;\r
847 IfrOpHdr = (EFI_IFR_OP_HEADER *)FormPackage->IfrData;\r
848 IfrQuestionHdr = NULL;\r
849 IfrQuestionType = 0;\r
850 EfiVarStoreMaxNum = 0;\r
851 EfiVarStoreNumber = 0;\r
852 DefaultIdMaxNum = 0;\r
853 DefaultIdNumber = 0;\r
854 EfiVarStoreList = NULL;\r
855 DefaultIdList = NULL;\r
856 StandardDefaultIsSet = FALSE;\r
857 ManufactDefaultIsSet = FALSE;\r
858 QuestionReferBitField = FALSE;\r
859\r
860 while (IfrOffset < PackageLength) {\r
861 switch (IfrOpHdr->OpCode) {\r
862 case EFI_IFR_VARSTORE_EFI_OP:\r
863 if (EfiVarStoreNumber >= EfiVarStoreMaxNum) {\r
864 //\r
865 // Reallocate EFI VarStore Buffer\r
866 //\r
867 EfiVarStoreList = ReallocatePool (EfiVarStoreMaxNum * sizeof (UINTN), (EfiVarStoreMaxNum + BASE_NUMBER) * sizeof (UINTN), EfiVarStoreList);\r
868 if (EfiVarStoreList == NULL) {\r
869 goto Done;\r
870 }\r
871\r
872 EfiVarStoreMaxNum = EfiVarStoreMaxNum + BASE_NUMBER;\r
873 }\r
874\r
875 IfrEfiVarStore = (EFI_IFR_VARSTORE_EFI *)IfrOpHdr;\r
876 //\r
877 // Convert VarStore Name from ASCII string to Unicode string.\r
878 //\r
879 EfiVarStoreList[EfiVarStoreNumber] = AllocatePool (IfrEfiVarStore->Header.Length + AsciiStrSize ((CHAR8 *)IfrEfiVarStore->Name));\r
880 if (EfiVarStoreList[EfiVarStoreNumber] == NULL) {\r
881 break;\r
882 }\r
883\r
884 CopyMem (EfiVarStoreList[EfiVarStoreNumber], IfrEfiVarStore, IfrEfiVarStore->Header.Length);\r
885 AsciiStrToUnicodeStrS ((CHAR8 *)IfrEfiVarStore->Name, (CHAR16 *)&(EfiVarStoreList[EfiVarStoreNumber]->Name[0]), AsciiStrSize ((CHAR8 *)IfrEfiVarStore->Name) * sizeof (CHAR16));\r
886 Status = FindQuestionDefaultSetting (EFI_HII_DEFAULT_CLASS_STANDARD, EfiVarStoreList[EfiVarStoreNumber], &VarStoreQuestionHeader, NULL, IfrEfiVarStore->Size, FALSE);\r
887 if (!EFI_ERROR (Status)) {\r
888 EfiVarStoreNumber++;\r
889 } else {\r
890 FreePool (EfiVarStoreList[EfiVarStoreNumber]);\r
891 EfiVarStoreList[EfiVarStoreNumber] = NULL;\r
892 }\r
893\r
894 break;\r
895 case EFI_IFR_DEFAULTSTORE_OP:\r
896 if (DefaultIdNumber >= DefaultIdMaxNum) {\r
897 //\r
898 // Reallocate DefaultIdNumber\r
899 //\r
900 DefaultIdList = ReallocatePool (DefaultIdMaxNum * sizeof (UINT16), (DefaultIdMaxNum + BASE_NUMBER) * sizeof (UINT16), DefaultIdList);\r
901 if (DefaultIdList == NULL) {\r
902 goto Done;\r
903 }\r
904\r
905 DefaultIdMaxNum = DefaultIdMaxNum + BASE_NUMBER;\r
906 }\r
907\r
908 DefaultIdList[DefaultIdNumber++] = ((EFI_IFR_DEFAULTSTORE *)IfrOpHdr)->DefaultId;\r
909 break;\r
910 case EFI_IFR_FORM_OP:\r
911 case EFI_IFR_FORM_MAP_OP:\r
912 //\r
913 // No EFI varstore is found and directly return.\r
914 //\r
915 if ((EfiVarStoreNumber == 0) || (DefaultIdNumber == 0)) {\r
916 goto Done;\r
917 }\r
918\r
919 break;\r
920 case EFI_IFR_CHECKBOX_OP:\r
921 IfrScope = IfrOpHdr->Scope;\r
922 IfrQuestionType = IfrOpHdr->OpCode;\r
923 IfrQuestionHdr = (EFI_IFR_QUESTION_HEADER *)(IfrOpHdr + 1);\r
924 IfrCheckBox = (EFI_IFR_CHECKBOX *)IfrOpHdr;\r
925 EfiVarStoreIndex = IsEfiVarStoreQuestion (IfrQuestionHdr, EfiVarStoreList, EfiVarStoreNumber);\r
926 Width = sizeof (BOOLEAN);\r
927 if (EfiVarStoreIndex < EfiVarStoreNumber) {\r
928 for (Index = 0; Index < DefaultIdNumber; Index++) {\r
929 if (DefaultIdList[Index] == EFI_HII_DEFAULT_CLASS_STANDARD) {\r
930 Status = FindQuestionDefaultSetting (DefaultIdList[Index], EfiVarStoreList[EfiVarStoreIndex], IfrQuestionHdr, &IfrValue, sizeof (BOOLEAN), QuestionReferBitField);\r
931 if (!EFI_ERROR (Status)) {\r
932 if (IfrValue.b) {\r
933 IfrCheckBox->Flags = IfrCheckBox->Flags | EFI_IFR_CHECKBOX_DEFAULT;\r
934 } else {\r
935 IfrCheckBox->Flags = IfrCheckBox->Flags & (~EFI_IFR_CHECKBOX_DEFAULT);\r
936 }\r
937 }\r
938 } else if (DefaultIdList[Index] == EFI_HII_DEFAULT_CLASS_MANUFACTURING) {\r
939 Status = FindQuestionDefaultSetting (DefaultIdList[Index], EfiVarStoreList[EfiVarStoreIndex], IfrQuestionHdr, &IfrValue, sizeof (BOOLEAN), QuestionReferBitField);\r
940 if (!EFI_ERROR (Status)) {\r
941 if (IfrValue.b) {\r
942 IfrCheckBox->Flags = IfrCheckBox->Flags | EFI_IFR_CHECKBOX_DEFAULT_MFG;\r
943 } else {\r
944 IfrCheckBox->Flags = IfrCheckBox->Flags & (~EFI_IFR_CHECKBOX_DEFAULT_MFG);\r
945 }\r
946 }\r
947 }\r
948 }\r
949 }\r
950\r
951 break;\r
952 case EFI_IFR_NUMERIC_OP:\r
953 IfrScope = IfrOpHdr->Scope;\r
954 IfrQuestionType = IfrOpHdr->OpCode;\r
955 IfrQuestionHdr = (EFI_IFR_QUESTION_HEADER *)(IfrOpHdr + 1);\r
956 if (QuestionReferBitField) {\r
957 Width = (UINTN)(((EFI_IFR_ONE_OF *)IfrOpHdr)->Flags & EDKII_IFR_NUMERIC_SIZE_BIT);\r
958 } else {\r
959 Width = (UINTN)((UINT32)1 << (((EFI_IFR_ONE_OF *)IfrOpHdr)->Flags & EFI_IFR_NUMERIC_SIZE));\r
960 }\r
961\r
962 break;\r
963 case EFI_IFR_ONE_OF_OP:\r
964 IfrScope = IfrOpHdr->Scope;\r
965 IfrQuestionType = IfrOpHdr->OpCode;\r
966 IfrQuestionHdr = (EFI_IFR_QUESTION_HEADER *)(IfrOpHdr + 1);\r
967 if (QuestionReferBitField) {\r
968 Width = (UINTN)(((EFI_IFR_ONE_OF *)IfrOpHdr)->Flags & EDKII_IFR_NUMERIC_SIZE_BIT);\r
969 } else {\r
970 Width = (UINTN)((UINT32)1 << (((EFI_IFR_ONE_OF *)IfrOpHdr)->Flags & EFI_IFR_NUMERIC_SIZE));\r
971 }\r
972\r
973 EfiVarStoreIndex = IsEfiVarStoreQuestion (IfrQuestionHdr, EfiVarStoreList, EfiVarStoreNumber);\r
974 StandardDefaultIsSet = FALSE;\r
975 ManufactDefaultIsSet = FALSE;\r
976 //\r
977 // Find Default and Manufacturing default for OneOf question\r
978 //\r
979 if (EfiVarStoreIndex < EfiVarStoreNumber) {\r
980 for (Index = 0; Index < DefaultIdNumber; Index++) {\r
981 if (DefaultIdList[Index] == EFI_HII_DEFAULT_CLASS_STANDARD) {\r
982 Status = FindQuestionDefaultSetting (EFI_HII_DEFAULT_CLASS_STANDARD, EfiVarStoreList[EfiVarStoreIndex], IfrQuestionHdr, &IfrValue, Width, QuestionReferBitField);\r
983 if (!EFI_ERROR (Status)) {\r
984 StandardDefaultIsSet = TRUE;\r
985 }\r
986 } else if (DefaultIdList[Index] == EFI_HII_DEFAULT_CLASS_MANUFACTURING) {\r
987 Status = FindQuestionDefaultSetting (EFI_HII_DEFAULT_CLASS_MANUFACTURING, EfiVarStoreList[EfiVarStoreIndex], IfrQuestionHdr, &IfrManufactValue, Width, QuestionReferBitField);\r
988 if (!EFI_ERROR (Status)) {\r
989 ManufactDefaultIsSet = TRUE;\r
990 }\r
991 }\r
992 }\r
993 }\r
994\r
995 break;\r
996 case EFI_IFR_ORDERED_LIST_OP:\r
997 IfrScope = IfrOpHdr->Scope;\r
998 IfrQuestionType = IfrOpHdr->OpCode;\r
999 IfrQuestionHdr = (EFI_IFR_QUESTION_HEADER *)(IfrOpHdr + 1);\r
1000 break;\r
1001 case EFI_IFR_ONE_OF_OPTION_OP:\r
1002 if ((IfrQuestionHdr != NULL) && (IfrScope > 0)) {\r
1003 IfrOneOfOption = (EFI_IFR_ONE_OF_OPTION *)IfrOpHdr;\r
1004 if (IfrQuestionType == EFI_IFR_ONE_OF_OP) {\r
1005 Width = (UINTN)((UINT32)1 << (IfrOneOfOption->Flags & EFI_IFR_NUMERIC_SIZE));\r
1006 if (StandardDefaultIsSet) {\r
1007 if (CompareMem (&IfrOneOfOption->Value, &IfrValue, Width) == 0) {\r
1008 IfrOneOfOption->Flags |= EFI_IFR_OPTION_DEFAULT;\r
1009 } else {\r
1010 IfrOneOfOption->Flags &= ~EFI_IFR_OPTION_DEFAULT;\r
1011 }\r
1012 }\r
1013\r
1014 if (ManufactDefaultIsSet) {\r
1015 if (CompareMem (&IfrOneOfOption->Value, &IfrManufactValue, Width) == 0) {\r
1016 IfrOneOfOption->Flags |= EFI_IFR_OPTION_DEFAULT_MFG;\r
1017 } else {\r
1018 IfrOneOfOption->Flags &= ~EFI_IFR_OPTION_DEFAULT_MFG;\r
1019 }\r
1020 }\r
1021 }\r
1022 }\r
1023\r
1024 break;\r
1025 case EFI_IFR_DEFAULT_OP:\r
1026 if ((IfrQuestionHdr != NULL) && (IfrScope > 0)) {\r
1027 IfrDefault = (EFI_IFR_DEFAULT *)IfrOpHdr;\r
1028 //\r
1029 // Collect default value width\r
1030 //\r
1031 if (!QuestionReferBitField) {\r
1032 Width = 0;\r
1033 if ((IfrDefault->Type == EFI_IFR_TYPE_NUM_SIZE_8) || (IfrDefault->Type == EFI_IFR_TYPE_BOOLEAN)) {\r
1034 Width = 1;\r
1035 } else if (IfrDefault->Type == EFI_IFR_TYPE_NUM_SIZE_16) {\r
1036 Width = 2;\r
1037 } else if (IfrDefault->Type == EFI_IFR_TYPE_NUM_SIZE_32) {\r
1038 Width = 4;\r
1039 } else if (IfrDefault->Type == EFI_IFR_TYPE_NUM_SIZE_64) {\r
1040 Width = 8;\r
1041 } else if (IfrDefault->Type == EFI_IFR_TYPE_BUFFER) {\r
1042 Width = IfrDefault->Header.Length - OFFSET_OF (EFI_IFR_DEFAULT, Value);\r
1043 }\r
1044 }\r
1045\r
1046 //\r
1047 // Update the default value\r
1048 //\r
1049 if (Width > 0) {\r
1050 EfiVarStoreIndex = IsEfiVarStoreQuestion (IfrQuestionHdr, EfiVarStoreList, EfiVarStoreNumber);\r
1051 if (EfiVarStoreIndex < EfiVarStoreNumber) {\r
1052 Status = FindQuestionDefaultSetting (IfrDefault->DefaultId, EfiVarStoreList[EfiVarStoreIndex], IfrQuestionHdr, &IfrDefault->Value, Width, QuestionReferBitField);\r
1053 }\r
1054 }\r
1055 }\r
1056\r
1057 break;\r
1058 case EFI_IFR_END_OP:\r
1059 if (IfrQuestionHdr != NULL) {\r
1060 if (IfrScope > 0) {\r
1061 IfrScope--;\r
1062 }\r
1063\r
1064 if (IfrScope == 0) {\r
1065 IfrQuestionHdr = NULL;\r
1066 QuestionReferBitField = FALSE;\r
1067 }\r
1068 }\r
1069\r
1070 break;\r
1071 case EFI_IFR_GUID_OP:\r
1072 if (CompareGuid ((EFI_GUID *)((UINT8 *)IfrOpHdr + sizeof (EFI_IFR_OP_HEADER)), &gEdkiiIfrBitVarstoreGuid)) {\r
1073 QuestionReferBitField = TRUE;\r
1074 }\r
1075\r
1076 break;\r
1077 default:\r
1078 break;\r
1079 }\r
1080\r
1081 IfrOffset = IfrOffset + IfrOpHdr->Length;\r
1082 IfrOpHdr = (EFI_IFR_OP_HEADER *)((UINT8 *)IfrOpHdr + IfrOpHdr->Length);\r
1083 if (IfrScope > 0) {\r
1084 IfrScope += IfrOpHdr->Scope;\r
1085 }\r
1086 }\r
1087\r
1088Done:\r
1089 if (EfiVarStoreList != NULL) {\r
1090 for (Index = 0; Index < EfiVarStoreNumber; Index++) {\r
1091 FreePool (EfiVarStoreList[Index]);\r
1092 }\r
1093 }\r
1094\r
1095 return;\r
1096}\r
1097\r
1098/**\r
1099 This function insert a Form package to a package list node.\r
1100 This is a internal function.\r
1101\r
1102 @param PackageHdr Pointer to a buffer stored with Form package\r
1103 information.\r
1104 @param NotifyType The type of change concerning the database.\r
1105 @param PackageList Pointer to a package list which will be inserted\r
1106 to.\r
1107 @param Package Created Form package\r
1108\r
1109 @retval EFI_SUCCESS Form Package is inserted successfully.\r
1110 @retval EFI_OUT_OF_RESOURCES Unable to allocate necessary resources for the new\r
1111 Form package.\r
1112 @retval EFI_INVALID_PARAMETER PackageHdr is NULL or PackageList is NULL.\r
1113\r
1114**/\r
1115EFI_STATUS\r
1116InsertFormPackage (\r
1117 IN VOID *PackageHdr,\r
1118 IN EFI_HII_DATABASE_NOTIFY_TYPE NotifyType,\r
1119 IN OUT HII_DATABASE_PACKAGE_LIST_INSTANCE *PackageList,\r
1120 OUT HII_IFR_PACKAGE_INSTANCE **Package\r
1121 )\r
1122{\r
1123 HII_IFR_PACKAGE_INSTANCE *FormPackage;\r
1124 EFI_HII_PACKAGE_HEADER PackageHeader;\r
1125\r
1126 if ((PackageHdr == NULL) || (PackageList == NULL)) {\r
1127 return EFI_INVALID_PARAMETER;\r
1128 }\r
1129\r
1130 //\r
1131 // Get the length of the package, including package header itself\r
1132 //\r
1133 CopyMem (&PackageHeader, PackageHdr, sizeof (EFI_HII_PACKAGE_HEADER));\r
1134\r
1135 //\r
1136 // Create a Form package node\r
1137 //\r
1138 FormPackage = (HII_IFR_PACKAGE_INSTANCE *)AllocateZeroPool (sizeof (HII_IFR_PACKAGE_INSTANCE));\r
1139 if (FormPackage == NULL) {\r
1140 return EFI_OUT_OF_RESOURCES;\r
1141 }\r
1142\r
1143 FormPackage->IfrData = (UINT8 *)AllocateZeroPool (PackageHeader.Length - sizeof (EFI_HII_PACKAGE_HEADER));\r
1144 if (FormPackage->IfrData == NULL) {\r
1145 FreePool (FormPackage);\r
1146 return EFI_OUT_OF_RESOURCES;\r
1147 }\r
1148\r
1149 FormPackage->Signature = HII_IFR_PACKAGE_SIGNATURE;\r
1150 //\r
1151 // Copy Package Header\r
1152 //\r
1153 CopyMem (&FormPackage->FormPkgHdr, &PackageHeader, sizeof (EFI_HII_PACKAGE_HEADER));\r
1154\r
1155 //\r
1156 // Copy Ifr contents\r
1157 //\r
1158 CopyMem (\r
1159 FormPackage->IfrData,\r
1160 (UINT8 *)PackageHdr + sizeof (EFI_HII_PACKAGE_HEADER),\r
1161 PackageHeader.Length - sizeof (EFI_HII_PACKAGE_HEADER)\r
1162 );\r
1163\r
1164 InsertTailList (&PackageList->FormPkgHdr, &FormPackage->IfrEntry);\r
1165 *Package = FormPackage;\r
1166\r
1167 //\r
1168 // Update FormPackage with the default setting\r
1169 //\r
1170 UpdateDefaultSettingInFormPackage (FormPackage);\r
1171\r
1172 if (NotifyType == EFI_HII_DATABASE_NOTIFY_ADD_PACK) {\r
1173 PackageList->PackageListHdr.PackageLength += FormPackage->FormPkgHdr.Length;\r
1174 }\r
1175\r
1176 return EFI_SUCCESS;\r
1177}\r
1178\r
1179/**\r
1180 This function exports Form packages to a buffer.\r
1181 This is a internal function.\r
1182\r
1183 @param Private Hii database private structure.\r
1184 @param Handle Identification of a package list.\r
1185 @param PackageList Pointer to a package list which will be exported.\r
1186 @param UsedSize The length of buffer be used.\r
1187 @param BufferSize Length of the Buffer.\r
1188 @param Buffer Allocated space for storing exported data.\r
1189 @param ResultSize The size of the already exported content of this\r
1190 package list.\r
1191\r
1192 @retval EFI_SUCCESS Form Packages are exported successfully.\r
1193 @retval EFI_INVALID_PARAMETER Any input parameter is invalid.\r
1194\r
1195**/\r
1196EFI_STATUS\r
1197ExportFormPackages (\r
1198 IN HII_DATABASE_PRIVATE_DATA *Private,\r
1199 IN EFI_HII_HANDLE Handle,\r
1200 IN HII_DATABASE_PACKAGE_LIST_INSTANCE *PackageList,\r
1201 IN UINTN UsedSize,\r
1202 IN UINTN BufferSize,\r
1203 IN OUT VOID *Buffer,\r
1204 IN OUT UINTN *ResultSize\r
1205 )\r
1206{\r
1207 HII_IFR_PACKAGE_INSTANCE *FormPackage;\r
1208 UINTN PackageLength;\r
1209 LIST_ENTRY *Link;\r
1210 EFI_STATUS Status;\r
1211\r
1212 if ((Private == NULL) || (PackageList == NULL) || (ResultSize == NULL)) {\r
1213 return EFI_INVALID_PARAMETER;\r
1214 }\r
1215\r
1216 if ((BufferSize > 0) && (Buffer == NULL)) {\r
1217 return EFI_INVALID_PARAMETER;\r
1218 }\r
1219\r
1220 PackageLength = 0;\r
1221 Status = EFI_SUCCESS;\r
1222\r
1223 //\r
1224 // Export Form packages.\r
1225 //\r
1226 for (Link = PackageList->FormPkgHdr.ForwardLink; Link != &PackageList->FormPkgHdr; Link = Link->ForwardLink) {\r
1227 FormPackage = CR (Link, HII_IFR_PACKAGE_INSTANCE, IfrEntry, HII_IFR_PACKAGE_SIGNATURE);\r
1228 PackageLength += FormPackage->FormPkgHdr.Length;\r
1229 if ((Buffer != NULL) && (PackageLength + *ResultSize + UsedSize <= BufferSize)) {\r
1230 //\r
1231 // Invoke registered notification if exists\r
1232 //\r
1233 Status = InvokeRegisteredFunction (\r
1234 Private,\r
1235 EFI_HII_DATABASE_NOTIFY_EXPORT_PACK,\r
1236 (VOID *)FormPackage,\r
1237 EFI_HII_PACKAGE_FORMS,\r
1238 Handle\r
1239 );\r
1240 ASSERT_EFI_ERROR (Status);\r
1241 //\r
1242 // Copy the Form package content.\r
1243 //\r
1244 CopyMem (Buffer, (VOID *)(&FormPackage->FormPkgHdr), sizeof (EFI_HII_PACKAGE_HEADER));\r
1245 Buffer = (UINT8 *)Buffer + sizeof (EFI_HII_PACKAGE_HEADER);\r
1246 CopyMem (\r
1247 Buffer,\r
1248 (VOID *)FormPackage->IfrData,\r
1249 FormPackage->FormPkgHdr.Length - sizeof (EFI_HII_PACKAGE_HEADER)\r
1250 );\r
1251 Buffer = (UINT8 *)Buffer + FormPackage->FormPkgHdr.Length - sizeof (EFI_HII_PACKAGE_HEADER);\r
1252 }\r
1253 }\r
1254\r
1255 *ResultSize += PackageLength;\r
1256\r
1257 return EFI_SUCCESS;\r
1258}\r
1259\r
1260/**\r
1261 This function deletes all Form packages from a package list node.\r
1262 This is a internal function.\r
1263\r
1264 @param Private Hii database private data.\r
1265 @param Handle Handle of the package list which contains the to\r
1266 be removed Form packages.\r
1267 @param PackageList Pointer to a package list that contains removing\r
1268 packages.\r
1269\r
1270 @retval EFI_SUCCESS Form Package(s) is deleted successfully.\r
1271 @retval EFI_INVALID_PARAMETER Any input parameter is not valid.\r
1272\r
1273**/\r
1274EFI_STATUS\r
1275RemoveFormPackages (\r
1276 IN HII_DATABASE_PRIVATE_DATA *Private,\r
1277 IN EFI_HII_HANDLE Handle,\r
1278 IN OUT HII_DATABASE_PACKAGE_LIST_INSTANCE *PackageList\r
1279 )\r
1280{\r
1281 LIST_ENTRY *ListHead;\r
1282 HII_IFR_PACKAGE_INSTANCE *Package;\r
1283 EFI_STATUS Status;\r
1284\r
1285 ListHead = &PackageList->FormPkgHdr;\r
1286\r
1287 while (!IsListEmpty (ListHead)) {\r
1288 Package = CR (\r
1289 ListHead->ForwardLink,\r
1290 HII_IFR_PACKAGE_INSTANCE,\r
1291 IfrEntry,\r
1292 HII_IFR_PACKAGE_SIGNATURE\r
1293 );\r
1294 Status = InvokeRegisteredFunction (\r
1295 Private,\r
1296 EFI_HII_DATABASE_NOTIFY_REMOVE_PACK,\r
1297 (VOID *)Package,\r
1298 EFI_HII_PACKAGE_FORMS,\r
1299 Handle\r
1300 );\r
1301 if (EFI_ERROR (Status)) {\r
1302 return Status;\r
1303 }\r
1304\r
1305 RemoveEntryList (&Package->IfrEntry);\r
1306 PackageList->PackageListHdr.PackageLength -= Package->FormPkgHdr.Length;\r
1307 FreePool (Package->IfrData);\r
1308 FreePool (Package);\r
1309 //\r
1310 // If Hii runtime support feature is enabled,\r
1311 // will export Hii info for runtime use after ReadyToBoot event triggered.\r
1312 // If some driver add/update/remove packages from HiiDatabase after ReadyToBoot,\r
1313 // will need to export the content of HiiDatabase.\r
1314 // But if form packages removed, also need to export the ConfigResp string\r
1315 //\r
1316 if (gExportAfterReadyToBoot) {\r
1317 gExportConfigResp = TRUE;\r
1318 }\r
1319 }\r
1320\r
1321 return EFI_SUCCESS;\r
1322}\r
1323\r
1324/**\r
1325 This function insert a String package to a package list node.\r
1326 This is a internal function.\r
1327\r
1328 @param Private Hii database private structure.\r
1329 @param PackageHdr Pointer to a buffer stored with String package\r
1330 information.\r
1331 @param NotifyType The type of change concerning the database.\r
1332 @param PackageList Pointer to a package list which will be inserted\r
1333 to.\r
1334 @param Package Created String package\r
1335\r
1336 @retval EFI_SUCCESS String Package is inserted successfully.\r
1337 @retval EFI_OUT_OF_RESOURCES Unable to allocate necessary resources for the new\r
1338 String package.\r
1339 @retval EFI_INVALID_PARAMETER PackageHdr is NULL or PackageList is NULL.\r
1340 @retval EFI_UNSUPPORTED A string package with the same language already\r
1341 exists in current package list.\r
1342\r
1343**/\r
1344EFI_STATUS\r
1345InsertStringPackage (\r
1346 IN HII_DATABASE_PRIVATE_DATA *Private,\r
1347 IN VOID *PackageHdr,\r
1348 IN EFI_HII_DATABASE_NOTIFY_TYPE NotifyType,\r
1349 IN OUT HII_DATABASE_PACKAGE_LIST_INSTANCE *PackageList,\r
1350 OUT HII_STRING_PACKAGE_INSTANCE **Package\r
1351 )\r
1352{\r
1353 HII_STRING_PACKAGE_INSTANCE *StringPackage;\r
1354 UINT32 HeaderSize;\r
1355 EFI_STATUS Status;\r
1356 EFI_HII_PACKAGE_HEADER PackageHeader;\r
1357 CHAR8 *Language;\r
1358 UINT32 LanguageSize;\r
1359 LIST_ENTRY *Link;\r
1360\r
1361 if ((Private == NULL) || (PackageHdr == NULL) || (PackageList == NULL)) {\r
1362 return EFI_INVALID_PARAMETER;\r
1363 }\r
1364\r
1365 if (Private->Signature != HII_DATABASE_PRIVATE_DATA_SIGNATURE) {\r
1366 return EFI_INVALID_PARAMETER;\r
1367 }\r
1368\r
1369 CopyMem (&PackageHeader, PackageHdr, sizeof (EFI_HII_PACKAGE_HEADER));\r
1370 CopyMem (&HeaderSize, (UINT8 *)PackageHdr + sizeof (EFI_HII_PACKAGE_HEADER), sizeof (UINT32));\r
1371\r
1372 //\r
1373 // It is illegal to have two string packages with same language within one packagelist\r
1374 // since the stringid will be duplicate if so. Check it to avoid this potential issue.\r
1375 //\r
1376 LanguageSize = HeaderSize - sizeof (EFI_HII_STRING_PACKAGE_HDR) + sizeof (CHAR8);\r
1377 Language = (CHAR8 *)AllocateZeroPool (LanguageSize);\r
1378 if (Language == NULL) {\r
1379 return EFI_OUT_OF_RESOURCES;\r
1380 }\r
1381\r
1382 AsciiStrCpyS (Language, LanguageSize / sizeof (CHAR8), (CHAR8 *)PackageHdr + HeaderSize - LanguageSize);\r
1383 for (Link = PackageList->StringPkgHdr.ForwardLink; Link != &PackageList->StringPkgHdr; Link = Link->ForwardLink) {\r
1384 StringPackage = CR (Link, HII_STRING_PACKAGE_INSTANCE, StringEntry, HII_STRING_PACKAGE_SIGNATURE);\r
1385 if (HiiCompareLanguage (Language, StringPackage->StringPkgHdr->Language)) {\r
1386 FreePool (Language);\r
1387 return EFI_UNSUPPORTED;\r
1388 }\r
1389 }\r
1390\r
1391 FreePool (Language);\r
1392\r
1393 //\r
1394 // Create a String package node\r
1395 //\r
1396 StringPackage = (HII_STRING_PACKAGE_INSTANCE *)AllocateZeroPool (sizeof (HII_STRING_PACKAGE_INSTANCE));\r
1397 if (StringPackage == NULL) {\r
1398 Status = EFI_OUT_OF_RESOURCES;\r
1399 goto Error;\r
1400 }\r
1401\r
1402 StringPackage->StringPkgHdr = (EFI_HII_STRING_PACKAGE_HDR *)AllocateZeroPool (HeaderSize);\r
1403 if (StringPackage->StringPkgHdr == NULL) {\r
1404 Status = EFI_OUT_OF_RESOURCES;\r
1405 goto Error;\r
1406 }\r
1407\r
1408 StringPackage->StringBlock = (UINT8 *)AllocateZeroPool (PackageHeader.Length - HeaderSize);\r
1409 if (StringPackage->StringBlock == NULL) {\r
1410 Status = EFI_OUT_OF_RESOURCES;\r
1411 goto Error;\r
1412 }\r
1413\r
1414 StringPackage->Signature = HII_STRING_PACKAGE_SIGNATURE;\r
1415 StringPackage->FontId = 0;\r
1416 InitializeListHead (&StringPackage->FontInfoList);\r
1417\r
1418 //\r
1419 // Copy the String package header.\r
1420 //\r
1421 CopyMem (StringPackage->StringPkgHdr, PackageHdr, HeaderSize);\r
1422\r
1423 //\r
1424 // Copy the String blocks\r
1425 //\r
1426 CopyMem (\r
1427 StringPackage->StringBlock,\r
1428 (UINT8 *)PackageHdr + HeaderSize,\r
1429 PackageHeader.Length - HeaderSize\r
1430 );\r
1431\r
1432 //\r
1433 // Collect all font block info\r
1434 //\r
1435 Status = FindStringBlock (Private, StringPackage, (EFI_STRING_ID)(-1), NULL, NULL, NULL, &StringPackage->MaxStringId, NULL);\r
1436 if (EFI_ERROR (Status)) {\r
1437 return Status;\r
1438 }\r
1439\r
1440 //\r
1441 // Insert to String package array\r
1442 //\r
1443 InsertTailList (&PackageList->StringPkgHdr, &StringPackage->StringEntry);\r
1444 *Package = StringPackage;\r
1445\r
1446 if (NotifyType == EFI_HII_DATABASE_NOTIFY_ADD_PACK) {\r
1447 PackageList->PackageListHdr.PackageLength += StringPackage->StringPkgHdr->Header.Length;\r
1448 }\r
1449\r
1450 return EFI_SUCCESS;\r
1451\r
1452Error:\r
1453\r
1454 if (StringPackage != NULL) {\r
1455 if (StringPackage->StringBlock != NULL) {\r
1456 FreePool (StringPackage->StringBlock);\r
1457 }\r
1458\r
1459 if (StringPackage->StringPkgHdr != NULL) {\r
1460 FreePool (StringPackage->StringPkgHdr);\r
1461 }\r
1462\r
1463 FreePool (StringPackage);\r
1464 }\r
1465\r
1466 return Status;\r
1467}\r
1468\r
1469/**\r
1470 Adjust all string packages in a single package list to have the same max string ID.\r
1471\r
1472 @param PackageList Pointer to a package list which will be adjusted.\r
1473\r
1474 @retval EFI_SUCCESS Adjust all string packages successfully.\r
1475 @retval others Can't adjust string packages.\r
1476\r
1477**/\r
1478EFI_STATUS\r
1479AdjustStringPackage (\r
1480 IN OUT HII_DATABASE_PACKAGE_LIST_INSTANCE *PackageList\r
1481 )\r
1482{\r
1483 LIST_ENTRY *Link;\r
1484 HII_STRING_PACKAGE_INSTANCE *StringPackage;\r
1485 UINT32 Skip2BlockSize;\r
1486 UINT32 OldBlockSize;\r
1487 UINT8 *StringBlock;\r
1488 UINT8 *BlockPtr;\r
1489 EFI_STRING_ID MaxStringId;\r
1490 UINT16 SkipCount;\r
1491\r
1492 MaxStringId = 0;\r
1493 for (Link = PackageList->StringPkgHdr.ForwardLink;\r
1494 Link != &PackageList->StringPkgHdr;\r
1495 Link = Link->ForwardLink\r
1496 )\r
1497 {\r
1498 StringPackage = CR (Link, HII_STRING_PACKAGE_INSTANCE, StringEntry, HII_STRING_PACKAGE_SIGNATURE);\r
1499 if (MaxStringId < StringPackage->MaxStringId) {\r
1500 MaxStringId = StringPackage->MaxStringId;\r
1501 }\r
1502 }\r
1503\r
1504 for (Link = PackageList->StringPkgHdr.ForwardLink;\r
1505 Link != &PackageList->StringPkgHdr;\r
1506 Link = Link->ForwardLink\r
1507 )\r
1508 {\r
1509 StringPackage = CR (Link, HII_STRING_PACKAGE_INSTANCE, StringEntry, HII_STRING_PACKAGE_SIGNATURE);\r
1510 if (StringPackage->MaxStringId < MaxStringId) {\r
1511 OldBlockSize = StringPackage->StringPkgHdr->Header.Length - StringPackage->StringPkgHdr->HdrSize;\r
1512 //\r
1513 // Create SKIP2 EFI_HII_SIBT_SKIP2_BLOCKs to reserve the missing string IDs.\r
1514 //\r
1515 SkipCount = (UINT16)(MaxStringId - StringPackage->MaxStringId);\r
1516 Skip2BlockSize = (UINT32)sizeof (EFI_HII_SIBT_SKIP2_BLOCK);\r
1517\r
1518 StringBlock = (UINT8 *)AllocateZeroPool (OldBlockSize + Skip2BlockSize);\r
1519 if (StringBlock == NULL) {\r
1520 return EFI_OUT_OF_RESOURCES;\r
1521 }\r
1522\r
1523 //\r
1524 // Copy original string blocks, except the EFI_HII_SIBT_END.\r
1525 //\r
1526 CopyMem (StringBlock, StringPackage->StringBlock, OldBlockSize - sizeof (EFI_HII_SIBT_END_BLOCK));\r
1527 //\r
1528 // Create SKIP2 EFI_HII_SIBT_SKIP2_BLOCK blocks\r
1529 //\r
1530 BlockPtr = StringBlock + OldBlockSize - sizeof (EFI_HII_SIBT_END_BLOCK);\r
1531 *BlockPtr = EFI_HII_SIBT_SKIP2;\r
1532 CopyMem (BlockPtr + 1, &SkipCount, sizeof (UINT16));\r
1533 BlockPtr += sizeof (EFI_HII_SIBT_SKIP2_BLOCK);\r
1534\r
1535 //\r
1536 // Append a EFI_HII_SIBT_END block to the end.\r
1537 //\r
1538 *BlockPtr = EFI_HII_SIBT_END;\r
1539 FreePool (StringPackage->StringBlock);\r
1540 StringPackage->StringBlock = StringBlock;\r
1541 StringPackage->StringPkgHdr->Header.Length += Skip2BlockSize;\r
1542 PackageList->PackageListHdr.PackageLength += Skip2BlockSize;\r
1543 StringPackage->MaxStringId = MaxStringId;\r
1544 }\r
1545 }\r
1546\r
1547 return EFI_SUCCESS;\r
1548}\r
1549\r
1550/**\r
1551 This function exports String packages to a buffer.\r
1552 This is a internal function.\r
1553\r
1554 @param Private Hii database private structure.\r
1555 @param Handle Identification of a package list.\r
1556 @param PackageList Pointer to a package list which will be exported.\r
1557 @param UsedSize The length of buffer be used.\r
1558 @param BufferSize Length of the Buffer.\r
1559 @param Buffer Allocated space for storing exported data.\r
1560 @param ResultSize The size of the already exported content of this\r
1561 package list.\r
1562\r
1563 @retval EFI_SUCCESS String Packages are exported successfully.\r
1564 @retval EFI_INVALID_PARAMETER Any input parameter is invalid.\r
1565\r
1566**/\r
1567EFI_STATUS\r
1568ExportStringPackages (\r
1569 IN HII_DATABASE_PRIVATE_DATA *Private,\r
1570 IN EFI_HII_HANDLE Handle,\r
1571 IN HII_DATABASE_PACKAGE_LIST_INSTANCE *PackageList,\r
1572 IN UINTN UsedSize,\r
1573 IN UINTN BufferSize,\r
1574 IN OUT VOID *Buffer,\r
1575 IN OUT UINTN *ResultSize\r
1576 )\r
1577{\r
1578 LIST_ENTRY *Link;\r
1579 UINTN PackageLength;\r
1580 EFI_STATUS Status;\r
1581 HII_STRING_PACKAGE_INSTANCE *StringPackage;\r
1582\r
1583 if ((Private == NULL) || (PackageList == NULL) || (ResultSize == NULL)) {\r
1584 return EFI_INVALID_PARAMETER;\r
1585 }\r
1586\r
1587 if ((BufferSize > 0) && (Buffer == NULL)) {\r
1588 return EFI_INVALID_PARAMETER;\r
1589 }\r
1590\r
1591 PackageLength = 0;\r
1592 Status = EFI_SUCCESS;\r
1593\r
1594 for (Link = PackageList->StringPkgHdr.ForwardLink; Link != &PackageList->StringPkgHdr; Link = Link->ForwardLink) {\r
1595 StringPackage = CR (Link, HII_STRING_PACKAGE_INSTANCE, StringEntry, HII_STRING_PACKAGE_SIGNATURE);\r
1596 PackageLength += StringPackage->StringPkgHdr->Header.Length;\r
1597 if (PackageLength + *ResultSize + UsedSize <= BufferSize) {\r
1598 //\r
1599 // Invoke registered notification function with EXPORT_PACK notify type\r
1600 //\r
1601 Status = InvokeRegisteredFunction (\r
1602 Private,\r
1603 EFI_HII_DATABASE_NOTIFY_EXPORT_PACK,\r
1604 (VOID *)StringPackage,\r
1605 EFI_HII_PACKAGE_STRINGS,\r
1606 Handle\r
1607 );\r
1608 ASSERT_EFI_ERROR (Status);\r
1609 //\r
1610 // Copy String package header\r
1611 //\r
1612 CopyMem (Buffer, StringPackage->StringPkgHdr, StringPackage->StringPkgHdr->HdrSize);\r
1613 Buffer = (UINT8 *)Buffer + StringPackage->StringPkgHdr->HdrSize;\r
1614\r
1615 //\r
1616 // Copy String blocks information\r
1617 //\r
1618 CopyMem (\r
1619 Buffer,\r
1620 StringPackage->StringBlock,\r
1621 StringPackage->StringPkgHdr->Header.Length - StringPackage->StringPkgHdr->HdrSize\r
1622 );\r
1623 Buffer = (UINT8 *)Buffer + StringPackage->StringPkgHdr->Header.Length - StringPackage->StringPkgHdr->HdrSize;\r
1624 }\r
1625 }\r
1626\r
1627 *ResultSize += PackageLength;\r
1628 return EFI_SUCCESS;\r
1629}\r
1630\r
1631/**\r
1632 This function deletes all String packages from a package list node.\r
1633 This is a internal function.\r
1634\r
1635 @param Private Hii database private data.\r
1636 @param Handle Handle of the package list which contains the to\r
1637 be removed String packages.\r
1638 @param PackageList Pointer to a package list that contains removing\r
1639 packages.\r
1640\r
1641 @retval EFI_SUCCESS String Package(s) is deleted successfully.\r
1642 @retval EFI_INVALID_PARAMETER Any input parameter is not valid.\r
1643\r
1644**/\r
1645EFI_STATUS\r
1646RemoveStringPackages (\r
1647 IN HII_DATABASE_PRIVATE_DATA *Private,\r
1648 IN EFI_HII_HANDLE Handle,\r
1649 IN OUT HII_DATABASE_PACKAGE_LIST_INSTANCE *PackageList\r
1650 )\r
1651{\r
1652 LIST_ENTRY *ListHead;\r
1653 HII_STRING_PACKAGE_INSTANCE *Package;\r
1654 HII_FONT_INFO *FontInfo;\r
1655 EFI_STATUS Status;\r
1656\r
1657 ListHead = &PackageList->StringPkgHdr;\r
1658\r
1659 while (!IsListEmpty (ListHead)) {\r
1660 Package = CR (\r
1661 ListHead->ForwardLink,\r
1662 HII_STRING_PACKAGE_INSTANCE,\r
1663 StringEntry,\r
1664 HII_STRING_PACKAGE_SIGNATURE\r
1665 );\r
1666 Status = InvokeRegisteredFunction (\r
1667 Private,\r
1668 EFI_HII_DATABASE_NOTIFY_REMOVE_PACK,\r
1669 (VOID *)Package,\r
1670 EFI_HII_PACKAGE_STRINGS,\r
1671 Handle\r
1672 );\r
1673 if (EFI_ERROR (Status)) {\r
1674 return Status;\r
1675 }\r
1676\r
1677 RemoveEntryList (&Package->StringEntry);\r
1678 PackageList->PackageListHdr.PackageLength -= Package->StringPkgHdr->Header.Length;\r
1679 FreePool (Package->StringBlock);\r
1680 FreePool (Package->StringPkgHdr);\r
1681 //\r
1682 // Delete font information\r
1683 //\r
1684 while (!IsListEmpty (&Package->FontInfoList)) {\r
1685 FontInfo = CR (\r
1686 Package->FontInfoList.ForwardLink,\r
1687 HII_FONT_INFO,\r
1688 Entry,\r
1689 HII_FONT_INFO_SIGNATURE\r
1690 );\r
1691 RemoveEntryList (&FontInfo->Entry);\r
1692 FreePool (FontInfo);\r
1693 }\r
1694\r
1695 FreePool (Package);\r
1696 }\r
1697\r
1698 return EFI_SUCCESS;\r
1699}\r
1700\r
1701/**\r
1702 This function insert a Font package to a package list node.\r
1703 This is a internal function.\r
1704\r
1705 @param Private Hii database private structure.\r
1706 @param PackageHdr Pointer to a buffer stored with Font package\r
1707 information.\r
1708 @param NotifyType The type of change concerning the database.\r
1709 @param PackageList Pointer to a package list which will be inserted\r
1710 to.\r
1711 @param Package Created Font package\r
1712\r
1713 @retval EFI_SUCCESS Font Package is inserted successfully.\r
1714 @retval EFI_OUT_OF_RESOURCES Unable to allocate necessary resources for the new\r
1715 Font package.\r
1716 @retval EFI_INVALID_PARAMETER PackageHdr is NULL or PackageList is NULL.\r
1717 @retval EFI_UNSUPPORTED A font package with same EFI_FONT_INFO already\r
1718 exists in current hii database.\r
1719\r
1720**/\r
1721EFI_STATUS\r
1722InsertFontPackage (\r
1723 IN HII_DATABASE_PRIVATE_DATA *Private,\r
1724 IN VOID *PackageHdr,\r
1725 IN EFI_HII_DATABASE_NOTIFY_TYPE NotifyType,\r
1726 IN OUT HII_DATABASE_PACKAGE_LIST_INSTANCE *PackageList,\r
1727 OUT HII_FONT_PACKAGE_INSTANCE **Package\r
1728 )\r
1729{\r
1730 HII_FONT_PACKAGE_INSTANCE *FontPackage;\r
1731 EFI_HII_FONT_PACKAGE_HDR *FontPkgHdr;\r
1732 UINT32 HeaderSize;\r
1733 EFI_STATUS Status;\r
1734 EFI_HII_PACKAGE_HEADER PackageHeader;\r
1735 EFI_FONT_INFO *FontInfo;\r
1736 UINT32 FontInfoSize;\r
1737 HII_GLOBAL_FONT_INFO *GlobalFont;\r
1738\r
1739 if ((Private == NULL) || (PackageHdr == NULL) || (PackageList == NULL)) {\r
1740 return EFI_INVALID_PARAMETER;\r
1741 }\r
1742\r
1743 CopyMem (&PackageHeader, PackageHdr, sizeof (EFI_HII_PACKAGE_HEADER));\r
1744 CopyMem (&HeaderSize, (UINT8 *)PackageHdr + sizeof (EFI_HII_PACKAGE_HEADER), sizeof (UINT32));\r
1745\r
1746 FontInfo = NULL;\r
1747 FontPackage = NULL;\r
1748 GlobalFont = NULL;\r
1749\r
1750 //\r
1751 // It is illegal to have two font packages with same EFI_FONT_INFO within hii\r
1752 // database. EFI_FONT_INFO (FontName, FontSize, FontStyle) describes font's\r
1753 // attributes and identify a font uniquely.\r
1754 //\r
1755 FontPkgHdr = (EFI_HII_FONT_PACKAGE_HDR *)AllocateZeroPool (HeaderSize);\r
1756 if (FontPkgHdr == NULL) {\r
1757 Status = EFI_OUT_OF_RESOURCES;\r
1758 goto Error;\r
1759 }\r
1760\r
1761 CopyMem (FontPkgHdr, PackageHdr, HeaderSize);\r
1762\r
1763 FontInfoSize = sizeof (EFI_FONT_INFO) + HeaderSize - sizeof (EFI_HII_FONT_PACKAGE_HDR);\r
1764 FontInfo = (EFI_FONT_INFO *)AllocateZeroPool (FontInfoSize);\r
1765 if (FontInfo == NULL) {\r
1766 Status = EFI_OUT_OF_RESOURCES;\r
1767 goto Error;\r
1768 }\r
1769\r
1770 FontInfo->FontStyle = FontPkgHdr->FontStyle;\r
1771 FontInfo->FontSize = FontPkgHdr->Cell.Height;\r
1772 StrCpyS (FontInfo->FontName, (FontInfoSize - OFFSET_OF (EFI_FONT_INFO, FontName)) / sizeof (CHAR16), FontPkgHdr->FontFamily);\r
1773\r
1774 if (IsFontInfoExisted (Private, FontInfo, NULL, NULL, NULL)) {\r
1775 Status = EFI_UNSUPPORTED;\r
1776 goto Error;\r
1777 }\r
1778\r
1779 //\r
1780 // Create a Font package node\r
1781 //\r
1782 FontPackage = (HII_FONT_PACKAGE_INSTANCE *)AllocateZeroPool (sizeof (HII_FONT_PACKAGE_INSTANCE));\r
1783 if (FontPackage == NULL) {\r
1784 Status = EFI_OUT_OF_RESOURCES;\r
1785 goto Error;\r
1786 }\r
1787\r
1788 FontPackage->Signature = HII_FONT_PACKAGE_SIGNATURE;\r
1789 FontPackage->FontPkgHdr = FontPkgHdr;\r
1790 InitializeListHead (&FontPackage->GlyphInfoList);\r
1791\r
1792 FontPackage->GlyphBlock = (UINT8 *)AllocateZeroPool (PackageHeader.Length - HeaderSize);\r
1793 if (FontPackage->GlyphBlock == NULL) {\r
1794 Status = EFI_OUT_OF_RESOURCES;\r
1795 goto Error;\r
1796 }\r
1797\r
1798 CopyMem (FontPackage->GlyphBlock, (UINT8 *)PackageHdr + HeaderSize, PackageHeader.Length - HeaderSize);\r
1799\r
1800 //\r
1801 // Collect all default character cell information and backup in GlyphInfoList.\r
1802 //\r
1803 Status = FindGlyphBlock (FontPackage, (CHAR16)(-1), NULL, NULL, NULL);\r
1804 if (EFI_ERROR (Status)) {\r
1805 goto Error;\r
1806 }\r
1807\r
1808 //\r
1809 // This font package describes an unique EFI_FONT_INFO. Backup it in global\r
1810 // font info list.\r
1811 //\r
1812 GlobalFont = (HII_GLOBAL_FONT_INFO *)AllocateZeroPool (sizeof (HII_GLOBAL_FONT_INFO));\r
1813 if (GlobalFont == NULL) {\r
1814 Status = EFI_OUT_OF_RESOURCES;\r
1815 goto Error;\r
1816 }\r
1817\r
1818 GlobalFont->Signature = HII_GLOBAL_FONT_INFO_SIGNATURE;\r
1819 GlobalFont->FontPackage = FontPackage;\r
1820 GlobalFont->FontInfoSize = FontInfoSize;\r
1821 GlobalFont->FontInfo = FontInfo;\r
1822 InsertTailList (&Private->FontInfoList, &GlobalFont->Entry);\r
1823\r
1824 //\r
1825 // Insert this font package to Font package array\r
1826 //\r
1827 InsertTailList (&PackageList->FontPkgHdr, &FontPackage->FontEntry);\r
1828 *Package = FontPackage;\r
1829\r
1830 if (NotifyType == EFI_HII_DATABASE_NOTIFY_ADD_PACK) {\r
1831 PackageList->PackageListHdr.PackageLength += FontPackage->FontPkgHdr->Header.Length;\r
1832 }\r
1833\r
1834 return EFI_SUCCESS;\r
1835\r
1836Error:\r
1837\r
1838 if (FontPkgHdr != NULL) {\r
1839 FreePool (FontPkgHdr);\r
1840 }\r
1841\r
1842 if (FontInfo != NULL) {\r
1843 FreePool (FontInfo);\r
1844 }\r
1845\r
1846 if (FontPackage != NULL) {\r
1847 if (FontPackage->GlyphBlock != NULL) {\r
1848 FreePool (FontPackage->GlyphBlock);\r
1849 }\r
1850\r
1851 FreePool (FontPackage);\r
1852 }\r
1853\r
1854 if (GlobalFont != NULL) {\r
1855 FreePool (GlobalFont);\r
1856 }\r
1857\r
1858 return Status;\r
1859}\r
1860\r
1861/**\r
1862 This function exports Font packages to a buffer.\r
1863 This is a internal function.\r
1864\r
1865 @param Private Hii database private structure.\r
1866 @param Handle Identification of a package list.\r
1867 @param PackageList Pointer to a package list which will be exported.\r
1868 @param UsedSize The length of buffer be used.\r
1869 @param BufferSize Length of the Buffer.\r
1870 @param Buffer Allocated space for storing exported data.\r
1871 @param ResultSize The size of the already exported content of this\r
1872 package list.\r
1873\r
1874 @retval EFI_SUCCESS Font Packages are exported successfully.\r
1875 @retval EFI_INVALID_PARAMETER Any input parameter is invalid.\r
1876\r
1877**/\r
1878EFI_STATUS\r
1879ExportFontPackages (\r
1880 IN HII_DATABASE_PRIVATE_DATA *Private,\r
1881 IN EFI_HII_HANDLE Handle,\r
1882 IN HII_DATABASE_PACKAGE_LIST_INSTANCE *PackageList,\r
1883 IN UINTN UsedSize,\r
1884 IN UINTN BufferSize,\r
1885 IN OUT VOID *Buffer,\r
1886 IN OUT UINTN *ResultSize\r
1887 )\r
1888{\r
1889 LIST_ENTRY *Link;\r
1890 UINTN PackageLength;\r
1891 EFI_STATUS Status;\r
1892 HII_FONT_PACKAGE_INSTANCE *Package;\r
1893\r
1894 if ((Private == NULL) || (PackageList == NULL) || (ResultSize == NULL)) {\r
1895 return EFI_INVALID_PARAMETER;\r
1896 }\r
1897\r
1898 if ((BufferSize > 0) && (Buffer == NULL)) {\r
1899 return EFI_INVALID_PARAMETER;\r
1900 }\r
1901\r
1902 PackageLength = 0;\r
1903 Status = EFI_SUCCESS;\r
1904\r
1905 for (Link = PackageList->FontPkgHdr.ForwardLink; Link != &PackageList->FontPkgHdr; Link = Link->ForwardLink) {\r
1906 Package = CR (Link, HII_FONT_PACKAGE_INSTANCE, FontEntry, HII_FONT_PACKAGE_SIGNATURE);\r
1907 PackageLength += Package->FontPkgHdr->Header.Length;\r
1908 if (PackageLength + *ResultSize + UsedSize <= BufferSize) {\r
1909 //\r
1910 // Invoke registered notification function with EXPORT_PACK notify type\r
1911 //\r
1912 Status = InvokeRegisteredFunction (\r
1913 Private,\r
1914 EFI_HII_DATABASE_NOTIFY_EXPORT_PACK,\r
1915 (VOID *)Package,\r
1916 EFI_HII_PACKAGE_FONTS,\r
1917 Handle\r
1918 );\r
1919 ASSERT_EFI_ERROR (Status);\r
1920 //\r
1921 // Copy Font package header\r
1922 //\r
1923 CopyMem (Buffer, Package->FontPkgHdr, Package->FontPkgHdr->HdrSize);\r
1924 Buffer = (UINT8 *)Buffer + Package->FontPkgHdr->HdrSize;\r
1925\r
1926 //\r
1927 // Copy Glyph blocks information\r
1928 //\r
1929 CopyMem (\r
1930 Buffer,\r
1931 Package->GlyphBlock,\r
1932 Package->FontPkgHdr->Header.Length - Package->FontPkgHdr->HdrSize\r
1933 );\r
1934 Buffer = (UINT8 *)Buffer + Package->FontPkgHdr->Header.Length - Package->FontPkgHdr->HdrSize;\r
1935 }\r
1936 }\r
1937\r
1938 *ResultSize += PackageLength;\r
1939 return EFI_SUCCESS;\r
1940}\r
1941\r
1942/**\r
1943 This function deletes all Font packages from a package list node.\r
1944 This is a internal function.\r
1945\r
1946 @param Private Hii database private data.\r
1947 @param Handle Handle of the package list which contains the to\r
1948 be removed Font packages.\r
1949 @param PackageList Pointer to a package list that contains removing\r
1950 packages.\r
1951\r
1952 @retval EFI_SUCCESS Font Package(s) is deleted successfully.\r
1953 @retval EFI_INVALID_PARAMETER Any input parameter is not valid.\r
1954\r
1955**/\r
1956EFI_STATUS\r
1957RemoveFontPackages (\r
1958 IN HII_DATABASE_PRIVATE_DATA *Private,\r
1959 IN EFI_HII_HANDLE Handle,\r
1960 IN OUT HII_DATABASE_PACKAGE_LIST_INSTANCE *PackageList\r
1961 )\r
1962{\r
1963 LIST_ENTRY *ListHead;\r
1964 HII_FONT_PACKAGE_INSTANCE *Package;\r
1965 EFI_STATUS Status;\r
1966 HII_GLYPH_INFO *GlyphInfo;\r
1967 LIST_ENTRY *Link;\r
1968 HII_GLOBAL_FONT_INFO *GlobalFont;\r
1969\r
1970 ListHead = &PackageList->FontPkgHdr;\r
1971\r
1972 while (!IsListEmpty (ListHead)) {\r
1973 Package = CR (\r
1974 ListHead->ForwardLink,\r
1975 HII_FONT_PACKAGE_INSTANCE,\r
1976 FontEntry,\r
1977 HII_FONT_PACKAGE_SIGNATURE\r
1978 );\r
1979 Status = InvokeRegisteredFunction (\r
1980 Private,\r
1981 EFI_HII_DATABASE_NOTIFY_REMOVE_PACK,\r
1982 (VOID *)Package,\r
1983 EFI_HII_PACKAGE_FONTS,\r
1984 Handle\r
1985 );\r
1986 if (EFI_ERROR (Status)) {\r
1987 return Status;\r
1988 }\r
1989\r
1990 RemoveEntryList (&Package->FontEntry);\r
1991 PackageList->PackageListHdr.PackageLength -= Package->FontPkgHdr->Header.Length;\r
1992\r
1993 if (Package->GlyphBlock != NULL) {\r
1994 FreePool (Package->GlyphBlock);\r
1995 }\r
1996\r
1997 FreePool (Package->FontPkgHdr);\r
1998 //\r
1999 // Delete default character cell information\r
2000 //\r
2001 while (!IsListEmpty (&Package->GlyphInfoList)) {\r
2002 GlyphInfo = CR (\r
2003 Package->GlyphInfoList.ForwardLink,\r
2004 HII_GLYPH_INFO,\r
2005 Entry,\r
2006 HII_GLYPH_INFO_SIGNATURE\r
2007 );\r
2008 RemoveEntryList (&GlyphInfo->Entry);\r
2009 FreePool (GlyphInfo);\r
2010 }\r
2011\r
2012 //\r
2013 // Remove corresponding global font info\r
2014 //\r
2015 for (Link = Private->FontInfoList.ForwardLink; Link != &Private->FontInfoList; Link = Link->ForwardLink) {\r
2016 GlobalFont = CR (Link, HII_GLOBAL_FONT_INFO, Entry, HII_GLOBAL_FONT_INFO_SIGNATURE);\r
2017 if (GlobalFont->FontPackage == Package) {\r
2018 RemoveEntryList (&GlobalFont->Entry);\r
2019 FreePool (GlobalFont->FontInfo);\r
2020 FreePool (GlobalFont);\r
2021 break;\r
2022 }\r
2023 }\r
2024\r
2025 FreePool (Package);\r
2026 }\r
2027\r
2028 return EFI_SUCCESS;\r
2029}\r
2030\r
2031/**\r
2032 This function insert a Image package to a package list node.\r
2033 This is a internal function.\r
2034\r
2035 @param PackageHdr Pointer to a buffer stored with Image package\r
2036 information.\r
2037 @param NotifyType The type of change concerning the database.\r
2038 @param PackageList Pointer to a package list which will be inserted\r
2039 to.\r
2040 @param Package Created Image package\r
2041\r
2042 @retval EFI_SUCCESS Image Package is inserted successfully.\r
2043 @retval EFI_OUT_OF_RESOURCES Unable to allocate necessary resources for the new\r
2044 Image package.\r
2045 @retval EFI_INVALID_PARAMETER PackageHdr is NULL or PackageList is NULL.\r
2046\r
2047**/\r
2048EFI_STATUS\r
2049InsertImagePackage (\r
2050 IN VOID *PackageHdr,\r
2051 IN EFI_HII_DATABASE_NOTIFY_TYPE NotifyType,\r
2052 IN OUT HII_DATABASE_PACKAGE_LIST_INSTANCE *PackageList,\r
2053 OUT HII_IMAGE_PACKAGE_INSTANCE **Package\r
2054 )\r
2055{\r
2056 HII_IMAGE_PACKAGE_INSTANCE *ImagePackage;\r
2057 UINT32 PaletteSize;\r
2058 UINT32 ImageSize;\r
2059 UINT16 Index;\r
2060 EFI_HII_IMAGE_PALETTE_INFO_HEADER *PaletteHdr;\r
2061 EFI_HII_IMAGE_PALETTE_INFO *PaletteInfo;\r
2062 UINT32 PaletteInfoOffset;\r
2063 UINT32 ImageInfoOffset;\r
2064 UINT16 CurrentSize;\r
2065\r
2066 if ((PackageHdr == NULL) || (PackageList == NULL)) {\r
2067 return EFI_INVALID_PARAMETER;\r
2068 }\r
2069\r
2070 //\r
2071 // Less than one image package is allowed in one package list.\r
2072 //\r
2073 if (PackageList->ImagePkg != NULL) {\r
2074 return EFI_INVALID_PARAMETER;\r
2075 }\r
2076\r
2077 //\r
2078 // Create a Image package node\r
2079 //\r
2080 ImagePackage = (HII_IMAGE_PACKAGE_INSTANCE *)AllocateZeroPool (sizeof (HII_IMAGE_PACKAGE_INSTANCE));\r
2081 if (ImagePackage == NULL) {\r
2082 return EFI_OUT_OF_RESOURCES;\r
2083 }\r
2084\r
2085 //\r
2086 // Copy the Image package header.\r
2087 //\r
2088 CopyMem (&ImagePackage->ImagePkgHdr, PackageHdr, sizeof (EFI_HII_IMAGE_PACKAGE_HDR));\r
2089\r
2090 PaletteInfoOffset = ImagePackage->ImagePkgHdr.PaletteInfoOffset;\r
2091 ImageInfoOffset = ImagePackage->ImagePkgHdr.ImageInfoOffset;\r
2092\r
2093 //\r
2094 // If PaletteInfoOffset is zero, there are no palettes in this image package.\r
2095 //\r
2096 PaletteSize = 0;\r
2097 ImagePackage->PaletteBlock = NULL;\r
2098 if (PaletteInfoOffset != 0) {\r
2099 PaletteHdr = (EFI_HII_IMAGE_PALETTE_INFO_HEADER *)((UINT8 *)PackageHdr + PaletteInfoOffset);\r
2100 PaletteSize = sizeof (EFI_HII_IMAGE_PALETTE_INFO_HEADER);\r
2101 PaletteInfo = (EFI_HII_IMAGE_PALETTE_INFO *)((UINT8 *)PaletteHdr + PaletteSize);\r
2102\r
2103 for (Index = 0; Index < PaletteHdr->PaletteCount; Index++) {\r
2104 CopyMem (&CurrentSize, PaletteInfo, sizeof (UINT16));\r
2105 CurrentSize += sizeof (UINT16);\r
2106 PaletteSize += (UINT32)CurrentSize;\r
2107 PaletteInfo = (EFI_HII_IMAGE_PALETTE_INFO *)((UINT8 *)PaletteInfo + CurrentSize);\r
2108 }\r
2109\r
2110 ImagePackage->PaletteBlock = (UINT8 *)AllocateZeroPool (PaletteSize);\r
2111 if (ImagePackage->PaletteBlock == NULL) {\r
2112 FreePool (ImagePackage);\r
2113 return EFI_OUT_OF_RESOURCES;\r
2114 }\r
2115\r
2116 CopyMem (\r
2117 ImagePackage->PaletteBlock,\r
2118 (UINT8 *)PackageHdr + PaletteInfoOffset,\r
2119 PaletteSize\r
2120 );\r
2121 }\r
2122\r
2123 //\r
2124 // If ImageInfoOffset is zero, there are no images in this package.\r
2125 //\r
2126 ImageSize = 0;\r
2127 ImagePackage->ImageBlock = NULL;\r
2128 if (ImageInfoOffset != 0) {\r
2129 ImageSize = ImagePackage->ImagePkgHdr.Header.Length -\r
2130 sizeof (EFI_HII_IMAGE_PACKAGE_HDR) - PaletteSize;\r
2131 ImagePackage->ImageBlock = AllocateZeroPool (ImageSize);\r
2132 if (ImagePackage->ImageBlock == NULL) {\r
2133 FreePool (ImagePackage->PaletteBlock);\r
2134 FreePool (ImagePackage);\r
2135 return EFI_OUT_OF_RESOURCES;\r
2136 }\r
2137\r
2138 CopyMem (\r
2139 ImagePackage->ImageBlock,\r
2140 (UINT8 *)PackageHdr + ImageInfoOffset,\r
2141 ImageSize\r
2142 );\r
2143 }\r
2144\r
2145 ImagePackage->ImageBlockSize = ImageSize;\r
2146 ImagePackage->PaletteInfoSize = PaletteSize;\r
2147 PackageList->ImagePkg = ImagePackage;\r
2148 *Package = ImagePackage;\r
2149\r
2150 if (NotifyType == EFI_HII_DATABASE_NOTIFY_ADD_PACK) {\r
2151 PackageList->PackageListHdr.PackageLength += ImagePackage->ImagePkgHdr.Header.Length;\r
2152 }\r
2153\r
2154 return EFI_SUCCESS;\r
2155}\r
2156\r
2157/**\r
2158 This function exports Image packages to a buffer.\r
2159 This is a internal function.\r
2160\r
2161 @param Private Hii database private structure.\r
2162 @param Handle Identification of a package list.\r
2163 @param PackageList Pointer to a package list which will be exported.\r
2164 @param UsedSize The length of buffer be used.\r
2165 @param BufferSize Length of the Buffer.\r
2166 @param Buffer Allocated space for storing exported data.\r
2167 @param ResultSize The size of the already exported content of this\r
2168 package list.\r
2169\r
2170 @retval EFI_SUCCESS Image Packages are exported successfully.\r
2171 @retval EFI_INVALID_PARAMETER Any input parameter is invalid.\r
2172\r
2173**/\r
2174EFI_STATUS\r
2175ExportImagePackages (\r
2176 IN HII_DATABASE_PRIVATE_DATA *Private,\r
2177 IN EFI_HII_HANDLE Handle,\r
2178 IN HII_DATABASE_PACKAGE_LIST_INSTANCE *PackageList,\r
2179 IN UINTN UsedSize,\r
2180 IN UINTN BufferSize,\r
2181 IN OUT VOID *Buffer,\r
2182 IN OUT UINTN *ResultSize\r
2183 )\r
2184{\r
2185 UINTN PackageLength;\r
2186 EFI_STATUS Status;\r
2187 HII_IMAGE_PACKAGE_INSTANCE *Package;\r
2188\r
2189 if ((Private == NULL) || (PackageList == NULL) || (ResultSize == NULL)) {\r
2190 return EFI_INVALID_PARAMETER;\r
2191 }\r
2192\r
2193 if ((BufferSize > 0) && (Buffer == NULL)) {\r
2194 return EFI_INVALID_PARAMETER;\r
2195 }\r
2196\r
2197 Package = PackageList->ImagePkg;\r
2198\r
2199 if (Package == NULL) {\r
2200 return EFI_SUCCESS;\r
2201 }\r
2202\r
2203 PackageLength = Package->ImagePkgHdr.Header.Length;\r
2204\r
2205 if (PackageLength + *ResultSize + UsedSize <= BufferSize) {\r
2206 //\r
2207 // Invoke registered notification function with EXPORT_PACK notify type\r
2208 //\r
2209 Status = InvokeRegisteredFunction (\r
2210 Private,\r
2211 EFI_HII_DATABASE_NOTIFY_EXPORT_PACK,\r
2212 (VOID *)Package,\r
2213 EFI_HII_PACKAGE_IMAGES,\r
2214 Handle\r
2215 );\r
2216 ASSERT_EFI_ERROR (Status);\r
2217 ASSERT (\r
2218 Package->ImagePkgHdr.Header.Length ==\r
2219 sizeof (EFI_HII_IMAGE_PACKAGE_HDR) + Package->ImageBlockSize + Package->PaletteInfoSize\r
2220 );\r
2221 //\r
2222 // Copy Image package header,\r
2223 // then justify the offset for image info and palette info in the header.\r
2224 //\r
2225 CopyMem (Buffer, &Package->ImagePkgHdr, sizeof (EFI_HII_IMAGE_PACKAGE_HDR));\r
2226 Buffer = (UINT8 *)Buffer + sizeof (EFI_HII_IMAGE_PACKAGE_HDR);\r
2227\r
2228 //\r
2229 // Copy Image blocks information\r
2230 //\r
2231 if (Package->ImageBlockSize != 0) {\r
2232 CopyMem (Buffer, Package->ImageBlock, Package->ImageBlockSize);\r
2233 Buffer = (UINT8 *)Buffer + Package->ImageBlockSize;\r
2234 }\r
2235\r
2236 //\r
2237 // Copy Palette information\r
2238 //\r
2239 if (Package->PaletteInfoSize != 0) {\r
2240 CopyMem (Buffer, Package->PaletteBlock, Package->PaletteInfoSize);\r
2241 Buffer = (UINT8 *)Buffer + Package->PaletteInfoSize;\r
2242 }\r
2243 }\r
2244\r
2245 *ResultSize += PackageLength;\r
2246 return EFI_SUCCESS;\r
2247}\r
2248\r
2249/**\r
2250 This function deletes Image package from a package list node.\r
2251 This is a internal function.\r
2252\r
2253 @param Private Hii database private data.\r
2254 @param Handle Handle of the package list which contains the to\r
2255 be removed Image packages.\r
2256 @param PackageList Package List which contains the to be removed\r
2257 Image package.\r
2258\r
2259 @retval EFI_SUCCESS Image Package(s) is deleted successfully.\r
2260 @retval EFI_INVALID_PARAMETER Any input parameter is not valid.\r
2261\r
2262**/\r
2263EFI_STATUS\r
2264RemoveImagePackages (\r
2265 IN HII_DATABASE_PRIVATE_DATA *Private,\r
2266 IN EFI_HII_HANDLE Handle,\r
2267 IN OUT HII_DATABASE_PACKAGE_LIST_INSTANCE *PackageList\r
2268 )\r
2269{\r
2270 HII_IMAGE_PACKAGE_INSTANCE *Package;\r
2271 EFI_STATUS Status;\r
2272\r
2273 Package = PackageList->ImagePkg;\r
2274\r
2275 //\r
2276 // Image package does not exist, return directly.\r
2277 //\r
2278 if (Package == NULL) {\r
2279 return EFI_SUCCESS;\r
2280 }\r
2281\r
2282 Status = InvokeRegisteredFunction (\r
2283 Private,\r
2284 EFI_HII_DATABASE_NOTIFY_REMOVE_PACK,\r
2285 (VOID *)Package,\r
2286 EFI_HII_PACKAGE_IMAGES,\r
2287 Handle\r
2288 );\r
2289 if (EFI_ERROR (Status)) {\r
2290 return Status;\r
2291 }\r
2292\r
2293 PackageList->PackageListHdr.PackageLength -= Package->ImagePkgHdr.Header.Length;\r
2294\r
2295 FreePool (Package->ImageBlock);\r
2296 if (Package->PaletteBlock != NULL) {\r
2297 FreePool (Package->PaletteBlock);\r
2298 }\r
2299\r
2300 FreePool (Package);\r
2301\r
2302 PackageList->ImagePkg = NULL;\r
2303\r
2304 return EFI_SUCCESS;\r
2305}\r
2306\r
2307/**\r
2308 This function insert a Simple Font package to a package list node.\r
2309 This is a internal function.\r
2310\r
2311 @param PackageHdr Pointer to a buffer stored with Simple Font\r
2312 package information.\r
2313 @param NotifyType The type of change concerning the database.\r
2314 @param PackageList Pointer to a package list which will be inserted\r
2315 to.\r
2316 @param Package Created Simple Font package\r
2317\r
2318 @retval EFI_SUCCESS Simple Font Package is inserted successfully.\r
2319 @retval EFI_OUT_OF_RESOURCES Unable to allocate necessary resources for the new\r
2320 Simple Font package.\r
2321 @retval EFI_INVALID_PARAMETER PackageHdr is NULL or PackageList is NULL.\r
2322\r
2323**/\r
2324EFI_STATUS\r
2325InsertSimpleFontPackage (\r
2326 IN VOID *PackageHdr,\r
2327 IN EFI_HII_DATABASE_NOTIFY_TYPE NotifyType,\r
2328 IN OUT HII_DATABASE_PACKAGE_LIST_INSTANCE *PackageList,\r
2329 OUT HII_SIMPLE_FONT_PACKAGE_INSTANCE **Package\r
2330 )\r
2331{\r
2332 HII_SIMPLE_FONT_PACKAGE_INSTANCE *SimpleFontPackage;\r
2333 EFI_STATUS Status;\r
2334 EFI_HII_PACKAGE_HEADER Header;\r
2335\r
2336 if ((PackageHdr == NULL) || (PackageList == NULL)) {\r
2337 return EFI_INVALID_PARAMETER;\r
2338 }\r
2339\r
2340 //\r
2341 // Create a Simple Font package node\r
2342 //\r
2343 SimpleFontPackage = AllocateZeroPool (sizeof (HII_SIMPLE_FONT_PACKAGE_INSTANCE));\r
2344 if (SimpleFontPackage == NULL) {\r
2345 Status = EFI_OUT_OF_RESOURCES;\r
2346 goto Error;\r
2347 }\r
2348\r
2349 SimpleFontPackage->Signature = HII_S_FONT_PACKAGE_SIGNATURE;\r
2350\r
2351 //\r
2352 // Copy the Simple Font package.\r
2353 //\r
2354 CopyMem (&Header, PackageHdr, sizeof (EFI_HII_PACKAGE_HEADER));\r
2355\r
2356 SimpleFontPackage->SimpleFontPkgHdr = AllocateZeroPool (Header.Length);\r
2357 if (SimpleFontPackage->SimpleFontPkgHdr == NULL) {\r
2358 Status = EFI_OUT_OF_RESOURCES;\r
2359 goto Error;\r
2360 }\r
2361\r
2362 CopyMem (SimpleFontPackage->SimpleFontPkgHdr, PackageHdr, Header.Length);\r
2363\r
2364 //\r
2365 // Insert to Simple Font package array\r
2366 //\r
2367 InsertTailList (&PackageList->SimpleFontPkgHdr, &SimpleFontPackage->SimpleFontEntry);\r
2368 *Package = SimpleFontPackage;\r
2369\r
2370 if (NotifyType == EFI_HII_DATABASE_NOTIFY_ADD_PACK) {\r
2371 PackageList->PackageListHdr.PackageLength += Header.Length;\r
2372 }\r
2373\r
2374 return EFI_SUCCESS;\r
2375\r
2376Error:\r
2377\r
2378 if (SimpleFontPackage != NULL) {\r
2379 if (SimpleFontPackage->SimpleFontPkgHdr != NULL) {\r
2380 FreePool (SimpleFontPackage->SimpleFontPkgHdr);\r
2381 }\r
2382\r
2383 FreePool (SimpleFontPackage);\r
2384 }\r
2385\r
2386 return Status;\r
2387}\r
2388\r
2389/**\r
2390 This function exports SimpleFont packages to a buffer.\r
2391 This is a internal function.\r
2392\r
2393 @param Private Hii database private structure.\r
2394 @param Handle Identification of a package list.\r
2395 @param PackageList Pointer to a package list which will be exported.\r
2396 @param UsedSize The length of buffer be used.\r
2397 @param BufferSize Length of the Buffer.\r
2398 @param Buffer Allocated space for storing exported data.\r
2399 @param ResultSize The size of the already exported content of this\r
2400 package list.\r
2401\r
2402 @retval EFI_SUCCESS SimpleFont Packages are exported successfully.\r
2403 @retval EFI_INVALID_PARAMETER Any input parameter is invalid.\r
2404\r
2405**/\r
2406EFI_STATUS\r
2407ExportSimpleFontPackages (\r
2408 IN HII_DATABASE_PRIVATE_DATA *Private,\r
2409 IN EFI_HII_HANDLE Handle,\r
2410 IN HII_DATABASE_PACKAGE_LIST_INSTANCE *PackageList,\r
2411 IN UINTN UsedSize,\r
2412 IN UINTN BufferSize,\r
2413 IN OUT VOID *Buffer,\r
2414 IN OUT UINTN *ResultSize\r
2415 )\r
2416{\r
2417 LIST_ENTRY *Link;\r
2418 UINTN PackageLength;\r
2419 EFI_STATUS Status;\r
2420 HII_SIMPLE_FONT_PACKAGE_INSTANCE *Package;\r
2421\r
2422 if ((Private == NULL) || (PackageList == NULL) || (ResultSize == NULL)) {\r
2423 return EFI_INVALID_PARAMETER;\r
2424 }\r
2425\r
2426 if ((BufferSize > 0) && (Buffer == NULL)) {\r
2427 return EFI_INVALID_PARAMETER;\r
2428 }\r
2429\r
2430 PackageLength = 0;\r
2431 Status = EFI_SUCCESS;\r
2432\r
2433 for (Link = PackageList->SimpleFontPkgHdr.ForwardLink; Link != &PackageList->SimpleFontPkgHdr; Link = Link->ForwardLink) {\r
2434 Package = CR (Link, HII_SIMPLE_FONT_PACKAGE_INSTANCE, SimpleFontEntry, HII_S_FONT_PACKAGE_SIGNATURE);\r
2435 PackageLength += Package->SimpleFontPkgHdr->Header.Length;\r
2436 if (PackageLength + *ResultSize + UsedSize <= BufferSize) {\r
2437 //\r
2438 // Invoke registered notification function with EXPORT_PACK notify type\r
2439 //\r
2440 Status = InvokeRegisteredFunction (\r
2441 Private,\r
2442 EFI_HII_DATABASE_NOTIFY_EXPORT_PACK,\r
2443 (VOID *)Package,\r
2444 EFI_HII_PACKAGE_SIMPLE_FONTS,\r
2445 Handle\r
2446 );\r
2447 ASSERT_EFI_ERROR (Status);\r
2448\r
2449 //\r
2450 // Copy SimpleFont package\r
2451 //\r
2452 CopyMem (Buffer, Package->SimpleFontPkgHdr, Package->SimpleFontPkgHdr->Header.Length);\r
2453 Buffer = (UINT8 *)Buffer + Package->SimpleFontPkgHdr->Header.Length;\r
2454 }\r
2455 }\r
2456\r
2457 *ResultSize += PackageLength;\r
2458 return EFI_SUCCESS;\r
2459}\r
2460\r
2461/**\r
2462 This function deletes all Simple Font packages from a package list node.\r
2463 This is a internal function.\r
2464\r
2465 @param Private Hii database private data.\r
2466 @param Handle Handle of the package list which contains the to\r
2467 be removed Simple Font packages.\r
2468 @param PackageList Pointer to a package list that contains removing\r
2469 packages.\r
2470\r
2471 @retval EFI_SUCCESS Simple Font Package(s) is deleted successfully.\r
2472 @retval EFI_INVALID_PARAMETER Any input parameter is not valid.\r
2473\r
2474**/\r
2475EFI_STATUS\r
2476RemoveSimpleFontPackages (\r
2477 IN HII_DATABASE_PRIVATE_DATA *Private,\r
2478 IN EFI_HII_HANDLE Handle,\r
2479 IN OUT HII_DATABASE_PACKAGE_LIST_INSTANCE *PackageList\r
2480 )\r
2481{\r
2482 LIST_ENTRY *ListHead;\r
2483 HII_SIMPLE_FONT_PACKAGE_INSTANCE *Package;\r
2484 EFI_STATUS Status;\r
2485\r
2486 ListHead = &PackageList->SimpleFontPkgHdr;\r
2487\r
2488 while (!IsListEmpty (ListHead)) {\r
2489 Package = CR (\r
2490 ListHead->ForwardLink,\r
2491 HII_SIMPLE_FONT_PACKAGE_INSTANCE,\r
2492 SimpleFontEntry,\r
2493 HII_S_FONT_PACKAGE_SIGNATURE\r
2494 );\r
2495 Status = InvokeRegisteredFunction (\r
2496 Private,\r
2497 EFI_HII_DATABASE_NOTIFY_REMOVE_PACK,\r
2498 (VOID *)Package,\r
2499 EFI_HII_PACKAGE_SIMPLE_FONTS,\r
2500 Handle\r
2501 );\r
2502 if (EFI_ERROR (Status)) {\r
2503 return Status;\r
2504 }\r
2505\r
2506 RemoveEntryList (&Package->SimpleFontEntry);\r
2507 PackageList->PackageListHdr.PackageLength -= Package->SimpleFontPkgHdr->Header.Length;\r
2508 FreePool (Package->SimpleFontPkgHdr);\r
2509 FreePool (Package);\r
2510 }\r
2511\r
2512 return EFI_SUCCESS;\r
2513}\r
2514\r
2515/**\r
2516 This function insert a Device path package to a package list node.\r
2517 This is a internal function.\r
2518\r
2519 @param DevicePath Pointer to a EFI_DEVICE_PATH_PROTOCOL protocol\r
2520 instance\r
2521 @param NotifyType The type of change concerning the database.\r
2522 @param PackageList Pointer to a package list which will be inserted\r
2523 to.\r
2524\r
2525 @retval EFI_SUCCESS Device path Package is inserted successfully.\r
2526 @retval EFI_OUT_OF_RESOURCES Unable to allocate necessary resources for the new\r
2527 Device path package.\r
2528 @retval EFI_INVALID_PARAMETER DevicePath is NULL or PackageList is NULL.\r
2529\r
2530**/\r
2531EFI_STATUS\r
2532InsertDevicePathPackage (\r
2533 IN EFI_DEVICE_PATH_PROTOCOL *DevicePath,\r
2534 IN EFI_HII_DATABASE_NOTIFY_TYPE NotifyType,\r
2535 IN OUT HII_DATABASE_PACKAGE_LIST_INSTANCE *PackageList\r
2536 )\r
2537{\r
2538 UINT32 PackageLength;\r
2539 EFI_HII_PACKAGE_HEADER Header;\r
2540\r
2541 if ((DevicePath == NULL) || (PackageList == NULL)) {\r
2542 return EFI_INVALID_PARAMETER;\r
2543 }\r
2544\r
2545 //\r
2546 // Less than one device path package is allowed in one package list.\r
2547 //\r
2548 if (PackageList->DevicePathPkg != NULL) {\r
2549 return EFI_INVALID_PARAMETER;\r
2550 }\r
2551\r
2552 PackageLength = (UINT32)GetDevicePathSize (DevicePath) + sizeof (EFI_HII_PACKAGE_HEADER);\r
2553 PackageList->DevicePathPkg = (UINT8 *)AllocateZeroPool (PackageLength);\r
2554 if (PackageList->DevicePathPkg == NULL) {\r
2555 return EFI_OUT_OF_RESOURCES;\r
2556 }\r
2557\r
2558 Header.Length = PackageLength;\r
2559 Header.Type = EFI_HII_PACKAGE_DEVICE_PATH;\r
2560 CopyMem (PackageList->DevicePathPkg, &Header, sizeof (EFI_HII_PACKAGE_HEADER));\r
2561 CopyMem (\r
2562 PackageList->DevicePathPkg + sizeof (EFI_HII_PACKAGE_HEADER),\r
2563 DevicePath,\r
2564 PackageLength - sizeof (EFI_HII_PACKAGE_HEADER)\r
2565 );\r
2566\r
2567 //\r
2568 // Since Device Path package is created by NewPackageList, either NEW_PACK\r
2569 // or ADD_PACK should increase the length of package list.\r
2570 //\r
2571 PackageList->PackageListHdr.PackageLength += PackageLength;\r
2572 return EFI_SUCCESS;\r
2573}\r
2574\r
2575/**\r
2576 This function exports device path package to a buffer.\r
2577 This is a internal function.\r
2578\r
2579 @param Private Hii database private structure.\r
2580 @param Handle Identification of a package list.\r
2581 @param PackageList Pointer to a package list which will be exported.\r
2582 @param UsedSize The length of buffer be used.\r
2583 @param BufferSize Length of the Buffer.\r
2584 @param Buffer Allocated space for storing exported data.\r
2585 @param ResultSize The size of the already exported content of this\r
2586 package list.\r
2587\r
2588 @retval EFI_SUCCESS Device path Package is exported successfully.\r
2589 @retval EFI_INVALID_PARAMETER Any input parameter is invalid.\r
2590\r
2591**/\r
2592EFI_STATUS\r
2593ExportDevicePathPackage (\r
2594 IN HII_DATABASE_PRIVATE_DATA *Private,\r
2595 IN EFI_HII_HANDLE Handle,\r
2596 IN HII_DATABASE_PACKAGE_LIST_INSTANCE *PackageList,\r
2597 IN UINTN UsedSize,\r
2598 IN UINTN BufferSize,\r
2599 IN OUT VOID *Buffer,\r
2600 IN OUT UINTN *ResultSize\r
2601 )\r
2602{\r
2603 EFI_STATUS Status;\r
2604 UINT8 *Package;\r
2605 EFI_HII_PACKAGE_HEADER Header;\r
2606\r
2607 if ((Private == NULL) || (PackageList == NULL) || (ResultSize == NULL)) {\r
2608 return EFI_INVALID_PARAMETER;\r
2609 }\r
2610\r
2611 if ((BufferSize > 0) && (Buffer == NULL)) {\r
2612 return EFI_INVALID_PARAMETER;\r
2613 }\r
2614\r
2615 Package = PackageList->DevicePathPkg;\r
2616\r
2617 if (Package == NULL) {\r
2618 return EFI_SUCCESS;\r
2619 }\r
2620\r
2621 CopyMem (&Header, Package, sizeof (EFI_HII_PACKAGE_HEADER));\r
2622\r
2623 if (Header.Length + *ResultSize + UsedSize <= BufferSize) {\r
2624 //\r
2625 // Invoke registered notification function with EXPORT_PACK notify type\r
2626 //\r
2627 Status = InvokeRegisteredFunction (\r
2628 Private,\r
2629 EFI_HII_DATABASE_NOTIFY_EXPORT_PACK,\r
2630 (VOID *)Package,\r
2631 EFI_HII_PACKAGE_DEVICE_PATH,\r
2632 Handle\r
2633 );\r
2634 ASSERT_EFI_ERROR (Status);\r
2635\r
2636 //\r
2637 // Copy Device path package\r
2638 //\r
2639 CopyMem (Buffer, Package, Header.Length);\r
2640 }\r
2641\r
2642 *ResultSize += Header.Length;\r
2643 return EFI_SUCCESS;\r
2644}\r
2645\r
2646/**\r
2647 This function deletes Device Path package from a package list node.\r
2648 This is a internal function.\r
2649\r
2650 @param Private Hii database private data.\r
2651 @param Handle Handle of the package list.\r
2652 @param PackageList Package List which contains the to be removed\r
2653 Device Path package.\r
2654\r
2655 @retval EFI_SUCCESS Device Path Package is deleted successfully.\r
2656 @retval EFI_INVALID_PARAMETER Any input parameter is not valid.\r
2657\r
2658**/\r
2659EFI_STATUS\r
2660RemoveDevicePathPackage (\r
2661 IN HII_DATABASE_PRIVATE_DATA *Private,\r
2662 IN EFI_HII_HANDLE Handle,\r
2663 IN OUT HII_DATABASE_PACKAGE_LIST_INSTANCE *PackageList\r
2664 )\r
2665{\r
2666 EFI_STATUS Status;\r
2667 UINT8 *Package;\r
2668 EFI_HII_PACKAGE_HEADER Header;\r
2669\r
2670 Package = PackageList->DevicePathPkg;\r
2671\r
2672 //\r
2673 // No device path, return directly.\r
2674 //\r
2675 if (Package == NULL) {\r
2676 return EFI_SUCCESS;\r
2677 }\r
2678\r
2679 Status = InvokeRegisteredFunction (\r
2680 Private,\r
2681 EFI_HII_DATABASE_NOTIFY_REMOVE_PACK,\r
2682 (VOID *)Package,\r
2683 EFI_HII_PACKAGE_DEVICE_PATH,\r
2684 Handle\r
2685 );\r
2686 if (EFI_ERROR (Status)) {\r
2687 return Status;\r
2688 }\r
2689\r
2690 CopyMem (&Header, Package, sizeof (EFI_HII_PACKAGE_HEADER));\r
2691 PackageList->PackageListHdr.PackageLength -= Header.Length;\r
2692\r
2693 FreePool (Package);\r
2694\r
2695 PackageList->DevicePathPkg = NULL;\r
2696\r
2697 return EFI_SUCCESS;\r
2698}\r
2699\r
2700/**\r
2701 This function will insert a device path package to package list firstly then\r
2702 invoke notification functions if any.\r
2703 This is a internal function.\r
2704\r
2705 @param Private Hii database private structure.\r
2706 @param NotifyType The type of change concerning the database.\r
2707 @param DevicePath Pointer to a EFI_DEVICE_PATH_PROTOCOL protocol\r
2708 instance\r
2709 @param DatabaseRecord Pointer to a database record contains a package\r
2710 list which will be inserted to.\r
2711\r
2712 @retval EFI_SUCCESS Device path Package is inserted successfully.\r
2713 @retval EFI_OUT_OF_RESOURCES Unable to allocate necessary resources for the new\r
2714 Device path package.\r
2715 @retval EFI_INVALID_PARAMETER DevicePath is NULL or PackageList is NULL.\r
2716\r
2717**/\r
2718EFI_STATUS\r
2719AddDevicePathPackage (\r
2720 IN HII_DATABASE_PRIVATE_DATA *Private,\r
2721 IN EFI_HII_DATABASE_NOTIFY_TYPE NotifyType,\r
2722 IN EFI_DEVICE_PATH_PROTOCOL *DevicePath,\r
2723 IN OUT HII_DATABASE_RECORD *DatabaseRecord\r
2724 )\r
2725{\r
2726 EFI_STATUS Status;\r
2727\r
2728 if (DevicePath == NULL) {\r
2729 return EFI_SUCCESS;\r
2730 }\r
2731\r
2732 ASSERT (Private != NULL);\r
2733 ASSERT (DatabaseRecord != NULL);\r
2734\r
2735 //\r
2736 // Create a device path package and insert to packagelist\r
2737 //\r
2738 Status = InsertDevicePathPackage (\r
2739 DevicePath,\r
2740 NotifyType,\r
2741 DatabaseRecord->PackageList\r
2742 );\r
2743 if (EFI_ERROR (Status)) {\r
2744 return Status;\r
2745 }\r
2746\r
2747 return InvokeRegisteredFunction (\r
2748 Private,\r
2749 NotifyType,\r
2750 (VOID *)DatabaseRecord->PackageList->DevicePathPkg,\r
2751 EFI_HII_PACKAGE_DEVICE_PATH,\r
2752 DatabaseRecord->Handle\r
2753 );\r
2754}\r
2755\r
2756/**\r
2757 This function insert a Keyboard Layout package to a package list node.\r
2758 This is a internal function.\r
2759\r
2760 @param PackageHdr Pointer to a buffer stored with Keyboard Layout\r
2761 package information.\r
2762 @param NotifyType The type of change concerning the database.\r
2763 @param PackageList Pointer to a package list which will be inserted\r
2764 to.\r
2765 @param Package Created Keyboard Layout package\r
2766\r
2767 @retval EFI_SUCCESS Keyboard Layout Package is inserted successfully.\r
2768 @retval EFI_OUT_OF_RESOURCES Unable to allocate necessary resources for the new\r
2769 Keyboard Layout package.\r
2770 @retval EFI_INVALID_PARAMETER PackageHdr is NULL or PackageList is NULL.\r
2771\r
2772**/\r
2773EFI_STATUS\r
2774InsertKeyboardLayoutPackage (\r
2775 IN VOID *PackageHdr,\r
2776 IN EFI_HII_DATABASE_NOTIFY_TYPE NotifyType,\r
2777 IN OUT HII_DATABASE_PACKAGE_LIST_INSTANCE *PackageList,\r
2778 OUT HII_KEYBOARD_LAYOUT_PACKAGE_INSTANCE **Package\r
2779 )\r
2780{\r
2781 HII_KEYBOARD_LAYOUT_PACKAGE_INSTANCE *KeyboardLayoutPackage;\r
2782 EFI_HII_PACKAGE_HEADER PackageHeader;\r
2783 EFI_STATUS Status;\r
2784\r
2785 if ((PackageHdr == NULL) || (PackageList == NULL)) {\r
2786 return EFI_INVALID_PARAMETER;\r
2787 }\r
2788\r
2789 CopyMem (&PackageHeader, PackageHdr, sizeof (EFI_HII_PACKAGE_HEADER));\r
2790\r
2791 //\r
2792 // Create a Keyboard Layout package node\r
2793 //\r
2794 KeyboardLayoutPackage = AllocateZeroPool (sizeof (HII_KEYBOARD_LAYOUT_PACKAGE_INSTANCE));\r
2795 if (KeyboardLayoutPackage == NULL) {\r
2796 Status = EFI_OUT_OF_RESOURCES;\r
2797 goto Error;\r
2798 }\r
2799\r
2800 KeyboardLayoutPackage->Signature = HII_KB_LAYOUT_PACKAGE_SIGNATURE;\r
2801\r
2802 KeyboardLayoutPackage->KeyboardPkg = (UINT8 *)AllocateZeroPool (PackageHeader.Length);\r
2803 if (KeyboardLayoutPackage->KeyboardPkg == NULL) {\r
2804 Status = EFI_OUT_OF_RESOURCES;\r
2805 goto Error;\r
2806 }\r
2807\r
2808 CopyMem (KeyboardLayoutPackage->KeyboardPkg, PackageHdr, PackageHeader.Length);\r
2809 InsertTailList (&PackageList->KeyboardLayoutHdr, &KeyboardLayoutPackage->KeyboardEntry);\r
2810\r
2811 *Package = KeyboardLayoutPackage;\r
2812\r
2813 if (NotifyType == EFI_HII_DATABASE_NOTIFY_ADD_PACK) {\r
2814 PackageList->PackageListHdr.PackageLength += PackageHeader.Length;\r
2815 }\r
2816\r
2817 return EFI_SUCCESS;\r
2818\r
2819Error:\r
2820\r
2821 if (KeyboardLayoutPackage != NULL) {\r
2822 if (KeyboardLayoutPackage->KeyboardPkg != NULL) {\r
2823 FreePool (KeyboardLayoutPackage->KeyboardPkg);\r
2824 }\r
2825\r
2826 FreePool (KeyboardLayoutPackage);\r
2827 }\r
2828\r
2829 return Status;\r
2830}\r
2831\r
2832/**\r
2833 This function exports Keyboard Layout packages to a buffer.\r
2834 This is a internal function.\r
2835\r
2836 @param Private Hii database private structure.\r
2837 @param Handle Identification of a package list.\r
2838 @param PackageList Pointer to a package list which will be exported.\r
2839 @param UsedSize The length of buffer be used.\r
2840 @param BufferSize Length of the Buffer.\r
2841 @param Buffer Allocated space for storing exported data.\r
2842 @param ResultSize The size of the already exported content of this\r
2843 package list.\r
2844\r
2845 @retval EFI_SUCCESS Keyboard Layout Packages are exported\r
2846 successfully.\r
2847 @retval EFI_INVALID_PARAMETER Any input parameter is invalid.\r
2848\r
2849**/\r
2850EFI_STATUS\r
2851ExportKeyboardLayoutPackages (\r
2852 IN HII_DATABASE_PRIVATE_DATA *Private,\r
2853 IN EFI_HII_HANDLE Handle,\r
2854 IN HII_DATABASE_PACKAGE_LIST_INSTANCE *PackageList,\r
2855 IN UINTN UsedSize,\r
2856 IN UINTN BufferSize,\r
2857 IN OUT VOID *Buffer,\r
2858 IN OUT UINTN *ResultSize\r
2859 )\r
2860{\r
2861 LIST_ENTRY *Link;\r
2862 UINTN PackageLength;\r
2863 EFI_STATUS Status;\r
2864 HII_KEYBOARD_LAYOUT_PACKAGE_INSTANCE *Package;\r
2865 EFI_HII_PACKAGE_HEADER PackageHeader;\r
2866\r
2867 if ((Private == NULL) || (PackageList == NULL) || (ResultSize == NULL)) {\r
2868 return EFI_INVALID_PARAMETER;\r
2869 }\r
2870\r
2871 if ((BufferSize > 0) && (Buffer == NULL)) {\r
2872 return EFI_INVALID_PARAMETER;\r
2873 }\r
2874\r
2875 PackageLength = 0;\r
2876 Status = EFI_SUCCESS;\r
2877\r
2878 for (Link = PackageList->KeyboardLayoutHdr.ForwardLink; Link != &PackageList->KeyboardLayoutHdr; Link = Link->ForwardLink) {\r
2879 Package = CR (Link, HII_KEYBOARD_LAYOUT_PACKAGE_INSTANCE, KeyboardEntry, HII_KB_LAYOUT_PACKAGE_SIGNATURE);\r
2880 CopyMem (&PackageHeader, Package->KeyboardPkg, sizeof (EFI_HII_PACKAGE_HEADER));\r
2881 PackageLength += PackageHeader.Length;\r
2882 if (PackageLength + *ResultSize + UsedSize <= BufferSize) {\r
2883 //\r
2884 // Invoke registered notification function with EXPORT_PACK notify type\r
2885 //\r
2886 Status = InvokeRegisteredFunction (\r
2887 Private,\r
2888 EFI_HII_DATABASE_NOTIFY_EXPORT_PACK,\r
2889 (EFI_HII_PACKAGE_HEADER *)Package,\r
2890 EFI_HII_PACKAGE_KEYBOARD_LAYOUT,\r
2891 Handle\r
2892 );\r
2893 ASSERT_EFI_ERROR (Status);\r
2894\r
2895 //\r
2896 // Copy Keyboard Layout package\r
2897 //\r
2898 CopyMem (Buffer, Package->KeyboardPkg, PackageHeader.Length);\r
2899 Buffer = (UINT8 *)Buffer + PackageHeader.Length;\r
2900 }\r
2901 }\r
2902\r
2903 *ResultSize += PackageLength;\r
2904 return EFI_SUCCESS;\r
2905}\r
2906\r
2907/**\r
2908 This function deletes all Keyboard Layout packages from a package list node.\r
2909 This is a internal function.\r
2910\r
2911 @param Private Hii database private data.\r
2912 @param Handle Handle of the package list which contains the to\r
2913 be removed Keyboard Layout packages.\r
2914 @param PackageList Pointer to a package list that contains removing\r
2915 packages.\r
2916\r
2917 @retval EFI_SUCCESS Keyboard Layout Package(s) is deleted\r
2918 successfully.\r
2919 @retval EFI_INVALID_PARAMETER Any input parameter is not valid.\r
2920\r
2921**/\r
2922EFI_STATUS\r
2923RemoveKeyboardLayoutPackages (\r
2924 IN HII_DATABASE_PRIVATE_DATA *Private,\r
2925 IN EFI_HII_HANDLE Handle,\r
2926 IN OUT HII_DATABASE_PACKAGE_LIST_INSTANCE *PackageList\r
2927 )\r
2928{\r
2929 LIST_ENTRY *ListHead;\r
2930 HII_KEYBOARD_LAYOUT_PACKAGE_INSTANCE *Package;\r
2931 EFI_HII_PACKAGE_HEADER PackageHeader;\r
2932 EFI_STATUS Status;\r
2933\r
2934 ListHead = &PackageList->KeyboardLayoutHdr;\r
2935\r
2936 while (!IsListEmpty (ListHead)) {\r
2937 Package = CR (\r
2938 ListHead->ForwardLink,\r
2939 HII_KEYBOARD_LAYOUT_PACKAGE_INSTANCE,\r
2940 KeyboardEntry,\r
2941 HII_KB_LAYOUT_PACKAGE_SIGNATURE\r
2942 );\r
2943 Status = InvokeRegisteredFunction (\r
2944 Private,\r
2945 EFI_HII_DATABASE_NOTIFY_REMOVE_PACK,\r
2946 (VOID *)Package,\r
2947 EFI_HII_PACKAGE_KEYBOARD_LAYOUT,\r
2948 Handle\r
2949 );\r
2950 if (EFI_ERROR (Status)) {\r
2951 return Status;\r
2952 }\r
2953\r
2954 RemoveEntryList (&Package->KeyboardEntry);\r
2955 CopyMem (&PackageHeader, Package->KeyboardPkg, sizeof (EFI_HII_PACKAGE_HEADER));\r
2956 PackageList->PackageListHdr.PackageLength -= PackageHeader.Length;\r
2957 FreePool (Package->KeyboardPkg);\r
2958 FreePool (Package);\r
2959 }\r
2960\r
2961 return EFI_SUCCESS;\r
2962}\r
2963\r
2964/**\r
2965 This function will insert a package list to hii database firstly then\r
2966 invoke notification functions if any. It is the worker function of\r
2967 HiiNewPackageList and HiiUpdatePackageList.\r
2968\r
2969 This is a internal function.\r
2970\r
2971 @param Private Hii database private structure.\r
2972 @param NotifyType The type of change concerning the database.\r
2973 @param PackageList Pointer to a package list.\r
2974 @param DatabaseRecord Pointer to a database record contains a package\r
2975 list instance which will be inserted to.\r
2976\r
2977 @retval EFI_SUCCESS All incoming packages are inserted to current\r
2978 database.\r
2979 @retval EFI_OUT_OF_RESOURCES Unable to allocate necessary resources for the new\r
2980 Device path package.\r
2981 @retval EFI_INVALID_PARAMETER Any input parameter is invalid.\r
2982\r
2983**/\r
2984EFI_STATUS\r
2985AddPackages (\r
2986 IN HII_DATABASE_PRIVATE_DATA *Private,\r
2987 IN EFI_HII_DATABASE_NOTIFY_TYPE NotifyType,\r
2988 IN CONST EFI_HII_PACKAGE_LIST_HEADER *PackageList,\r
2989 IN OUT HII_DATABASE_RECORD *DatabaseRecord\r
2990 )\r
2991{\r
2992 EFI_STATUS Status;\r
2993 HII_GUID_PACKAGE_INSTANCE *GuidPackage;\r
2994 HII_IFR_PACKAGE_INSTANCE *FormPackage;\r
2995 HII_KEYBOARD_LAYOUT_PACKAGE_INSTANCE *KeyboardLayoutPackage;\r
2996 HII_STRING_PACKAGE_INSTANCE *StringPackage;\r
2997 HII_FONT_PACKAGE_INSTANCE *FontPackage;\r
2998 HII_SIMPLE_FONT_PACKAGE_INSTANCE *SimpleFontPackage;\r
2999 HII_IMAGE_PACKAGE_INSTANCE *ImagePackage;\r
3000 EFI_HII_PACKAGE_HEADER *PackageHdrPtr;\r
3001 EFI_HII_PACKAGE_HEADER PackageHeader;\r
3002 UINT32 OldPackageListLen;\r
3003 BOOLEAN StringPkgIsAdd;\r
3004\r
3005 //\r
3006 // Initialize Variables\r
3007 //\r
3008 StringPkgIsAdd = FALSE;\r
3009 FontPackage = NULL;\r
3010 StringPackage = NULL;\r
3011 GuidPackage = NULL;\r
3012 FormPackage = NULL;\r
3013 ImagePackage = NULL;\r
3014 SimpleFontPackage = NULL;\r
3015 KeyboardLayoutPackage = NULL;\r
3016\r
3017 //\r
3018 // Process the package list header\r
3019 //\r
3020 OldPackageListLen = DatabaseRecord->PackageList->PackageListHdr.PackageLength;\r
3021 CopyMem (\r
3022 &DatabaseRecord->PackageList->PackageListHdr,\r
3023 (VOID *)PackageList,\r
3024 sizeof (EFI_HII_PACKAGE_LIST_HEADER)\r
3025 );\r
3026 if (NotifyType == EFI_HII_DATABASE_NOTIFY_ADD_PACK) {\r
3027 DatabaseRecord->PackageList->PackageListHdr.PackageLength = OldPackageListLen;\r
3028 }\r
3029\r
3030 PackageHdrPtr = (EFI_HII_PACKAGE_HEADER *)((UINT8 *)PackageList + sizeof (EFI_HII_PACKAGE_LIST_HEADER));\r
3031 CopyMem (&PackageHeader, PackageHdrPtr, sizeof (EFI_HII_PACKAGE_HEADER));\r
3032\r
3033 Status = EFI_SUCCESS;\r
3034\r
3035 while (PackageHeader.Type != EFI_HII_PACKAGE_END) {\r
3036 switch (PackageHeader.Type) {\r
3037 case EFI_HII_PACKAGE_TYPE_GUID:\r
3038 Status = InsertGuidPackage (\r
3039 PackageHdrPtr,\r
3040 NotifyType,\r
3041 DatabaseRecord->PackageList,\r
3042 &GuidPackage\r
3043 );\r
3044 if (EFI_ERROR (Status)) {\r
3045 return Status;\r
3046 }\r
3047\r
3048 Status = InvokeRegisteredFunction (\r
3049 Private,\r
3050 NotifyType,\r
3051 (VOID *)GuidPackage,\r
3052 (UINT8)(PackageHeader.Type),\r
3053 DatabaseRecord->Handle\r
3054 );\r
3055 break;\r
3056 case EFI_HII_PACKAGE_FORMS:\r
3057 Status = InsertFormPackage (\r
3058 PackageHdrPtr,\r
3059 NotifyType,\r
3060 DatabaseRecord->PackageList,\r
3061 &FormPackage\r
3062 );\r
3063 if (EFI_ERROR (Status)) {\r
3064 return Status;\r
3065 }\r
3066\r
3067 Status = InvokeRegisteredFunction (\r
3068 Private,\r
3069 NotifyType,\r
3070 (VOID *)FormPackage,\r
3071 (UINT8)(PackageHeader.Type),\r
3072 DatabaseRecord->Handle\r
3073 );\r
3074 //\r
3075 // If Hii runtime support feature is enabled,\r
3076 // will export Hii info for runtime use after ReadyToBoot event triggered.\r
3077 // If some driver add/update/remove packages from HiiDatabase after ReadyToBoot,\r
3078 // will need to export the content of HiiDatabase.\r
3079 // But if form packages added/updated, also need to export the ConfigResp string.\r
3080 //\r
3081 if (gExportAfterReadyToBoot) {\r
3082 gExportConfigResp = TRUE;\r
3083 }\r
3084\r
3085 break;\r
3086 case EFI_HII_PACKAGE_KEYBOARD_LAYOUT:\r
3087 Status = InsertKeyboardLayoutPackage (\r
3088 PackageHdrPtr,\r
3089 NotifyType,\r
3090 DatabaseRecord->PackageList,\r
3091 &KeyboardLayoutPackage\r
3092 );\r
3093 if (EFI_ERROR (Status)) {\r
3094 return Status;\r
3095 }\r
3096\r
3097 Status = InvokeRegisteredFunction (\r
3098 Private,\r
3099 NotifyType,\r
3100 (VOID *)KeyboardLayoutPackage,\r
3101 (UINT8)(PackageHeader.Type),\r
3102 DatabaseRecord->Handle\r
3103 );\r
3104 break;\r
3105 case EFI_HII_PACKAGE_STRINGS:\r
3106 Status = InsertStringPackage (\r
3107 Private,\r
3108 PackageHdrPtr,\r
3109 NotifyType,\r
3110 DatabaseRecord->PackageList,\r
3111 &StringPackage\r
3112 );\r
3113 if (EFI_ERROR (Status)) {\r
3114 return Status;\r
3115 }\r
3116\r
3117 ASSERT (StringPackage != NULL);\r
3118 Status = InvokeRegisteredFunction (\r
3119 Private,\r
3120 NotifyType,\r
3121 (VOID *)StringPackage,\r
3122 (UINT8)(PackageHeader.Type),\r
3123 DatabaseRecord->Handle\r
3124 );\r
3125 StringPkgIsAdd = TRUE;\r
3126 break;\r
3127 case EFI_HII_PACKAGE_FONTS:\r
3128 Status = InsertFontPackage (\r
3129 Private,\r
3130 PackageHdrPtr,\r
3131 NotifyType,\r
3132 DatabaseRecord->PackageList,\r
3133 &FontPackage\r
3134 );\r
3135 if (EFI_ERROR (Status)) {\r
3136 return Status;\r
3137 }\r
3138\r
3139 Status = InvokeRegisteredFunction (\r
3140 Private,\r
3141 NotifyType,\r
3142 (VOID *)FontPackage,\r
3143 (UINT8)(PackageHeader.Type),\r
3144 DatabaseRecord->Handle\r
3145 );\r
3146 break;\r
3147 case EFI_HII_PACKAGE_IMAGES:\r
3148 Status = InsertImagePackage (\r
3149 PackageHdrPtr,\r
3150 NotifyType,\r
3151 DatabaseRecord->PackageList,\r
3152 &ImagePackage\r
3153 );\r
3154 if (EFI_ERROR (Status)) {\r
3155 return Status;\r
3156 }\r
3157\r
3158 Status = InvokeRegisteredFunction (\r
3159 Private,\r
3160 NotifyType,\r
3161 (VOID *)ImagePackage,\r
3162 (UINT8)(PackageHeader.Type),\r
3163 DatabaseRecord->Handle\r
3164 );\r
3165 break;\r
3166 case EFI_HII_PACKAGE_SIMPLE_FONTS:\r
3167 Status = InsertSimpleFontPackage (\r
3168 PackageHdrPtr,\r
3169 NotifyType,\r
3170 DatabaseRecord->PackageList,\r
3171 &SimpleFontPackage\r
3172 );\r
3173 if (EFI_ERROR (Status)) {\r
3174 return Status;\r
3175 }\r
3176\r
3177 Status = InvokeRegisteredFunction (\r
3178 Private,\r
3179 NotifyType,\r
3180 (VOID *)SimpleFontPackage,\r
3181 (UINT8)(PackageHeader.Type),\r
3182 DatabaseRecord->Handle\r
3183 );\r
3184 break;\r
3185 case EFI_HII_PACKAGE_DEVICE_PATH:\r
3186 Status = AddDevicePathPackage (\r
3187 Private,\r
3188 NotifyType,\r
3189 (EFI_DEVICE_PATH_PROTOCOL *)((UINT8 *)PackageHdrPtr + sizeof (EFI_HII_PACKAGE_HEADER)),\r
3190 DatabaseRecord\r
3191 );\r
3192 break;\r
3193 default:\r
3194 break;\r
3195 }\r
3196\r
3197 if (EFI_ERROR (Status)) {\r
3198 return Status;\r
3199 }\r
3200\r
3201 //\r
3202 // goto header of next package\r
3203 //\r
3204 PackageHdrPtr = (EFI_HII_PACKAGE_HEADER *)((UINT8 *)PackageHdrPtr + PackageHeader.Length);\r
3205 CopyMem (&PackageHeader, PackageHdrPtr, sizeof (EFI_HII_PACKAGE_HEADER));\r
3206 }\r
3207\r
3208 //\r
3209 // Adjust String Package to make sure all string packages have the same max string ID.\r
3210 //\r
3211 if (!EFI_ERROR (Status) && StringPkgIsAdd) {\r
3212 Status = AdjustStringPackage (DatabaseRecord->PackageList);\r
3213 }\r
3214\r
3215 return Status;\r
3216}\r
3217\r
3218/**\r
3219 This function exports a package list to a buffer. It is the worker function\r
3220 of HiiExportPackageList.\r
3221\r
3222 This is a internal function.\r
3223\r
3224 @param Private Hii database private structure.\r
3225 @param Handle Identification of a package list.\r
3226 @param PackageList Pointer to a package list which will be exported.\r
3227 @param UsedSize The length of buffer has been used by exporting\r
3228 package lists when Handle is NULL.\r
3229 @param BufferSize Length of the Buffer.\r
3230 @param Buffer Allocated space for storing exported data.\r
3231\r
3232 @retval EFI_SUCCESS Keyboard Layout Packages are exported\r
3233 successfully.\r
3234 @retval EFI_INVALID_PARAMETER Any input parameter is invalid.\r
3235\r
3236**/\r
3237EFI_STATUS\r
3238ExportPackageList (\r
3239 IN HII_DATABASE_PRIVATE_DATA *Private,\r
3240 IN EFI_HII_HANDLE Handle,\r
3241 IN HII_DATABASE_PACKAGE_LIST_INSTANCE *PackageList,\r
3242 IN OUT UINTN *UsedSize,\r
3243 IN UINTN BufferSize,\r
3244 OUT EFI_HII_PACKAGE_LIST_HEADER *Buffer\r
3245 )\r
3246{\r
3247 EFI_STATUS Status;\r
3248 UINTN ResultSize;\r
3249 EFI_HII_PACKAGE_HEADER EndofPackageList;\r
3250\r
3251 ASSERT (Private != NULL && PackageList != NULL && UsedSize != NULL);\r
3252 ASSERT (Private->Signature == HII_DATABASE_PRIVATE_DATA_SIGNATURE);\r
3253 ASSERT (IsHiiHandleValid (Handle));\r
3254\r
3255 if ((BufferSize > 0) && (Buffer == NULL)) {\r
3256 return EFI_INVALID_PARAMETER;\r
3257 }\r
3258\r
3259 //\r
3260 // Copy the package list header\r
3261 // ResultSize indicates the length of the exported bytes of this package list\r
3262 //\r
3263 ResultSize = sizeof (EFI_HII_PACKAGE_LIST_HEADER);\r
3264 if (ResultSize + *UsedSize <= BufferSize) {\r
3265 CopyMem ((VOID *)Buffer, PackageList, ResultSize);\r
3266 }\r
3267\r
3268 //\r
3269 // Copy the packages and invoke EXPORT_PACK notify functions if exists.\r
3270 //\r
3271 Status = ExportGuidPackages (\r
3272 Private,\r
3273 Handle,\r
3274 PackageList,\r
3275 *UsedSize,\r
3276 BufferSize,\r
3277 (VOID *)((UINT8 *)Buffer + ResultSize),\r
3278 &ResultSize\r
3279 );\r
3280 if (EFI_ERROR (Status)) {\r
3281 return Status;\r
3282 }\r
3283\r
3284 Status = ExportFormPackages (\r
3285 Private,\r
3286 Handle,\r
3287 PackageList,\r
3288 *UsedSize,\r
3289 BufferSize,\r
3290 (VOID *)((UINT8 *)Buffer + ResultSize),\r
3291 &ResultSize\r
3292 );\r
3293 if (EFI_ERROR (Status)) {\r
3294 return Status;\r
3295 }\r
3296\r
3297 Status = ExportKeyboardLayoutPackages (\r
3298 Private,\r
3299 Handle,\r
3300 PackageList,\r
3301 *UsedSize,\r
3302 BufferSize,\r
3303 (VOID *)((UINT8 *)Buffer + ResultSize),\r
3304 &ResultSize\r
3305 );\r
3306 if (EFI_ERROR (Status)) {\r
3307 return Status;\r
3308 }\r
3309\r
3310 Status = ExportStringPackages (\r
3311 Private,\r
3312 Handle,\r
3313 PackageList,\r
3314 *UsedSize,\r
3315 BufferSize,\r
3316 (VOID *)((UINT8 *)Buffer + ResultSize),\r
3317 &ResultSize\r
3318 );\r
3319 if (EFI_ERROR (Status)) {\r
3320 return Status;\r
3321 }\r
3322\r
3323 Status = ExportFontPackages (\r
3324 Private,\r
3325 Handle,\r
3326 PackageList,\r
3327 *UsedSize,\r
3328 BufferSize,\r
3329 (VOID *)((UINT8 *)Buffer + ResultSize),\r
3330 &ResultSize\r
3331 );\r
3332 if (EFI_ERROR (Status)) {\r
3333 return Status;\r
3334 }\r
3335\r
3336 Status = ExportImagePackages (\r
3337 Private,\r
3338 Handle,\r
3339 PackageList,\r
3340 *UsedSize,\r
3341 BufferSize,\r
3342 (VOID *)((UINT8 *)Buffer + ResultSize),\r
3343 &ResultSize\r
3344 );\r
3345 if (EFI_ERROR (Status)) {\r
3346 return Status;\r
3347 }\r
3348\r
3349 Status = ExportSimpleFontPackages (\r
3350 Private,\r
3351 Handle,\r
3352 PackageList,\r
3353 *UsedSize,\r
3354 BufferSize,\r
3355 (VOID *)((UINT8 *)Buffer + ResultSize),\r
3356 &ResultSize\r
3357 );\r
3358 if (EFI_ERROR (Status)) {\r
3359 return Status;\r
3360 }\r
3361\r
3362 Status = ExportDevicePathPackage (\r
3363 Private,\r
3364 Handle,\r
3365 PackageList,\r
3366 *UsedSize,\r
3367 BufferSize,\r
3368 (VOID *)((UINT8 *)Buffer + ResultSize),\r
3369 &ResultSize\r
3370 );\r
3371 if (EFI_ERROR (Status)) {\r
3372 return Status;\r
3373 }\r
3374\r
3375 //\r
3376 // Append the package list end.\r
3377 //\r
3378 EndofPackageList.Length = sizeof (EFI_HII_PACKAGE_HEADER);\r
3379 EndofPackageList.Type = EFI_HII_PACKAGE_END;\r
3380 if (ResultSize + *UsedSize + sizeof (EFI_HII_PACKAGE_HEADER) <= BufferSize) {\r
3381 CopyMem (\r
3382 (VOID *)((UINT8 *)Buffer + ResultSize),\r
3383 (VOID *)&EndofPackageList,\r
3384 sizeof (EFI_HII_PACKAGE_HEADER)\r
3385 );\r
3386 }\r
3387\r
3388 *UsedSize += ResultSize + sizeof (EFI_HII_PACKAGE_HEADER);\r
3389\r
3390 return EFI_SUCCESS;\r
3391}\r
3392\r
3393/**\r
3394This function mainly use to get and update ConfigResp string.\r
3395\r
3396@param This A pointer to the EFI_HII_DATABASE_PROTOCOL instance.\r
3397\r
3398@retval EFI_SUCCESS Get the information successfully.\r
3399@retval EFI_OUT_OF_RESOURCES Not enough memory to store the Configuration Setting data.\r
3400\r
3401**/\r
3402EFI_STATUS\r
3403HiiGetConfigRespInfo (\r
3404 IN CONST EFI_HII_DATABASE_PROTOCOL *This\r
3405 )\r
3406{\r
3407 EFI_STATUS Status;\r
3408 HII_DATABASE_PRIVATE_DATA *Private;\r
3409 EFI_STRING ConfigAltResp;\r
3410 UINTN ConfigSize;\r
3411\r
3412 ConfigAltResp = NULL;\r
3413 ConfigSize = 0;\r
3414\r
3415 Private = HII_DATABASE_DATABASE_PRIVATE_DATA_FROM_THIS (This);\r
3416\r
3417 //\r
3418 // Get ConfigResp string\r
3419 //\r
3420 Status = HiiConfigRoutingExportConfig (&Private->ConfigRouting, &ConfigAltResp);\r
3421\r
3422 if (!EFI_ERROR (Status)) {\r
3423 ConfigSize = StrSize (ConfigAltResp);\r
3424 if (ConfigSize > gConfigRespSize) {\r
3425 //\r
3426 // Do 25% overallocation to minimize the number of memory allocations after ReadyToBoot.\r
3427 // Since lots of allocation after ReadyToBoot may change memory map and cause S4 resume issue.\r
3428 //\r
3429 gConfigRespSize = ConfigSize + (ConfigSize >> 2);\r
3430 if (gRTConfigRespBuffer != NULL) {\r
3431 FreePool (gRTConfigRespBuffer);\r
3432 DEBUG ((DEBUG_WARN, "[HiiDatabase]: Memory allocation is required after ReadyToBoot, which may change memory map and cause S4 resume issue.\n"));\r
3433 }\r
3434\r
3435 gRTConfigRespBuffer = (EFI_STRING)AllocateRuntimeZeroPool (gConfigRespSize);\r
3436 if (gRTConfigRespBuffer == NULL) {\r
3437 FreePool (ConfigAltResp);\r
3438 DEBUG ((DEBUG_ERROR, "[HiiDatabase]: No enough memory resource to store the ConfigResp string.\n"));\r
3439 //\r
3440 // Remove from the System Table when the configuration runtime buffer is freed.\r
3441 //\r
3442 gBS->InstallConfigurationTable (&gEfiHiiConfigRoutingProtocolGuid, NULL);\r
3443 return EFI_OUT_OF_RESOURCES;\r
3444 }\r
3445 } else {\r
3446 ZeroMem (gRTConfigRespBuffer, gConfigRespSize);\r
3447 }\r
3448\r
3449 CopyMem (gRTConfigRespBuffer, ConfigAltResp, ConfigSize);\r
3450 gBS->InstallConfigurationTable (&gEfiHiiConfigRoutingProtocolGuid, gRTConfigRespBuffer);\r
3451 FreePool (ConfigAltResp);\r
3452 }\r
3453\r
3454 return EFI_SUCCESS;\r
3455}\r
3456\r
3457/**\r
3458This is an internal function,mainly use to get HiiDatabase information.\r
3459\r
3460@param This A pointer to the EFI_HII_DATABASE_PROTOCOL instance.\r
3461\r
3462@retval EFI_SUCCESS Get the information successfully.\r
3463@retval EFI_OUT_OF_RESOURCES Not enough memory to store the Hiidatabase data.\r
3464\r
3465**/\r
3466EFI_STATUS\r
3467HiiGetDatabaseInfo (\r
3468 IN CONST EFI_HII_DATABASE_PROTOCOL *This\r
3469 )\r
3470{\r
3471 EFI_STATUS Status;\r
3472 EFI_HII_PACKAGE_LIST_HEADER *DatabaseInfo;\r
3473 UINTN DatabaseInfoSize;\r
3474\r
3475 DatabaseInfo = NULL;\r
3476 DatabaseInfoSize = 0;\r
3477\r
3478 //\r
3479 // Get HiiDatabase information.\r
3480 //\r
3481 Status = HiiExportPackageLists (This, NULL, &DatabaseInfoSize, DatabaseInfo);\r
3482\r
3483 ASSERT (Status == EFI_BUFFER_TOO_SMALL);\r
3484\r
3485 if (DatabaseInfoSize > gDatabaseInfoSize ) {\r
3486 //\r
3487 // Do 25% overallocation to minimize the number of memory allocations after ReadyToBoot.\r
3488 // Since lots of allocation after ReadyToBoot may change memory map and cause S4 resume issue.\r
3489 //\r
3490 gDatabaseInfoSize = DatabaseInfoSize + (DatabaseInfoSize >> 2);\r
3491 if (gRTDatabaseInfoBuffer != NULL) {\r
3492 FreePool (gRTDatabaseInfoBuffer);\r
3493 DEBUG ((DEBUG_WARN, "[HiiDatabase]: Memory allocation is required after ReadyToBoot, which may change memory map and cause S4 resume issue.\n"));\r
3494 }\r
3495\r
3496 gRTDatabaseInfoBuffer = AllocateRuntimeZeroPool (gDatabaseInfoSize);\r
3497 if (gRTDatabaseInfoBuffer == NULL) {\r
3498 DEBUG ((DEBUG_ERROR, "[HiiDatabase]: No enough memory resource to store the HiiDatabase info.\n"));\r
3499 //\r
3500 // Remove from the System Table when the configuration runtime buffer is freed.\r
3501 //\r
3502 gBS->InstallConfigurationTable (&gEfiHiiDatabaseProtocolGuid, NULL);\r
3503 return EFI_OUT_OF_RESOURCES;\r
3504 }\r
3505 } else {\r
3506 ZeroMem (gRTDatabaseInfoBuffer, gDatabaseInfoSize);\r
3507 }\r
3508\r
3509 Status = HiiExportPackageLists (This, NULL, &DatabaseInfoSize, gRTDatabaseInfoBuffer);\r
3510 ASSERT_EFI_ERROR (Status);\r
3511 gBS->InstallConfigurationTable (&gEfiHiiDatabaseProtocolGuid, gRTDatabaseInfoBuffer);\r
3512\r
3513 return EFI_SUCCESS;\r
3514}\r
3515\r
3516/**\r
3517 This function adds the packages in the package list to the database and returns a handle. If there is a\r
3518 EFI_DEVICE_PATH_PROTOCOL associated with the DriverHandle, then this function will\r
3519 create a package of type EFI_PACKAGE_TYPE_DEVICE_PATH and add it to the package list.\r
3520\r
3521 @param This A pointer to the EFI_HII_DATABASE_PROTOCOL\r
3522 instance.\r
3523 @param PackageList A pointer to an EFI_HII_PACKAGE_LIST_HEADER\r
3524 structure.\r
3525 @param DriverHandle Associate the package list with this EFI handle.\r
3526 If a NULL is specified, this data will not be associate\r
3527 with any drivers and cannot have a callback induced.\r
3528 @param Handle A pointer to the EFI_HII_HANDLE instance.\r
3529\r
3530 @retval EFI_SUCCESS The package list associated with the Handle was\r
3531 added to the HII database.\r
3532 @retval EFI_OUT_OF_RESOURCES Unable to allocate necessary resources for the new\r
3533 database contents.\r
3534 @retval EFI_INVALID_PARAMETER PackageList is NULL or Handle is NULL.\r
3535 @retval EFI_INVALID_PARAMETER PackageListGuid already exists in database.\r
3536\r
3537**/\r
3538EFI_STATUS\r
3539EFIAPI\r
3540HiiNewPackageList (\r
3541 IN CONST EFI_HII_DATABASE_PROTOCOL *This,\r
3542 IN CONST EFI_HII_PACKAGE_LIST_HEADER *PackageList,\r
3543 IN CONST EFI_HANDLE DriverHandle OPTIONAL,\r
3544 OUT EFI_HII_HANDLE *Handle\r
3545 )\r
3546{\r
3547 EFI_STATUS Status;\r
3548 HII_DATABASE_PRIVATE_DATA *Private;\r
3549 HII_DATABASE_RECORD *DatabaseRecord;\r
3550 EFI_DEVICE_PATH_PROTOCOL *DevicePath;\r
3551 LIST_ENTRY *Link;\r
3552 EFI_GUID PackageListGuid;\r
3553\r
3554 if ((This == NULL) || (PackageList == NULL) || (Handle == NULL)) {\r
3555 return EFI_INVALID_PARAMETER;\r
3556 }\r
3557\r
3558 Private = HII_DATABASE_DATABASE_PRIVATE_DATA_FROM_THIS (This);\r
3559 CopyMem (&PackageListGuid, (VOID *)PackageList, sizeof (EFI_GUID));\r
3560\r
3561 //\r
3562 // Check the Package list GUID to guarantee this GUID is unique in database.\r
3563 //\r
3564 for (Link = Private->DatabaseList.ForwardLink; Link != &Private->DatabaseList; Link = Link->ForwardLink) {\r
3565 DatabaseRecord = CR (Link, HII_DATABASE_RECORD, DatabaseEntry, HII_DATABASE_RECORD_SIGNATURE);\r
3566 if (CompareGuid (\r
3567 &(DatabaseRecord->PackageList->PackageListHdr.PackageListGuid),\r
3568 &PackageListGuid\r
3569 ) &&\r
3570 (DatabaseRecord->DriverHandle == DriverHandle))\r
3571 {\r
3572 return EFI_INVALID_PARAMETER;\r
3573 }\r
3574 }\r
3575\r
3576 EfiAcquireLock (&mHiiDatabaseLock);\r
3577\r
3578 //\r
3579 // Build a PackageList node\r
3580 //\r
3581 Status = GenerateHiiDatabaseRecord (Private, &DatabaseRecord);\r
3582 if (EFI_ERROR (Status)) {\r
3583 EfiReleaseLock (&mHiiDatabaseLock);\r
3584 return Status;\r
3585 }\r
3586\r
3587 //\r
3588 // Fill in information of the created Package List node\r
3589 // according to incoming package list.\r
3590 //\r
3591 Status = AddPackages (Private, EFI_HII_DATABASE_NOTIFY_NEW_PACK, PackageList, DatabaseRecord);\r
3592 if (EFI_ERROR (Status)) {\r
3593 EfiReleaseLock (&mHiiDatabaseLock);\r
3594 return Status;\r
3595 }\r
3596\r
3597 DatabaseRecord->DriverHandle = DriverHandle;\r
3598\r
3599 //\r
3600 // Create a Device path package and add into the package list if exists.\r
3601 //\r
3602 Status = gBS->HandleProtocol (\r
3603 DriverHandle,\r
3604 &gEfiDevicePathProtocolGuid,\r
3605 (VOID **)&DevicePath\r
3606 );\r
3607 if (!EFI_ERROR (Status)) {\r
3608 Status = AddDevicePathPackage (Private, EFI_HII_DATABASE_NOTIFY_NEW_PACK, DevicePath, DatabaseRecord);\r
3609 ASSERT_EFI_ERROR (Status);\r
3610 }\r
3611\r
3612 *Handle = DatabaseRecord->Handle;\r
3613\r
3614 //\r
3615 // Check whether need to get the Database info.\r
3616 // Only after ReadyToBoot, need to do the export.\r
3617 //\r
3618 if (gExportAfterReadyToBoot) {\r
3619 HiiGetDatabaseInfo (This);\r
3620 }\r
3621\r
3622 EfiReleaseLock (&mHiiDatabaseLock);\r
3623\r
3624 //\r
3625 // Notes:\r
3626 // HiiGetDatabaseInfo () will get the contents of HII data base,\r
3627 // belong to the atomic behavior of Hii Database update.\r
3628 // And since HiiGetConfigRespInfo () will get the configuration setting info from HII drivers\r
3629 // we can not think it belong to the atomic behavior of Hii Database update.\r
3630 // That's why EfiReleaseLock (&mHiiDatabaseLock) is callled before HiiGetConfigRespInfo ().\r
3631 //\r
3632\r
3633 // Check whether need to get the configuration setting info from HII drivers.\r
3634 // When after ReadyToBoot and need to do the export for form package add.\r
3635 //\r
3636 if (gExportAfterReadyToBoot && gExportConfigResp) {\r
3637 HiiGetConfigRespInfo (This);\r
3638 }\r
3639\r
3640 return EFI_SUCCESS;\r
3641}\r
3642\r
3643/**\r
3644 This function removes the package list that is associated with Handle\r
3645 from the HII database. Before removing the package, any registered functions\r
3646 with the notification type REMOVE_PACK and the same package type will be called.\r
3647\r
3648 @param This A pointer to the EFI_HII_DATABASE_PROTOCOL\r
3649 instance.\r
3650 @param Handle The handle that was registered to the data that is\r
3651 requested for removal.\r
3652\r
3653 @retval EFI_SUCCESS The data associated with the Handle was removed\r
3654 from the HII database.\r
3655 @retval EFI_NOT_FOUND The specified handle is not in database.\r
3656 @retval EFI_INVALID_PARAMETER The Handle was not valid.\r
3657\r
3658**/\r
3659EFI_STATUS\r
3660EFIAPI\r
3661HiiRemovePackageList (\r
3662 IN CONST EFI_HII_DATABASE_PROTOCOL *This,\r
3663 IN EFI_HII_HANDLE Handle\r
3664 )\r
3665{\r
3666 EFI_STATUS Status;\r
3667 HII_DATABASE_PRIVATE_DATA *Private;\r
3668 LIST_ENTRY *Link;\r
3669 HII_DATABASE_RECORD *Node;\r
3670 HII_DATABASE_PACKAGE_LIST_INSTANCE *PackageList;\r
3671 HII_HANDLE *HiiHandle;\r
3672\r
3673 if (This == NULL) {\r
3674 return EFI_INVALID_PARAMETER;\r
3675 }\r
3676\r
3677 if (!IsHiiHandleValid (Handle)) {\r
3678 return EFI_NOT_FOUND;\r
3679 }\r
3680\r
3681 EfiAcquireLock (&mHiiDatabaseLock);\r
3682\r
3683 Private = HII_DATABASE_DATABASE_PRIVATE_DATA_FROM_THIS (This);\r
3684\r
3685 //\r
3686 // Get the packagelist to be removed.\r
3687 //\r
3688 for (Link = Private->DatabaseList.ForwardLink; Link != &Private->DatabaseList; Link = Link->ForwardLink) {\r
3689 Node = CR (Link, HII_DATABASE_RECORD, DatabaseEntry, HII_DATABASE_RECORD_SIGNATURE);\r
3690 if (Node->Handle == Handle) {\r
3691 PackageList = (HII_DATABASE_PACKAGE_LIST_INSTANCE *)(Node->PackageList);\r
3692 ASSERT (PackageList != NULL);\r
3693\r
3694 //\r
3695 // Call registered functions with REMOVE_PACK before removing packages\r
3696 // then remove them.\r
3697 //\r
3698 Status = RemoveGuidPackages (Private, Handle, PackageList);\r
3699 if (EFI_ERROR (Status)) {\r
3700 EfiReleaseLock (&mHiiDatabaseLock);\r
3701 return Status;\r
3702 }\r
3703\r
3704 Status = RemoveFormPackages (Private, Handle, PackageList);\r
3705 if (EFI_ERROR (Status)) {\r
3706 EfiReleaseLock (&mHiiDatabaseLock);\r
3707 return Status;\r
3708 }\r
3709\r
3710 Status = RemoveKeyboardLayoutPackages (Private, Handle, PackageList);\r
3711 if (EFI_ERROR (Status)) {\r
3712 EfiReleaseLock (&mHiiDatabaseLock);\r
3713 return Status;\r
3714 }\r
3715\r
3716 Status = RemoveStringPackages (Private, Handle, PackageList);\r
3717 if (EFI_ERROR (Status)) {\r
3718 EfiReleaseLock (&mHiiDatabaseLock);\r
3719 return Status;\r
3720 }\r
3721\r
3722 Status = RemoveFontPackages (Private, Handle, PackageList);\r
3723 if (EFI_ERROR (Status)) {\r
3724 EfiReleaseLock (&mHiiDatabaseLock);\r
3725 return Status;\r
3726 }\r
3727\r
3728 Status = RemoveImagePackages (Private, Handle, PackageList);\r
3729 if (EFI_ERROR (Status)) {\r
3730 EfiReleaseLock (&mHiiDatabaseLock);\r
3731 return Status;\r
3732 }\r
3733\r
3734 Status = RemoveSimpleFontPackages (Private, Handle, PackageList);\r
3735 if (EFI_ERROR (Status)) {\r
3736 EfiReleaseLock (&mHiiDatabaseLock);\r
3737 return Status;\r
3738 }\r
3739\r
3740 Status = RemoveDevicePathPackage (Private, Handle, PackageList);\r
3741 if (EFI_ERROR (Status)) {\r
3742 EfiReleaseLock (&mHiiDatabaseLock);\r
3743 return Status;\r
3744 }\r
3745\r
3746 //\r
3747 // Free resources of the package list\r
3748 //\r
3749 RemoveEntryList (&Node->DatabaseEntry);\r
3750\r
3751 HiiHandle = (HII_HANDLE *)Handle;\r
3752 RemoveEntryList (&HiiHandle->Handle);\r
3753 Private->HiiHandleCount--;\r
3754 ASSERT (Private->HiiHandleCount >= 0);\r
3755\r
3756 HiiHandle->Signature = 0;\r
3757 FreePool (HiiHandle);\r
3758 FreePool (Node->PackageList);\r
3759 FreePool (Node);\r
3760\r
3761 //\r
3762 // Check whether need to get the Database info.\r
3763 // Only after ReadyToBoot, need to do the export.\r
3764 //\r
3765 if (gExportAfterReadyToBoot) {\r
3766 HiiGetDatabaseInfo (This);\r
3767 }\r
3768\r
3769 EfiReleaseLock (&mHiiDatabaseLock);\r
3770\r
3771 //\r
3772 // Notes:\r
3773 // HiiGetDatabaseInfo () will get the contents of HII data base,\r
3774 // belong to the atomic behavior of Hii Database update.\r
3775 // And since HiiGetConfigRespInfo () will get the configuration setting info from HII drivers\r
3776 // we can not think it belong to the atomic behavior of Hii Database update.\r
3777 // That's why EfiReleaseLock (&mHiiDatabaseLock) is callled before HiiGetConfigRespInfo ().\r
3778 //\r
3779\r
3780 //\r
3781 // Check whether need to get the configuration setting info from HII drivers.\r
3782 // When after ReadyToBoot and need to do the export for form package remove.\r
3783 //\r
3784 if (gExportAfterReadyToBoot && gExportConfigResp) {\r
3785 HiiGetConfigRespInfo (This);\r
3786 }\r
3787\r
3788 return EFI_SUCCESS;\r
3789 }\r
3790 }\r
3791\r
3792 EfiReleaseLock (&mHiiDatabaseLock);\r
3793 return EFI_NOT_FOUND;\r
3794}\r
3795\r
3796/**\r
3797 This function updates the existing package list (which has the specified Handle)\r
3798 in the HII databases, using the new package list specified by PackageList.\r
3799\r
3800 @param This A pointer to the EFI_HII_DATABASE_PROTOCOL\r
3801 instance.\r
3802 @param Handle The handle that was registered to the data that is\r
3803 requested to be updated.\r
3804 @param PackageList A pointer to an EFI_HII_PACKAGE_LIST_HEADER\r
3805 package.\r
3806\r
3807 @retval EFI_SUCCESS The HII database was successfully updated.\r
3808 @retval EFI_OUT_OF_RESOURCES Unable to allocate enough memory for the updated\r
3809 database.\r
3810 @retval EFI_INVALID_PARAMETER PackageList was NULL.\r
3811 @retval EFI_NOT_FOUND The specified Handle is not in database.\r
3812\r
3813**/\r
3814EFI_STATUS\r
3815EFIAPI\r
3816HiiUpdatePackageList (\r
3817 IN CONST EFI_HII_DATABASE_PROTOCOL *This,\r
3818 IN EFI_HII_HANDLE Handle,\r
3819 IN CONST EFI_HII_PACKAGE_LIST_HEADER *PackageList\r
3820 )\r
3821{\r
3822 EFI_STATUS Status;\r
3823 HII_DATABASE_PRIVATE_DATA *Private;\r
3824 LIST_ENTRY *Link;\r
3825 HII_DATABASE_RECORD *Node;\r
3826 EFI_HII_PACKAGE_HEADER *PackageHdrPtr;\r
3827 HII_DATABASE_PACKAGE_LIST_INSTANCE *OldPackageList;\r
3828 EFI_HII_PACKAGE_HEADER PackageHeader;\r
3829\r
3830 if ((This == NULL) || (PackageList == NULL)) {\r
3831 return EFI_INVALID_PARAMETER;\r
3832 }\r
3833\r
3834 if (!IsHiiHandleValid (Handle)) {\r
3835 return EFI_NOT_FOUND;\r
3836 }\r
3837\r
3838 Private = HII_DATABASE_DATABASE_PRIVATE_DATA_FROM_THIS (This);\r
3839\r
3840 PackageHdrPtr = (EFI_HII_PACKAGE_HEADER *)((UINT8 *)PackageList + sizeof (EFI_HII_PACKAGE_LIST_HEADER));\r
3841\r
3842 Status = EFI_SUCCESS;\r
3843\r
3844 EfiAcquireLock (&mHiiDatabaseLock);\r
3845 //\r
3846 // Get original packagelist to be updated\r
3847 //\r
3848 for (Link = Private->DatabaseList.ForwardLink; Link != &Private->DatabaseList; Link = Link->ForwardLink) {\r
3849 Node = CR (Link, HII_DATABASE_RECORD, DatabaseEntry, HII_DATABASE_RECORD_SIGNATURE);\r
3850 if (Node->Handle == Handle) {\r
3851 OldPackageList = Node->PackageList;\r
3852 //\r
3853 // Remove the package if its type matches one of the package types which is\r
3854 // contained in the new package list.\r
3855 //\r
3856 CopyMem (&PackageHeader, PackageHdrPtr, sizeof (EFI_HII_PACKAGE_HEADER));\r
3857 while (PackageHeader.Type != EFI_HII_PACKAGE_END) {\r
3858 switch (PackageHeader.Type) {\r
3859 case EFI_HII_PACKAGE_TYPE_GUID:\r
3860 Status = RemoveGuidPackages (Private, Handle, OldPackageList);\r
3861 break;\r
3862 case EFI_HII_PACKAGE_FORMS:\r
3863 Status = RemoveFormPackages (Private, Handle, OldPackageList);\r
3864 break;\r
3865 case EFI_HII_PACKAGE_KEYBOARD_LAYOUT:\r
3866 Status = RemoveKeyboardLayoutPackages (Private, Handle, OldPackageList);\r
3867 break;\r
3868 case EFI_HII_PACKAGE_STRINGS:\r
3869 Status = RemoveStringPackages (Private, Handle, OldPackageList);\r
3870 break;\r
3871 case EFI_HII_PACKAGE_FONTS:\r
3872 Status = RemoveFontPackages (Private, Handle, OldPackageList);\r
3873 break;\r
3874 case EFI_HII_PACKAGE_IMAGES:\r
3875 Status = RemoveImagePackages (Private, Handle, OldPackageList);\r
3876 break;\r
3877 case EFI_HII_PACKAGE_SIMPLE_FONTS:\r
3878 Status = RemoveSimpleFontPackages (Private, Handle, OldPackageList);\r
3879 break;\r
3880 case EFI_HII_PACKAGE_DEVICE_PATH:\r
3881 Status = RemoveDevicePathPackage (Private, Handle, OldPackageList);\r
3882 break;\r
3883 }\r
3884\r
3885 if (EFI_ERROR (Status)) {\r
3886 EfiReleaseLock (&mHiiDatabaseLock);\r
3887 return Status;\r
3888 }\r
3889\r
3890 PackageHdrPtr = (EFI_HII_PACKAGE_HEADER *)((UINT8 *)PackageHdrPtr + PackageHeader.Length);\r
3891 CopyMem (&PackageHeader, PackageHdrPtr, sizeof (EFI_HII_PACKAGE_HEADER));\r
3892 }\r
3893\r
3894 //\r
3895 // Add all of the packages within the new package list\r
3896 //\r
3897 Status = AddPackages (Private, EFI_HII_DATABASE_NOTIFY_ADD_PACK, PackageList, Node);\r
3898\r
3899 //\r
3900 // Check whether need to get the Database info.\r
3901 // Only after ReadyToBoot, need to do the export.\r
3902 //\r
3903 if (gExportAfterReadyToBoot && (Status == EFI_SUCCESS)) {\r
3904 HiiGetDatabaseInfo (This);\r
3905 }\r
3906\r
3907 EfiReleaseLock (&mHiiDatabaseLock);\r
3908\r
3909 //\r
3910 // Notes:\r
3911 // HiiGetDatabaseInfo () will get the contents of HII data base,\r
3912 // belong to the atomic behavior of Hii Database update.\r
3913 // And since HiiGetConfigRespInfo () will get the configuration setting info from HII drivers\r
3914 // we can not think it belong to the atomic behavior of Hii Database update.\r
3915 // That's why EfiReleaseLock (&mHiiDatabaseLock) is callled before HiiGetConfigRespInfo ().\r
3916 //\r
3917\r
3918 //\r
3919 // Check whether need to get the configuration setting info from HII drivers.\r
3920 // When after ReadyToBoot and need to do the export for form package update.\r
3921 //\r
3922 if (gExportAfterReadyToBoot && gExportConfigResp && (Status == EFI_SUCCESS)) {\r
3923 HiiGetConfigRespInfo (This);\r
3924 }\r
3925\r
3926 return Status;\r
3927 }\r
3928 }\r
3929\r
3930 EfiReleaseLock (&mHiiDatabaseLock);\r
3931 return EFI_NOT_FOUND;\r
3932}\r
3933\r
3934/**\r
3935 This function returns a list of the package handles of the specified type\r
3936 that are currently active in the database. The pseudo-type\r
3937 EFI_HII_PACKAGE_TYPE_ALL will cause all package handles to be listed.\r
3938\r
3939 @param This A pointer to the EFI_HII_DATABASE_PROTOCOL\r
3940 instance.\r
3941 @param PackageType Specifies the package type of the packages to list\r
3942 or EFI_HII_PACKAGE_TYPE_ALL for all packages to be\r
3943 listed.\r
3944 @param PackageGuid If PackageType is EFI_HII_PACKAGE_TYPE_GUID, then\r
3945 this is the pointer to the GUID which must match\r
3946 the Guid field of EFI_HII_GUID_PACKAGE_GUID_HDR.\r
3947 Otherwise, it must be NULL.\r
3948 @param HandleBufferLength On input, a pointer to the length of the handle\r
3949 buffer. On output, the length of the handle\r
3950 buffer that is required for the handles found.\r
3951 @param Handle An array of EFI_HII_HANDLE instances returned.\r
3952\r
3953 @retval EFI_SUCCESS The matching handles are outputted successfully.\r
3954 HandleBufferLength is updated with the actual length.\r
3955 @retval EFI_BUFFER_TO_SMALL The HandleBufferLength parameter indicates that\r
3956 Handle is too small to support the number of\r
3957 handles. HandleBufferLength is updated with a\r
3958 value that will enable the data to fit.\r
3959 @retval EFI_NOT_FOUND No matching handle could not be found in database.\r
3960 @retval EFI_INVALID_PARAMETER HandleBufferLength was NULL.\r
3961 @retval EFI_INVALID_PARAMETER The value referenced by HandleBufferLength was not\r
3962 zero and Handle was NULL.\r
3963 @retval EFI_INVALID_PARAMETER PackageType is not a EFI_HII_PACKAGE_TYPE_GUID but\r
3964 PackageGuid is not NULL, PackageType is a EFI_HII_\r
3965 PACKAGE_TYPE_GUID but PackageGuid is NULL.\r
3966\r
3967**/\r
3968EFI_STATUS\r
3969EFIAPI\r
3970HiiListPackageLists (\r
3971 IN CONST EFI_HII_DATABASE_PROTOCOL *This,\r
3972 IN UINT8 PackageType,\r
3973 IN CONST EFI_GUID *PackageGuid,\r
3974 IN OUT UINTN *HandleBufferLength,\r
3975 OUT EFI_HII_HANDLE *Handle\r
3976 )\r
3977{\r
3978 HII_GUID_PACKAGE_INSTANCE *GuidPackage;\r
3979 HII_DATABASE_PRIVATE_DATA *Private;\r
3980 HII_DATABASE_RECORD *Node;\r
3981 LIST_ENTRY *Link;\r
3982 BOOLEAN Matched;\r
3983 HII_HANDLE **Result;\r
3984 UINTN ResultSize;\r
3985 HII_DATABASE_PACKAGE_LIST_INSTANCE *PackageList;\r
3986 LIST_ENTRY *Link1;\r
3987\r
3988 //\r
3989 // Check input parameters\r
3990 //\r
3991 if ((This == NULL) || (HandleBufferLength == NULL)) {\r
3992 return EFI_INVALID_PARAMETER;\r
3993 }\r
3994\r
3995 if ((*HandleBufferLength > 0) && (Handle == NULL)) {\r
3996 return EFI_INVALID_PARAMETER;\r
3997 }\r
3998\r
3999 if (((PackageType == EFI_HII_PACKAGE_TYPE_GUID) && (PackageGuid == NULL)) ||\r
4000 ((PackageType != EFI_HII_PACKAGE_TYPE_GUID) && (PackageGuid != NULL)))\r
4001 {\r
4002 return EFI_INVALID_PARAMETER;\r
4003 }\r
4004\r
4005 Private = HII_DATABASE_DATABASE_PRIVATE_DATA_FROM_THIS (This);\r
4006 Matched = FALSE;\r
4007 Result = (HII_HANDLE **)Handle;\r
4008 ResultSize = 0;\r
4009\r
4010 for (Link = Private->DatabaseList.ForwardLink; Link != &Private->DatabaseList; Link = Link->ForwardLink) {\r
4011 Node = CR (Link, HII_DATABASE_RECORD, DatabaseEntry, HII_DATABASE_RECORD_SIGNATURE);\r
4012 PackageList = (HII_DATABASE_PACKAGE_LIST_INSTANCE *)(Node->PackageList);\r
4013 switch (PackageType) {\r
4014 case EFI_HII_PACKAGE_TYPE_GUID:\r
4015 for (Link1 = PackageList->GuidPkgHdr.ForwardLink; Link1 != &PackageList->GuidPkgHdr; Link1 = Link1->ForwardLink) {\r
4016 GuidPackage = CR (Link1, HII_GUID_PACKAGE_INSTANCE, GuidEntry, HII_GUID_PACKAGE_SIGNATURE);\r
4017 if (CompareGuid (\r
4018 (EFI_GUID *)PackageGuid,\r
4019 (EFI_GUID *)(GuidPackage->GuidPkg + sizeof (EFI_HII_PACKAGE_HEADER))\r
4020 ))\r
4021 {\r
4022 Matched = TRUE;\r
4023 break;\r
4024 }\r
4025 }\r
4026\r
4027 break;\r
4028 case EFI_HII_PACKAGE_FORMS:\r
4029 if (!IsListEmpty (&PackageList->FormPkgHdr)) {\r
4030 Matched = TRUE;\r
4031 }\r
4032\r
4033 break;\r
4034 case EFI_HII_PACKAGE_KEYBOARD_LAYOUT:\r
4035 if (!IsListEmpty (&PackageList->KeyboardLayoutHdr)) {\r
4036 Matched = TRUE;\r
4037 }\r
4038\r
4039 break;\r
4040 case EFI_HII_PACKAGE_STRINGS:\r
4041 if (!IsListEmpty (&PackageList->StringPkgHdr)) {\r
4042 Matched = TRUE;\r
4043 }\r
4044\r
4045 break;\r
4046 case EFI_HII_PACKAGE_FONTS:\r
4047 if (!IsListEmpty (&PackageList->FontPkgHdr)) {\r
4048 Matched = TRUE;\r
4049 }\r
4050\r
4051 break;\r
4052 case EFI_HII_PACKAGE_IMAGES:\r
4053 if (PackageList->ImagePkg != NULL) {\r
4054 Matched = TRUE;\r
4055 }\r
4056\r
4057 break;\r
4058 case EFI_HII_PACKAGE_SIMPLE_FONTS:\r
4059 if (!IsListEmpty (&PackageList->SimpleFontPkgHdr)) {\r
4060 Matched = TRUE;\r
4061 }\r
4062\r
4063 break;\r
4064 case EFI_HII_PACKAGE_DEVICE_PATH:\r
4065 if (PackageList->DevicePathPkg != NULL) {\r
4066 Matched = TRUE;\r
4067 }\r
4068\r
4069 break;\r
4070 //\r
4071 // Pseudo-type EFI_HII_PACKAGE_TYPE_ALL will cause all package handles\r
4072 // to be listed.\r
4073 //\r
4074 case EFI_HII_PACKAGE_TYPE_ALL:\r
4075 Matched = TRUE;\r
4076 break;\r
4077 default:\r
4078 break;\r
4079 }\r
4080\r
4081 //\r
4082 // This active package list has the specified package type, list it.\r
4083 //\r
4084 if (Matched) {\r
4085 ResultSize += sizeof (EFI_HII_HANDLE);\r
4086 if (ResultSize <= *HandleBufferLength) {\r
4087 *Result++ = Node->Handle;\r
4088 }\r
4089 }\r
4090\r
4091 Matched = FALSE;\r
4092 }\r
4093\r
4094 if (ResultSize == 0) {\r
4095 return EFI_NOT_FOUND;\r
4096 }\r
4097\r
4098 if (*HandleBufferLength < ResultSize) {\r
4099 *HandleBufferLength = ResultSize;\r
4100 return EFI_BUFFER_TOO_SMALL;\r
4101 }\r
4102\r
4103 *HandleBufferLength = ResultSize;\r
4104 return EFI_SUCCESS;\r
4105}\r
4106\r
4107/**\r
4108 This function will export one or all package lists in the database to a buffer.\r
4109 For each package list exported, this function will call functions registered\r
4110 with EXPORT_PACK and then copy the package list to the buffer.\r
4111\r
4112 @param This A pointer to the EFI_HII_DATABASE_PROTOCOL\r
4113 instance.\r
4114 @param Handle An EFI_HII_HANDLE that corresponds to the desired\r
4115 package list in the HII database to export or NULL\r
4116 to indicate all package lists should be exported.\r
4117 @param BufferSize On input, a pointer to the length of the buffer.\r
4118 On output, the length of the buffer that is\r
4119 required for the exported data.\r
4120 @param Buffer A pointer to a buffer that will contain the\r
4121 results of the export function.\r
4122\r
4123 @retval EFI_SUCCESS Package exported.\r
4124 @retval EFI_BUFFER_TO_SMALL The HandleBufferLength parameter indicates that\r
4125 Handle is too small to support the number of\r
4126 handles. HandleBufferLength is updated with a\r
4127 value that will enable the data to fit.\r
4128 @retval EFI_NOT_FOUND The specified Handle could not be found in the\r
4129 current database.\r
4130 @retval EFI_INVALID_PARAMETER BufferSize was NULL.\r
4131 @retval EFI_INVALID_PARAMETER The value referenced by BufferSize was not zero\r
4132 and Buffer was NULL.\r
4133\r
4134**/\r
4135EFI_STATUS\r
4136EFIAPI\r
4137HiiExportPackageLists (\r
4138 IN CONST EFI_HII_DATABASE_PROTOCOL *This,\r
4139 IN EFI_HII_HANDLE Handle,\r
4140 IN OUT UINTN *BufferSize,\r
4141 OUT EFI_HII_PACKAGE_LIST_HEADER *Buffer\r
4142 )\r
4143{\r
4144 LIST_ENTRY *Link;\r
4145 EFI_STATUS Status;\r
4146 HII_DATABASE_PRIVATE_DATA *Private;\r
4147 HII_DATABASE_RECORD *Node;\r
4148 UINTN UsedSize;\r
4149\r
4150 if ((This == NULL) || (BufferSize == NULL)) {\r
4151 return EFI_INVALID_PARAMETER;\r
4152 }\r
4153\r
4154 if ((*BufferSize > 0) && (Buffer == NULL)) {\r
4155 return EFI_INVALID_PARAMETER;\r
4156 }\r
4157\r
4158 if ((Handle != NULL) && (!IsHiiHandleValid (Handle))) {\r
4159 return EFI_NOT_FOUND;\r
4160 }\r
4161\r
4162 Private = HII_DATABASE_DATABASE_PRIVATE_DATA_FROM_THIS (This);\r
4163 UsedSize = 0;\r
4164\r
4165 for (Link = Private->DatabaseList.ForwardLink; Link != &Private->DatabaseList; Link = Link->ForwardLink) {\r
4166 Node = CR (Link, HII_DATABASE_RECORD, DatabaseEntry, HII_DATABASE_RECORD_SIGNATURE);\r
4167 if (Handle == NULL) {\r
4168 //\r
4169 // Export all package lists in current hii database.\r
4170 //\r
4171 Status = ExportPackageList (\r
4172 Private,\r
4173 Node->Handle,\r
4174 (HII_DATABASE_PACKAGE_LIST_INSTANCE *)(Node->PackageList),\r
4175 &UsedSize,\r
4176 *BufferSize,\r
4177 (EFI_HII_PACKAGE_LIST_HEADER *)((UINT8 *)Buffer + UsedSize)\r
4178 );\r
4179 ASSERT_EFI_ERROR (Status);\r
4180 } else if ((Handle != NULL) && (Node->Handle == Handle)) {\r
4181 Status = ExportPackageList (\r
4182 Private,\r
4183 Handle,\r
4184 (HII_DATABASE_PACKAGE_LIST_INSTANCE *)(Node->PackageList),\r
4185 &UsedSize,\r
4186 *BufferSize,\r
4187 Buffer\r
4188 );\r
4189 ASSERT_EFI_ERROR (Status);\r
4190 if (*BufferSize < UsedSize) {\r
4191 *BufferSize = UsedSize;\r
4192 return EFI_BUFFER_TOO_SMALL;\r
4193 }\r
4194\r
4195 return EFI_SUCCESS;\r
4196 }\r
4197 }\r
4198\r
4199 if ((Handle == NULL) && (UsedSize != 0)) {\r
4200 if (*BufferSize < UsedSize) {\r
4201 *BufferSize = UsedSize;\r
4202 return EFI_BUFFER_TOO_SMALL;\r
4203 }\r
4204\r
4205 return EFI_SUCCESS;\r
4206 }\r
4207\r
4208 return EFI_NOT_FOUND;\r
4209}\r
4210\r
4211/**\r
4212 This function registers a function which will be called when specified actions related to packages of\r
4213 the specified type occur in the HII database. By registering a function, other HII-related drivers are\r
4214 notified when specific package types are added, removed or updated in the HII database.\r
4215 Each driver or application which registers a notification should use\r
4216 EFI_HII_DATABASE_PROTOCOL.UnregisterPackageNotify() before exiting.\r
4217\r
4218 @param This A pointer to the EFI_HII_DATABASE_PROTOCOL\r
4219 instance.\r
4220 @param PackageType Specifies the package type of the packages to list\r
4221 or EFI_HII_PACKAGE_TYPE_ALL for all packages to be\r
4222 listed.\r
4223 @param PackageGuid If PackageType is EFI_HII_PACKAGE_TYPE_GUID, then\r
4224 this is the pointer to the GUID which must match\r
4225 the Guid field of\r
4226 EFI_HII_GUID_PACKAGE_GUID_HDR. Otherwise, it must\r
4227 be NULL.\r
4228 @param PackageNotifyFn Points to the function to be called when the event\r
4229 specified by\r
4230 NotificationType occurs.\r
4231 @param NotifyType Describes the types of notification which this\r
4232 function will be receiving.\r
4233 @param NotifyHandle Points to the unique handle assigned to the\r
4234 registered notification. Can be used in\r
4235 EFI_HII_DATABASE_PROTOCOL.UnregisterPackageNotify()\r
4236 to stop notifications.\r
4237\r
4238 @retval EFI_SUCCESS Notification registered successfully.\r
4239 @retval EFI_OUT_OF_RESOURCES Unable to allocate necessary data structures\r
4240 @retval EFI_INVALID_PARAMETER NotifyHandle is NULL.\r
4241 @retval EFI_INVALID_PARAMETER PackageGuid is not NULL when PackageType is not\r
4242 EFI_HII_PACKAGE_TYPE_GUID.\r
4243 @retval EFI_INVALID_PARAMETER PackageGuid is NULL when PackageType is\r
4244 EFI_HII_PACKAGE_TYPE_GUID.\r
4245\r
4246**/\r
4247EFI_STATUS\r
4248EFIAPI\r
4249HiiRegisterPackageNotify (\r
4250 IN CONST EFI_HII_DATABASE_PROTOCOL *This,\r
4251 IN UINT8 PackageType,\r
4252 IN CONST EFI_GUID *PackageGuid,\r
4253 IN CONST EFI_HII_DATABASE_NOTIFY PackageNotifyFn,\r
4254 IN EFI_HII_DATABASE_NOTIFY_TYPE NotifyType,\r
4255 OUT EFI_HANDLE *NotifyHandle\r
4256 )\r
4257{\r
4258 HII_DATABASE_PRIVATE_DATA *Private;\r
4259 HII_DATABASE_NOTIFY *Notify;\r
4260 EFI_STATUS Status;\r
4261\r
4262 if ((This == NULL) || (NotifyHandle == NULL)) {\r
4263 return EFI_INVALID_PARAMETER;\r
4264 }\r
4265\r
4266 if (((PackageType == EFI_HII_PACKAGE_TYPE_GUID) && (PackageGuid == NULL)) ||\r
4267 ((PackageType != EFI_HII_PACKAGE_TYPE_GUID) && (PackageGuid != NULL)))\r
4268 {\r
4269 return EFI_INVALID_PARAMETER;\r
4270 }\r
4271\r
4272 Private = HII_DATABASE_DATABASE_PRIVATE_DATA_FROM_THIS (This);\r
4273\r
4274 //\r
4275 // Allocate a notification node\r
4276 //\r
4277 Notify = (HII_DATABASE_NOTIFY *)AllocateZeroPool (sizeof (HII_DATABASE_NOTIFY));\r
4278 if (Notify == NULL) {\r
4279 return EFI_OUT_OF_RESOURCES;\r
4280 }\r
4281\r
4282 //\r
4283 // Generate a notify handle\r
4284 //\r
4285 Status = gBS->InstallMultipleProtocolInterfaces (\r
4286 &Notify->NotifyHandle,\r
4287 &gEfiCallerIdGuid,\r
4288 NULL,\r
4289 NULL\r
4290 );\r
4291 ASSERT_EFI_ERROR (Status);\r
4292\r
4293 //\r
4294 // Fill in the information to the notification node\r
4295 //\r
4296 Notify->Signature = HII_DATABASE_NOTIFY_SIGNATURE;\r
4297 Notify->PackageType = PackageType;\r
4298 Notify->PackageGuid = (EFI_GUID *)PackageGuid;\r
4299 Notify->PackageNotifyFn = (EFI_HII_DATABASE_NOTIFY)PackageNotifyFn;\r
4300 Notify->NotifyType = NotifyType;\r
4301\r
4302 InsertTailList (&Private->DatabaseNotifyList, &Notify->DatabaseNotifyEntry);\r
4303 *NotifyHandle = Notify->NotifyHandle;\r
4304\r
4305 return EFI_SUCCESS;\r
4306}\r
4307\r
4308/**\r
4309 Removes the specified HII database package-related notification.\r
4310\r
4311 @param This A pointer to the EFI_HII_DATABASE_PROTOCOL\r
4312 instance.\r
4313 @param NotificationHandle The handle of the notification function being\r
4314 unregistered.\r
4315\r
4316 @retval EFI_SUCCESS Notification is unregistered successfully.\r
4317 @retval EFI_INVALID_PARAMETER The Handle is invalid.\r
4318 @retval EFI_NOT_FOUND The incoming notification handle does not exist\r
4319 in current hii database.\r
4320\r
4321**/\r
4322EFI_STATUS\r
4323EFIAPI\r
4324HiiUnregisterPackageNotify (\r
4325 IN CONST EFI_HII_DATABASE_PROTOCOL *This,\r
4326 IN EFI_HANDLE NotificationHandle\r
4327 )\r
4328{\r
4329 HII_DATABASE_PRIVATE_DATA *Private;\r
4330 HII_DATABASE_NOTIFY *Notify;\r
4331 LIST_ENTRY *Link;\r
4332 EFI_STATUS Status;\r
4333\r
4334 if (This == NULL) {\r
4335 return EFI_INVALID_PARAMETER;\r
4336 }\r
4337\r
4338 if (NotificationHandle == NULL) {\r
4339 return EFI_NOT_FOUND;\r
4340 }\r
4341\r
4342 Status = gBS->OpenProtocol (\r
4343 NotificationHandle,\r
4344 &gEfiCallerIdGuid,\r
4345 NULL,\r
4346 NULL,\r
4347 NULL,\r
4348 EFI_OPEN_PROTOCOL_TEST_PROTOCOL\r
4349 );\r
4350 if (EFI_ERROR (Status)) {\r
4351 return EFI_NOT_FOUND;\r
4352 }\r
4353\r
4354 Private = HII_DATABASE_DATABASE_PRIVATE_DATA_FROM_THIS (This);\r
4355\r
4356 for (Link = Private->DatabaseNotifyList.ForwardLink; Link != &Private->DatabaseNotifyList; Link = Link->ForwardLink) {\r
4357 Notify = CR (Link, HII_DATABASE_NOTIFY, DatabaseNotifyEntry, HII_DATABASE_NOTIFY_SIGNATURE);\r
4358 if (Notify->NotifyHandle == NotificationHandle) {\r
4359 //\r
4360 // Remove the matching notification node\r
4361 //\r
4362 RemoveEntryList (&Notify->DatabaseNotifyEntry);\r
4363 Status = gBS->UninstallMultipleProtocolInterfaces (\r
4364 Notify->NotifyHandle,\r
4365 &gEfiCallerIdGuid,\r
4366 NULL,\r
4367 NULL\r
4368 );\r
4369 ASSERT_EFI_ERROR (Status);\r
4370 FreePool (Notify);\r
4371\r
4372 return EFI_SUCCESS;\r
4373 }\r
4374 }\r
4375\r
4376 return EFI_NOT_FOUND;\r
4377}\r
4378\r
4379/**\r
4380 This routine retrieves an array of GUID values for each keyboard layout that\r
4381 was previously registered in the system.\r
4382\r
4383 @param This A pointer to the EFI_HII_DATABASE_PROTOCOL\r
4384 instance.\r
4385 @param KeyGuidBufferLength On input, a pointer to the length of the keyboard\r
4386 GUID buffer. On output, the length of the handle\r
4387 buffer that is required for the handles found.\r
4388 @param KeyGuidBuffer An array of keyboard layout GUID instances\r
4389 returned.\r
4390\r
4391 @retval EFI_SUCCESS KeyGuidBuffer was updated successfully.\r
4392 @retval EFI_BUFFER_TOO_SMALL The KeyGuidBufferLength parameter indicates\r
4393 that KeyGuidBuffer is too small to support the\r
4394 number of GUIDs. KeyGuidBufferLength is\r
4395 updated with a value that will enable the data to\r
4396 fit.\r
4397 @retval EFI_INVALID_PARAMETER The KeyGuidBufferLength is NULL.\r
4398 @retval EFI_INVALID_PARAMETER The value referenced by KeyGuidBufferLength is not\r
4399 zero and KeyGuidBuffer is NULL.\r
4400 @retval EFI_NOT_FOUND There was no keyboard layout.\r
4401\r
4402**/\r
4403EFI_STATUS\r
4404EFIAPI\r
4405HiiFindKeyboardLayouts (\r
4406 IN CONST EFI_HII_DATABASE_PROTOCOL *This,\r
4407 IN OUT UINT16 *KeyGuidBufferLength,\r
4408 OUT EFI_GUID *KeyGuidBuffer\r
4409 )\r
4410{\r
4411 HII_DATABASE_PRIVATE_DATA *Private;\r
4412 HII_DATABASE_RECORD *Node;\r
4413 HII_DATABASE_PACKAGE_LIST_INSTANCE *PackageList;\r
4414 LIST_ENTRY *Link;\r
4415 LIST_ENTRY *Link1;\r
4416 UINT16 ResultSize;\r
4417 UINTN Index;\r
4418 UINT16 LayoutCount;\r
4419 UINT16 LayoutLength;\r
4420 UINT8 *Layout;\r
4421 HII_KEYBOARD_LAYOUT_PACKAGE_INSTANCE *Package;\r
4422\r
4423 if ((This == NULL) || (KeyGuidBufferLength == NULL)) {\r
4424 return EFI_INVALID_PARAMETER;\r
4425 }\r
4426\r
4427 if ((*KeyGuidBufferLength > 0) && (KeyGuidBuffer == NULL)) {\r
4428 return EFI_INVALID_PARAMETER;\r
4429 }\r
4430\r
4431 Private = HII_DATABASE_DATABASE_PRIVATE_DATA_FROM_THIS (This);\r
4432 ResultSize = 0;\r
4433\r
4434 //\r
4435 // Search all package lists in whole database to retrieve keyboard layout.\r
4436 //\r
4437 for (Link = Private->DatabaseList.ForwardLink; Link != &Private->DatabaseList; Link = Link->ForwardLink) {\r
4438 Node = CR (Link, HII_DATABASE_RECORD, DatabaseEntry, HII_DATABASE_RECORD_SIGNATURE);\r
4439 PackageList = Node->PackageList;\r
4440 for (Link1 = PackageList->KeyboardLayoutHdr.ForwardLink;\r
4441 Link1 != &PackageList->KeyboardLayoutHdr;\r
4442 Link1 = Link1->ForwardLink\r
4443 )\r
4444 {\r
4445 //\r
4446 // Find out all Keyboard Layout packages in this package list.\r
4447 //\r
4448 Package = CR (\r
4449 Link1,\r
4450 HII_KEYBOARD_LAYOUT_PACKAGE_INSTANCE,\r
4451 KeyboardEntry,\r
4452 HII_KB_LAYOUT_PACKAGE_SIGNATURE\r
4453 );\r
4454 Layout = (UINT8 *)Package->KeyboardPkg + sizeof (EFI_HII_PACKAGE_HEADER) + sizeof (UINT16);\r
4455 CopyMem (\r
4456 &LayoutCount,\r
4457 (UINT8 *)Package->KeyboardPkg + sizeof (EFI_HII_PACKAGE_HEADER),\r
4458 sizeof (UINT16)\r
4459 );\r
4460 for (Index = 0; Index < LayoutCount; Index++) {\r
4461 ResultSize += sizeof (EFI_GUID);\r
4462 if (ResultSize <= *KeyGuidBufferLength) {\r
4463 CopyMem (KeyGuidBuffer + (ResultSize / sizeof (EFI_GUID) - 1), Layout + sizeof (UINT16), sizeof (EFI_GUID));\r
4464 CopyMem (&LayoutLength, Layout, sizeof (UINT16));\r
4465 Layout = Layout + LayoutLength;\r
4466 }\r
4467 }\r
4468 }\r
4469 }\r
4470\r
4471 if (ResultSize == 0) {\r
4472 return EFI_NOT_FOUND;\r
4473 }\r
4474\r
4475 if (*KeyGuidBufferLength < ResultSize) {\r
4476 *KeyGuidBufferLength = ResultSize;\r
4477 return EFI_BUFFER_TOO_SMALL;\r
4478 }\r
4479\r
4480 *KeyGuidBufferLength = ResultSize;\r
4481 return EFI_SUCCESS;\r
4482}\r
4483\r
4484/**\r
4485 This routine retrieves the requested keyboard layout. The layout is a physical description of the keys\r
4486 on a keyboard and the character(s) that are associated with a particular set of key strokes.\r
4487\r
4488 @param This A pointer to the EFI_HII_DATABASE_PROTOCOL\r
4489 instance.\r
4490 @param KeyGuid A pointer to the unique ID associated with a given\r
4491 keyboard layout. If KeyGuid is NULL then the\r
4492 current layout will be retrieved.\r
4493 @param KeyboardLayoutLength On input, a pointer to the length of the\r
4494 KeyboardLayout buffer. On output, the length of\r
4495 the data placed into KeyboardLayout.\r
4496 @param KeyboardLayout A pointer to a buffer containing the retrieved\r
4497 keyboard layout.\r
4498\r
4499 @retval EFI_SUCCESS The keyboard layout was retrieved successfully.\r
4500 @retval EFI_NOT_FOUND The requested keyboard layout was not found.\r
4501 @retval EFI_INVALID_PARAMETER The KeyboardLayout or KeyboardLayoutLength was\r
4502 NULL.\r
4503 @retval EFI_BUFFER_TOO_SMALL The KeyboardLayoutLength parameter indicates\r
4504 that KeyboardLayout is too small to support the\r
4505 requested keyboard layout. KeyboardLayoutLength is\r
4506 updated with a value that will enable the\r
4507 data to fit.\r
4508\r
4509**/\r
4510EFI_STATUS\r
4511EFIAPI\r
4512HiiGetKeyboardLayout (\r
4513 IN CONST EFI_HII_DATABASE_PROTOCOL *This,\r
4514 IN CONST EFI_GUID *KeyGuid,\r
4515 IN OUT UINT16 *KeyboardLayoutLength,\r
4516 OUT EFI_HII_KEYBOARD_LAYOUT *KeyboardLayout\r
4517 )\r
4518{\r
4519 HII_DATABASE_PRIVATE_DATA *Private;\r
4520 HII_DATABASE_RECORD *Node;\r
4521 HII_DATABASE_PACKAGE_LIST_INSTANCE *PackageList;\r
4522 LIST_ENTRY *Link;\r
4523 LIST_ENTRY *Link1;\r
4524 UINTN Index;\r
4525 UINT8 *Layout;\r
4526 UINT16 LayoutCount;\r
4527 UINT16 LayoutLength;\r
4528 HII_KEYBOARD_LAYOUT_PACKAGE_INSTANCE *Package;\r
4529\r
4530 if ((This == NULL) || (KeyboardLayoutLength == NULL)) {\r
4531 return EFI_INVALID_PARAMETER;\r
4532 }\r
4533\r
4534 if ((*KeyboardLayoutLength > 0) && (KeyboardLayout == NULL)) {\r
4535 return EFI_INVALID_PARAMETER;\r
4536 }\r
4537\r
4538 Private = HII_DATABASE_DATABASE_PRIVATE_DATA_FROM_THIS (This);\r
4539 //\r
4540 // Retrieve the current keyboard layout.\r
4541 //\r
4542 if (KeyGuid == NULL) {\r
4543 if (Private->CurrentLayout == NULL) {\r
4544 return EFI_NOT_FOUND;\r
4545 }\r
4546\r
4547 CopyMem (&LayoutLength, Private->CurrentLayout, sizeof (UINT16));\r
4548 if (*KeyboardLayoutLength < LayoutLength) {\r
4549 *KeyboardLayoutLength = LayoutLength;\r
4550 return EFI_BUFFER_TOO_SMALL;\r
4551 }\r
4552\r
4553 CopyMem (KeyboardLayout, Private->CurrentLayout, LayoutLength);\r
4554 return EFI_SUCCESS;\r
4555 }\r
4556\r
4557 for (Link = Private->DatabaseList.ForwardLink; Link != &Private->DatabaseList; Link = Link->ForwardLink) {\r
4558 Node = CR (Link, HII_DATABASE_RECORD, DatabaseEntry, HII_DATABASE_RECORD_SIGNATURE);\r
4559 PackageList = (HII_DATABASE_PACKAGE_LIST_INSTANCE *)(Node->PackageList);\r
4560 for (Link1 = PackageList->KeyboardLayoutHdr.ForwardLink;\r
4561 Link1 != &PackageList->KeyboardLayoutHdr;\r
4562 Link1 = Link1->ForwardLink\r
4563 )\r
4564 {\r
4565 Package = CR (\r
4566 Link1,\r
4567 HII_KEYBOARD_LAYOUT_PACKAGE_INSTANCE,\r
4568 KeyboardEntry,\r
4569 HII_KB_LAYOUT_PACKAGE_SIGNATURE\r
4570 );\r
4571\r
4572 Layout = (UINT8 *)Package->KeyboardPkg +\r
4573 sizeof (EFI_HII_PACKAGE_HEADER) + sizeof (UINT16);\r
4574 CopyMem (&LayoutCount, Layout - sizeof (UINT16), sizeof (UINT16));\r
4575 for (Index = 0; Index < LayoutCount; Index++) {\r
4576 CopyMem (&LayoutLength, Layout, sizeof (UINT16));\r
4577 if (CompareMem (Layout + sizeof (UINT16), KeyGuid, sizeof (EFI_GUID)) == 0) {\r
4578 if (LayoutLength <= *KeyboardLayoutLength) {\r
4579 CopyMem (KeyboardLayout, Layout, LayoutLength);\r
4580 return EFI_SUCCESS;\r
4581 } else {\r
4582 *KeyboardLayoutLength = LayoutLength;\r
4583 return EFI_BUFFER_TOO_SMALL;\r
4584 }\r
4585 }\r
4586\r
4587 Layout = Layout + LayoutLength;\r
4588 }\r
4589 }\r
4590 }\r
4591\r
4592 return EFI_NOT_FOUND;\r
4593}\r
4594\r
4595/**\r
4596 This routine sets the default keyboard layout to the one referenced by KeyGuid. When this routine\r
4597 is called, an event will be signaled of the EFI_HII_SET_KEYBOARD_LAYOUT_EVENT_GUID\r
4598 group type. This is so that agents which are sensitive to the current keyboard layout being changed\r
4599 can be notified of this change.\r
4600\r
4601 @param This A pointer to the EFI_HII_DATABASE_PROTOCOL\r
4602 instance.\r
4603 @param KeyGuid A pointer to the unique ID associated with a given\r
4604 keyboard layout.\r
4605\r
4606 @retval EFI_SUCCESS The current keyboard layout was successfully set.\r
4607 @retval EFI_NOT_FOUND The referenced keyboard layout was not found, so\r
4608 action was taken.\r
4609 @retval EFI_INVALID_PARAMETER The KeyGuid was NULL.\r
4610\r
4611**/\r
4612EFI_STATUS\r
4613EFIAPI\r
4614HiiSetKeyboardLayout (\r
4615 IN CONST EFI_HII_DATABASE_PROTOCOL *This,\r
4616 IN CONST EFI_GUID *KeyGuid\r
4617 )\r
4618{\r
4619 HII_DATABASE_PRIVATE_DATA *Private;\r
4620 EFI_HII_KEYBOARD_LAYOUT *KeyboardLayout;\r
4621 UINT16 KeyboardLayoutLength;\r
4622 EFI_STATUS Status;\r
4623\r
4624 if ((This == NULL) || (KeyGuid == NULL)) {\r
4625 return EFI_INVALID_PARAMETER;\r
4626 }\r
4627\r
4628 Private = HII_DATABASE_DATABASE_PRIVATE_DATA_FROM_THIS (This);\r
4629\r
4630 //\r
4631 // The specified GUID equals the current keyboard layout GUID,\r
4632 // return directly.\r
4633 //\r
4634 if (CompareGuid (&Private->CurrentLayoutGuid, KeyGuid)) {\r
4635 return EFI_SUCCESS;\r
4636 }\r
4637\r
4638 //\r
4639 // Try to find the incoming keyboard layout data in current database.\r
4640 //\r
4641 KeyboardLayoutLength = 0;\r
4642 KeyboardLayout = NULL;\r
4643 Status = HiiGetKeyboardLayout (This, KeyGuid, &KeyboardLayoutLength, KeyboardLayout);\r
4644 if (Status != EFI_BUFFER_TOO_SMALL) {\r
4645 return Status;\r
4646 }\r
4647\r
4648 KeyboardLayout = (EFI_HII_KEYBOARD_LAYOUT *)AllocateZeroPool (KeyboardLayoutLength);\r
4649 ASSERT (KeyboardLayout != NULL);\r
4650 Status = HiiGetKeyboardLayout (This, KeyGuid, &KeyboardLayoutLength, KeyboardLayout);\r
4651 ASSERT_EFI_ERROR (Status);\r
4652\r
4653 //\r
4654 // Backup current keyboard layout.\r
4655 //\r
4656 CopyMem (&Private->CurrentLayoutGuid, KeyGuid, sizeof (EFI_GUID));\r
4657 if (Private->CurrentLayout != NULL) {\r
4658 FreePool (Private->CurrentLayout);\r
4659 }\r
4660\r
4661 Private->CurrentLayout = KeyboardLayout;\r
4662\r
4663 //\r
4664 // Signal EFI_HII_SET_KEYBOARD_LAYOUT_EVENT_GUID group to notify\r
4665 // current keyboard layout is changed.\r
4666 //\r
4667 Status = gBS->SignalEvent (gHiiKeyboardLayoutChanged);\r
4668 ASSERT_EFI_ERROR (Status);\r
4669\r
4670 return EFI_SUCCESS;\r
4671}\r
4672\r
4673/**\r
4674 Return the EFI handle associated with a package list.\r
4675\r
4676 @param This A pointer to the EFI_HII_DATABASE_PROTOCOL\r
4677 instance.\r
4678 @param PackageListHandle An EFI_HII_HANDLE that corresponds to the desired\r
4679 package list in the HIIdatabase.\r
4680 @param DriverHandle On return, contains the EFI_HANDLE which was\r
4681 registered with the package list in\r
4682 NewPackageList().\r
4683\r
4684 @retval EFI_SUCCESS The DriverHandle was returned successfully.\r
4685 @retval EFI_INVALID_PARAMETER The PackageListHandle was not valid or\r
4686 DriverHandle was NULL.\r
4687 @retval EFI_NOT_FOUND This PackageList handle can not be found in\r
4688 current database.\r
4689\r
4690**/\r
4691EFI_STATUS\r
4692EFIAPI\r
4693HiiGetPackageListHandle (\r
4694 IN CONST EFI_HII_DATABASE_PROTOCOL *This,\r
4695 IN EFI_HII_HANDLE PackageListHandle,\r
4696 OUT EFI_HANDLE *DriverHandle\r
4697 )\r
4698{\r
4699 HII_DATABASE_PRIVATE_DATA *Private;\r
4700 HII_DATABASE_RECORD *Node;\r
4701 LIST_ENTRY *Link;\r
4702\r
4703 if ((This == NULL) || (DriverHandle == NULL)) {\r
4704 return EFI_INVALID_PARAMETER;\r
4705 }\r
4706\r
4707 if (!IsHiiHandleValid (PackageListHandle)) {\r
4708 return EFI_INVALID_PARAMETER;\r
4709 }\r
4710\r
4711 Private = HII_DATABASE_DATABASE_PRIVATE_DATA_FROM_THIS (This);\r
4712\r
4713 for (Link = Private->DatabaseList.ForwardLink; Link != &Private->DatabaseList; Link = Link->ForwardLink) {\r
4714 Node = CR (Link, HII_DATABASE_RECORD, DatabaseEntry, HII_DATABASE_RECORD_SIGNATURE);\r
4715 if (Node->Handle == PackageListHandle) {\r
4716 *DriverHandle = Node->DriverHandle;\r
4717 return EFI_SUCCESS;\r
4718 }\r
4719 }\r
4720\r
4721 return EFI_NOT_FOUND;\r
4722}\r