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.
23 #include "HiiDatabase.h"
35 // Convert the ASCII Lang variable to a Unicode Language variable
37 for (Count
= 0; Count
< 3; Count
++) {
38 Language
[Count
] = (CHAR16
) Lang
[Count
];
45 IN EFI_HII_PROTOCOL
*This
,
46 IN CHAR16
*StringToTest
,
47 IN OUT UINT32
*FirstMissing
,
48 OUT UINT32
*GlyphBufferSize
53 Test if all of the characters in a string have corresponding font characters.
61 EFI_HII_GLOBAL_DATA
*GlobalData
;
62 EFI_HII_DATA
*HiiData
;
67 return EFI_INVALID_PARAMETER
;
70 HiiData
= EFI_HII_DATA_FROM_THIS (This
);
71 GlobalData
= HiiData
->GlobalData
;
75 // Rewind through the string looking for a glyph width identifier
76 // If no width identifier exists, we assume string has narrow width identifier
78 for (WideChar
= FALSE
, Location
= (INT32
) *FirstMissing
; Location
>= 0; Location
--) {
79 if ((StringToTest
[Location
] == NARROW_CHAR
) || (StringToTest
[Location
] == WIDE_CHAR
)) {
81 // We found something that identifies what glyph database to look in
83 WideChar
= (BOOLEAN
) (StringToTest
[Location
] == WIDE_CHAR
);
89 // Walk through the string until you hit the null terminator
91 for (*GlyphBufferSize
= 0; StringToTest
[*FirstMissing
] != CHAR_NULL
; (*FirstMissing
)++) {
93 // We found something that identifies what glyph database to look in
95 if ((StringToTest
[*FirstMissing
] == NARROW_CHAR
) || (StringToTest
[*FirstMissing
] == WIDE_CHAR
)) {
96 WideChar
= (BOOLEAN
) (StringToTest
[*FirstMissing
] == WIDE_CHAR
);
102 GlobalData
->NarrowGlyphs
[StringToTest
[*FirstMissing
]].GlyphCol1
,
104 NARROW_GLYPH_ARRAY_SIZE
108 // Break since this glyph isn't defined
110 return EFI_NOT_FOUND
;
114 // Can compare wide glyph against only GlyphCol1 since GlyphCol1 and GlyphCol2 are contiguous - just give correct size
117 GlobalData
->WideGlyphs
[StringToTest
[*FirstMissing
]].GlyphCol1
,
119 WIDE_GLYPH_ARRAY_SIZE
123 // Break since this glyph isn't defined
125 return EFI_NOT_FOUND
;
129 *GlyphBufferSize
+= (WideChar
? sizeof (EFI_WIDE_GLYPH
) : sizeof (EFI_NARROW_GLYPH
));
138 IN EFI_HII_PROTOCOL
*This
,
140 IN EFI_HII_HANDLE Handle
,
141 IN OUT STRING_REF
*Reference
,
142 IN CHAR16
*NewString
,
143 IN BOOLEAN ResetStrings
149 This function allows a new String to be added to an already existing String Package.
150 We will make a buffer the size of the package + EfiStrSize of the new string. We will
151 copy the string package that first gets changed and the following language packages until
152 we encounter the NULL string package. All this time we will ensure that the offsets have
157 This - Pointer to the HII protocol.
158 Language - Pointer to buffer which contains the language code of this NewString.
159 Handle - Handle of the package instance to be processed.
160 Reference - The token number for the string. If 0, new string token to be returned through this parameter.
161 NewString - Buffer pointer for the new string.
162 ResetStrings - Indicate if we are resetting a string.
166 EFI_SUCCESS - The string has been added or reset to Hii database.
167 EFI_INVALID_PARAMETER - Some parameter passed in is invalid.
171 EFI_HII_PACKAGE_INSTANCE
*PackageInstance
;
172 EFI_HII_PACKAGE_INSTANCE
*StringPackageInstance
;
173 EFI_HII_DATA
*HiiData
;
174 EFI_HII_STRING_PACK
*StringPack
;
175 EFI_HII_STRING_PACK
*NewStringPack
;
176 EFI_HII_HANDLE_DATABASE
*HandleDatabase
;
177 EFI_HII_PACKAGE_INSTANCE
*NewBuffer
;
179 UINT8
*StringLocation
;
180 RELOFST
*StringPointer
;
189 UINT32 TotalStringCount
;
190 UINT32 OriginalStringCount
;
196 return EFI_INVALID_PARAMETER
;
199 HiiData
= EFI_HII_DATA_FROM_THIS (This
);
201 HandleDatabase
= HiiData
->DatabaseHead
;
202 PackageInstance
= NULL
;
206 TotalStringCount
= 0;
207 OriginalStringCount
= 0;
210 // Check numeric value against the head of the database
212 for (; HandleDatabase
!= NULL
; HandleDatabase
= HandleDatabase
->NextHandleDatabase
) {
214 // Match the numeric value with the database entry - if matched, extract PackageInstance
216 if (Handle
== HandleDatabase
->Handle
) {
217 PackageInstance
= HandleDatabase
->Buffer
;
219 TotalStringCount
= HandleDatabase
->NumberOfTokens
;
225 // No handle was found - error condition
227 if (PackageInstance
== NULL
) {
228 return EFI_INVALID_PARAMETER
;
231 Status
= ValidatePack (This
, PackageInstance
, &StringPackageInstance
, &TotalStringCount
);
234 // This sets Count to 0 or the size of the IfrData. We intend to use Count as an offset value
236 Count
= StringPackageInstance
->IfrSize
;
239 // This is the size of the complete series of string packs
241 Size
= StringPackageInstance
->StringSize
;
244 // Based on if there is IFR data in this package instance, determine
245 // what the location is of the beginning of the string data.
247 if (StringPackageInstance
->IfrSize
> 0) {
248 Location
= (UINT8
*) (&StringPackageInstance
->IfrData
) + StringPackageInstance
->IfrSize
;
250 Location
= (UINT8
*) (&StringPackageInstance
->IfrData
);
253 // We allocate a buffer which is big enough for both adding and resetting string.
254 // The size is slightly larger than the real size of the packages when we are resetting a string.
256 NewBuffer
= AllocateZeroPool (
257 sizeof (EFI_HII_PACKAGE_INSTANCE
) -
258 2 * sizeof (VOID
*) +
259 StringPackageInstance
->IfrSize
+
260 StringPackageInstance
->StringSize
+
267 // Copy data to new buffer
269 NewBuffer
->Handle
= StringPackageInstance
->Handle
;
270 NewBuffer
->IfrSize
= StringPackageInstance
->IfrSize
;
273 // The worst case scenario for sizing is that we are adding a new string (not replacing one) and there was not a string
274 // package to begin with.
276 NewBuffer
->StringSize
= StringPackageInstance
->StringSize
+ StrSize (NewString
) + sizeof (EFI_HII_STRING_PACK
);
278 if (StringPackageInstance
->IfrSize
> 0) {
279 CopyMem (&NewBuffer
->IfrData
, &StringPackageInstance
->IfrData
, StringPackageInstance
->IfrSize
);
282 StringPack
= (EFI_HII_STRING_PACK
*) Location
;
285 // There may be multiple instances packed together of strings
286 // so we must walk the self describing structures until we encounter
287 // what we are looking for. In the meantime, copy everything we encounter
288 // to the new buffer.
290 CopyMem (&Length
, &StringPack
->Header
.Length
, sizeof (UINT32
));
291 for (; Length
!= 0;) {
293 // If passed in Language ISO value is in this string pack's language string
294 // then we are dealing with the strings we want.
296 CopyMem (&Offset
, &StringPack
->LanguageNameString
, sizeof (RELOFST
));
297 Status
= HiiCompareLanguage ((CHAR16
*) ((CHAR8
*) (StringPack
) + Offset
), Language
);
299 if (!EFI_ERROR (Status
)) {
303 CopyMem (((CHAR8
*) (&NewBuffer
->IfrData
) + Count
), StringPack
, Length
);
305 Count
= Count
+ Length
;
306 StringPack
= (EFI_HII_STRING_PACK
*) ((CHAR8
*) (StringPack
) + Length
);
307 CopyMem (&Length
, &StringPack
->Header
.Length
, sizeof (UINT32
));
310 // Found the language pack to update on a particular handle
311 // We need to Copy the Contents of this pack and adjust the offset values associated
312 // with adding/changing a string. This is a particular piece of code that screams for
313 // it being prone to programming error.
316 // Copy the string package up to the string data
318 StringPointer
= (RELOFST
*) (StringPack
+ 1);
320 ((CHAR8
*) (&NewBuffer
->IfrData
) + Count
),
322 (UINTN
) ((UINTN
) (StringPointer
) - (UINTN
) (StringPack
))
326 // Determine the number of StringPointers
329 CopyMem (&TotalStringCount
, &StringPack
->NumStringPointers
, sizeof (RELOFST
));
332 // If we are resetting the strings, use the original value when exported
334 CopyMem (&OriginalStringCount
, &StringPack
->NumStringPointers
, sizeof (RELOFST
));
335 ((EFI_HII_STRING_PACK
*) ((CHAR8
*) (&NewBuffer
->IfrData
) + Count
))->LanguageNameString
-=
337 (RELOFST
) (OriginalStringCount
- TotalStringCount
) *
340 ((EFI_HII_STRING_PACK
*) ((CHAR8
*) (&NewBuffer
->IfrData
) + Count
))->PrintableLanguageName
-=
342 (RELOFST
) (OriginalStringCount
- TotalStringCount
) *
345 ((EFI_HII_STRING_PACK
*) ((CHAR8
*) (&NewBuffer
->IfrData
) + Count
))->NumStringPointers
= TotalStringCount
;
346 *Reference
= (STRING_REF
) (TotalStringCount
);
349 // If the token value is not valid, error out
351 if ((*Reference
>= TotalStringCount
) && !ResetStrings
) {
352 FreePool (NewBuffer
);
353 return EFI_INVALID_PARAMETER
;
356 // If Reference is 0, update it with what the new token reference will be and turn the AddString flag on
358 if (*Reference
== 0) {
359 *Reference
= (STRING_REF
) (TotalStringCount
);
364 ((EFI_HII_STRING_PACK
*) ((CHAR8
*) (&NewBuffer
->IfrData
) + Count
))->LanguageNameString
+= sizeof (RELOFST
);
365 ((EFI_HII_STRING_PACK
*) ((CHAR8
*) (&NewBuffer
->IfrData
) + Count
))->PrintableLanguageName
+= sizeof (RELOFST
);
366 ((EFI_HII_STRING_PACK
*) ((CHAR8
*) (&NewBuffer
->IfrData
) + Count
))->NumStringPointers
++;
369 // Increment offset by amount of copied data
371 Count
= Count
+ ((UINTN
) (StringPointer
) - (UINTN
) StringPack
);
373 for (Index
= 0; Index
< TotalStringCount
; Index
++) {
375 // If we are pointing to the size of the changing string value
376 // then cache the old string value so you know what the difference is
378 if (Index
== *Reference
) {
379 CopyMem (&Offset
, &StringPointer
[Index
], sizeof (RELOFST
));
381 StringLocation
= ((UINT8
*) (StringPack
) + Offset
);
382 for (SecondIndex
= 0;
383 (StringLocation
[SecondIndex
] != 0) || (StringLocation
[SecondIndex
+ 1] != 0);
384 SecondIndex
= SecondIndex
+ 2
387 SecondIndex
= SecondIndex
+ 2;
392 // NewString is a passed in local string which is assumed to be aligned
394 Size
= StrSize (NewString
) - Size
;
397 // If we are about to copy the offset of the string that follows the changed string make
398 // sure that the offsets are adjusted accordingly
400 if ((Index
> *Reference
) && !ResetStrings
) {
401 CopyMem (&Offset
, &StringPointer
[Index
], sizeof (RELOFST
));
402 Offset
= (RELOFST
) (Offset
+ Size
);
403 CopyMem (&StringPointer
[Index
], &Offset
, sizeof (RELOFST
));
406 // If we are adding a string that means we will have an extra string pointer that will affect all string offsets
409 CopyMem (&Offset
, &StringPointer
[Index
], sizeof (RELOFST
));
410 Offset
= (UINT32
) (Offset
+ sizeof (RELOFST
));
411 CopyMem (&StringPointer
[Index
], &Offset
, sizeof (RELOFST
));
414 // If resetting the strings, we need to reduce the offset by the difference in the strings
417 CopyMem (&Length
, &StringPointer
[Index
], sizeof (RELOFST
));
418 Length
= Length
- ((RELOFST
) (OriginalStringCount
- TotalStringCount
) * sizeof (RELOFST
));
419 CopyMem (&StringPointer
[Index
], &Length
, sizeof (RELOFST
));
422 // Notice that if the string was being added as a new token, we don't have to worry about the
423 // offsets changing in the other indexes
425 CopyMem (((CHAR8
*) (&NewBuffer
->IfrData
) + Count
), &StringPointer
[Index
], sizeof (RELOFST
));
426 Count
= Count
+ sizeof (RELOFST
);
430 // If we are adding a new string the above for loop did not copy the offset for us
434 // Since the Index is pointing to the beginning of the first string, we need to gather the size of the previous
435 // offset's string and create an offset to our new string.
437 CopyMem (&Offset
, &StringPointer
[Index
- 1], sizeof (RELOFST
));
438 StringLocation
= (UINT8
*) StringPack
;
439 StringLocation
= StringLocation
+ Offset
- sizeof (RELOFST
);
442 // Since StringPack is a packed structure, we need to size it carefully (byte-wise) to avoid alignment issues
445 (StringLocation
[Length
] != 0) || (StringLocation
[Length
+ 1] != 0);
446 Length
= (RELOFST
) (Length
+ 2)
449 Length
= (RELOFST
) (Length
+ 2);
451 StringSize
= (RELOFST
) (Offset
+ Length
);
454 // Copy the new string offset
456 CopyMem (((CHAR8
*) (&NewBuffer
->IfrData
) + Count
), &StringSize
, sizeof (RELOFST
));
457 Count
= Count
+ sizeof (RELOFST
);
459 CopyMem (&Length
, &StringPack
->Header
.Length
, sizeof (UINT32
));
460 Length
= Length
+ sizeof (RELOFST
);
461 CopyMem (&StringPack
->Header
.Length
, &Length
, sizeof (UINT32
));
464 // Set Location to the First String
467 Index
= OriginalStringCount
;
470 // Set Location to the First String
472 Location
= (UINT8
*) &StringPointer
[Index
];
476 // Keep copying strings until you run into two CHAR16's in a row that are NULL
479 if ((*Reference
== Increment
) && !AddString
) {
480 StringLocation
= ((UINT8
*) (&NewBuffer
->IfrData
) + Count
);
481 CopyMem (StringLocation
, NewString
, StrSize (NewString
));
484 // Advance the destination location by Count number of bytes
486 Count
= Count
+ StrSize (NewString
);
489 // Add the difference between the new string and the old string to the length
491 CopyMem (&Length
, &StringPack
->Header
.Length
, sizeof (UINT32
));
494 // Since StringPack is a packed structure, we need to size it carefully (byte-wise) to avoid alignment issues
496 StringLocation
= (UINT8
*) &Location
[Index
];
498 (StringLocation
[Offset
] != 0) || (StringLocation
[Offset
+ 1] != 0);
499 Offset
= (RELOFST
) (Offset
+ 2)
502 Offset
= (RELOFST
) (Offset
+ 2);
504 Length
= Length
+ (UINT32
) StrSize (NewString
) - Offset
;
506 CopyMem (&StringPack
->Header
.Length
, &Length
, sizeof (UINT32
));
508 StringLocation
= (UINT8
*) &Location
[Index
];
510 (StringLocation
[Offset
] != 0) || (StringLocation
[Offset
+ 1] != 0);
511 Offset
= (RELOFST
) (Offset
+ 2)
514 Offset
= (RELOFST
) (Offset
+ 2);
516 CopyMem (((CHAR8
*) (&NewBuffer
->IfrData
) + Count
), StringLocation
, Offset
);
519 // Advance the destination location by Count number of bytes
521 Count
= Count
+ Offset
;
524 // Retrieve the number of characters to advance the index - should land at beginning of next string
526 Index
= Index
+ Offset
;
530 } while (StringCount
> 0);
533 // If we are adding a new string, then the above do/while will not suffice
536 Offset
= (RELOFST
) StrSize (NewString
);
537 CopyMem (((CHAR8
*) (&NewBuffer
->IfrData
) + Count
), NewString
, Offset
);
539 Count
= Count
+ StrSize (NewString
);
540 CopyMem (&Length
, &StringPack
->Header
.Length
, sizeof (UINT32
));
541 Length
= Length
+ (UINT32
) StrSize (NewString
);
542 CopyMem (&StringPack
->Header
.Length
, &Length
, sizeof (UINT32
));
547 // Skip the remainder of strings in the string package
549 StringCount
= OriginalStringCount
- TotalStringCount
;
551 while (StringCount
> 0) {
552 StringLocation
= (UINT8
*) &Location
[Index
];
554 (StringLocation
[Offset
] != 0) || (StringLocation
[Offset
+ 1] != 0);
555 Offset
= (RELOFST
) (Offset
+ 2)
558 Offset
= (RELOFST
) (Offset
+ 2);
559 Index
= Index
+ Offset
;
563 // Adjust the size of the string pack by the string size we just skipped.
564 // Also reduce the length by the size of a RelativeOffset value since we
565 // obviously would have skipped that as well.
567 CopyMem (&Length
, &StringPack
->Header
.Length
, sizeof (UINT32
));
568 Length
= Length
- Offset
- sizeof (RELOFST
);
569 CopyMem (&StringPack
->Header
.Length
, &Length
, sizeof (UINT32
));
573 StringPack
= (EFI_HII_STRING_PACK
*) &Location
[Index
];
575 CopyMem (&Length
, &StringPack
->Header
.Length
, sizeof (UINT32
));
576 for (; Length
!= 0;) {
578 CopyMem (((CHAR8
*) (&NewBuffer
->IfrData
) + Count
), StringPack
, Length
);
580 Count
= Count
+ Length
;
581 StringPack
= (EFI_HII_STRING_PACK
*) ((CHAR8
*) (StringPack
) + Length
);
582 CopyMem (&Length
, &StringPack
->Header
.Length
, sizeof (UINT32
));
585 // Copy the null terminator to the new buffer
587 CopyMem (((CHAR8
*) (&NewBuffer
->IfrData
) + Count
), StringPack
, sizeof (EFI_HII_STRING_PACK
));
590 // Based on if there is IFR data in this package instance, determine
591 // what the location is of the beginning of the string data.
593 if (StringPackageInstance
->IfrSize
> 0) {
594 Location
= (UINT8
*) (&StringPackageInstance
->IfrData
) + StringPackageInstance
->IfrSize
;
595 StringPack
= (EFI_HII_STRING_PACK
*) Location
;
596 Location
= (UINT8
*) (&NewBuffer
->IfrData
) + NewBuffer
->IfrSize
;
597 NewStringPack
= (EFI_HII_STRING_PACK
*) Location
;
599 StringPack
= (EFI_HII_STRING_PACK
*) (&StringPackageInstance
->IfrData
);
600 NewStringPack
= (EFI_HII_STRING_PACK
*) (&NewBuffer
->IfrData
);
603 CopyMem (&Length
, &StringPack
->Header
.Length
, sizeof (UINT32
));
604 for (; Length
!= 0;) {
606 // Since we updated the old version of the string data as we moved things over
607 // And we had a chicken-egg problem with the data we copied, let's post-fix the new
608 // buffer with accurate length data.
610 CopyMem (&Count
, &NewStringPack
->Header
.Length
, sizeof (UINT32
));
611 CopyMem (&NewStringPack
->Header
.Length
, &StringPack
->Header
.Length
, sizeof (UINT32
));
612 CopyMem (&StringPack
->Header
.Length
, &Count
, sizeof (UINT32
));
614 CopyMem (&Count
, &NewStringPack
->Header
.Length
, sizeof (UINT32
));
615 NewStringPack
= (EFI_HII_STRING_PACK
*) ((CHAR8
*) (NewStringPack
) + Count
);
616 CopyMem (&Count
, &StringPack
->Header
.Length
, sizeof (UINT32
));
617 StringPack
= (EFI_HII_STRING_PACK
*) ((CHAR8
*) (StringPack
) + Count
);
618 CopyMem (&Length
, &StringPack
->Header
.Length
, sizeof (UINT32
));
621 GetPackSize ((VOID
*) ((CHAR8
*) (&NewBuffer
->IfrData
) + NewBuffer
->IfrSize
), &NewBuffer
->StringSize
, NULL
);
624 // Search through the handles until the requested handle is found.
626 for (HandleDatabase
= HiiData
->DatabaseHead
;
627 HandleDatabase
->Handle
!= 0;
628 HandleDatabase
= HandleDatabase
->NextHandleDatabase
630 if (HandleDatabase
->Handle
== StringPackageInstance
->Handle
) {
632 // Free the previous buffer associated with this handle, and assign the new buffer to the handle
634 FreePool (HandleDatabase
->Buffer
);
635 HandleDatabase
->Buffer
= NewBuffer
;
646 IN EFI_HII_PROTOCOL
*This
,
648 IN EFI_HII_HANDLE Handle
,
649 IN OUT STRING_REF
*Reference
,
655 This function allows a new String to be added to an already existing String Package.
656 We will make a buffer the size of the package + StrSize of the new string. We will
657 copy the string package that first gets changed and the following language packages until
658 we encounter the NULL string package. All this time we will ensure that the offsets have
670 STRING_REF OriginalValue
;
674 // To avoid a warning 4 uninitialized variable warning
676 Status
= EFI_SUCCESS
;
678 Status
= HiiGetPrimaryLanguages (
684 if (!EFI_ERROR (Status
)) {
685 OriginalValue
= *Reference
;
687 if (Language
== NULL
) {
688 for (Index
= 0; LangCodes
[Index
] != 0; Index
+= 3) {
689 *Reference
= OriginalValue
;
690 CopyMem (Lang
, &LangCodes
[Index
], 6);
692 Status
= HiiNewString2 (
703 Status
= HiiNewString2 (
713 FreePool (LangCodes
);
722 IN EFI_HII_PROTOCOL
*This
,
723 IN EFI_HII_HANDLE Handle
729 This function removes any new strings that were added after the initial string export for this handle.
740 STRING_REF Reference
;
747 HiiGetPrimaryLanguages (
753 for (Index
= 0; LangCodes
[Index
] != 0; Index
+= 3) {
754 CopyMem (Lang
, &LangCodes
[Index
], 6);
756 Status
= HiiNewString2 (
764 ASSERT_EFI_ERROR (Status
);
767 FreePool (LangCodes
);
774 IN EFI_HII_PROTOCOL
*This
,
775 IN EFI_HII_HANDLE Handle
,
778 IN CHAR16
*LanguageString
,
779 IN OUT UINTN
*BufferLengthTemp
,
780 OUT EFI_STRING StringBuffer
786 This function extracts a string from a package already registered with the EFI HII database.
789 This - A pointer to the EFI_HII_PROTOCOL instance.
790 Handle - The HII handle on which the string resides.
791 Token - The string token assigned to the string.
792 Raw - If TRUE, the string is returned unedited in the internal storage format described
793 above. If false, the string returned is edited by replacing <cr> with <space>
794 and by removing special characters such as the <wide> prefix.
795 LanguageString - Pointer to a NULL-terminated string containing a single ISO 639-2 language
796 identifier, indicating the language to print. If the LanguageString is empty (starts
797 with a NULL), the default system language will be used to determine the language.
798 BufferLength - Length of the StringBuffer. If the status reports that the buffer width is too
799 small, this parameter is filled with the length of the buffer needed.
800 StringBuffer - The buffer designed to receive the characters in the string. Type EFI_STRING is
804 EFI_INVALID_PARAMETER - If input parameter is invalid.
805 EFI_BUFFER_TOO_SMALL - If the *BufferLength is too small.
806 EFI_SUCCESS - Operation is successful.
810 EFI_HII_PACKAGE_INSTANCE
*PackageInstance
;
811 EFI_HII_PACKAGE_INSTANCE
*StringPackageInstance
;
812 EFI_HII_DATA
*HiiData
;
813 EFI_HII_HANDLE_DATABASE
*HandleDatabase
;
814 EFI_HII_STRING_PACK
*StringPack
;
815 RELOFST
*StringPointer
;
829 UINT16
*BufferLength
= (UINT16
*) BufferLengthTemp
;
832 return EFI_INVALID_PARAMETER
;
837 DataSize
= sizeof (Lang
);
839 HiiData
= EFI_HII_DATA_FROM_THIS (This
);
841 PackageInstance
= NULL
;
843 Narrow
= NARROW_CHAR
;
845 NoBreak
= NON_BREAKING_CHAR
;
848 // Check numeric value against the head of the database
850 for (HandleDatabase
= HiiData
->DatabaseHead
;
851 HandleDatabase
!= NULL
;
852 HandleDatabase
= HandleDatabase
->NextHandleDatabase
855 // Match the numeric value with the database entry - if matched, extract PackageInstance
857 if (Handle
== HandleDatabase
->Handle
) {
858 PackageInstance
= HandleDatabase
->Buffer
;
863 // No handle was found - error condition
865 if (PackageInstance
== NULL
) {
866 return EFI_INVALID_PARAMETER
;
869 Status
= ValidatePack (This
, PackageInstance
, &StringPackageInstance
, NULL
);
872 // If there is no specified language, assume the system default language
874 if (LanguageString
== NULL
) {
876 // Get system default language
878 Status
= gRT
->GetVariable (
880 &gEfiGlobalVariableGuid
,
886 if (EFI_ERROR (Status
)) {
888 // If Lang doesn't exist, just use the first language you find
894 // Convert the ASCII Lang variable to a Unicode Language variable
896 AsciiToUnicode ((UINT8
*)Lang
, Language
);
899 // Copy input ISO value to Language variable
901 CopyMem (Language
, LanguageString
, 6);
904 // Based on if there is IFR data in this package instance, determine
905 // what the location is of the beginning of the string data.
908 if (StringPackageInstance
->IfrSize
> 0) {
909 StringPack
= (EFI_HII_STRING_PACK
*) ((CHAR8
*) (&StringPackageInstance
->IfrData
) + StringPackageInstance
->IfrSize
);
911 StringPack
= (EFI_HII_STRING_PACK
*) (&StringPackageInstance
->IfrData
);
914 // If Token is 0, extract entire string package
918 // Compute the entire string pack length, including all languages' and the terminating pack's.
921 while (0 != StringPack
->Header
.Length
) {
922 Length
+= StringPack
->Header
.Length
;
923 StringPack
= (VOID
*)(((UINT8
*)StringPack
) + StringPack
->Header
.Length
);
926 // Back to the start of package.
928 StringPack
= (VOID
*)(((UINT8
*)StringPack
) - Length
);
930 // Terminating zero sub-pack.
932 Length
+= sizeof (EFI_HII_STRING_PACK
);
935 // If trying to get the entire string package and have insufficient space. Return error.
937 if (Length
> *BufferLength
|| StringBuffer
== NULL
) {
938 *BufferLength
= (UINT16
)Length
;
939 return EFI_BUFFER_TOO_SMALL
;
942 // Copy the Pack to the caller's buffer.
944 *BufferLength
= (UINT16
)Length
;
945 CopyMem (StringBuffer
, StringPack
, Length
);
950 // There may be multiple instances packed together of strings
951 // so we must walk the self describing structures until we encounter
952 // what we are looking for, and then extract the string we are looking for
954 CopyMem (&Length
, &StringPack
->Header
.Length
, sizeof (UINT32
));
955 for (; Length
!= 0;) {
957 // If passed in Language ISO value is in this string pack's language string
958 // then we are dealing with the strings we want.
960 CopyMem (&Offset
, &StringPack
->LanguageNameString
, sizeof (RELOFST
));
961 Status
= HiiCompareLanguage ((CHAR16
*) ((CHAR8
*) (StringPack
) + Offset
), Language
);
964 // If we cannot find the lang variable, we skip this check and use the first language available
967 if (EFI_ERROR (Status
)) {
968 StringPack
= (EFI_HII_STRING_PACK
*) ((CHAR8
*) (StringPack
) + Length
);
969 CopyMem (&Length
, &StringPack
->Header
.Length
, sizeof (UINT32
));
974 StringPointer
= (RELOFST
*) (StringPack
+ 1);
977 // We have the right string package - size it, and copy it to the StringBuffer
979 if (Token
>= StringPack
->NumStringPointers
) {
980 return EFI_INVALID_PARAMETER
;
982 CopyMem (&Offset
, &StringPointer
[Token
], sizeof (RELOFST
));
985 // Since StringPack is a packed structure, we need to determine the string's
986 // size safely, thus byte-wise. Post-increment the size to include the null-terminator
988 Local
= (UINT16
*) ((CHAR8
*) (StringPack
) + Offset
);
989 for (Count
= 0; CompareMem (&Local
[Count
], &Zero
, 2); Count
++)
993 Count
= Count
* sizeof (CHAR16
);;
995 if (*BufferLength
>= Count
&& StringBuffer
!= NULL
) {
997 // Copy the string to the user's buffer
1000 CopyMem (StringBuffer
, Local
, Count
);
1002 for (Count
= 0; CompareMem (Local
, &Zero
, 2); Local
++) {
1004 // Skip "Narraw, Wide, NoBreak"
1006 if (CompareMem (Local
, &Narrow
, 2) &&
1007 CompareMem (Local
, &Wide
, 2) &&
1008 CompareMem (Local
, &NoBreak
, 2)) {
1009 CopyMem (&StringBuffer
[Count
++], Local
, 2);
1013 // Add "NULL" at the end.
1015 CopyMem (&StringBuffer
[Count
], &Zero
, 2);
1017 Count
*= sizeof (CHAR16
);
1020 *BufferLength
= (UINT16
) Count
;
1023 *BufferLength
= (UINT16
) Count
;
1024 return EFI_BUFFER_TOO_SMALL
;
1036 IN EFI_HII_PROTOCOL
*This
,
1037 IN EFI_HII_HANDLE Handle
,
1038 IN STRING_REF Token
,
1039 IN OUT UINT16
*Index
,
1040 IN UINT16 LineWidth
,
1041 IN CHAR16
*LanguageString
,
1042 IN OUT UINT16
*BufferLength
,
1043 OUT EFI_STRING StringBuffer
1047 Routine Description:
1049 This function allows a program to extract a part of a string of not more than a given width.
1050 With repeated calls, this allows a calling program to extract "lines" of text that fit inside
1051 columns. The effort of measuring the fit of strings inside columns is localized to this call.
1060 EFI_HII_PACKAGE_INSTANCE
*PackageInstance
;
1061 EFI_HII_PACKAGE_INSTANCE
*StringPackageInstance
;
1062 EFI_HII_DATA
*HiiData
;
1063 EFI_HII_HANDLE_DATABASE
*HandleDatabase
;
1064 EFI_HII_STRING_PACK
*StringPack
;
1065 RELOFST
*StringPointer
;
1073 return EFI_INVALID_PARAMETER
;
1076 HiiData
= EFI_HII_DATA_FROM_THIS (This
);
1078 HandleDatabase
= HiiData
->DatabaseHead
;
1080 PackageInstance
= NULL
;
1084 // Check numeric value against the head of the database
1086 for (; HandleDatabase
!= NULL
; HandleDatabase
= HandleDatabase
->NextHandleDatabase
) {
1088 // Match the numeric value with the database entry - if matched, extract PackageInstance
1090 if (Handle
== HandleDatabase
->Handle
) {
1091 PackageInstance
= HandleDatabase
->Buffer
;
1095 // No handle was found - error condition
1097 if (PackageInstance
== NULL
) {
1098 return EFI_INVALID_PARAMETER
;
1101 Status
= ValidatePack (This
, PackageInstance
, &StringPackageInstance
, NULL
);
1104 // If there is no specified language, assume the system default language
1106 if (LanguageString
== NULL
) {
1108 // Get system default language
1110 Status
= gRT
->GetVariable (
1112 &gEfiGlobalVariableGuid
,
1118 if (EFI_ERROR (Status
)) {
1122 // Convert the ASCII Lang variable to a Unicode Language variable
1124 AsciiToUnicode ((UINT8
*)Lang
, Language
);
1127 // Copy input ISO value to Language variable
1129 CopyMem (Language
, LanguageString
, 6);
1132 // Based on if there is IFR data in this package instance, determine
1133 // what the location is of the beginning of the string data.
1135 if (StringPackageInstance
->IfrSize
> 0) {
1136 StringPack
= (EFI_HII_STRING_PACK
*) ((CHAR8
*) (&StringPackageInstance
->IfrData
) + StringPackageInstance
->IfrSize
);
1138 StringPack
= (EFI_HII_STRING_PACK
*) (&StringPackageInstance
->IfrData
);
1141 StringPointer
= (RELOFST
*) (StringPack
+ 1);
1144 // There may be multiple instances packed together of strings
1145 // so we must walk the self describing structures until we encounter
1146 // what we are looking for, and then extract the string we are looking for
1148 for (; StringPack
->Header
.Length
!= 0;) {
1150 // If passed in Language ISO value is in this string pack's language string
1151 // then we are dealing with the strings we want.
1153 Status
= HiiCompareLanguage ((CHAR16
*) ((CHAR8
*) (StringPack
) + StringPack
->LanguageNameString
), Language
);
1155 if (EFI_ERROR (Status
)) {
1156 StringPack
= (EFI_HII_STRING_PACK
*) ((CHAR8
*) (StringPack
) + StringPack
->Header
.Length
);
1160 Location
= (CHAR16
*) ((CHAR8
*) (StringPack
) + StringPointer
[Token
] +*Index
* 2);
1163 // If the size of the remaining string is less than the LineWidth
1164 // then copy the entire thing
1166 if (StrSize (Location
) <= LineWidth
) {
1167 if (*BufferLength
>= StrSize (Location
)) {
1168 StrCpy (StringBuffer
, Location
);
1171 *BufferLength
= (UINT16
) StrSize (Location
);
1172 return EFI_BUFFER_TOO_SMALL
;
1176 // Rewind the string from the maximum size until we see a space the break the line
1178 for (Count
= LineWidth
; Location
[Count
] != 0x0020; Count
--)
1182 // Put the index at the next character
1184 *Index
= (UINT16
) (Count
+ 1);
1186 if (*BufferLength
>= Count
) {
1187 StrnCpy (StringBuffer
, Location
, Count
);
1190 *BufferLength
= (UINT16
) Count
;
1191 return EFI_BUFFER_TOO_SMALL
;
1200 HiiCompareLanguage (
1201 IN CHAR16
*LanguageStringLocation
,
1207 CHAR16
*InputString
;
1208 CHAR16
*OriginalInputString
;
1211 // Allocate a temporary buffer for InputString
1213 InputString
= AllocateZeroPool (0x100);
1215 ASSERT (InputString
);
1217 OriginalInputString
= InputString
;
1219 Local
= (UINT8
*) LanguageStringLocation
;
1222 // Determine the size of this packed string safely (e.g. access by byte), post-increment
1223 // to include the null-terminator
1225 for (Index
= 0; Local
[Index
] != 0; Index
= Index
+ 2)
1228 // MARMAR Index = Index + 2;
1230 // This is a packed structure that this location comes from, so let's make sure
1231 // the value is aligned by copying it to a local variable and working on it.
1233 CopyMem (InputString
, LanguageStringLocation
, Index
);
1235 for (Index
= 0; Index
< 3; Index
++) {
1236 InputString
[Index
] = (CHAR16
) (InputString
[Index
] | 0x20);
1237 Language
[Index
] = (CHAR16
) (Language
[Index
] | 0x20);
1240 // If the Language is the same return success
1242 if (CompareMem (LanguageStringLocation
, Language
, 6) == 0) {
1243 FreePool (InputString
);
1247 // Skip the first three letters that comprised the primary language,
1248 // see if what is being compared against is a secondary language
1250 InputString
= InputString
+ 3;
1253 // If the Language is not the same as the Primary language, see if there are any
1254 // secondary languages, and if there are see if we have a match. If not, return an error.
1256 for (Index
= 0; InputString
[Index
] != 0; Index
= Index
+ 3) {
1258 // Getting in here means we have a secondary language
1260 if (CompareMem (&InputString
[Index
], Language
, 6) == 0) {
1261 FreePool (InputString
);
1266 // If nothing was found, return the error
1268 FreePool (OriginalInputString
);
1269 return EFI_NOT_FOUND
;