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 string processing code to the HII database.
24 // Include common header file for this module.
26 #include "CommonHeader.h"
28 #include "HiiDatabase.h"
40 // Convert the ASCII Lang variable to a Unicode Language variable
42 for (Count
= 0; Count
< 3; Count
++) {
43 Language
[Count
] = (CHAR16
) Lang
[Count
];
50 IN EFI_HII_PROTOCOL
*This
,
51 IN CHAR16
*StringToTest
,
52 IN OUT UINT32
*FirstMissing
,
53 OUT UINT32
*GlyphBufferSize
58 Test if all of the characters in a string have corresponding font characters.
66 EFI_HII_GLOBAL_DATA
*GlobalData
;
67 EFI_HII_DATA
*HiiData
;
72 return EFI_INVALID_PARAMETER
;
75 HiiData
= EFI_HII_DATA_FROM_THIS (This
);
76 GlobalData
= HiiData
->GlobalData
;
80 // Rewind through the string looking for a glyph width identifier
81 // If no width identifier exists, we assume string has narrow width identifier
83 for (WideChar
= FALSE
, Location
= (INT32
) *FirstMissing
; Location
>= 0; Location
--) {
84 if ((StringToTest
[Location
] == NARROW_CHAR
) || (StringToTest
[Location
] == WIDE_CHAR
)) {
86 // We found something that identifies what glyph database to look in
88 WideChar
= (BOOLEAN
) (StringToTest
[Location
] == WIDE_CHAR
);
94 // Walk through the string until you hit the null terminator
96 for (*GlyphBufferSize
= 0; StringToTest
[*FirstMissing
] != CHAR_NULL
; (*FirstMissing
)++) {
98 // We found something that identifies what glyph database to look in
100 if ((StringToTest
[*FirstMissing
] == NARROW_CHAR
) || (StringToTest
[*FirstMissing
] == WIDE_CHAR
)) {
101 WideChar
= (BOOLEAN
) (StringToTest
[*FirstMissing
] == WIDE_CHAR
);
107 GlobalData
->NarrowGlyphs
[StringToTest
[*FirstMissing
]].GlyphCol1
,
109 NARROW_GLYPH_ARRAY_SIZE
113 // Break since this glyph isn't defined
115 return EFI_NOT_FOUND
;
119 // Can compare wide glyph against only GlyphCol1 since GlyphCol1 and GlyphCol2 are contiguous - just give correct size
122 GlobalData
->WideGlyphs
[StringToTest
[*FirstMissing
]].GlyphCol1
,
124 WIDE_GLYPH_ARRAY_SIZE
128 // Break since this glyph isn't defined
130 return EFI_NOT_FOUND
;
134 *GlyphBufferSize
+= (WideChar
? sizeof (EFI_WIDE_GLYPH
) : sizeof (EFI_NARROW_GLYPH
));
143 IN EFI_HII_PROTOCOL
*This
,
145 IN EFI_HII_HANDLE Handle
,
146 IN OUT STRING_REF
*Reference
,
147 IN CHAR16
*NewString
,
148 IN BOOLEAN ResetStrings
154 This function allows a new String to be added to an already existing String Package.
155 We will make a buffer the size of the package + EfiStrSize of the new string. We will
156 copy the string package that first gets changed and the following language packages until
157 we encounter the NULL string package. All this time we will ensure that the offsets have
162 This - Pointer to the HII protocol.
163 Language - Pointer to buffer which contains the language code of this NewString.
164 Handle - Handle of the package instance to be processed.
165 Reference - The token number for the string. If 0, new string token to be returned through this parameter.
166 NewString - Buffer pointer for the new string.
167 ResetStrings - Indicate if we are resetting a string.
171 EFI_SUCCESS - The string has been added or reset to Hii database.
172 EFI_INVALID_PARAMETER - Some parameter passed in is invalid.
176 EFI_HII_PACKAGE_INSTANCE
*PackageInstance
;
177 EFI_HII_PACKAGE_INSTANCE
*StringPackageInstance
;
178 EFI_HII_DATA
*HiiData
;
179 EFI_HII_STRING_PACK
*StringPack
;
180 EFI_HII_STRING_PACK
*NewStringPack
;
181 EFI_HII_HANDLE_DATABASE
*HandleDatabase
;
182 EFI_HII_PACKAGE_INSTANCE
*NewBuffer
;
184 UINT8
*StringLocation
;
185 RELOFST
*StringPointer
;
194 UINT32 TotalStringCount
;
195 UINT32 OriginalStringCount
;
201 return EFI_INVALID_PARAMETER
;
204 HiiData
= EFI_HII_DATA_FROM_THIS (This
);
206 HandleDatabase
= HiiData
->DatabaseHead
;
207 PackageInstance
= NULL
;
211 TotalStringCount
= 0;
212 OriginalStringCount
= 0;
215 // Check numeric value against the head of the database
217 for (; HandleDatabase
!= NULL
; HandleDatabase
= HandleDatabase
->NextHandleDatabase
) {
219 // Match the numeric value with the database entry - if matched, extract PackageInstance
221 if (Handle
== HandleDatabase
->Handle
) {
222 PackageInstance
= HandleDatabase
->Buffer
;
224 TotalStringCount
= HandleDatabase
->NumberOfTokens
;
230 // No handle was found - error condition
232 if (PackageInstance
== NULL
) {
233 return EFI_INVALID_PARAMETER
;
236 Status
= ValidatePack (This
, PackageInstance
, &StringPackageInstance
, &TotalStringCount
);
239 // This sets Count to 0 or the size of the IfrData. We intend to use Count as an offset value
241 Count
= StringPackageInstance
->IfrSize
;
244 // This is the size of the complete series of string packs
246 Size
= StringPackageInstance
->StringSize
;
249 // Based on if there is IFR data in this package instance, determine
250 // what the location is of the beginning of the string data.
252 if (StringPackageInstance
->IfrSize
> 0) {
253 Location
= (UINT8
*) (&StringPackageInstance
->IfrData
) + StringPackageInstance
->IfrSize
;
255 Location
= (UINT8
*) (&StringPackageInstance
->IfrData
);
258 // We allocate a buffer which is big enough for both adding and resetting string.
259 // The size is slightly larger than the real size of the packages when we are resetting a string.
261 NewBuffer
= AllocateZeroPool (
262 sizeof (EFI_HII_PACKAGE_INSTANCE
) -
263 2 * sizeof (VOID
*) +
264 StringPackageInstance
->IfrSize
+
265 StringPackageInstance
->StringSize
+
272 // Copy data to new buffer
274 NewBuffer
->Handle
= StringPackageInstance
->Handle
;
275 NewBuffer
->IfrSize
= StringPackageInstance
->IfrSize
;
278 // The worst case scenario for sizing is that we are adding a new string (not replacing one) and there was not a string
279 // package to begin with.
281 NewBuffer
->StringSize
= StringPackageInstance
->StringSize
+ StrSize (NewString
) + sizeof (EFI_HII_STRING_PACK
);
283 if (StringPackageInstance
->IfrSize
> 0) {
284 CopyMem (&NewBuffer
->IfrData
, &StringPackageInstance
->IfrData
, StringPackageInstance
->IfrSize
);
287 StringPack
= (EFI_HII_STRING_PACK
*) Location
;
290 // There may be multiple instances packed together of strings
291 // so we must walk the self describing structures until we encounter
292 // what we are looking for. In the meantime, copy everything we encounter
293 // to the new buffer.
295 CopyMem (&Length
, &StringPack
->Header
.Length
, sizeof (UINT32
));
296 for (; Length
!= 0;) {
298 // If passed in Language ISO value is in this string pack's language string
299 // then we are dealing with the strings we want.
301 CopyMem (&Offset
, &StringPack
->LanguageNameString
, sizeof (RELOFST
));
302 Status
= HiiCompareLanguage ((CHAR16
*) ((CHAR8
*) (StringPack
) + Offset
), Language
);
304 if (!EFI_ERROR (Status
)) {
308 CopyMem (((CHAR8
*) (&NewBuffer
->IfrData
) + Count
), StringPack
, Length
);
310 Count
= Count
+ Length
;
311 StringPack
= (EFI_HII_STRING_PACK
*) ((CHAR8
*) (StringPack
) + Length
);
312 CopyMem (&Length
, &StringPack
->Header
.Length
, sizeof (UINT32
));
315 // Found the language pack to update on a particular handle
316 // We need to Copy the Contents of this pack and adjust the offset values associated
317 // with adding/changing a string. This is a particular piece of code that screams for
318 // it being prone to programming error.
321 // Copy the string package up to the string data
323 StringPointer
= (RELOFST
*) (StringPack
+ 1);
325 ((CHAR8
*) (&NewBuffer
->IfrData
) + Count
),
327 (UINTN
) ((UINTN
) (StringPointer
) - (UINTN
) (StringPack
))
331 // Determine the number of StringPointers
334 CopyMem (&TotalStringCount
, &StringPack
->NumStringPointers
, sizeof (RELOFST
));
337 // If we are resetting the strings, use the original value when exported
339 CopyMem (&OriginalStringCount
, &StringPack
->NumStringPointers
, sizeof (RELOFST
));
340 ((EFI_HII_STRING_PACK
*) ((CHAR8
*) (&NewBuffer
->IfrData
) + Count
))->LanguageNameString
-=
342 (RELOFST
) (OriginalStringCount
- TotalStringCount
) *
345 ((EFI_HII_STRING_PACK
*) ((CHAR8
*) (&NewBuffer
->IfrData
) + Count
))->PrintableLanguageName
-=
347 (RELOFST
) (OriginalStringCount
- TotalStringCount
) *
350 ((EFI_HII_STRING_PACK
*) ((CHAR8
*) (&NewBuffer
->IfrData
) + Count
))->NumStringPointers
= TotalStringCount
;
351 *Reference
= (STRING_REF
) (TotalStringCount
);
354 // If the token value is not valid, error out
356 if ((*Reference
>= TotalStringCount
) && !ResetStrings
) {
357 FreePool (NewBuffer
);
358 return EFI_INVALID_PARAMETER
;
361 // If Reference is 0, update it with what the new token reference will be and turn the AddString flag on
363 if (*Reference
== 0) {
364 *Reference
= (STRING_REF
) (TotalStringCount
);
369 ((EFI_HII_STRING_PACK
*) ((CHAR8
*) (&NewBuffer
->IfrData
) + Count
))->LanguageNameString
+= sizeof (RELOFST
);
370 ((EFI_HII_STRING_PACK
*) ((CHAR8
*) (&NewBuffer
->IfrData
) + Count
))->PrintableLanguageName
+= sizeof (RELOFST
);
371 ((EFI_HII_STRING_PACK
*) ((CHAR8
*) (&NewBuffer
->IfrData
) + Count
))->NumStringPointers
++;
374 // Increment offset by amount of copied data
376 Count
= Count
+ ((UINTN
) (StringPointer
) - (UINTN
) StringPack
);
378 for (Index
= 0; Index
< TotalStringCount
; Index
++) {
380 // If we are pointing to the size of the changing string value
381 // then cache the old string value so you know what the difference is
383 if (Index
== *Reference
) {
384 CopyMem (&Offset
, &StringPointer
[Index
], sizeof (RELOFST
));
386 StringLocation
= ((UINT8
*) (StringPack
) + Offset
);
387 for (SecondIndex
= 0;
388 (StringLocation
[SecondIndex
] != 0) || (StringLocation
[SecondIndex
+ 1] != 0);
389 SecondIndex
= SecondIndex
+ 2
392 SecondIndex
= SecondIndex
+ 2;
397 // NewString is a passed in local string which is assumed to be aligned
399 Size
= StrSize (NewString
) - Size
;
402 // If we are about to copy the offset of the string that follows the changed string make
403 // sure that the offsets are adjusted accordingly
405 if ((Index
> *Reference
) && !ResetStrings
) {
406 CopyMem (&Offset
, &StringPointer
[Index
], sizeof (RELOFST
));
407 Offset
= (RELOFST
) (Offset
+ Size
);
408 CopyMem (&StringPointer
[Index
], &Offset
, sizeof (RELOFST
));
411 // If we are adding a string that means we will have an extra string pointer that will affect all string offsets
414 CopyMem (&Offset
, &StringPointer
[Index
], sizeof (RELOFST
));
415 Offset
= (UINT32
) (Offset
+ sizeof (RELOFST
));
416 CopyMem (&StringPointer
[Index
], &Offset
, sizeof (RELOFST
));
419 // If resetting the strings, we need to reduce the offset by the difference in the strings
422 CopyMem (&Length
, &StringPointer
[Index
], sizeof (RELOFST
));
423 Length
= Length
- ((RELOFST
) (OriginalStringCount
- TotalStringCount
) * sizeof (RELOFST
));
424 CopyMem (&StringPointer
[Index
], &Length
, sizeof (RELOFST
));
427 // Notice that if the string was being added as a new token, we don't have to worry about the
428 // offsets changing in the other indexes
430 CopyMem (((CHAR8
*) (&NewBuffer
->IfrData
) + Count
), &StringPointer
[Index
], sizeof (RELOFST
));
431 Count
= Count
+ sizeof (RELOFST
);
435 // If we are adding a new string the above for loop did not copy the offset for us
439 // Since the Index is pointing to the beginning of the first string, we need to gather the size of the previous
440 // offset's string and create an offset to our new string.
442 CopyMem (&Offset
, &StringPointer
[Index
- 1], sizeof (RELOFST
));
443 StringLocation
= (UINT8
*) StringPack
;
444 StringLocation
= StringLocation
+ Offset
- sizeof (RELOFST
);
447 // Since StringPack is a packed structure, we need to size it carefully (byte-wise) to avoid alignment issues
450 (StringLocation
[Length
] != 0) || (StringLocation
[Length
+ 1] != 0);
451 Length
= (RELOFST
) (Length
+ 2)
454 Length
= (RELOFST
) (Length
+ 2);
456 StringSize
= (RELOFST
) (Offset
+ Length
);
459 // Copy the new string offset
461 CopyMem (((CHAR8
*) (&NewBuffer
->IfrData
) + Count
), &StringSize
, sizeof (RELOFST
));
462 Count
= Count
+ sizeof (RELOFST
);
464 CopyMem (&Length
, &StringPack
->Header
.Length
, sizeof (UINT32
));
465 Length
= Length
+ sizeof (RELOFST
);
466 CopyMem (&StringPack
->Header
.Length
, &Length
, sizeof (UINT32
));
469 // Set Location to the First String
472 Index
= OriginalStringCount
;
475 // Set Location to the First String
477 Location
= (UINT8
*) &StringPointer
[Index
];
481 // Keep copying strings until you run into two CHAR16's in a row that are NULL
484 if ((*Reference
== Increment
) && !AddString
) {
485 StringLocation
= ((UINT8
*) (&NewBuffer
->IfrData
) + Count
);
486 CopyMem (StringLocation
, NewString
, StrSize (NewString
));
489 // Advance the destination location by Count number of bytes
491 Count
= Count
+ StrSize (NewString
);
494 // Add the difference between the new string and the old string to the length
496 CopyMem (&Length
, &StringPack
->Header
.Length
, sizeof (UINT32
));
499 // Since StringPack is a packed structure, we need to size it carefully (byte-wise) to avoid alignment issues
501 StringLocation
= (UINT8
*) &Location
[Index
];
503 (StringLocation
[Offset
] != 0) || (StringLocation
[Offset
+ 1] != 0);
504 Offset
= (RELOFST
) (Offset
+ 2)
507 Offset
= (RELOFST
) (Offset
+ 2);
509 Length
= Length
+ (UINT32
) StrSize (NewString
) - Offset
;
511 CopyMem (&StringPack
->Header
.Length
, &Length
, sizeof (UINT32
));
513 StringLocation
= (UINT8
*) &Location
[Index
];
515 (StringLocation
[Offset
] != 0) || (StringLocation
[Offset
+ 1] != 0);
516 Offset
= (RELOFST
) (Offset
+ 2)
519 Offset
= (RELOFST
) (Offset
+ 2);
521 CopyMem (((CHAR8
*) (&NewBuffer
->IfrData
) + Count
), StringLocation
, Offset
);
524 // Advance the destination location by Count number of bytes
526 Count
= Count
+ Offset
;
529 // Retrieve the number of characters to advance the index - should land at beginning of next string
531 Index
= Index
+ Offset
;
535 } while (StringCount
> 0);
538 // If we are adding a new string, then the above do/while will not suffice
541 Offset
= (RELOFST
) StrSize (NewString
);
542 CopyMem (((CHAR8
*) (&NewBuffer
->IfrData
) + Count
), NewString
, Offset
);
544 Count
= Count
+ StrSize (NewString
);
545 CopyMem (&Length
, &StringPack
->Header
.Length
, sizeof (UINT32
));
546 Length
= Length
+ (UINT32
) StrSize (NewString
);
547 CopyMem (&StringPack
->Header
.Length
, &Length
, sizeof (UINT32
));
552 // Skip the remainder of strings in the string package
554 StringCount
= OriginalStringCount
- TotalStringCount
;
556 while (StringCount
> 0) {
557 StringLocation
= (UINT8
*) &Location
[Index
];
559 (StringLocation
[Offset
] != 0) || (StringLocation
[Offset
+ 1] != 0);
560 Offset
= (RELOFST
) (Offset
+ 2)
563 Offset
= (RELOFST
) (Offset
+ 2);
564 Index
= Index
+ Offset
;
568 // Adjust the size of the string pack by the string size we just skipped.
569 // Also reduce the length by the size of a RelativeOffset value since we
570 // obviously would have skipped that as well.
572 CopyMem (&Length
, &StringPack
->Header
.Length
, sizeof (UINT32
));
573 Length
= Length
- Offset
- sizeof (RELOFST
);
574 CopyMem (&StringPack
->Header
.Length
, &Length
, sizeof (UINT32
));
578 StringPack
= (EFI_HII_STRING_PACK
*) &Location
[Index
];
580 CopyMem (&Length
, &StringPack
->Header
.Length
, sizeof (UINT32
));
581 for (; Length
!= 0;) {
583 CopyMem (((CHAR8
*) (&NewBuffer
->IfrData
) + Count
), StringPack
, Length
);
585 Count
= Count
+ Length
;
586 StringPack
= (EFI_HII_STRING_PACK
*) ((CHAR8
*) (StringPack
) + Length
);
587 CopyMem (&Length
, &StringPack
->Header
.Length
, sizeof (UINT32
));
590 // Copy the null terminator to the new buffer
592 CopyMem (((CHAR8
*) (&NewBuffer
->IfrData
) + Count
), StringPack
, sizeof (EFI_HII_STRING_PACK
));
595 // Based on if there is IFR data in this package instance, determine
596 // what the location is of the beginning of the string data.
598 if (StringPackageInstance
->IfrSize
> 0) {
599 Location
= (UINT8
*) (&StringPackageInstance
->IfrData
) + StringPackageInstance
->IfrSize
;
600 StringPack
= (EFI_HII_STRING_PACK
*) Location
;
601 Location
= (UINT8
*) (&NewBuffer
->IfrData
) + NewBuffer
->IfrSize
;
602 NewStringPack
= (EFI_HII_STRING_PACK
*) Location
;
604 StringPack
= (EFI_HII_STRING_PACK
*) (&StringPackageInstance
->IfrData
);
605 NewStringPack
= (EFI_HII_STRING_PACK
*) (&NewBuffer
->IfrData
);
608 CopyMem (&Length
, &StringPack
->Header
.Length
, sizeof (UINT32
));
609 for (; Length
!= 0;) {
611 // Since we updated the old version of the string data as we moved things over
612 // And we had a chicken-egg problem with the data we copied, let's post-fix the new
613 // buffer with accurate length data.
615 CopyMem (&Count
, &NewStringPack
->Header
.Length
, sizeof (UINT32
));
616 CopyMem (&NewStringPack
->Header
.Length
, &StringPack
->Header
.Length
, sizeof (UINT32
));
617 CopyMem (&StringPack
->Header
.Length
, &Count
, sizeof (UINT32
));
619 CopyMem (&Count
, &NewStringPack
->Header
.Length
, sizeof (UINT32
));
620 NewStringPack
= (EFI_HII_STRING_PACK
*) ((CHAR8
*) (NewStringPack
) + Count
);
621 CopyMem (&Count
, &StringPack
->Header
.Length
, sizeof (UINT32
));
622 StringPack
= (EFI_HII_STRING_PACK
*) ((CHAR8
*) (StringPack
) + Count
);
623 CopyMem (&Length
, &StringPack
->Header
.Length
, sizeof (UINT32
));
626 GetPackSize ((VOID
*) ((CHAR8
*) (&NewBuffer
->IfrData
) + NewBuffer
->IfrSize
), &NewBuffer
->StringSize
, NULL
);
629 // Search through the handles until the requested handle is found.
631 for (HandleDatabase
= HiiData
->DatabaseHead
;
632 HandleDatabase
->Handle
!= 0;
633 HandleDatabase
= HandleDatabase
->NextHandleDatabase
635 if (HandleDatabase
->Handle
== StringPackageInstance
->Handle
) {
637 // Free the previous buffer associated with this handle, and assign the new buffer to the handle
639 FreePool (HandleDatabase
->Buffer
);
640 HandleDatabase
->Buffer
= NewBuffer
;
651 IN EFI_HII_PROTOCOL
*This
,
653 IN EFI_HII_HANDLE Handle
,
654 IN OUT STRING_REF
*Reference
,
660 This function allows a new String to be added to an already existing String Package.
661 We will make a buffer the size of the package + StrSize of the new string. We will
662 copy the string package that first gets changed and the following language packages until
663 we encounter the NULL string package. All this time we will ensure that the offsets have
675 STRING_REF OriginalValue
;
679 // To avoid a warning 4 uninitialized variable warning
681 Status
= EFI_SUCCESS
;
683 Status
= HiiGetPrimaryLanguages (
689 if (!EFI_ERROR (Status
)) {
690 OriginalValue
= *Reference
;
692 if (Language
== NULL
) {
693 for (Index
= 0; LangCodes
[Index
] != 0; Index
+= 3) {
694 *Reference
= OriginalValue
;
695 CopyMem (Lang
, &LangCodes
[Index
], 6);
697 Status
= HiiNewString2 (
708 Status
= HiiNewString2 (
718 FreePool (LangCodes
);
727 IN EFI_HII_PROTOCOL
*This
,
728 IN EFI_HII_HANDLE Handle
734 This function removes any new strings that were added after the initial string export for this handle.
745 STRING_REF Reference
;
752 HiiGetPrimaryLanguages (
758 for (Index
= 0; LangCodes
[Index
] != 0; Index
+= 3) {
759 CopyMem (Lang
, &LangCodes
[Index
], 6);
761 Status
= HiiNewString2 (
769 ASSERT_EFI_ERROR (Status
);
772 FreePool (LangCodes
);
779 IN EFI_HII_PROTOCOL
*This
,
780 IN EFI_HII_HANDLE Handle
,
783 IN CHAR16
*LanguageString
,
784 IN OUT UINTN
*BufferLengthTemp
,
785 OUT EFI_STRING StringBuffer
791 This function extracts a string from a package already registered with the EFI HII database.
794 This - A pointer to the EFI_HII_PROTOCOL instance.
795 Handle - The HII handle on which the string resides.
796 Token - The string token assigned to the string.
797 Raw - If TRUE, the string is returned unedited in the internal storage format described
798 above. If false, the string returned is edited by replacing <cr> with <space>
799 and by removing special characters such as the <wide> prefix.
800 LanguageString - Pointer to a NULL-terminated string containing a single ISO 639-2 language
801 identifier, indicating the language to print. If the LanguageString is empty (starts
802 with a NULL), the default system language will be used to determine the language.
803 BufferLength - Length of the StringBuffer. If the status reports that the buffer width is too
804 small, this parameter is filled with the length of the buffer needed.
805 StringBuffer - The buffer designed to receive the characters in the string. Type EFI_STRING is
809 EFI_INVALID_PARAMETER - If input parameter is invalid.
810 EFI_BUFFER_TOO_SMALL - If the *BufferLength is too small.
811 EFI_SUCCESS - Operation is successful.
815 EFI_HII_PACKAGE_INSTANCE
*PackageInstance
;
816 EFI_HII_PACKAGE_INSTANCE
*StringPackageInstance
;
817 EFI_HII_DATA
*HiiData
;
818 EFI_HII_HANDLE_DATABASE
*HandleDatabase
;
819 EFI_HII_STRING_PACK
*StringPack
;
820 RELOFST
*StringPointer
;
834 UINT16
*BufferLength
= (UINT16
*) BufferLengthTemp
;
837 return EFI_INVALID_PARAMETER
;
842 DataSize
= sizeof (Lang
);
844 HiiData
= EFI_HII_DATA_FROM_THIS (This
);
846 PackageInstance
= NULL
;
848 Narrow
= NARROW_CHAR
;
850 NoBreak
= NON_BREAKING_CHAR
;
853 // Check numeric value against the head of the database
855 for (HandleDatabase
= HiiData
->DatabaseHead
;
856 HandleDatabase
!= NULL
;
857 HandleDatabase
= HandleDatabase
->NextHandleDatabase
860 // Match the numeric value with the database entry - if matched, extract PackageInstance
862 if (Handle
== HandleDatabase
->Handle
) {
863 PackageInstance
= HandleDatabase
->Buffer
;
868 // No handle was found - error condition
870 if (PackageInstance
== NULL
) {
871 return EFI_INVALID_PARAMETER
;
874 Status
= ValidatePack (This
, PackageInstance
, &StringPackageInstance
, NULL
);
877 // If there is no specified language, assume the system default language
879 if (LanguageString
== NULL
) {
881 // Get system default language
883 Status
= gRT
->GetVariable (
885 &gEfiGlobalVariableGuid
,
891 if (EFI_ERROR (Status
)) {
893 // If Lang doesn't exist, just use the first language you find
899 // Convert the ASCII Lang variable to a Unicode Language variable
901 AsciiToUnicode ((UINT8
*)Lang
, Language
);
904 // Copy input ISO value to Language variable
906 CopyMem (Language
, LanguageString
, 6);
909 // Based on if there is IFR data in this package instance, determine
910 // what the location is of the beginning of the string data.
913 if (StringPackageInstance
->IfrSize
> 0) {
914 StringPack
= (EFI_HII_STRING_PACK
*) ((CHAR8
*) (&StringPackageInstance
->IfrData
) + StringPackageInstance
->IfrSize
);
916 StringPack
= (EFI_HII_STRING_PACK
*) (&StringPackageInstance
->IfrData
);
919 // If Token is 0, extract entire string package
923 // Compute the entire string pack length, including all languages' and the terminating pack's.
926 while (0 != StringPack
->Header
.Length
) {
927 Length
+= StringPack
->Header
.Length
;
928 StringPack
= (VOID
*)(((UINT8
*)StringPack
) + StringPack
->Header
.Length
);
931 // Back to the start of package.
933 StringPack
= (VOID
*)(((UINT8
*)StringPack
) - Length
);
935 // Terminating zero sub-pack.
937 Length
+= sizeof (EFI_HII_STRING_PACK
);
940 // If trying to get the entire string package and have insufficient space. Return error.
942 if (Length
> *BufferLength
|| StringBuffer
== NULL
) {
943 *BufferLength
= (UINT16
)Length
;
944 return EFI_BUFFER_TOO_SMALL
;
947 // Copy the Pack to the caller's buffer.
949 *BufferLength
= (UINT16
)Length
;
950 CopyMem (StringBuffer
, StringPack
, Length
);
955 // There may be multiple instances packed together of strings
956 // so we must walk the self describing structures until we encounter
957 // what we are looking for, and then extract the string we are looking for
959 CopyMem (&Length
, &StringPack
->Header
.Length
, sizeof (UINT32
));
960 for (; Length
!= 0;) {
962 // If passed in Language ISO value is in this string pack's language string
963 // then we are dealing with the strings we want.
965 CopyMem (&Offset
, &StringPack
->LanguageNameString
, sizeof (RELOFST
));
966 Status
= HiiCompareLanguage ((CHAR16
*) ((CHAR8
*) (StringPack
) + Offset
), Language
);
969 // If we cannot find the lang variable, we skip this check and use the first language available
972 if (EFI_ERROR (Status
)) {
973 StringPack
= (EFI_HII_STRING_PACK
*) ((CHAR8
*) (StringPack
) + Length
);
974 CopyMem (&Length
, &StringPack
->Header
.Length
, sizeof (UINT32
));
979 StringPointer
= (RELOFST
*) (StringPack
+ 1);
982 // We have the right string package - size it, and copy it to the StringBuffer
984 if (Token
>= StringPack
->NumStringPointers
) {
985 return EFI_INVALID_PARAMETER
;
987 CopyMem (&Offset
, &StringPointer
[Token
], sizeof (RELOFST
));
990 // Since StringPack is a packed structure, we need to determine the string's
991 // size safely, thus byte-wise. Post-increment the size to include the null-terminator
993 Local
= (UINT16
*) ((CHAR8
*) (StringPack
) + Offset
);
994 for (Count
= 0; CompareMem (&Local
[Count
], &Zero
, 2); Count
++)
998 Count
= Count
* sizeof (CHAR16
);;
1000 if (*BufferLength
>= Count
&& StringBuffer
!= NULL
) {
1002 // Copy the string to the user's buffer
1005 CopyMem (StringBuffer
, Local
, Count
);
1007 for (Count
= 0; CompareMem (Local
, &Zero
, 2); Local
++) {
1009 // Skip "Narraw, Wide, NoBreak"
1011 if (CompareMem (Local
, &Narrow
, 2) &&
1012 CompareMem (Local
, &Wide
, 2) &&
1013 CompareMem (Local
, &NoBreak
, 2)) {
1014 CopyMem (&StringBuffer
[Count
++], Local
, 2);
1018 // Add "NULL" at the end.
1020 CopyMem (&StringBuffer
[Count
], &Zero
, 2);
1022 Count
*= sizeof (CHAR16
);
1025 *BufferLength
= (UINT16
) Count
;
1028 *BufferLength
= (UINT16
) Count
;
1029 return EFI_BUFFER_TOO_SMALL
;
1041 IN EFI_HII_PROTOCOL
*This
,
1042 IN EFI_HII_HANDLE Handle
,
1043 IN STRING_REF Token
,
1044 IN OUT UINT16
*Index
,
1045 IN UINT16 LineWidth
,
1046 IN CHAR16
*LanguageString
,
1047 IN OUT UINT16
*BufferLength
,
1048 OUT EFI_STRING StringBuffer
1052 Routine Description:
1054 This function allows a program to extract a part of a string of not more than a given width.
1055 With repeated calls, this allows a calling program to extract "lines" of text that fit inside
1056 columns. The effort of measuring the fit of strings inside columns is localized to this call.
1065 EFI_HII_PACKAGE_INSTANCE
*PackageInstance
;
1066 EFI_HII_PACKAGE_INSTANCE
*StringPackageInstance
;
1067 EFI_HII_DATA
*HiiData
;
1068 EFI_HII_HANDLE_DATABASE
*HandleDatabase
;
1069 EFI_HII_STRING_PACK
*StringPack
;
1070 RELOFST
*StringPointer
;
1078 return EFI_INVALID_PARAMETER
;
1081 HiiData
= EFI_HII_DATA_FROM_THIS (This
);
1083 HandleDatabase
= HiiData
->DatabaseHead
;
1085 PackageInstance
= NULL
;
1089 // Check numeric value against the head of the database
1091 for (; HandleDatabase
!= NULL
; HandleDatabase
= HandleDatabase
->NextHandleDatabase
) {
1093 // Match the numeric value with the database entry - if matched, extract PackageInstance
1095 if (Handle
== HandleDatabase
->Handle
) {
1096 PackageInstance
= HandleDatabase
->Buffer
;
1100 // No handle was found - error condition
1102 if (PackageInstance
== NULL
) {
1103 return EFI_INVALID_PARAMETER
;
1106 Status
= ValidatePack (This
, PackageInstance
, &StringPackageInstance
, NULL
);
1109 // If there is no specified language, assume the system default language
1111 if (LanguageString
== NULL
) {
1113 // Get system default language
1115 Status
= gRT
->GetVariable (
1117 &gEfiGlobalVariableGuid
,
1123 if (EFI_ERROR (Status
)) {
1127 // Convert the ASCII Lang variable to a Unicode Language variable
1129 AsciiToUnicode ((UINT8
*)Lang
, Language
);
1132 // Copy input ISO value to Language variable
1134 CopyMem (Language
, LanguageString
, 6);
1137 // Based on if there is IFR data in this package instance, determine
1138 // what the location is of the beginning of the string data.
1140 if (StringPackageInstance
->IfrSize
> 0) {
1141 StringPack
= (EFI_HII_STRING_PACK
*) ((CHAR8
*) (&StringPackageInstance
->IfrData
) + StringPackageInstance
->IfrSize
);
1143 StringPack
= (EFI_HII_STRING_PACK
*) (&StringPackageInstance
->IfrData
);
1146 StringPointer
= (RELOFST
*) (StringPack
+ 1);
1149 // There may be multiple instances packed together of strings
1150 // so we must walk the self describing structures until we encounter
1151 // what we are looking for, and then extract the string we are looking for
1153 for (; StringPack
->Header
.Length
!= 0;) {
1155 // If passed in Language ISO value is in this string pack's language string
1156 // then we are dealing with the strings we want.
1158 Status
= HiiCompareLanguage ((CHAR16
*) ((CHAR8
*) (StringPack
) + StringPack
->LanguageNameString
), Language
);
1160 if (EFI_ERROR (Status
)) {
1161 StringPack
= (EFI_HII_STRING_PACK
*) ((CHAR8
*) (StringPack
) + StringPack
->Header
.Length
);
1165 Location
= (CHAR16
*) ((CHAR8
*) (StringPack
) + StringPointer
[Token
] +*Index
* 2);
1168 // If the size of the remaining string is less than the LineWidth
1169 // then copy the entire thing
1171 if (StrSize (Location
) <= LineWidth
) {
1172 if (*BufferLength
>= StrSize (Location
)) {
1173 StrCpy (StringBuffer
, Location
);
1176 *BufferLength
= (UINT16
) StrSize (Location
);
1177 return EFI_BUFFER_TOO_SMALL
;
1181 // Rewind the string from the maximum size until we see a space the break the line
1183 for (Count
= LineWidth
; Location
[Count
] != 0x0020; Count
--)
1187 // Put the index at the next character
1189 *Index
= (UINT16
) (Count
+ 1);
1191 if (*BufferLength
>= Count
) {
1192 StrnCpy (StringBuffer
, Location
, Count
);
1195 *BufferLength
= (UINT16
) Count
;
1196 return EFI_BUFFER_TOO_SMALL
;
1205 HiiCompareLanguage (
1206 IN CHAR16
*LanguageStringLocation
,
1212 CHAR16
*InputString
;
1213 CHAR16
*OriginalInputString
;
1216 // Allocate a temporary buffer for InputString
1218 InputString
= AllocateZeroPool (0x100);
1220 ASSERT (InputString
);
1222 OriginalInputString
= InputString
;
1224 Local
= (UINT8
*) LanguageStringLocation
;
1227 // Determine the size of this packed string safely (e.g. access by byte), post-increment
1228 // to include the null-terminator
1230 for (Index
= 0; Local
[Index
] != 0; Index
= Index
+ 2)
1233 // MARMAR Index = Index + 2;
1235 // This is a packed structure that this location comes from, so let's make sure
1236 // the value is aligned by copying it to a local variable and working on it.
1238 CopyMem (InputString
, LanguageStringLocation
, Index
);
1240 for (Index
= 0; Index
< 3; Index
++) {
1241 InputString
[Index
] = (CHAR16
) (InputString
[Index
] | 0x20);
1242 Language
[Index
] = (CHAR16
) (Language
[Index
] | 0x20);
1245 // If the Language is the same return success
1247 if (CompareMem (LanguageStringLocation
, Language
, 6) == 0) {
1248 FreePool (InputString
);
1252 // Skip the first three letters that comprised the primary language,
1253 // see if what is being compared against is a secondary language
1255 InputString
= InputString
+ 3;
1258 // If the Language is not the same as the Primary language, see if there are any
1259 // secondary languages, and if there are see if we have a match. If not, return an error.
1261 for (Index
= 0; InputString
[Index
] != 0; Index
= Index
+ 3) {
1263 // Getting in here means we have a secondary language
1265 if (CompareMem (&InputString
[Index
], Language
, 6) == 0) {
1266 FreePool (InputString
);
1271 // If nothing was found, return the error
1273 FreePool (OriginalInputString
);
1274 return EFI_NOT_FOUND
;