3 Copyright (c) 2006, Intel Corporation
4 All rights reserved. This program and the accompanying materials
5 are licensed and made available under the terms and conditions of the BSD License
6 which accompanies this distribution. The full text of the license may be found at
7 http://opensource.org/licenses/bsd-license.php
9 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
10 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
18 This file contains the package processing code to the HII database.
23 #include "HiiDatabase.h"
29 OUT UINT32
*NumberOfTokens
34 Determines the passed in Pack's size and returns the value.
42 EFI_HII_STRING_PACK
*StringPack
;
49 if (!CompareMem (&((EFI_HII_PACK_HEADER
*) Pack
)->Type
, &Type
, sizeof (UINT16
))) {
51 // The header contains the full IFR length
53 CopyMem (&Length
, &((EFI_HII_PACK_HEADER
*) Pack
)->Length
, sizeof (Length
));
54 *PackSize
= (UINTN
) Length
;
58 Type
= EFI_HII_STRING
;
59 if (!CompareMem (&((EFI_HII_PACK_HEADER
*) Pack
)->Type
, &Type
, sizeof (UINT16
))) {
61 // The header contains the STRING package length
62 // The assumption is that the strings for all languages
63 // are a contiguous block of data and there is a series of
64 // these package instances which will terminate with a NULL package
67 StringPack
= (EFI_HII_STRING_PACK
*) Pack
;
70 // There may be multiple instances packed together of strings
71 // so we must walk the self describing structures until we encounter
72 // the NULL structure to determine the full size.
74 CopyMem (&Length
, &StringPack
->Header
.Length
, sizeof (Length
));
75 if (NumberOfTokens
!= NULL
) {
76 CopyMem (NumberOfTokens
, &StringPack
->NumStringPointers
, sizeof (UINT32
));
80 *PackSize
= *PackSize
+ Length
;
81 StringPack
= (EFI_HII_STRING_PACK
*) ((CHAR8
*) StringPack
+ Length
);
82 CopyMem (&Length
, &StringPack
->Header
.Length
, sizeof (Length
));
85 // Encountered a length of 0, so let's add the space for the NULL terminator
86 // pack's length and call it done.
88 *PackSize
= *PackSize
+ sizeof (EFI_HII_STRING_PACK
);
92 // We only determine the size of the non-global Package types.
93 // If neither IFR or STRING data were found, return an error
100 IN EFI_HII_PROTOCOL
*This
,
101 IN EFI_HII_PACKAGE_INSTANCE
*PackageInstance
,
102 OUT EFI_HII_PACKAGE_INSTANCE
**StringPackageInstance
,
103 OUT UINT32
*TotalStringCount
108 Verifies that the package instance is using the correct handle for string operations.
116 EFI_HII_DATA
*HiiData
;
117 EFI_HII_HANDLE_DATABASE
*HandleDatabase
;
118 EFI_HII_PACKAGE_INSTANCE
*HandlePackageInstance
;
121 EFI_HII_IFR_PACK
*FormPack
;
125 return EFI_INVALID_PARAMETER
;
128 HiiData
= EFI_HII_DATA_FROM_THIS (This
);
130 HandleDatabase
= HiiData
->DatabaseHead
;
131 ZeroMem (&Guid
, sizeof (EFI_GUID
));
133 *StringPackageInstance
= PackageInstance
;
136 // Based on if there is IFR data in this package instance, determine
137 // what the location is of the beginning of the string data.
139 if (PackageInstance
->IfrSize
> 0) {
140 FormPack
= (EFI_HII_IFR_PACK
*) ((CHAR8
*) (&PackageInstance
->IfrData
) + sizeof (EFI_HII_PACK_HEADER
));
143 // If there is no IFR data assume the caller knows what they are doing.
148 RawData
= (UINT8
*) FormPack
;
150 for (Index
= 0; RawData
[Index
] != EFI_IFR_END_FORM_SET_OP
;) {
151 if (RawData
[Index
] == EFI_IFR_FORM_SET_OP
) {
153 // Cache the guid for this formset
155 CopyMem (&Guid
, &((EFI_IFR_FORM_SET
*) &RawData
[Index
])->Guid
, sizeof (EFI_GUID
));
159 Index
= RawData
[Index
+ 1] + Index
;
162 // If there is no string package, and the PackageInstance->IfrPack.Guid and PackageInstance->Guid are
163 // different, we should return the correct handle for the caller to use for strings.
165 if ((PackageInstance
->StringSize
== 0) && (!CompareGuid (&Guid
, &PackageInstance
->Guid
))) {
167 // Search the database for a handle that matches the PackageInstance->Guid
169 for (; HandleDatabase
!= NULL
; HandleDatabase
= HandleDatabase
->NextHandleDatabase
) {
171 // Get Ifrdata and extract the Guid for it
173 HandlePackageInstance
= HandleDatabase
->Buffer
;
175 ASSERT (HandlePackageInstance
->IfrSize
!= 0);
177 FormPack
= (EFI_HII_IFR_PACK
*) ((CHAR8
*) (&HandlePackageInstance
->IfrData
) + sizeof (EFI_HII_PACK_HEADER
));
178 RawData
= (UINT8
*) FormPack
;
180 for (Index
= 0; RawData
[Index
] != EFI_IFR_END_FORM_SET_OP
;) {
181 if (RawData
[Index
] == EFI_IFR_FORM_SET_OP
) {
183 // Cache the guid for this formset
185 CopyMem (&Guid
, &((EFI_IFR_FORM_SET
*) &RawData
[Index
])->Guid
, sizeof (EFI_GUID
));
189 Index
= RawData
[Index
+ 1] + Index
;
192 // If the Guid from the new handle matches the original Guid referenced in the original package data
193 // return the appropriate package instance data to use.
195 if (CompareGuid (&Guid
, &PackageInstance
->Guid
)) {
196 if (TotalStringCount
!= NULL
) {
197 *TotalStringCount
= HandleDatabase
->NumberOfTokens
;
200 *StringPackageInstance
= HandlePackageInstance
;
216 IN EFI_HII_PROTOCOL
*This
,
217 IN EFI_HII_PACKAGES
*Packages
,
218 OUT EFI_HII_HANDLE
*Handle
224 Extracts the various packs from a package list.
228 This - Pointer of HII protocol.
229 Packages - Pointer of HII packages.
230 Handle - Handle value to be returned.
234 EFI_SUCCESS - Pacakges has added to HII database successfully.
235 EFI_INVALID_PARAMETER - Invalid parameter.
239 EFI_HII_PACKAGE_INSTANCE
*PackageInstance
;
240 EFI_HII_DATA
*HiiData
;
241 EFI_HII_HANDLE_DATABASE
*HandleDatabase
;
242 EFI_HII_HANDLE_DATABASE
*Database
;
243 EFI_HII_PACK_HEADER
*PackageHeader
;
244 EFI_HII_GLOBAL_DATA
*GlobalData
;
245 EFI_HII_IFR_PACK
*IfrPack
;
246 EFI_HII_STRING_PACK
*StringPack
;
247 EFI_HII_FONT_PACK
*FontPack
;
248 EFI_HII_KEYBOARD_PACK
*KeyboardPack
;
252 UINTN TotalStringSize
;
258 EFI_FORM_SET_STUB FormSetStub
;
261 UINT16 NumWideGlyphs
;
262 UINT16 NumNarrowGlyphs
;
263 UINT32 NumberOfTokens
;
264 UINT32 TotalTokenNumber
;
266 EFI_NARROW_GLYPH
*NarrowGlyph
;
268 if (Packages
->NumberOfPackages
== 0 || This
== NULL
) {
269 return EFI_INVALID_PARAMETER
;
272 HiiData
= EFI_HII_DATA_FROM_THIS (This
);
274 GlobalData
= HiiData
->GlobalData
;
276 Database
= HiiData
->DatabaseHead
;
278 PackageInstance
= NULL
;
286 TotalTokenNumber
= 0;
289 // Search through the passed in Packages for the IfrPack and any StringPack.
291 for (Index
= 0; Index
< Packages
->NumberOfPackages
; Index
++) {
293 PackageHeader
= *(EFI_HII_PACK_HEADER
**) (((UINT8
*) Packages
) + sizeof (EFI_HII_PACKAGES
) + Index
* sizeof (VOID
*));
295 switch (PackageHeader
->Type
) {
298 // There shoule be only one Ifr package.
300 ASSERT (IfrPack
== NULL
);
301 IfrPack
= (EFI_HII_IFR_PACK
*) PackageHeader
;
305 StringPack
= (EFI_HII_STRING_PACK
*) PackageHeader
;
307 // Sending me a String Package. Get its size.
309 Status
= GetPackSize ((VOID
*) StringPack
, &StringSize
, &NumberOfTokens
);
310 ASSERT (!EFI_ERROR (Status
));
313 // The size which GetPackSize() returns include the null terminator. So if multiple
314 // string packages are passed in, merge all these packages, and only pad one null terminator.
316 if (TotalStringSize
> 0) {
317 TotalStringSize
-= sizeof (EFI_HII_STRING_PACK
);
320 TotalStringSize
+= StringSize
;
321 TotalTokenNumber
+= NumberOfTokens
;
326 // If sending a StringPack without an IfrPack, you must include a GuidId
328 if ((StringPack
!= NULL
) && (IfrPack
== NULL
)) {
329 if (Packages
->GuidId
== NULL
) {
330 return EFI_INVALID_PARAMETER
;
334 // If passing in an IfrPack and a GuidId is provided, ensure they are the same value.
336 if ((IfrPack
!= NULL
) && (Packages
->GuidId
!= NULL
)) {
337 Location
= ((UINT8
*) IfrPack
);
338 Location
= (UINT8
*) (((UINTN
) Location
) + sizeof (EFI_HII_PACK_HEADER
));
341 // Advance to the Form Set Op-code
343 for (Count
= 0; ((EFI_IFR_OP_HEADER
*) &Location
[Count
])->OpCode
!= EFI_IFR_FORM_SET_OP
;) {
344 Count
= Count
+ ((EFI_IFR_OP_HEADER
*) &Location
[Count
])->Length
;
347 // Copy to local variable
349 CopyMem (&Guid
, &((EFI_IFR_FORM_SET
*) &Location
[Count
])->Guid
, sizeof (EFI_GUID
));
352 // Check to see if IfrPack->Guid != GuidId
354 if (!CompareGuid (&Guid
, Packages
->GuidId
)) {
356 // If a string package is present, the GUIDs should have agreed. Return an error
358 if (StringPack
!= NULL
) {
359 return EFI_INVALID_PARAMETER
;
364 // If someone is passing in a string only, create a dummy IfrPack with a Guid
365 // to enable future searching of this data.
367 if ((IfrPack
== NULL
) && (StringPack
!= NULL
)) {
368 ZeroMem (&FormSetStub
, sizeof (FormSetStub
));
370 FormSetStub
.Header
.Type
= EFI_HII_IFR
;
371 FormSetStub
.Header
.Length
= sizeof (EFI_FORM_SET_STUB
);
373 FormSetStub
.FormSet
.Header
.OpCode
= EFI_IFR_FORM_SET_OP
;
374 FormSetStub
.FormSet
.Header
.Length
= (UINT8
) sizeof (EFI_IFR_FORM_SET
);
378 FormSetStub
.FormSet
.FormSetTitle
= 0x02;
379 CopyMem (&FormSetStub
.FormSet
.Guid
, Packages
->GuidId
, sizeof (EFI_GUID
));
381 FormSetStub
.EndFormSet
.Header
.OpCode
= EFI_IFR_END_FORM_SET_OP
;
382 FormSetStub
.EndFormSet
.Header
.Length
= (UINT8
) sizeof (EFI_IFR_END_FORM_SET
);
383 IfrPack
= (EFI_HII_IFR_PACK
*) &FormSetStub
;
386 if (IfrPack
!= NULL
) {
388 // Sending me an IFR Package. Get its size.
390 Status
= GetPackSize ((VOID
*) IfrPack
, &IfrSize
, NULL
);
391 ASSERT (!EFI_ERROR (Status
));
394 // Prepare the internal package instace buffer to store package data.
396 InstanceSize
= IfrSize
+ TotalStringSize
;
398 if (InstanceSize
!= 0) {
399 PackageInstance
= AllocateZeroPool (InstanceSize
+ sizeof (EFI_HII_PACKAGE_INSTANCE
));
401 ASSERT (PackageInstance
);
404 // If there is no DatabaseHead allocated - allocate one
406 if (HiiData
->DatabaseHead
== NULL
) {
407 HiiData
->DatabaseHead
= AllocateZeroPool (sizeof (EFI_HII_HANDLE_DATABASE
));
408 ASSERT (HiiData
->DatabaseHead
);
411 // If the head is being used (Handle is non-zero), allocate next Database and
412 // add it to the linked-list
414 if (HiiData
->DatabaseHead
->Handle
!= 0) {
415 HandleDatabase
= AllocateZeroPool (sizeof (EFI_HII_HANDLE_DATABASE
));
417 ASSERT (HandleDatabase
);
419 for (; Database
->NextHandleDatabase
!= NULL
; Database
= Database
->NextHandleDatabase
)
423 // We are sitting on the Database entry which contains the null Next pointer. Fix it.
425 Database
->NextHandleDatabase
= HandleDatabase
;
429 Database
= HiiData
->DatabaseHead
;
432 // Initialize this instance data
434 for (*Handle
= 1; Database
->NextHandleDatabase
!= NULL
; Database
= Database
->NextHandleDatabase
) {
436 // Since the first Database instance will have a passed back handle of 1, we will continue
437 // down the linked list of entries until we encounter the end of the linked list. Each time
438 // we go down one level deeper, increment the handle value that will be passed back.
440 if (Database
->Handle
>= *Handle
) {
441 *Handle
= (EFI_HII_HANDLE
) (Database
->Handle
+ 1);
445 PackageInstance
->Handle
= *Handle
;
446 PackageInstance
->IfrSize
= IfrSize
;
447 PackageInstance
->StringSize
= TotalStringSize
;
448 if (Packages
->GuidId
!= NULL
) {
449 CopyMem (&PackageInstance
->Guid
, Packages
->GuidId
, sizeof (EFI_GUID
));
452 Database
->Buffer
= PackageInstance
;
453 Database
->Handle
= PackageInstance
->Handle
;
454 Database
->NumberOfTokens
= TotalTokenNumber
;
455 Database
->NextHandleDatabase
= NULL
;
458 // Copy the Ifr package data into package instance.
461 CopyMem (&PackageInstance
->IfrData
, IfrPack
, IfrSize
);
464 // Main loop to store package data into HII database.
469 for (Index
= 0; Index
< Packages
->NumberOfPackages
; Index
++) {
471 PackageHeader
= *(EFI_HII_PACK_HEADER
**) (((UINT8
*) Packages
) + sizeof (EFI_HII_PACKAGES
) + Index
* sizeof (VOID
*));
473 switch (PackageHeader
->Type
) {
475 StringPack
= (EFI_HII_STRING_PACK
*) PackageHeader
;
477 // The size which GetPackSize() returns include the null terminator. So if multiple
478 // string packages are passed in, merge all these packages, and only pad one null terminator.
480 if (TotalStringSize
> 0) {
481 TotalStringSize
-= sizeof (EFI_HII_STRING_PACK
);
484 GetPackSize ((VOID
*) StringPack
, &StringSize
, &NumberOfTokens
);
485 CopyMem ((CHAR8
*) (&PackageInstance
->IfrData
) + IfrSize
+ TotalStringSize
, StringPack
, StringSize
);
487 TotalStringSize
+= StringSize
;
490 case EFI_HII_HANDLES
:
491 CopyMem (&PackageInstance
->HandlePack
, PackageHeader
, sizeof (EFI_HII_HANDLE_PACK
));
495 FontPack
= (EFI_HII_FONT_PACK
*) PackageHeader
;
497 // Add whatever narrow glyphs were passed to us if undefined
499 CopyMem (&NumNarrowGlyphs
, &FontPack
->NumberOfNarrowGlyphs
, sizeof (UINT16
));
500 for (Count
= 0; Count
<= NumNarrowGlyphs
; Count
++) {
501 Local
= (UINT8
*) (&FontPack
->NumberOfWideGlyphs
+ sizeof (UINT8
)) + (sizeof (EFI_NARROW_GLYPH
)) * Count
;
502 NarrowGlyph
= (EFI_NARROW_GLYPH
*) Local
;
503 CopyMem (&Member
, &NarrowGlyph
->UnicodeWeight
, sizeof (UINT16
));
505 // If the glyph is already defined, do not overwrite it. It is what it is.
507 CopyMem (&Unicode
, &GlobalData
->NarrowGlyphs
[Member
].UnicodeWeight
, sizeof (UINT16
));
509 CopyMem (&GlobalData
->NarrowGlyphs
[Member
], Local
, sizeof (EFI_NARROW_GLYPH
));
513 // Add whatever wide glyphs were passed to us if undefined
515 CopyMem (&NumWideGlyphs
, &FontPack
->NumberOfWideGlyphs
, sizeof (UINT16
));
516 for (Count
= 0; Count
<= NumWideGlyphs
; Count
++) {
517 Local
= (UINT8
*) (&FontPack
->NumberOfWideGlyphs
+ sizeof (UINT8
)) +
518 (sizeof (EFI_NARROW_GLYPH
)) *
522 (UINTN
*) (Local
+ sizeof (EFI_WIDE_GLYPH
) * Count
),
526 // If the glyph is already defined, do not overwrite it. It is what it is.
528 CopyMem (&Unicode
, &GlobalData
->WideGlyphs
[Member
].UnicodeWeight
, sizeof (UINT16
));
530 Local
= (UINT8
*)(&FontPack
->NumberOfWideGlyphs
+ sizeof(UINT8
)) + (sizeof(EFI_NARROW_GLYPH
)) * NumNarrowGlyphs
;
532 &GlobalData
->WideGlyphs
[Member
],
533 (UINTN
*) (Local
+ sizeof (EFI_WIDE_GLYPH
) * Count
),
534 sizeof (EFI_WIDE_GLYPH
)
540 case EFI_HII_KEYBOARD
:
541 KeyboardPack
= (EFI_HII_KEYBOARD_PACK
*) PackageHeader
;
543 // Sending me a Keyboard Package
545 if (KeyboardPack
->DescriptorCount
> 105) {
546 return EFI_INVALID_PARAMETER
;
549 // If someone updates the Descriptors with a count of 0, blow aware the overrides.
551 if (KeyboardPack
->DescriptorCount
== 0) {
552 ZeroMem (GlobalData
->OverrideKeyboardLayout
, sizeof (EFI_KEY_DESCRIPTOR
) * 106);
555 if (KeyboardPack
->DescriptorCount
< 106 && KeyboardPack
->DescriptorCount
> 0) {
557 // If SystemKeyboard was updated already, then steer changes to the override database
559 if (GlobalData
->SystemKeyboardUpdate
) {
560 ZeroMem (GlobalData
->OverrideKeyboardLayout
, sizeof (EFI_KEY_DESCRIPTOR
) * 106);
561 for (Count
= 0; Count
< KeyboardPack
->DescriptorCount
; Count
++) {
562 CopyMem (&Member
, &KeyboardPack
->Descriptor
[Count
].Key
, sizeof (UINT16
));
564 &GlobalData
->OverrideKeyboardLayout
[Member
],
565 &KeyboardPack
->Descriptor
[Count
],
566 sizeof (EFI_KEY_DESCRIPTOR
)
571 // SystemKeyboard was never updated, so this is likely the keyboard driver setting the System database.
573 ZeroMem (GlobalData
->SystemKeyboardLayout
, sizeof (EFI_KEY_DESCRIPTOR
) * 106);
574 for (Count
= 0; Count
< KeyboardPack
->DescriptorCount
; Count
++) {
575 CopyMem (&Member
, &KeyboardPack
->Descriptor
->Key
, sizeof (UINT16
));
577 &GlobalData
->SystemKeyboardLayout
[Member
],
578 &KeyboardPack
->Descriptor
[Count
],
579 sizeof (EFI_KEY_DESCRIPTOR
)
583 // Just updated the system keyboard database, reflect that in the global flag.
585 GlobalData
->SystemKeyboardUpdate
= TRUE
;
601 IN EFI_HII_PROTOCOL
*This
,
602 IN EFI_HII_HANDLE Handle
607 Removes the various packs from a Handle
615 EFI_HII_PACKAGE_INSTANCE
*PackageInstance
;
616 EFI_HII_DATA
*HiiData
;
617 EFI_HII_HANDLE_DATABASE
*HandleDatabase
;
618 EFI_HII_HANDLE_DATABASE
*PreviousHandleDatabase
;
620 if (This
== NULL
|| Handle
== 0) {
621 return EFI_INVALID_PARAMETER
;
624 HiiData
= EFI_HII_DATA_FROM_THIS (This
);
626 HandleDatabase
= HiiData
->DatabaseHead
;
627 PackageInstance
= NULL
;
630 // Initialize the Previous with the Head of the Database
632 PreviousHandleDatabase
= HandleDatabase
;
634 for (; HandleDatabase
!= NULL
; HandleDatabase
= HandleDatabase
->NextHandleDatabase
) {
636 // Match the numeric value with the database entry - if matched,
637 // free the package instance and apply fix-up to database linked list
639 if (Handle
== HandleDatabase
->Handle
) {
640 PackageInstance
= HandleDatabase
->Buffer
;
643 // Free the Package Instance
645 gBS
->FreePool (PackageInstance
);
648 // If this was the only Handle in the database
650 if (HiiData
->DatabaseHead
== HandleDatabase
) {
651 HiiData
->DatabaseHead
= NULL
;
654 // Make the parent->Next point to the current->Next
656 PreviousHandleDatabase
->NextHandleDatabase
= HandleDatabase
->NextHandleDatabase
;
657 gBS
->FreePool (HandleDatabase
);
661 // If this was not the HandleDatabase entry we were looking for, cache it just in case the next one is
663 PreviousHandleDatabase
= HandleDatabase
;
666 // No handle was found - error condition
668 if (PackageInstance
== NULL
) {
669 return EFI_INVALID_PARAMETER
;