3 This file contains the keyboard processing code to the HII database.
5 Copyright (c) 2006, Intel Corporation
6 All rights reserved. This program and the accompanying materials
7 are licensed and made available under the terms and conditions of the BSD License
8 which accompanies this distribution. The full text of the license may be found at
9 http://opensource.org/licenses/bsd-license.php
11 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
12 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
17 #include "HiiDatabase.h"
23 OUT UINT32
*NumberOfTokens
28 Determines the passed in Pack's size and returns the value.
36 EFI_HII_STRING_PACK
*StringPack
;
43 if (!CompareMem (&((EFI_HII_PACK_HEADER
*) Pack
)->Type
, &Type
, sizeof (UINT16
))) {
45 // The header contains the full IFR length
47 CopyMem (&Length
, &((EFI_HII_PACK_HEADER
*) Pack
)->Length
, sizeof (Length
));
48 *PackSize
= (UINTN
) Length
;
52 Type
= EFI_HII_STRING
;
53 if (!CompareMem (&((EFI_HII_PACK_HEADER
*) Pack
)->Type
, &Type
, sizeof (UINT16
))) {
55 // The header contains the STRING package length
56 // The assumption is that the strings for all languages
57 // are a contiguous block of data and there is a series of
58 // these package instances which will terminate with a NULL package
61 StringPack
= (EFI_HII_STRING_PACK
*) Pack
;
64 // There may be multiple instances packed together of strings
65 // so we must walk the self describing structures until we encounter
66 // the NULL structure to determine the full size.
68 CopyMem (&Length
, &StringPack
->Header
.Length
, sizeof (Length
));
69 if (NumberOfTokens
!= NULL
) {
70 CopyMem (NumberOfTokens
, &StringPack
->NumStringPointers
, sizeof (UINT32
));
74 *PackSize
= *PackSize
+ Length
;
75 StringPack
= (EFI_HII_STRING_PACK
*) ((CHAR8
*) StringPack
+ Length
);
76 CopyMem (&Length
, &StringPack
->Header
.Length
, sizeof (Length
));
79 // Encountered a length of 0, so let's add the space for the NULL terminator
80 // pack's length and call it done.
82 *PackSize
= *PackSize
+ sizeof (EFI_HII_STRING_PACK
);
86 // We only determine the size of the non-global Package types.
87 // If neither IFR or STRING data were found, return an error
94 IN EFI_HII_PROTOCOL
*This
,
95 IN EFI_HII_PACKAGE_INSTANCE
*PackageInstance
,
96 OUT EFI_HII_PACKAGE_INSTANCE
**StringPackageInstance
,
97 OUT UINT32
*TotalStringCount
102 Verifies that the package instance is using the correct handle for string operations.
110 EFI_HII_DATA
*HiiData
;
111 EFI_HII_HANDLE_DATABASE
*HandleDatabase
;
112 EFI_HII_PACKAGE_INSTANCE
*HandlePackageInstance
;
115 EFI_HII_IFR_PACK
*FormPack
;
119 return EFI_INVALID_PARAMETER
;
122 HiiData
= EFI_HII_DATA_FROM_THIS (This
);
124 HandleDatabase
= HiiData
->DatabaseHead
;
125 ZeroMem (&Guid
, sizeof (EFI_GUID
));
127 *StringPackageInstance
= PackageInstance
;
130 // Based on if there is IFR data in this package instance, determine
131 // what the location is of the beginning of the string data.
133 if (PackageInstance
->IfrSize
> 0) {
134 FormPack
= (EFI_HII_IFR_PACK
*) ((CHAR8
*) (&PackageInstance
->IfrData
) + sizeof (EFI_HII_PACK_HEADER
));
137 // If there is no IFR data assume the caller knows what they are doing.
142 RawData
= (UINT8
*) FormPack
;
144 for (Index
= 0; RawData
[Index
] != EFI_IFR_END_FORM_SET_OP
;) {
145 if (RawData
[Index
] == EFI_IFR_FORM_SET_OP
) {
147 // Cache the guid for this formset
149 CopyMem (&Guid
, &((EFI_IFR_FORM_SET
*) &RawData
[Index
])->Guid
, sizeof (EFI_GUID
));
153 Index
= RawData
[Index
+ 1] + Index
;
156 // If there is no string package, and the PackageInstance->IfrPack.Guid and PackageInstance->Guid are
157 // different, we should return the correct handle for the caller to use for strings.
159 if ((PackageInstance
->StringSize
== 0) && (!CompareGuid (&Guid
, &PackageInstance
->Guid
))) {
161 // Search the database for a handle that matches the PackageInstance->Guid
163 for (; HandleDatabase
!= NULL
; HandleDatabase
= HandleDatabase
->NextHandleDatabase
) {
165 // Get Ifrdata and extract the Guid for it
167 HandlePackageInstance
= HandleDatabase
->Buffer
;
169 ASSERT (HandlePackageInstance
->IfrSize
!= 0);
171 FormPack
= (EFI_HII_IFR_PACK
*) ((CHAR8
*) (&HandlePackageInstance
->IfrData
) + sizeof (EFI_HII_PACK_HEADER
));
172 RawData
= (UINT8
*) FormPack
;
174 for (Index
= 0; RawData
[Index
] != EFI_IFR_END_FORM_SET_OP
;) {
175 if (RawData
[Index
] == EFI_IFR_FORM_SET_OP
) {
177 // Cache the guid for this formset
179 CopyMem (&Guid
, &((EFI_IFR_FORM_SET
*) &RawData
[Index
])->Guid
, sizeof (EFI_GUID
));
183 Index
= RawData
[Index
+ 1] + Index
;
186 // If the Guid from the new handle matches the original Guid referenced in the original package data
187 // return the appropriate package instance data to use.
189 if (CompareGuid (&Guid
, &PackageInstance
->Guid
)) {
190 if (TotalStringCount
!= NULL
) {
191 *TotalStringCount
= HandleDatabase
->NumberOfTokens
;
194 *StringPackageInstance
= HandlePackageInstance
;
210 IN EFI_HII_PROTOCOL
*This
,
211 IN EFI_HII_PACKAGES
*Packages
,
212 OUT EFI_HII_HANDLE
*Handle
218 Extracts the various packs from a package list.
222 This - Pointer of HII protocol.
223 Packages - Pointer of HII packages.
224 Handle - Handle value to be returned.
228 EFI_SUCCESS - Pacakges has added to HII database successfully.
229 EFI_INVALID_PARAMETER - Invalid parameter.
233 EFI_HII_PACKAGE_INSTANCE
*PackageInstance
;
234 EFI_HII_DATA
*HiiData
;
235 EFI_HII_HANDLE_DATABASE
*HandleDatabase
;
236 EFI_HII_HANDLE_DATABASE
*Database
;
237 EFI_HII_PACK_HEADER
*PackageHeader
;
238 EFI_HII_GLOBAL_DATA
*GlobalData
;
239 EFI_HII_IFR_PACK
*IfrPack
;
240 EFI_HII_STRING_PACK
*StringPack
;
241 EFI_HII_FONT_PACK
*FontPack
;
242 EFI_HII_KEYBOARD_PACK
*KeyboardPack
;
246 UINTN TotalStringSize
;
252 EFI_FORM_SET_STUB FormSetStub
;
255 UINT16 NumWideGlyphs
;
256 UINT16 NumNarrowGlyphs
;
257 UINT32 NumberOfTokens
;
258 UINT32 TotalTokenNumber
;
260 EFI_NARROW_GLYPH
*NarrowGlyph
;
262 if (Packages
->NumberOfPackages
== 0 || This
== NULL
) {
263 return EFI_INVALID_PARAMETER
;
266 HiiData
= EFI_HII_DATA_FROM_THIS (This
);
268 GlobalData
= HiiData
->GlobalData
;
270 Database
= HiiData
->DatabaseHead
;
272 PackageInstance
= NULL
;
280 TotalTokenNumber
= 0;
283 // Search through the passed in Packages for the IfrPack and any StringPack.
285 for (Index
= 0; Index
< Packages
->NumberOfPackages
; Index
++) {
287 PackageHeader
= *(EFI_HII_PACK_HEADER
**) (((UINT8
*) Packages
) + sizeof (EFI_HII_PACKAGES
) + Index
* sizeof (VOID
*));
289 switch (PackageHeader
->Type
) {
292 // There shoule be only one Ifr package.
294 ASSERT (IfrPack
== NULL
);
295 IfrPack
= (EFI_HII_IFR_PACK
*) PackageHeader
;
299 StringPack
= (EFI_HII_STRING_PACK
*) PackageHeader
;
301 // Sending me a String Package. Get its size.
303 Status
= GetPackSize ((VOID
*) StringPack
, &StringSize
, &NumberOfTokens
);
304 ASSERT (!EFI_ERROR (Status
));
307 // The size which GetPackSize() returns include the null terminator. So if multiple
308 // string packages are passed in, merge all these packages, and only pad one null terminator.
310 if (TotalStringSize
> 0) {
311 TotalStringSize
-= sizeof (EFI_HII_STRING_PACK
);
314 TotalStringSize
+= StringSize
;
315 TotalTokenNumber
+= NumberOfTokens
;
320 // If sending a StringPack without an IfrPack, you must include a GuidId
322 if ((StringPack
!= NULL
) && (IfrPack
== NULL
)) {
323 if (Packages
->GuidId
== NULL
) {
324 return EFI_INVALID_PARAMETER
;
328 // If passing in an IfrPack and a GuidId is provided, ensure they are the same value.
330 if ((IfrPack
!= NULL
) && (Packages
->GuidId
!= NULL
)) {
331 Location
= ((UINT8
*) IfrPack
);
332 Location
= (UINT8
*) (((UINTN
) Location
) + sizeof (EFI_HII_PACK_HEADER
));
335 // Advance to the Form Set Op-code
337 for (Count
= 0; ((EFI_IFR_OP_HEADER
*) &Location
[Count
])->OpCode
!= EFI_IFR_FORM_SET_OP
;) {
338 Count
= Count
+ ((EFI_IFR_OP_HEADER
*) &Location
[Count
])->Length
;
341 // Copy to local variable
343 CopyMem (&Guid
, &((EFI_IFR_FORM_SET
*) &Location
[Count
])->Guid
, sizeof (EFI_GUID
));
346 // Check to see if IfrPack->Guid != GuidId
348 if (!CompareGuid (&Guid
, Packages
->GuidId
)) {
350 // If a string package is present, the GUIDs should have agreed. Return an error
352 if (StringPack
!= NULL
) {
353 return EFI_INVALID_PARAMETER
;
358 // If someone is passing in a string only, create a dummy IfrPack with a Guid
359 // to enable future searching of this data.
361 if ((IfrPack
== NULL
) && (StringPack
!= NULL
)) {
362 ZeroMem (&FormSetStub
, sizeof (FormSetStub
));
364 FormSetStub
.Header
.Type
= EFI_HII_IFR
;
365 FormSetStub
.Header
.Length
= sizeof (EFI_FORM_SET_STUB
);
367 FormSetStub
.FormSet
.Header
.OpCode
= EFI_IFR_FORM_SET_OP
;
368 FormSetStub
.FormSet
.Header
.Length
= (UINT8
) sizeof (EFI_IFR_FORM_SET
);
372 FormSetStub
.FormSet
.FormSetTitle
= 0x02;
373 CopyMem (&FormSetStub
.FormSet
.Guid
, Packages
->GuidId
, sizeof (EFI_GUID
));
375 FormSetStub
.EndFormSet
.Header
.OpCode
= EFI_IFR_END_FORM_SET_OP
;
376 FormSetStub
.EndFormSet
.Header
.Length
= (UINT8
) sizeof (EFI_IFR_END_FORM_SET
);
377 IfrPack
= (EFI_HII_IFR_PACK
*) &FormSetStub
;
380 if (IfrPack
!= NULL
) {
382 // Sending me an IFR Package. Get its size.
384 Status
= GetPackSize ((VOID
*) IfrPack
, &IfrSize
, NULL
);
385 ASSERT (!EFI_ERROR (Status
));
388 // Prepare the internal package instace buffer to store package data.
390 InstanceSize
= IfrSize
+ TotalStringSize
;
392 if (InstanceSize
!= 0) {
393 PackageInstance
= AllocateZeroPool (InstanceSize
+ sizeof (EFI_HII_PACKAGE_INSTANCE
));
395 ASSERT (PackageInstance
);
398 // If there is no DatabaseHead allocated - allocate one
400 if (HiiData
->DatabaseHead
== NULL
) {
401 HiiData
->DatabaseHead
= AllocateZeroPool (sizeof (EFI_HII_HANDLE_DATABASE
));
402 ASSERT (HiiData
->DatabaseHead
);
405 // If the head is being used (Handle is non-zero), allocate next Database and
406 // add it to the linked-list
408 if (HiiData
->DatabaseHead
->Handle
!= 0) {
409 HandleDatabase
= AllocateZeroPool (sizeof (EFI_HII_HANDLE_DATABASE
));
411 ASSERT (HandleDatabase
);
413 for (; Database
->NextHandleDatabase
!= NULL
; Database
= Database
->NextHandleDatabase
)
417 // We are sitting on the Database entry which contains the null Next pointer. Fix it.
419 Database
->NextHandleDatabase
= HandleDatabase
;
423 Database
= HiiData
->DatabaseHead
;
426 // Initialize this instance data
428 for (*Handle
= 1; Database
->NextHandleDatabase
!= NULL
; Database
= Database
->NextHandleDatabase
) {
430 // Since the first Database instance will have a passed back handle of 1, we will continue
431 // down the linked list of entries until we encounter the end of the linked list. Each time
432 // we go down one level deeper, increment the handle value that will be passed back.
434 if (Database
->Handle
>= *Handle
) {
435 *Handle
= (EFI_HII_HANDLE
) (Database
->Handle
+ 1);
439 PackageInstance
->Handle
= *Handle
;
440 PackageInstance
->IfrSize
= IfrSize
;
441 PackageInstance
->StringSize
= TotalStringSize
;
442 if (Packages
->GuidId
!= NULL
) {
443 CopyMem (&PackageInstance
->Guid
, Packages
->GuidId
, sizeof (EFI_GUID
));
446 Database
->Buffer
= PackageInstance
;
447 Database
->Handle
= PackageInstance
->Handle
;
448 Database
->NumberOfTokens
= TotalTokenNumber
;
449 Database
->NextHandleDatabase
= NULL
;
452 // Copy the Ifr package data into package instance.
455 CopyMem (&PackageInstance
->IfrData
, IfrPack
, IfrSize
);
458 // Main loop to store package data into HII database.
463 for (Index
= 0; Index
< Packages
->NumberOfPackages
; Index
++) {
465 PackageHeader
= *(EFI_HII_PACK_HEADER
**) (((UINT8
*) Packages
) + sizeof (EFI_HII_PACKAGES
) + Index
* sizeof (VOID
*));
467 switch (PackageHeader
->Type
) {
469 StringPack
= (EFI_HII_STRING_PACK
*) PackageHeader
;
471 // The size which GetPackSize() returns include the null terminator. So if multiple
472 // string packages are passed in, merge all these packages, and only pad one null terminator.
474 if (TotalStringSize
> 0) {
475 TotalStringSize
-= sizeof (EFI_HII_STRING_PACK
);
478 GetPackSize ((VOID
*) StringPack
, &StringSize
, &NumberOfTokens
);
479 CopyMem ((CHAR8
*) (&PackageInstance
->IfrData
) + IfrSize
+ TotalStringSize
, StringPack
, StringSize
);
481 TotalStringSize
+= StringSize
;
484 case EFI_HII_HANDLES
:
485 CopyMem (&PackageInstance
->HandlePack
, PackageHeader
, sizeof (EFI_HII_HANDLE_PACK
));
489 FontPack
= (EFI_HII_FONT_PACK
*) PackageHeader
;
491 // Add whatever narrow glyphs were passed to us if undefined
493 CopyMem (&NumNarrowGlyphs
, &FontPack
->NumberOfNarrowGlyphs
, sizeof (UINT16
));
494 for (Count
= 0; Count
<= NumNarrowGlyphs
; Count
++) {
495 Local
= (UINT8
*) (&FontPack
->NumberOfWideGlyphs
+ sizeof (UINT8
)) + (sizeof (EFI_NARROW_GLYPH
)) * Count
;
496 NarrowGlyph
= (EFI_NARROW_GLYPH
*) Local
;
497 CopyMem (&Member
, &NarrowGlyph
->UnicodeWeight
, sizeof (UINT16
));
499 // If the glyph is already defined, do not overwrite it. It is what it is.
501 CopyMem (&Unicode
, &GlobalData
->NarrowGlyphs
[Member
].UnicodeWeight
, sizeof (UINT16
));
503 CopyMem (&GlobalData
->NarrowGlyphs
[Member
], Local
, sizeof (EFI_NARROW_GLYPH
));
507 // Add whatever wide glyphs were passed to us if undefined
509 CopyMem (&NumWideGlyphs
, &FontPack
->NumberOfWideGlyphs
, sizeof (UINT16
));
510 for (Count
= 0; Count
<= NumWideGlyphs
; Count
++) {
511 Local
= (UINT8
*) (&FontPack
->NumberOfWideGlyphs
+ sizeof (UINT8
)) +
512 (sizeof (EFI_NARROW_GLYPH
)) *
516 (UINTN
*) (Local
+ sizeof (EFI_WIDE_GLYPH
) * Count
),
520 // If the glyph is already defined, do not overwrite it. It is what it is.
522 CopyMem (&Unicode
, &GlobalData
->WideGlyphs
[Member
].UnicodeWeight
, sizeof (UINT16
));
524 Local
= (UINT8
*)(&FontPack
->NumberOfWideGlyphs
+ sizeof(UINT8
)) + (sizeof(EFI_NARROW_GLYPH
)) * NumNarrowGlyphs
;
526 &GlobalData
->WideGlyphs
[Member
],
527 (UINTN
*) (Local
+ sizeof (EFI_WIDE_GLYPH
) * Count
),
528 sizeof (EFI_WIDE_GLYPH
)
534 case EFI_HII_KEYBOARD
:
535 KeyboardPack
= (EFI_HII_KEYBOARD_PACK
*) PackageHeader
;
537 // Sending me a Keyboard Package
539 if (KeyboardPack
->DescriptorCount
> 105) {
540 return EFI_INVALID_PARAMETER
;
543 // If someone updates the Descriptors with a count of 0, blow aware the overrides.
545 if (KeyboardPack
->DescriptorCount
== 0) {
546 ZeroMem (GlobalData
->OverrideKeyboardLayout
, sizeof (EFI_KEY_DESCRIPTOR
) * 106);
549 if (KeyboardPack
->DescriptorCount
< 106 && KeyboardPack
->DescriptorCount
> 0) {
551 // If SystemKeyboard was updated already, then steer changes to the override database
553 if (GlobalData
->SystemKeyboardUpdate
) {
554 ZeroMem (GlobalData
->OverrideKeyboardLayout
, sizeof (EFI_KEY_DESCRIPTOR
) * 106);
555 for (Count
= 0; Count
< KeyboardPack
->DescriptorCount
; Count
++) {
556 CopyMem (&Member
, &KeyboardPack
->Descriptor
[Count
].Key
, sizeof (UINT16
));
558 &GlobalData
->OverrideKeyboardLayout
[Member
],
559 &KeyboardPack
->Descriptor
[Count
],
560 sizeof (EFI_KEY_DESCRIPTOR
)
565 // SystemKeyboard was never updated, so this is likely the keyboard driver setting the System database.
567 ZeroMem (GlobalData
->SystemKeyboardLayout
, sizeof (EFI_KEY_DESCRIPTOR
) * 106);
568 for (Count
= 0; Count
< KeyboardPack
->DescriptorCount
; Count
++) {
569 CopyMem (&Member
, &KeyboardPack
->Descriptor
->Key
, sizeof (UINT16
));
571 &GlobalData
->SystemKeyboardLayout
[Member
],
572 &KeyboardPack
->Descriptor
[Count
],
573 sizeof (EFI_KEY_DESCRIPTOR
)
577 // Just updated the system keyboard database, reflect that in the global flag.
579 GlobalData
->SystemKeyboardUpdate
= TRUE
;
595 IN EFI_HII_PROTOCOL
*This
,
596 IN EFI_HII_HANDLE Handle
601 Removes the various packs from a Handle
609 EFI_HII_PACKAGE_INSTANCE
*PackageInstance
;
610 EFI_HII_DATA
*HiiData
;
611 EFI_HII_HANDLE_DATABASE
*HandleDatabase
;
612 EFI_HII_HANDLE_DATABASE
*PreviousHandleDatabase
;
614 if (This
== NULL
|| Handle
== 0) {
615 return EFI_INVALID_PARAMETER
;
618 HiiData
= EFI_HII_DATA_FROM_THIS (This
);
620 HandleDatabase
= HiiData
->DatabaseHead
;
621 PackageInstance
= NULL
;
624 // Initialize the Previous with the Head of the Database
626 PreviousHandleDatabase
= HandleDatabase
;
628 for (; HandleDatabase
!= NULL
; HandleDatabase
= HandleDatabase
->NextHandleDatabase
) {
630 // Match the numeric value with the database entry - if matched,
631 // free the package instance and apply fix-up to database linked list
633 if (Handle
== HandleDatabase
->Handle
) {
634 PackageInstance
= HandleDatabase
->Buffer
;
637 // Free the Package Instance
639 FreePool (PackageInstance
);
642 // If this was the only Handle in the database
644 if (HiiData
->DatabaseHead
== HandleDatabase
) {
645 HiiData
->DatabaseHead
= NULL
;
648 // Make the parent->Next point to the current->Next
650 PreviousHandleDatabase
->NextHandleDatabase
= HandleDatabase
->NextHandleDatabase
;
651 FreePool (HandleDatabase
);
655 // If this was not the HandleDatabase entry we were looking for, cache it just in case the next one is
657 PreviousHandleDatabase
= HandleDatabase
;
660 // No handle was found - error condition
662 if (PackageInstance
== NULL
) {
663 return EFI_INVALID_PARAMETER
;