3 Copyright (c) 2006 - 2007, 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.
24 // Include common header file for this module.
26 #include "CommonHeader.h"
28 #include "HiiDatabase.h"
34 OUT UINT32
*NumberOfTokens
39 Determines the passed in Pack's size and returns the value.
47 EFI_HII_STRING_PACK
*StringPack
;
54 if (!CompareMem (&((EFI_HII_PACK_HEADER
*) Pack
)->Type
, &Type
, sizeof (UINT16
))) {
56 // The header contains the full IFR length
58 CopyMem (&Length
, &((EFI_HII_PACK_HEADER
*) Pack
)->Length
, sizeof (Length
));
59 *PackSize
= (UINTN
) Length
;
63 Type
= EFI_HII_STRING
;
64 if (!CompareMem (&((EFI_HII_PACK_HEADER
*) Pack
)->Type
, &Type
, sizeof (UINT16
))) {
66 // The header contains the STRING package length
67 // The assumption is that the strings for all languages
68 // are a contiguous block of data and there is a series of
69 // these package instances which will terminate with a NULL package
72 StringPack
= (EFI_HII_STRING_PACK
*) Pack
;
75 // There may be multiple instances packed together of strings
76 // so we must walk the self describing structures until we encounter
77 // the NULL structure to determine the full size.
79 CopyMem (&Length
, &StringPack
->Header
.Length
, sizeof (Length
));
80 if (NumberOfTokens
!= NULL
) {
81 CopyMem (NumberOfTokens
, &StringPack
->NumStringPointers
, sizeof (UINT32
));
85 *PackSize
= *PackSize
+ Length
;
86 StringPack
= (EFI_HII_STRING_PACK
*) ((CHAR8
*) StringPack
+ Length
);
87 CopyMem (&Length
, &StringPack
->Header
.Length
, sizeof (Length
));
90 // Encountered a length of 0, so let's add the space for the NULL terminator
91 // pack's length and call it done.
93 *PackSize
= *PackSize
+ sizeof (EFI_HII_STRING_PACK
);
97 // We only determine the size of the non-global Package types.
98 // If neither IFR or STRING data were found, return an error
100 return EFI_NOT_FOUND
;
105 IN EFI_HII_PROTOCOL
*This
,
106 IN EFI_HII_PACKAGE_INSTANCE
*PackageInstance
,
107 OUT EFI_HII_PACKAGE_INSTANCE
**StringPackageInstance
,
108 OUT UINT32
*TotalStringCount
113 Verifies that the package instance is using the correct handle for string operations.
121 EFI_HII_DATA
*HiiData
;
122 EFI_HII_HANDLE_DATABASE
*HandleDatabase
;
123 EFI_HII_PACKAGE_INSTANCE
*HandlePackageInstance
;
126 EFI_HII_IFR_PACK
*FormPack
;
130 return EFI_INVALID_PARAMETER
;
133 HiiData
= EFI_HII_DATA_FROM_THIS (This
);
135 HandleDatabase
= HiiData
->DatabaseHead
;
136 ZeroMem (&Guid
, sizeof (EFI_GUID
));
138 *StringPackageInstance
= PackageInstance
;
141 // Based on if there is IFR data in this package instance, determine
142 // what the location is of the beginning of the string data.
144 if (PackageInstance
->IfrSize
> 0) {
145 FormPack
= (EFI_HII_IFR_PACK
*) ((CHAR8
*) (&PackageInstance
->IfrData
) + sizeof (EFI_HII_PACK_HEADER
));
148 // If there is no IFR data assume the caller knows what they are doing.
153 RawData
= (UINT8
*) FormPack
;
155 for (Index
= 0; RawData
[Index
] != EFI_IFR_END_FORM_SET_OP
;) {
156 if (RawData
[Index
] == EFI_IFR_FORM_SET_OP
) {
158 // Cache the guid for this formset
160 CopyMem (&Guid
, &((EFI_IFR_FORM_SET
*) &RawData
[Index
])->Guid
, sizeof (EFI_GUID
));
164 Index
= RawData
[Index
+ 1] + Index
;
167 // If there is no string package, and the PackageInstance->IfrPack.Guid and PackageInstance->Guid are
168 // different, we should return the correct handle for the caller to use for strings.
170 if ((PackageInstance
->StringSize
== 0) && (!CompareGuid (&Guid
, &PackageInstance
->Guid
))) {
172 // Search the database for a handle that matches the PackageInstance->Guid
174 for (; HandleDatabase
!= NULL
; HandleDatabase
= HandleDatabase
->NextHandleDatabase
) {
176 // Get Ifrdata and extract the Guid for it
178 HandlePackageInstance
= HandleDatabase
->Buffer
;
180 ASSERT (HandlePackageInstance
->IfrSize
!= 0);
182 FormPack
= (EFI_HII_IFR_PACK
*) ((CHAR8
*) (&HandlePackageInstance
->IfrData
) + sizeof (EFI_HII_PACK_HEADER
));
183 RawData
= (UINT8
*) FormPack
;
185 for (Index
= 0; RawData
[Index
] != EFI_IFR_END_FORM_SET_OP
;) {
186 if (RawData
[Index
] == EFI_IFR_FORM_SET_OP
) {
188 // Cache the guid for this formset
190 CopyMem (&Guid
, &((EFI_IFR_FORM_SET
*) &RawData
[Index
])->Guid
, sizeof (EFI_GUID
));
194 Index
= RawData
[Index
+ 1] + Index
;
197 // If the Guid from the new handle matches the original Guid referenced in the original package data
198 // return the appropriate package instance data to use.
200 if (CompareGuid (&Guid
, &PackageInstance
->Guid
)) {
201 if (TotalStringCount
!= NULL
) {
202 *TotalStringCount
= HandleDatabase
->NumberOfTokens
;
205 *StringPackageInstance
= HandlePackageInstance
;
221 IN EFI_HII_PROTOCOL
*This
,
222 IN EFI_HII_PACKAGES
*Packages
,
223 OUT EFI_HII_HANDLE
*Handle
229 Extracts the various packs from a package list.
233 This - Pointer of HII protocol.
234 Packages - Pointer of HII packages.
235 Handle - Handle value to be returned.
239 EFI_SUCCESS - Pacakges has added to HII database successfully.
240 EFI_INVALID_PARAMETER - Invalid parameter.
244 EFI_HII_PACKAGE_INSTANCE
*PackageInstance
;
245 EFI_HII_DATA
*HiiData
;
246 EFI_HII_HANDLE_DATABASE
*HandleDatabase
;
247 EFI_HII_HANDLE_DATABASE
*Database
;
248 EFI_HII_PACK_HEADER
*PackageHeader
;
249 EFI_HII_GLOBAL_DATA
*GlobalData
;
250 EFI_HII_IFR_PACK
*IfrPack
;
251 EFI_HII_STRING_PACK
*StringPack
;
252 EFI_HII_FONT_PACK
*FontPack
;
253 EFI_HII_KEYBOARD_PACK
*KeyboardPack
;
257 UINTN TotalStringSize
;
263 EFI_FORM_SET_STUB FormSetStub
;
266 UINT16 NumWideGlyphs
;
267 UINT16 NumNarrowGlyphs
;
268 UINT32 NumberOfTokens
;
269 UINT32 TotalTokenNumber
;
271 EFI_NARROW_GLYPH
*NarrowGlyph
;
273 if (Packages
->NumberOfPackages
== 0 || This
== NULL
) {
274 return EFI_INVALID_PARAMETER
;
277 HiiData
= EFI_HII_DATA_FROM_THIS (This
);
279 GlobalData
= HiiData
->GlobalData
;
281 Database
= HiiData
->DatabaseHead
;
283 PackageInstance
= NULL
;
291 TotalTokenNumber
= 0;
294 // Search through the passed in Packages for the IfrPack and any StringPack.
296 for (Index
= 0; Index
< Packages
->NumberOfPackages
; Index
++) {
298 PackageHeader
= *(EFI_HII_PACK_HEADER
**) (((UINT8
*) Packages
) + sizeof (EFI_HII_PACKAGES
) + Index
* sizeof (VOID
*));
300 switch (PackageHeader
->Type
) {
303 // There shoule be only one Ifr package.
305 ASSERT (IfrPack
== NULL
);
306 IfrPack
= (EFI_HII_IFR_PACK
*) PackageHeader
;
310 StringPack
= (EFI_HII_STRING_PACK
*) PackageHeader
;
312 // Sending me a String Package. Get its size.
314 Status
= GetPackSize ((VOID
*) StringPack
, &StringSize
, &NumberOfTokens
);
315 ASSERT (!EFI_ERROR (Status
));
318 // The size which GetPackSize() returns include the null terminator. So if multiple
319 // string packages are passed in, merge all these packages, and only pad one null terminator.
321 if (TotalStringSize
> 0) {
322 TotalStringSize
-= sizeof (EFI_HII_STRING_PACK
);
325 TotalStringSize
+= StringSize
;
326 TotalTokenNumber
+= NumberOfTokens
;
331 // If sending a StringPack without an IfrPack, you must include a GuidId
333 if ((StringPack
!= NULL
) && (IfrPack
== NULL
)) {
334 if (Packages
->GuidId
== NULL
) {
335 return EFI_INVALID_PARAMETER
;
339 // If passing in an IfrPack and a GuidId is provided, ensure they are the same value.
341 if ((IfrPack
!= NULL
) && (Packages
->GuidId
!= NULL
)) {
342 Location
= ((UINT8
*) IfrPack
);
343 Location
= (UINT8
*) (((UINTN
) Location
) + sizeof (EFI_HII_PACK_HEADER
));
346 // Advance to the Form Set Op-code
348 for (Count
= 0; ((EFI_IFR_OP_HEADER
*) &Location
[Count
])->OpCode
!= EFI_IFR_FORM_SET_OP
;) {
349 Count
= Count
+ ((EFI_IFR_OP_HEADER
*) &Location
[Count
])->Length
;
352 // Copy to local variable
354 CopyMem (&Guid
, &((EFI_IFR_FORM_SET
*) &Location
[Count
])->Guid
, sizeof (EFI_GUID
));
357 // Check to see if IfrPack->Guid != GuidId
359 if (!CompareGuid (&Guid
, Packages
->GuidId
)) {
361 // If a string package is present, the GUIDs should have agreed. Return an error
363 if (StringPack
!= NULL
) {
364 return EFI_INVALID_PARAMETER
;
369 // If someone is passing in a string only, create a dummy IfrPack with a Guid
370 // to enable future searching of this data.
372 if ((IfrPack
== NULL
) && (StringPack
!= NULL
)) {
373 ZeroMem (&FormSetStub
, sizeof (FormSetStub
));
375 FormSetStub
.Header
.Type
= EFI_HII_IFR
;
376 FormSetStub
.Header
.Length
= sizeof (EFI_FORM_SET_STUB
);
378 FormSetStub
.FormSet
.Header
.OpCode
= EFI_IFR_FORM_SET_OP
;
379 FormSetStub
.FormSet
.Header
.Length
= (UINT8
) sizeof (EFI_IFR_FORM_SET
);
383 FormSetStub
.FormSet
.FormSetTitle
= 0x02;
384 CopyMem (&FormSetStub
.FormSet
.Guid
, Packages
->GuidId
, sizeof (EFI_GUID
));
386 FormSetStub
.EndFormSet
.Header
.OpCode
= EFI_IFR_END_FORM_SET_OP
;
387 FormSetStub
.EndFormSet
.Header
.Length
= (UINT8
) sizeof (EFI_IFR_END_FORM_SET
);
388 IfrPack
= (EFI_HII_IFR_PACK
*) &FormSetStub
;
391 if (IfrPack
!= NULL
) {
393 // Sending me an IFR Package. Get its size.
395 Status
= GetPackSize ((VOID
*) IfrPack
, &IfrSize
, NULL
);
396 ASSERT (!EFI_ERROR (Status
));
399 // Prepare the internal package instace buffer to store package data.
401 InstanceSize
= IfrSize
+ TotalStringSize
;
403 if (InstanceSize
!= 0) {
404 PackageInstance
= AllocateZeroPool (InstanceSize
+ sizeof (EFI_HII_PACKAGE_INSTANCE
));
406 ASSERT (PackageInstance
);
409 // If there is no DatabaseHead allocated - allocate one
411 if (HiiData
->DatabaseHead
== NULL
) {
412 HiiData
->DatabaseHead
= AllocateZeroPool (sizeof (EFI_HII_HANDLE_DATABASE
));
413 ASSERT (HiiData
->DatabaseHead
);
416 // If the head is being used (Handle is non-zero), allocate next Database and
417 // add it to the linked-list
419 if (HiiData
->DatabaseHead
->Handle
!= 0) {
420 HandleDatabase
= AllocateZeroPool (sizeof (EFI_HII_HANDLE_DATABASE
));
422 ASSERT (HandleDatabase
);
424 for (; Database
->NextHandleDatabase
!= NULL
; Database
= Database
->NextHandleDatabase
)
428 // We are sitting on the Database entry which contains the null Next pointer. Fix it.
430 Database
->NextHandleDatabase
= HandleDatabase
;
434 Database
= HiiData
->DatabaseHead
;
437 // Initialize this instance data
439 for (*Handle
= 1; Database
->NextHandleDatabase
!= NULL
; Database
= Database
->NextHandleDatabase
) {
441 // Since the first Database instance will have a passed back handle of 1, we will continue
442 // down the linked list of entries until we encounter the end of the linked list. Each time
443 // we go down one level deeper, increment the handle value that will be passed back.
445 if (Database
->Handle
>= *Handle
) {
446 *Handle
= (EFI_HII_HANDLE
) (Database
->Handle
+ 1);
450 PackageInstance
->Handle
= *Handle
;
451 PackageInstance
->IfrSize
= IfrSize
;
452 PackageInstance
->StringSize
= TotalStringSize
;
453 if (Packages
->GuidId
!= NULL
) {
454 CopyMem (&PackageInstance
->Guid
, Packages
->GuidId
, sizeof (EFI_GUID
));
457 Database
->Buffer
= PackageInstance
;
458 Database
->Handle
= PackageInstance
->Handle
;
459 Database
->NumberOfTokens
= TotalTokenNumber
;
460 Database
->NextHandleDatabase
= NULL
;
463 // Copy the Ifr package data into package instance.
466 CopyMem (&PackageInstance
->IfrData
, IfrPack
, IfrSize
);
469 // Main loop to store package data into HII database.
474 for (Index
= 0; Index
< Packages
->NumberOfPackages
; Index
++) {
476 PackageHeader
= *(EFI_HII_PACK_HEADER
**) (((UINT8
*) Packages
) + sizeof (EFI_HII_PACKAGES
) + Index
* sizeof (VOID
*));
478 switch (PackageHeader
->Type
) {
480 StringPack
= (EFI_HII_STRING_PACK
*) PackageHeader
;
482 // The size which GetPackSize() returns include the null terminator. So if multiple
483 // string packages are passed in, merge all these packages, and only pad one null terminator.
485 if (TotalStringSize
> 0) {
486 TotalStringSize
-= sizeof (EFI_HII_STRING_PACK
);
489 GetPackSize ((VOID
*) StringPack
, &StringSize
, &NumberOfTokens
);
490 CopyMem ((CHAR8
*) (&PackageInstance
->IfrData
) + IfrSize
+ TotalStringSize
, StringPack
, StringSize
);
492 TotalStringSize
+= StringSize
;
495 case EFI_HII_HANDLES
:
496 CopyMem (&PackageInstance
->HandlePack
, PackageHeader
, sizeof (EFI_HII_HANDLE_PACK
));
500 FontPack
= (EFI_HII_FONT_PACK
*) PackageHeader
;
502 // Add whatever narrow glyphs were passed to us if undefined
504 CopyMem (&NumNarrowGlyphs
, &FontPack
->NumberOfNarrowGlyphs
, sizeof (UINT16
));
505 for (Count
= 0; Count
<= NumNarrowGlyphs
; Count
++) {
506 Local
= (UINT8
*) (&FontPack
->NumberOfWideGlyphs
+ sizeof (UINT8
)) + (sizeof (EFI_NARROW_GLYPH
)) * Count
;
507 NarrowGlyph
= (EFI_NARROW_GLYPH
*) Local
;
508 CopyMem (&Member
, &NarrowGlyph
->UnicodeWeight
, sizeof (UINT16
));
510 // If the glyph is already defined, do not overwrite it. It is what it is.
512 CopyMem (&Unicode
, &GlobalData
->NarrowGlyphs
[Member
].UnicodeWeight
, sizeof (UINT16
));
514 CopyMem (&GlobalData
->NarrowGlyphs
[Member
], Local
, sizeof (EFI_NARROW_GLYPH
));
518 // Add whatever wide glyphs were passed to us if undefined
520 CopyMem (&NumWideGlyphs
, &FontPack
->NumberOfWideGlyphs
, sizeof (UINT16
));
521 for (Count
= 0; Count
<= NumWideGlyphs
; Count
++) {
522 Local
= (UINT8
*) (&FontPack
->NumberOfWideGlyphs
+ sizeof (UINT8
)) +
523 (sizeof (EFI_NARROW_GLYPH
)) *
527 (UINTN
*) (Local
+ sizeof (EFI_WIDE_GLYPH
) * Count
),
531 // If the glyph is already defined, do not overwrite it. It is what it is.
533 CopyMem (&Unicode
, &GlobalData
->WideGlyphs
[Member
].UnicodeWeight
, sizeof (UINT16
));
535 Local
= (UINT8
*)(&FontPack
->NumberOfWideGlyphs
+ sizeof(UINT8
)) + (sizeof(EFI_NARROW_GLYPH
)) * NumNarrowGlyphs
;
537 &GlobalData
->WideGlyphs
[Member
],
538 (UINTN
*) (Local
+ sizeof (EFI_WIDE_GLYPH
) * Count
),
539 sizeof (EFI_WIDE_GLYPH
)
545 case EFI_HII_KEYBOARD
:
546 KeyboardPack
= (EFI_HII_KEYBOARD_PACK
*) PackageHeader
;
548 // Sending me a Keyboard Package
550 if (KeyboardPack
->DescriptorCount
> 105) {
551 return EFI_INVALID_PARAMETER
;
554 // If someone updates the Descriptors with a count of 0, blow aware the overrides.
556 if (KeyboardPack
->DescriptorCount
== 0) {
557 ZeroMem (GlobalData
->OverrideKeyboardLayout
, sizeof (EFI_KEY_DESCRIPTOR
) * 106);
560 if (KeyboardPack
->DescriptorCount
< 106 && KeyboardPack
->DescriptorCount
> 0) {
562 // If SystemKeyboard was updated already, then steer changes to the override database
564 if (GlobalData
->SystemKeyboardUpdate
) {
565 ZeroMem (GlobalData
->OverrideKeyboardLayout
, sizeof (EFI_KEY_DESCRIPTOR
) * 106);
566 for (Count
= 0; Count
< KeyboardPack
->DescriptorCount
; Count
++) {
567 CopyMem (&Member
, &KeyboardPack
->Descriptor
[Count
].Key
, sizeof (UINT16
));
569 &GlobalData
->OverrideKeyboardLayout
[Member
],
570 &KeyboardPack
->Descriptor
[Count
],
571 sizeof (EFI_KEY_DESCRIPTOR
)
576 // SystemKeyboard was never updated, so this is likely the keyboard driver setting the System database.
578 ZeroMem (GlobalData
->SystemKeyboardLayout
, sizeof (EFI_KEY_DESCRIPTOR
) * 106);
579 for (Count
= 0; Count
< KeyboardPack
->DescriptorCount
; Count
++) {
580 CopyMem (&Member
, &KeyboardPack
->Descriptor
->Key
, sizeof (UINT16
));
582 &GlobalData
->SystemKeyboardLayout
[Member
],
583 &KeyboardPack
->Descriptor
[Count
],
584 sizeof (EFI_KEY_DESCRIPTOR
)
588 // Just updated the system keyboard database, reflect that in the global flag.
590 GlobalData
->SystemKeyboardUpdate
= TRUE
;
606 IN EFI_HII_PROTOCOL
*This
,
607 IN EFI_HII_HANDLE Handle
612 Removes the various packs from a Handle
620 EFI_HII_PACKAGE_INSTANCE
*PackageInstance
;
621 EFI_HII_DATA
*HiiData
;
622 EFI_HII_HANDLE_DATABASE
*HandleDatabase
;
623 EFI_HII_HANDLE_DATABASE
*PreviousHandleDatabase
;
625 if (This
== NULL
|| Handle
== 0) {
626 return EFI_INVALID_PARAMETER
;
629 HiiData
= EFI_HII_DATA_FROM_THIS (This
);
631 HandleDatabase
= HiiData
->DatabaseHead
;
632 PackageInstance
= NULL
;
635 // Initialize the Previous with the Head of the Database
637 PreviousHandleDatabase
= HandleDatabase
;
639 for (; HandleDatabase
!= NULL
; HandleDatabase
= HandleDatabase
->NextHandleDatabase
) {
641 // Match the numeric value with the database entry - if matched,
642 // free the package instance and apply fix-up to database linked list
644 if (Handle
== HandleDatabase
->Handle
) {
645 PackageInstance
= HandleDatabase
->Buffer
;
648 // Free the Package Instance
650 FreePool (PackageInstance
);
653 // If this was the only Handle in the database
655 if (HiiData
->DatabaseHead
== HandleDatabase
) {
656 HiiData
->DatabaseHead
= NULL
;
659 // Make the parent->Next point to the current->Next
661 PreviousHandleDatabase
->NextHandleDatabase
= HandleDatabase
->NextHandleDatabase
;
662 FreePool (HandleDatabase
);
666 // If this was not the HandleDatabase entry we were looking for, cache it just in case the next one is
668 PreviousHandleDatabase
= HandleDatabase
;
671 // No handle was found - error condition
673 if (PackageInstance
== NULL
) {
674 return EFI_INVALID_PARAMETER
;