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"
29 // Convert the ASCII Lang variable to a Unicode Language variable
31 for (Count
= 0; Count
< 3; Count
++) {
32 Language
[Count
] = (CHAR16
) Lang
[Count
];
39 IN EFI_HII_PROTOCOL
*This
,
40 IN CHAR16
*StringToTest
,
41 IN OUT UINT32
*FirstMissing
,
42 OUT UINT32
*GlyphBufferSize
47 Test if all of the characters in a string have corresponding font characters.
55 EFI_HII_GLOBAL_DATA
*GlobalData
;
56 EFI_HII_DATA
*HiiData
;
61 return EFI_INVALID_PARAMETER
;
64 HiiData
= EFI_HII_DATA_FROM_THIS (This
);
65 GlobalData
= HiiData
->GlobalData
;
69 // Rewind through the string looking for a glyph width identifier
70 // If no width identifier exists, we assume string has narrow width identifier
72 for (WideChar
= FALSE
, Location
= (INT32
) *FirstMissing
; Location
>= 0; Location
--) {
73 if ((StringToTest
[Location
] == NARROW_CHAR
) || (StringToTest
[Location
] == WIDE_CHAR
)) {
75 // We found something that identifies what glyph database to look in
77 WideChar
= (BOOLEAN
) (StringToTest
[Location
] == WIDE_CHAR
);
83 // Walk through the string until you hit the null terminator
85 for (*GlyphBufferSize
= 0; StringToTest
[*FirstMissing
] != CHAR_NULL
; (*FirstMissing
)++) {
87 // We found something that identifies what glyph database to look in
89 if ((StringToTest
[*FirstMissing
] == NARROW_CHAR
) || (StringToTest
[*FirstMissing
] == WIDE_CHAR
)) {
90 WideChar
= (BOOLEAN
) (StringToTest
[*FirstMissing
] == WIDE_CHAR
);
96 GlobalData
->NarrowGlyphs
[StringToTest
[*FirstMissing
]].GlyphCol1
,
98 NARROW_GLYPH_ARRAY_SIZE
102 // Break since this glyph isn't defined
104 return EFI_NOT_FOUND
;
108 // Can compare wide glyph against only GlyphCol1 since GlyphCol1 and GlyphCol2 are contiguous - just give correct size
111 GlobalData
->WideGlyphs
[StringToTest
[*FirstMissing
]].GlyphCol1
,
113 WIDE_GLYPH_ARRAY_SIZE
117 // Break since this glyph isn't defined
119 return EFI_NOT_FOUND
;
123 *GlyphBufferSize
+= (WideChar
? sizeof (EFI_WIDE_GLYPH
) : sizeof (EFI_NARROW_GLYPH
));
132 IN EFI_HII_PROTOCOL
*This
,
134 IN EFI_HII_HANDLE Handle
,
135 IN OUT STRING_REF
*Reference
,
136 IN CHAR16
*NewString
,
137 IN BOOLEAN ResetStrings
143 This function allows a new String to be added to an already existing String Package.
144 We will make a buffer the size of the package + EfiStrSize of the new string. We will
145 copy the string package that first gets changed and the following language packages until
146 we encounter the NULL string package. All this time we will ensure that the offsets have
151 This - Pointer to the HII protocol.
152 Language - Pointer to buffer which contains the language code of this NewString.
153 Handle - Handle of the package instance to be processed.
154 Reference - The token number for the string. If 0, new string token to be returned through this parameter.
155 NewString - Buffer pointer for the new string.
156 ResetStrings - Indicate if we are resetting a string.
160 EFI_SUCCESS - The string has been added or reset to Hii database.
161 EFI_INVALID_PARAMETER - Some parameter passed in is invalid.
165 EFI_HII_PACKAGE_INSTANCE
*PackageInstance
;
166 EFI_HII_PACKAGE_INSTANCE
*StringPackageInstance
;
167 EFI_HII_DATA
*HiiData
;
168 EFI_HII_STRING_PACK
*StringPack
;
169 EFI_HII_STRING_PACK
*NewStringPack
;
170 EFI_HII_HANDLE_DATABASE
*HandleDatabase
;
171 EFI_HII_PACKAGE_INSTANCE
*NewBuffer
;
173 UINT8
*StringLocation
;
174 RELOFST
*StringPointer
;
183 UINT32 TotalStringCount
;
184 UINT32 OriginalStringCount
;
190 return EFI_INVALID_PARAMETER
;
193 HiiData
= EFI_HII_DATA_FROM_THIS (This
);
195 HandleDatabase
= HiiData
->DatabaseHead
;
196 PackageInstance
= NULL
;
200 TotalStringCount
= 0;
201 OriginalStringCount
= 0;
204 // Check numeric value against the head of the database
206 for (; HandleDatabase
!= NULL
; HandleDatabase
= HandleDatabase
->NextHandleDatabase
) {
208 // Match the numeric value with the database entry - if matched, extract PackageInstance
210 if (Handle
== HandleDatabase
->Handle
) {
211 PackageInstance
= HandleDatabase
->Buffer
;
213 TotalStringCount
= HandleDatabase
->NumberOfTokens
;
219 // No handle was found - error condition
221 if (PackageInstance
== NULL
) {
222 return EFI_INVALID_PARAMETER
;
225 Status
= ValidatePack (This
, PackageInstance
, &StringPackageInstance
, &TotalStringCount
);
228 // This sets Count to 0 or the size of the IfrData. We intend to use Count as an offset value
230 Count
= StringPackageInstance
->IfrSize
;
233 // This is the size of the complete series of string packs
235 Size
= StringPackageInstance
->StringSize
;
238 // Based on if there is IFR data in this package instance, determine
239 // what the location is of the beginning of the string data.
241 if (StringPackageInstance
->IfrSize
> 0) {
242 Location
= (UINT8
*) (&StringPackageInstance
->IfrData
) + StringPackageInstance
->IfrSize
;
244 Location
= (UINT8
*) (&StringPackageInstance
->IfrData
);
247 // We allocate a buffer which is big enough for both adding and resetting string.
248 // The size is slightly larger than the real size of the packages when we are resetting a string.
250 NewBuffer
= AllocateZeroPool (
251 sizeof (EFI_HII_PACKAGE_INSTANCE
) -
252 2 * sizeof (VOID
*) +
253 StringPackageInstance
->IfrSize
+
254 StringPackageInstance
->StringSize
+
261 // Copy data to new buffer
263 NewBuffer
->Handle
= StringPackageInstance
->Handle
;
264 NewBuffer
->IfrSize
= StringPackageInstance
->IfrSize
;
267 // The worst case scenario for sizing is that we are adding a new string (not replacing one) and there was not a string
268 // package to begin with.
270 NewBuffer
->StringSize
= StringPackageInstance
->StringSize
+ StrSize (NewString
) + sizeof (EFI_HII_STRING_PACK
);
272 if (StringPackageInstance
->IfrSize
> 0) {
273 CopyMem (&NewBuffer
->IfrData
, &StringPackageInstance
->IfrData
, StringPackageInstance
->IfrSize
);
276 StringPack
= (EFI_HII_STRING_PACK
*) Location
;
279 // There may be multiple instances packed together of strings
280 // so we must walk the self describing structures until we encounter
281 // what we are looking for. In the meantime, copy everything we encounter
282 // to the new buffer.
284 CopyMem (&Length
, &StringPack
->Header
.Length
, sizeof (UINT32
));
285 for (; Length
!= 0;) {
287 // If passed in Language ISO value is in this string pack's language string
288 // then we are dealing with the strings we want.
290 CopyMem (&Offset
, &StringPack
->LanguageNameString
, sizeof (RELOFST
));
291 Status
= HiiCompareLanguage ((CHAR16
*) ((CHAR8
*) (StringPack
) + Offset
), Language
);
293 if (!EFI_ERROR (Status
)) {
297 CopyMem (((CHAR8
*) (&NewBuffer
->IfrData
) + Count
), StringPack
, Length
);
299 Count
= Count
+ Length
;
300 StringPack
= (EFI_HII_STRING_PACK
*) ((CHAR8
*) (StringPack
) + Length
);
301 CopyMem (&Length
, &StringPack
->Header
.Length
, sizeof (UINT32
));
304 // Found the language pack to update on a particular handle
305 // We need to Copy the Contents of this pack and adjust the offset values associated
306 // with adding/changing a string. This is a particular piece of code that screams for
307 // it being prone to programming error.
310 // Copy the string package up to the string data
312 StringPointer
= (RELOFST
*) (StringPack
+ 1);
314 ((CHAR8
*) (&NewBuffer
->IfrData
) + Count
),
316 (UINTN
) ((UINTN
) (StringPointer
) - (UINTN
) (StringPack
))
320 // Determine the number of StringPointers
323 CopyMem (&TotalStringCount
, &StringPack
->NumStringPointers
, sizeof (RELOFST
));
326 // If we are resetting the strings, use the original value when exported
328 CopyMem (&OriginalStringCount
, &StringPack
->NumStringPointers
, sizeof (RELOFST
));
329 ((EFI_HII_STRING_PACK
*) ((CHAR8
*) (&NewBuffer
->IfrData
) + Count
))->LanguageNameString
-=
331 (RELOFST
) (OriginalStringCount
- TotalStringCount
) *
334 ((EFI_HII_STRING_PACK
*) ((CHAR8
*) (&NewBuffer
->IfrData
) + Count
))->PrintableLanguageName
-=
336 (RELOFST
) (OriginalStringCount
- TotalStringCount
) *
339 ((EFI_HII_STRING_PACK
*) ((CHAR8
*) (&NewBuffer
->IfrData
) + Count
))->NumStringPointers
= TotalStringCount
;
340 *Reference
= (STRING_REF
) (TotalStringCount
);
343 // If the token value is not valid, error out
345 if ((*Reference
>= TotalStringCount
) && !ResetStrings
) {
346 FreePool (NewBuffer
);
347 return EFI_INVALID_PARAMETER
;
350 // If Reference is 0, update it with what the new token reference will be and turn the AddString flag on
352 if (*Reference
== 0) {
353 *Reference
= (STRING_REF
) (TotalStringCount
);
358 ((EFI_HII_STRING_PACK
*) ((CHAR8
*) (&NewBuffer
->IfrData
) + Count
))->LanguageNameString
+= sizeof (RELOFST
);
359 ((EFI_HII_STRING_PACK
*) ((CHAR8
*) (&NewBuffer
->IfrData
) + Count
))->PrintableLanguageName
+= sizeof (RELOFST
);
360 ((EFI_HII_STRING_PACK
*) ((CHAR8
*) (&NewBuffer
->IfrData
) + Count
))->NumStringPointers
++;
363 // Increment offset by amount of copied data
365 Count
= Count
+ ((UINTN
) (StringPointer
) - (UINTN
) StringPack
);
367 for (Index
= 0; Index
< TotalStringCount
; Index
++) {
369 // If we are pointing to the size of the changing string value
370 // then cache the old string value so you know what the difference is
372 if (Index
== *Reference
) {
373 CopyMem (&Offset
, &StringPointer
[Index
], sizeof (RELOFST
));
375 StringLocation
= ((UINT8
*) (StringPack
) + Offset
);
376 for (SecondIndex
= 0;
377 (StringLocation
[SecondIndex
] != 0) || (StringLocation
[SecondIndex
+ 1] != 0);
378 SecondIndex
= SecondIndex
+ 2
381 SecondIndex
= SecondIndex
+ 2;
386 // NewString is a passed in local string which is assumed to be aligned
388 Size
= StrSize (NewString
) - Size
;
391 // If we are about to copy the offset of the string that follows the changed string make
392 // sure that the offsets are adjusted accordingly
394 if ((Index
> *Reference
) && !ResetStrings
) {
395 CopyMem (&Offset
, &StringPointer
[Index
], sizeof (RELOFST
));
396 Offset
= (RELOFST
) (Offset
+ Size
);
397 CopyMem (&StringPointer
[Index
], &Offset
, sizeof (RELOFST
));
400 // If we are adding a string that means we will have an extra string pointer that will affect all string offsets
403 CopyMem (&Offset
, &StringPointer
[Index
], sizeof (RELOFST
));
404 Offset
= (UINT32
) (Offset
+ sizeof (RELOFST
));
405 CopyMem (&StringPointer
[Index
], &Offset
, sizeof (RELOFST
));
408 // If resetting the strings, we need to reduce the offset by the difference in the strings
411 CopyMem (&Length
, &StringPointer
[Index
], sizeof (RELOFST
));
412 Length
= Length
- ((RELOFST
) (OriginalStringCount
- TotalStringCount
) * sizeof (RELOFST
));
413 CopyMem (&StringPointer
[Index
], &Length
, sizeof (RELOFST
));
416 // Notice that if the string was being added as a new token, we don't have to worry about the
417 // offsets changing in the other indexes
419 CopyMem (((CHAR8
*) (&NewBuffer
->IfrData
) + Count
), &StringPointer
[Index
], sizeof (RELOFST
));
420 Count
= Count
+ sizeof (RELOFST
);
424 // If we are adding a new string the above for loop did not copy the offset for us
428 // Since the Index is pointing to the beginning of the first string, we need to gather the size of the previous
429 // offset's string and create an offset to our new string.
431 CopyMem (&Offset
, &StringPointer
[Index
- 1], sizeof (RELOFST
));
432 StringLocation
= (UINT8
*) StringPack
;
433 StringLocation
= StringLocation
+ Offset
- sizeof (RELOFST
);
436 // Since StringPack is a packed structure, we need to size it carefully (byte-wise) to avoid alignment issues
439 (StringLocation
[Length
] != 0) || (StringLocation
[Length
+ 1] != 0);
440 Length
= (RELOFST
) (Length
+ 2)
443 Length
= (RELOFST
) (Length
+ 2);
445 StringSize
= (RELOFST
) (Offset
+ Length
);
448 // Copy the new string offset
450 CopyMem (((CHAR8
*) (&NewBuffer
->IfrData
) + Count
), &StringSize
, sizeof (RELOFST
));
451 Count
= Count
+ sizeof (RELOFST
);
453 CopyMem (&Length
, &StringPack
->Header
.Length
, sizeof (UINT32
));
454 Length
= Length
+ sizeof (RELOFST
);
455 CopyMem (&StringPack
->Header
.Length
, &Length
, sizeof (UINT32
));
458 // Set Location to the First String
461 Index
= OriginalStringCount
;
464 // Set Location to the First String
466 Location
= (UINT8
*) &StringPointer
[Index
];
470 // Keep copying strings until you run into two CHAR16's in a row that are NULL
473 if ((*Reference
== Increment
) && !AddString
) {
474 StringLocation
= ((UINT8
*) (&NewBuffer
->IfrData
) + Count
);
475 CopyMem (StringLocation
, NewString
, StrSize (NewString
));
478 // Advance the destination location by Count number of bytes
480 Count
= Count
+ StrSize (NewString
);
483 // Add the difference between the new string and the old string to the length
485 CopyMem (&Length
, &StringPack
->Header
.Length
, sizeof (UINT32
));
488 // Since StringPack is a packed structure, we need to size it carefully (byte-wise) to avoid alignment issues
490 StringLocation
= (UINT8
*) &Location
[Index
];
492 (StringLocation
[Offset
] != 0) || (StringLocation
[Offset
+ 1] != 0);
493 Offset
= (RELOFST
) (Offset
+ 2)
496 Offset
= (RELOFST
) (Offset
+ 2);
498 Length
= Length
+ (UINT32
) StrSize (NewString
) - Offset
;
500 CopyMem (&StringPack
->Header
.Length
, &Length
, sizeof (UINT32
));
502 StringLocation
= (UINT8
*) &Location
[Index
];
504 (StringLocation
[Offset
] != 0) || (StringLocation
[Offset
+ 1] != 0);
505 Offset
= (RELOFST
) (Offset
+ 2)
508 Offset
= (RELOFST
) (Offset
+ 2);
510 CopyMem (((CHAR8
*) (&NewBuffer
->IfrData
) + Count
), StringLocation
, Offset
);
513 // Advance the destination location by Count number of bytes
515 Count
= Count
+ Offset
;
518 // Retrieve the number of characters to advance the index - should land at beginning of next string
520 Index
= Index
+ Offset
;
524 } while (StringCount
> 0);
527 // If we are adding a new string, then the above do/while will not suffice
530 Offset
= (RELOFST
) StrSize (NewString
);
531 CopyMem (((CHAR8
*) (&NewBuffer
->IfrData
) + Count
), NewString
, Offset
);
533 Count
= Count
+ StrSize (NewString
);
534 CopyMem (&Length
, &StringPack
->Header
.Length
, sizeof (UINT32
));
535 Length
= Length
+ (UINT32
) StrSize (NewString
);
536 CopyMem (&StringPack
->Header
.Length
, &Length
, sizeof (UINT32
));
541 // Skip the remainder of strings in the string package
543 StringCount
= OriginalStringCount
- TotalStringCount
;
545 while (StringCount
> 0) {
546 StringLocation
= (UINT8
*) &Location
[Index
];
548 (StringLocation
[Offset
] != 0) || (StringLocation
[Offset
+ 1] != 0);
549 Offset
= (RELOFST
) (Offset
+ 2)
552 Offset
= (RELOFST
) (Offset
+ 2);
553 Index
= Index
+ Offset
;
557 // Adjust the size of the string pack by the string size we just skipped.
558 // Also reduce the length by the size of a RelativeOffset value since we
559 // obviously would have skipped that as well.
561 CopyMem (&Length
, &StringPack
->Header
.Length
, sizeof (UINT32
));
562 Length
= Length
- Offset
- sizeof (RELOFST
);
563 CopyMem (&StringPack
->Header
.Length
, &Length
, sizeof (UINT32
));
567 StringPack
= (EFI_HII_STRING_PACK
*) &Location
[Index
];
569 CopyMem (&Length
, &StringPack
->Header
.Length
, sizeof (UINT32
));
570 for (; Length
!= 0;) {
572 CopyMem (((CHAR8
*) (&NewBuffer
->IfrData
) + Count
), StringPack
, Length
);
574 Count
= Count
+ Length
;
575 StringPack
= (EFI_HII_STRING_PACK
*) ((CHAR8
*) (StringPack
) + Length
);
576 CopyMem (&Length
, &StringPack
->Header
.Length
, sizeof (UINT32
));
579 // Copy the null terminator to the new buffer
581 CopyMem (((CHAR8
*) (&NewBuffer
->IfrData
) + Count
), StringPack
, sizeof (EFI_HII_STRING_PACK
));
584 // Based on if there is IFR data in this package instance, determine
585 // what the location is of the beginning of the string data.
587 if (StringPackageInstance
->IfrSize
> 0) {
588 Location
= (UINT8
*) (&StringPackageInstance
->IfrData
) + StringPackageInstance
->IfrSize
;
589 StringPack
= (EFI_HII_STRING_PACK
*) Location
;
590 Location
= (UINT8
*) (&NewBuffer
->IfrData
) + NewBuffer
->IfrSize
;
591 NewStringPack
= (EFI_HII_STRING_PACK
*) Location
;
593 StringPack
= (EFI_HII_STRING_PACK
*) (&StringPackageInstance
->IfrData
);
594 NewStringPack
= (EFI_HII_STRING_PACK
*) (&NewBuffer
->IfrData
);
597 CopyMem (&Length
, &StringPack
->Header
.Length
, sizeof (UINT32
));
598 for (; Length
!= 0;) {
600 // Since we updated the old version of the string data as we moved things over
601 // And we had a chicken-egg problem with the data we copied, let's post-fix the new
602 // buffer with accurate length data.
604 CopyMem (&Count
, &NewStringPack
->Header
.Length
, sizeof (UINT32
));
605 CopyMem (&NewStringPack
->Header
.Length
, &StringPack
->Header
.Length
, sizeof (UINT32
));
606 CopyMem (&StringPack
->Header
.Length
, &Count
, sizeof (UINT32
));
608 CopyMem (&Count
, &NewStringPack
->Header
.Length
, sizeof (UINT32
));
609 NewStringPack
= (EFI_HII_STRING_PACK
*) ((CHAR8
*) (NewStringPack
) + Count
);
610 CopyMem (&Count
, &StringPack
->Header
.Length
, sizeof (UINT32
));
611 StringPack
= (EFI_HII_STRING_PACK
*) ((CHAR8
*) (StringPack
) + Count
);
612 CopyMem (&Length
, &StringPack
->Header
.Length
, sizeof (UINT32
));
615 GetPackSize ((VOID
*) ((CHAR8
*) (&NewBuffer
->IfrData
) + NewBuffer
->IfrSize
), &NewBuffer
->StringSize
, NULL
);
618 // Search through the handles until the requested handle is found.
620 for (HandleDatabase
= HiiData
->DatabaseHead
;
621 HandleDatabase
->Handle
!= 0;
622 HandleDatabase
= HandleDatabase
->NextHandleDatabase
624 if (HandleDatabase
->Handle
== StringPackageInstance
->Handle
) {
626 // Free the previous buffer associated with this handle, and assign the new buffer to the handle
628 FreePool (HandleDatabase
->Buffer
);
629 HandleDatabase
->Buffer
= NewBuffer
;
640 IN EFI_HII_PROTOCOL
*This
,
642 IN EFI_HII_HANDLE Handle
,
643 IN OUT STRING_REF
*Reference
,
649 This function allows a new String to be added to an already existing String Package.
650 We will make a buffer the size of the package + StrSize of the new string. We will
651 copy the string package that first gets changed and the following language packages until
652 we encounter the NULL string package. All this time we will ensure that the offsets have
664 STRING_REF OriginalValue
;
668 // To avoid a warning 4 uninitialized variable warning
670 Status
= EFI_SUCCESS
;
672 Status
= HiiGetPrimaryLanguages (
678 if (!EFI_ERROR (Status
)) {
679 OriginalValue
= *Reference
;
681 if (Language
== NULL
) {
682 for (Index
= 0; LangCodes
[Index
] != 0; Index
+= 3) {
683 *Reference
= OriginalValue
;
684 CopyMem (Lang
, &LangCodes
[Index
], 6);
686 Status
= HiiNewString2 (
697 Status
= HiiNewString2 (
707 FreePool (LangCodes
);
716 IN EFI_HII_PROTOCOL
*This
,
717 IN EFI_HII_HANDLE Handle
723 This function removes any new strings that were added after the initial string export for this handle.
734 STRING_REF Reference
;
741 HiiGetPrimaryLanguages (
747 for (Index
= 0; LangCodes
[Index
] != 0; Index
+= 3) {
748 CopyMem (Lang
, &LangCodes
[Index
], 6);
750 Status
= HiiNewString2 (
758 ASSERT_EFI_ERROR (Status
);
761 FreePool (LangCodes
);
768 IN EFI_HII_PROTOCOL
*This
,
769 IN EFI_HII_HANDLE Handle
,
772 IN CHAR16
*LanguageString
,
773 IN OUT UINTN
*BufferLengthTemp
,
774 OUT EFI_STRING StringBuffer
780 This function extracts a string from a package already registered with the EFI HII database.
783 This - A pointer to the EFI_HII_PROTOCOL instance.
784 Handle - The HII handle on which the string resides.
785 Token - The string token assigned to the string.
786 Raw - If TRUE, the string is returned unedited in the internal storage format described
787 above. If false, the string returned is edited by replacing <cr> with <space>
788 and by removing special characters such as the <wide> prefix.
789 LanguageString - Pointer to a NULL-terminated string containing a single ISO 639-2 language
790 identifier, indicating the language to print. If the LanguageString is empty (starts
791 with a NULL), the default system language will be used to determine the language.
792 BufferLength - Length of the StringBuffer. If the status reports that the buffer width is too
793 small, this parameter is filled with the length of the buffer needed.
794 StringBuffer - The buffer designed to receive the characters in the string. Type EFI_STRING is
798 EFI_INVALID_PARAMETER - If input parameter is invalid.
799 EFI_BUFFER_TOO_SMALL - If the *BufferLength is too small.
800 EFI_SUCCESS - Operation is successful.
804 EFI_HII_PACKAGE_INSTANCE
*PackageInstance
;
805 EFI_HII_PACKAGE_INSTANCE
*StringPackageInstance
;
806 EFI_HII_DATA
*HiiData
;
807 EFI_HII_HANDLE_DATABASE
*HandleDatabase
;
808 EFI_HII_STRING_PACK
*StringPack
;
809 RELOFST
*StringPointer
;
823 UINT16
*BufferLength
= (UINT16
*) BufferLengthTemp
;
826 return EFI_INVALID_PARAMETER
;
831 DataSize
= sizeof (Lang
);
833 HiiData
= EFI_HII_DATA_FROM_THIS (This
);
835 PackageInstance
= NULL
;
837 Narrow
= NARROW_CHAR
;
839 NoBreak
= NON_BREAKING_CHAR
;
842 // Check numeric value against the head of the database
844 for (HandleDatabase
= HiiData
->DatabaseHead
;
845 HandleDatabase
!= NULL
;
846 HandleDatabase
= HandleDatabase
->NextHandleDatabase
849 // Match the numeric value with the database entry - if matched, extract PackageInstance
851 if (Handle
== HandleDatabase
->Handle
) {
852 PackageInstance
= HandleDatabase
->Buffer
;
857 // No handle was found - error condition
859 if (PackageInstance
== NULL
) {
860 return EFI_INVALID_PARAMETER
;
863 Status
= ValidatePack (This
, PackageInstance
, &StringPackageInstance
, NULL
);
866 // If there is no specified language, assume the system default language
868 if (LanguageString
== NULL
) {
870 // Get system default language
872 Status
= gRT
->GetVariable (
874 &gEfiGlobalVariableGuid
,
880 if (EFI_ERROR (Status
)) {
882 // If Lang doesn't exist, just use the first language you find
888 // Convert the ASCII Lang variable to a Unicode Language variable
890 AsciiToUnicode ((UINT8
*)Lang
, Language
);
893 // Copy input ISO value to Language variable
895 CopyMem (Language
, LanguageString
, 6);
898 // Based on if there is IFR data in this package instance, determine
899 // what the location is of the beginning of the string data.
902 if (StringPackageInstance
->IfrSize
> 0) {
903 StringPack
= (EFI_HII_STRING_PACK
*) ((CHAR8
*) (&StringPackageInstance
->IfrData
) + StringPackageInstance
->IfrSize
);
905 StringPack
= (EFI_HII_STRING_PACK
*) (&StringPackageInstance
->IfrData
);
908 // If Token is 0, extract entire string package
912 // Compute the entire string pack length, including all languages' and the terminating pack's.
915 while (0 != StringPack
->Header
.Length
) {
916 Length
+= StringPack
->Header
.Length
;
917 StringPack
= (VOID
*)(((UINT8
*)StringPack
) + StringPack
->Header
.Length
);
920 // Back to the start of package.
922 StringPack
= (VOID
*)(((UINT8
*)StringPack
) - Length
);
924 // Terminating zero sub-pack.
926 Length
+= sizeof (EFI_HII_STRING_PACK
);
929 // If trying to get the entire string package and have insufficient space. Return error.
931 if (Length
> *BufferLength
|| StringBuffer
== NULL
) {
932 *BufferLength
= (UINT16
)Length
;
933 return EFI_BUFFER_TOO_SMALL
;
936 // Copy the Pack to the caller's buffer.
938 *BufferLength
= (UINT16
)Length
;
939 CopyMem (StringBuffer
, StringPack
, Length
);
944 // There may be multiple instances packed together of strings
945 // so we must walk the self describing structures until we encounter
946 // what we are looking for, and then extract the string we are looking for
948 CopyMem (&Length
, &StringPack
->Header
.Length
, sizeof (UINT32
));
949 for (; Length
!= 0;) {
951 // If passed in Language ISO value is in this string pack's language string
952 // then we are dealing with the strings we want.
954 CopyMem (&Offset
, &StringPack
->LanguageNameString
, sizeof (RELOFST
));
955 Status
= HiiCompareLanguage ((CHAR16
*) ((CHAR8
*) (StringPack
) + Offset
), Language
);
958 // If we cannot find the lang variable, we skip this check and use the first language available
961 if (EFI_ERROR (Status
)) {
962 StringPack
= (EFI_HII_STRING_PACK
*) ((CHAR8
*) (StringPack
) + Length
);
963 CopyMem (&Length
, &StringPack
->Header
.Length
, sizeof (UINT32
));
968 StringPointer
= (RELOFST
*) (StringPack
+ 1);
971 // We have the right string package - size it, and copy it to the StringBuffer
973 if (Token
>= StringPack
->NumStringPointers
) {
974 return EFI_INVALID_PARAMETER
;
976 CopyMem (&Offset
, &StringPointer
[Token
], sizeof (RELOFST
));
979 // Since StringPack is a packed structure, we need to determine the string's
980 // size safely, thus byte-wise. Post-increment the size to include the null-terminator
982 Local
= (UINT16
*) ((CHAR8
*) (StringPack
) + Offset
);
983 for (Count
= 0; CompareMem (&Local
[Count
], &Zero
, 2); Count
++)
987 Count
= Count
* sizeof (CHAR16
);;
989 if (*BufferLength
>= Count
&& StringBuffer
!= NULL
) {
991 // Copy the string to the user's buffer
994 CopyMem (StringBuffer
, Local
, Count
);
996 for (Count
= 0; CompareMem (Local
, &Zero
, 2); Local
++) {
998 // Skip "Narraw, Wide, NoBreak"
1000 if (CompareMem (Local
, &Narrow
, 2) &&
1001 CompareMem (Local
, &Wide
, 2) &&
1002 CompareMem (Local
, &NoBreak
, 2)) {
1003 CopyMem (&StringBuffer
[Count
++], Local
, 2);
1007 // Add "NULL" at the end.
1009 CopyMem (&StringBuffer
[Count
], &Zero
, 2);
1011 Count
*= sizeof (CHAR16
);
1014 *BufferLength
= (UINT16
) Count
;
1017 *BufferLength
= (UINT16
) Count
;
1018 return EFI_BUFFER_TOO_SMALL
;
1030 IN EFI_HII_PROTOCOL
*This
,
1031 IN EFI_HII_HANDLE Handle
,
1032 IN STRING_REF Token
,
1033 IN OUT UINT16
*Index
,
1034 IN UINT16 LineWidth
,
1035 IN CHAR16
*LanguageString
,
1036 IN OUT UINT16
*BufferLength
,
1037 OUT EFI_STRING StringBuffer
1041 Routine Description:
1043 This function allows a program to extract a part of a string of not more than a given width.
1044 With repeated calls, this allows a calling program to extract "lines" of text that fit inside
1045 columns. The effort of measuring the fit of strings inside columns is localized to this call.
1054 EFI_HII_PACKAGE_INSTANCE
*PackageInstance
;
1055 EFI_HII_PACKAGE_INSTANCE
*StringPackageInstance
;
1056 EFI_HII_DATA
*HiiData
;
1057 EFI_HII_HANDLE_DATABASE
*HandleDatabase
;
1058 EFI_HII_STRING_PACK
*StringPack
;
1059 RELOFST
*StringPointer
;
1067 return EFI_INVALID_PARAMETER
;
1070 HiiData
= EFI_HII_DATA_FROM_THIS (This
);
1072 HandleDatabase
= HiiData
->DatabaseHead
;
1074 PackageInstance
= NULL
;
1078 // Check numeric value against the head of the database
1080 for (; HandleDatabase
!= NULL
; HandleDatabase
= HandleDatabase
->NextHandleDatabase
) {
1082 // Match the numeric value with the database entry - if matched, extract PackageInstance
1084 if (Handle
== HandleDatabase
->Handle
) {
1085 PackageInstance
= HandleDatabase
->Buffer
;
1089 // No handle was found - error condition
1091 if (PackageInstance
== NULL
) {
1092 return EFI_INVALID_PARAMETER
;
1095 Status
= ValidatePack (This
, PackageInstance
, &StringPackageInstance
, NULL
);
1098 // If there is no specified language, assume the system default language
1100 if (LanguageString
== NULL
) {
1102 // Get system default language
1104 Status
= gRT
->GetVariable (
1106 &gEfiGlobalVariableGuid
,
1112 if (EFI_ERROR (Status
)) {
1116 // Convert the ASCII Lang variable to a Unicode Language variable
1118 AsciiToUnicode ((UINT8
*)Lang
, Language
);
1121 // Copy input ISO value to Language variable
1123 CopyMem (Language
, LanguageString
, 6);
1126 // Based on if there is IFR data in this package instance, determine
1127 // what the location is of the beginning of the string data.
1129 if (StringPackageInstance
->IfrSize
> 0) {
1130 StringPack
= (EFI_HII_STRING_PACK
*) ((CHAR8
*) (&StringPackageInstance
->IfrData
) + StringPackageInstance
->IfrSize
);
1132 StringPack
= (EFI_HII_STRING_PACK
*) (&StringPackageInstance
->IfrData
);
1135 StringPointer
= (RELOFST
*) (StringPack
+ 1);
1138 // There may be multiple instances packed together of strings
1139 // so we must walk the self describing structures until we encounter
1140 // what we are looking for, and then extract the string we are looking for
1142 for (; StringPack
->Header
.Length
!= 0;) {
1144 // If passed in Language ISO value is in this string pack's language string
1145 // then we are dealing with the strings we want.
1147 Status
= HiiCompareLanguage ((CHAR16
*) ((CHAR8
*) (StringPack
) + StringPack
->LanguageNameString
), Language
);
1149 if (EFI_ERROR (Status
)) {
1150 StringPack
= (EFI_HII_STRING_PACK
*) ((CHAR8
*) (StringPack
) + StringPack
->Header
.Length
);
1154 Location
= (CHAR16
*) ((CHAR8
*) (StringPack
) + StringPointer
[Token
] +*Index
* 2);
1157 // If the size of the remaining string is less than the LineWidth
1158 // then copy the entire thing
1160 if (StrSize (Location
) <= LineWidth
) {
1161 if (*BufferLength
>= StrSize (Location
)) {
1162 StrCpy (StringBuffer
, Location
);
1165 *BufferLength
= (UINT16
) StrSize (Location
);
1166 return EFI_BUFFER_TOO_SMALL
;
1170 // Rewind the string from the maximum size until we see a space the break the line
1172 for (Count
= LineWidth
; Location
[Count
] != 0x0020; Count
--)
1176 // Put the index at the next character
1178 *Index
= (UINT16
) (Count
+ 1);
1180 if (*BufferLength
>= Count
) {
1181 StrnCpy (StringBuffer
, Location
, Count
);
1184 *BufferLength
= (UINT16
) Count
;
1185 return EFI_BUFFER_TOO_SMALL
;
1194 HiiCompareLanguage (
1195 IN CHAR16
*LanguageStringLocation
,
1201 CHAR16
*InputString
;
1202 CHAR16
*OriginalInputString
;
1205 // Allocate a temporary buffer for InputString
1207 InputString
= AllocateZeroPool (0x100);
1209 ASSERT (InputString
);
1211 OriginalInputString
= InputString
;
1213 Local
= (UINT8
*) LanguageStringLocation
;
1216 // Determine the size of this packed string safely (e.g. access by byte), post-increment
1217 // to include the null-terminator
1219 for (Index
= 0; Local
[Index
] != 0; Index
= Index
+ 2)
1222 // MARMAR Index = Index + 2;
1224 // This is a packed structure that this location comes from, so let's make sure
1225 // the value is aligned by copying it to a local variable and working on it.
1227 CopyMem (InputString
, LanguageStringLocation
, Index
);
1229 for (Index
= 0; Index
< 3; Index
++) {
1230 InputString
[Index
] = (CHAR16
) (InputString
[Index
] | 0x20);
1231 Language
[Index
] = (CHAR16
) (Language
[Index
] | 0x20);
1234 // If the Language is the same return success
1236 if (CompareMem (LanguageStringLocation
, Language
, 6) == 0) {
1237 FreePool (InputString
);
1241 // Skip the first three letters that comprised the primary language,
1242 // see if what is being compared against is a secondary language
1244 InputString
= InputString
+ 3;
1247 // If the Language is not the same as the Primary language, see if there are any
1248 // secondary languages, and if there are see if we have a match. If not, return an error.
1250 for (Index
= 0; InputString
[Index
] != 0; Index
= Index
+ 3) {
1252 // Getting in here means we have a secondary language
1254 if (CompareMem (&InputString
[Index
], Language
, 6) == 0) {
1255 FreePool (InputString
);
1260 // If nothing was found, return the error
1262 FreePool (OriginalInputString
);
1263 return EFI_NOT_FOUND
;