sync patch r11075, r11087, r11088, r11091, r11092, r11119 from main trunk.
Fix AutoUpdateLangVariable() logic to handle the case PlatformLang/Lang is set before PlatformLangCodes/LangCodes.
Pre-allocate pool for runtime phase.

git-svn-id: https://edk2.svn.sourceforge.net/svnroot/edk2/branches/UDK2008@13050 6f19259b-4bc3-4df7-8a09-765794883524
diff --git a/DuetPkg/FSVariable/FSVariable.c b/DuetPkg/FSVariable/FSVariable.c
index f3d5203..b38de46 100644
--- a/DuetPkg/FSVariable/FSVariable.c
+++ b/DuetPkg/FSVariable/FSVariable.c
@@ -1,6 +1,6 @@
 /*++

 

-Copyright (c) 2006 - 2007, Intel Corporation

+Copyright (c) 2006 - 2012, Intel Corporation

 All rights reserved. This program and the accompanying materials

 are licensed and made available under the terms and conditions of the BSD License

 which accompanies this distribution.  The full text of the license may be found at

@@ -576,7 +576,6 @@
 

 **/

 UINTN

-EFIAPI

 GetIndexFromSupportedLangCodes(

   IN  CHAR8            *SupportedLang,

   IN  CHAR8            *Lang,

@@ -584,13 +583,11 @@
   ) 

 {

   UINTN    Index;

-  UINT32   CompareLength;

-  CHAR8    *Supported;

+  UINTN    CompareLength;

+  UINTN    LanguageLength;

 

-  Index = 0;

-  Supported = SupportedLang;

   if (Iso639Language) {

-    CompareLength = 3;

+    CompareLength = ISO_639_2_ENTRY_SIZE;

     for (Index = 0; Index < AsciiStrLen (SupportedLang); Index += CompareLength) {

       if (AsciiStrnCmp (Lang, SupportedLang + Index, CompareLength) == 0) {

         //

@@ -606,20 +603,26 @@
     //

     // Compare RFC4646 language code

     //

-    while (*Supported != '\0') {

+    Index = 0;

+    for (LanguageLength = 0; Lang[LanguageLength] != '\0'; LanguageLength++);

+

+    for (Index = 0; *SupportedLang != '\0'; Index++, SupportedLang += CompareLength) {

       //

-      // take semicolon as delimitation, sequentially traverse supported language codes.

+      // Skip ';' characters in SupportedLang

       //

-      for (CompareLength = 0; *Supported != ';' && *Supported != '\0'; CompareLength++) {

-        Supported++;

-      }

-      if (AsciiStrnCmp (Lang, Supported - CompareLength, CompareLength) == 0) {

+      for (; *SupportedLang != '\0' && *SupportedLang == ';'; SupportedLang++);

+      //

+      // Determine the length of the next language code in SupportedLang

+      //

+      for (CompareLength = 0; SupportedLang[CompareLength] != '\0' && SupportedLang[CompareLength] != ';'; CompareLength++);

+      

+      if ((CompareLength == LanguageLength) && 

+          (AsciiStrnCmp (Lang, SupportedLang, CompareLength) == 0)) {

         //

         // Successfully find the index of Lang string in SupportedLang string.

         //

         return Index;

       }

-      Index++;

     }

     ASSERT (FALSE);

     return 0;

@@ -653,7 +656,6 @@
 

 **/

 CHAR8 *

-EFIAPI

 GetLangFromSupportedLangCodes (

   IN  CHAR8            *SupportedLang,

   IN  UINTN            Index,

@@ -661,7 +663,7 @@
 )

 {

   UINTN    SubIndex;

-  UINT32   CompareLength;

+  UINTN    CompareLength;

   CHAR8    *Supported;

 

   SubIndex  = 0;

@@ -672,10 +674,10 @@
     // As this code will be invoked in RUNTIME, therefore there is not memory allocate/free operation.

     // In driver entry, it pre-allocates a runtime attribute memory to accommodate this string.

     //

-    CompareLength = 3;

-    SetMem (mGlobal->Lang, sizeof(mGlobal->Lang), 0);

+    CompareLength = ISO_639_2_ENTRY_SIZE;

+    mGlobal->Lang[CompareLength] = '\0';

     return CopyMem (mGlobal->Lang, SupportedLang + Index * CompareLength, CompareLength);

-      

+

   } else {

     while (TRUE) {

       //

@@ -698,15 +700,151 @@
         // As this code will be invoked in RUNTIME, therefore there is not memory allocate/free operation.

         // In driver entry, it pre-allocates a runtime attribute memory to accommodate this string.

         //

-        SetMem (mGlobal->PlatformLang, sizeof (mGlobal->PlatformLang), 0);

+        mGlobal->PlatformLang[CompareLength] = '\0';

         return CopyMem (mGlobal->PlatformLang, Supported - CompareLength, CompareLength);

       }

       SubIndex++;

+

+      //

+      // Skip ';' characters in Supported

+      //

+      for (; *Supported != '\0' && *Supported == ';'; Supported++);

     }

   }

 }

 

 /**

+  Returns a pointer to an allocated buffer that contains the best matching language 

+  from a set of supported languages.  

+  

+  This function supports both ISO 639-2 and RFC 4646 language codes, but language 

+  code types may not be mixed in a single call to this function. This function

+  supports a variable argument list that allows the caller to pass in a prioritized

+  list of language codes to test against all the language codes in SupportedLanguages.

+

+  If SupportedLanguages is NULL, then ASSERT().

+

+  @param[in]  SupportedLanguages  A pointer to a Null-terminated ASCII string that

+                                  contains a set of language codes in the format 

+                                  specified by Iso639Language.

+  @param[in]  Iso639Language      If TRUE, then all language codes are assumed to be

+                                  in ISO 639-2 format.  If FALSE, then all language

+                                  codes are assumed to be in RFC 4646 language format

+  @param[in]  ...                 A variable argument list that contains pointers to 

+                                  Null-terminated ASCII strings that contain one or more

+                                  language codes in the format specified by Iso639Language.

+                                  The first language code from each of these language

+                                  code lists is used to determine if it is an exact or

+                                  close match to any of the language codes in 

+                                  SupportedLanguages.  Close matches only apply to RFC 4646

+                                  language codes, and the matching algorithm from RFC 4647

+                                  is used to determine if a close match is present.  If 

+                                  an exact or close match is found, then the matching

+                                  language code from SupportedLanguages is returned.  If

+                                  no matches are found, then the next variable argument

+                                  parameter is evaluated.  The variable argument list 

+                                  is terminated by a NULL.

+

+  @retval NULL   The best matching language could not be found in SupportedLanguages.

+  @retval NULL   There are not enough resources available to return the best matching 

+                 language.

+  @retval Other  A pointer to a Null-terminated ASCII string that is the best matching 

+                 language in SupportedLanguages.

+

+**/

+CHAR8 *

+EFIAPI

+VariableGetBestLanguage (

+  IN CONST CHAR8  *SupportedLanguages, 

+  IN BOOLEAN      Iso639Language,

+  ...

+  )

+{

+  VA_LIST      Args;

+  CHAR8        *Language;

+  UINTN        CompareLength;

+  UINTN        LanguageLength;

+  CONST CHAR8  *Supported;

+  CHAR8        *Buffer;

+

+  ASSERT (SupportedLanguages != NULL);

+

+  VA_START (Args, Iso639Language);

+  while ((Language = VA_ARG (Args, CHAR8 *)) != NULL) {

+    //

+    // Default to ISO 639-2 mode

+    //

+    CompareLength  = 3;

+    LanguageLength = MIN (3, AsciiStrLen (Language));

+

+    //

+    // If in RFC 4646 mode, then determine the length of the first RFC 4646 language code in Language

+    //

+    if (!Iso639Language) {

+      for (LanguageLength = 0; Language[LanguageLength] != 0 && Language[LanguageLength] != ';'; LanguageLength++);

+    }

+

+    //

+    // Trim back the length of Language used until it is empty

+    //

+    while (LanguageLength > 0) {

+      //

+      // Loop through all language codes in SupportedLanguages

+      //

+      for (Supported = SupportedLanguages; *Supported != '\0'; Supported += CompareLength) {

+        //

+        // In RFC 4646 mode, then Loop through all language codes in SupportedLanguages

+        //

+        if (!Iso639Language) {

+          //

+          // Skip ';' characters in Supported

+          //

+          for (; *Supported != '\0' && *Supported == ';'; Supported++);

+          //

+          // Determine the length of the next language code in Supported

+          //

+          for (CompareLength = 0; Supported[CompareLength] != 0 && Supported[CompareLength] != ';'; CompareLength++);

+          //

+          // If Language is longer than the Supported, then skip to the next language

+          //

+          if (LanguageLength > CompareLength) {

+            continue;

+          }

+        }

+        //

+        // See if the first LanguageLength characters in Supported match Language

+        //

+        if (AsciiStrnCmp (Supported, Language, LanguageLength) == 0) {

+          VA_END (Args);

+

+          Buffer = Iso639Language ? mGlobal->Lang : mGlobal->PlatformLang;

+          Buffer[CompareLength] = '\0';

+          return CopyMem (Buffer, Supported, CompareLength);

+        }

+      }

+

+      if (Iso639Language) {

+        //

+        // If ISO 639 mode, then each language can only be tested once

+        //

+        LanguageLength = 0;

+      } else {

+        //

+        // If RFC 4646 mode, then trim Language from the right to the next '-' character 

+        //

+        for (LanguageLength--; LanguageLength > 0 && Language[LanguageLength] != '-'; LanguageLength--);

+      }

+    }

+  }

+  VA_END (Args);

+

+  //

+  // No matches were found 

+  //

+  return NULL;

+}

+

+/**

   Hook the operations in PlatformLangCodes, LangCodes, PlatformLang and Lang.

 

   When setting Lang/LangCodes, simultaneously update PlatformLang/PlatformLangCodes.

@@ -720,101 +858,186 @@
 

   @param[in] DataSize           Size of data. 0 means delete

 

-  @retval EFI_SUCCESS  auto update operation is successful.

-

 **/

-EFI_STATUS

-EFIAPI

+VOID

 AutoUpdateLangVariable(

   IN  CHAR16             *VariableName,

   IN  VOID               *Data,

   IN  UINTN              DataSize

   )

 {

-  EFI_STATUS     Status;

-  CHAR8          *BestPlatformLang;

-  CHAR8          *BestLang;

-  UINTN          Index;

-  UINT32         Attributes;

+  EFI_STATUS             Status;

+  CHAR8                  *BestPlatformLang;

+  CHAR8                  *BestLang;

+  UINTN                  Index;

+  UINT32                 Attributes;

   VARIABLE_POINTER_TRACK Variable;

+  BOOLEAN                SetLanguageCodes;

 

   //

+  // Don't do updates for delete operation

+  //

+  if (DataSize == 0) {

+    return;

+  }

+

+  SetLanguageCodes = FALSE;

+

+  if (StrCmp (VariableName, L"PlatformLangCodes") == 0) {

+    //

+    // PlatformLangCodes is a volatile variable, so it can not be updated at runtime.

+    //

+    if (EfiAtRuntime ()) {

+      return;

+    }

+

+    SetLanguageCodes = TRUE;

+

+    //

+    // According to UEFI spec, PlatformLangCodes is only set once in firmware initialization, and is read-only

+    // Therefore, in variable driver, only store the original value for other use.

+    //

+    if (mGlobal->PlatformLangCodes != NULL) {

+      FreePool (mGlobal->PlatformLangCodes);

+    }

+    mGlobal->PlatformLangCodes = AllocateRuntimeCopyPool (DataSize, Data);

+    ASSERT (mGlobal->PlatformLangCodes != NULL);

+

+    //

+    // PlatformLang holds a single language from PlatformLangCodes, 

+    // so the size of PlatformLangCodes is enough for the PlatformLang.

+    //

+    if (mGlobal->PlatformLang != NULL) {

+      FreePool (mGlobal->PlatformLang);

+    }

+    mGlobal->PlatformLang = AllocateRuntimePool (DataSize);

+    ASSERT (mGlobal->PlatformLang != NULL);

+

+  } else if (StrCmp (VariableName, L"LangCodes") == 0) {

+    //

+    // LangCodes is a volatile variable, so it can not be updated at runtime.

+    //

+    if (EfiAtRuntime ()) {

+      return;

+    }

+

+    SetLanguageCodes = TRUE;

+

+    //

+    // According to UEFI spec, LangCodes is only set once in firmware initialization, and is read-only

+    // Therefore, in variable driver, only store the original value for other use.

+    //

+    if (mGlobal->LangCodes != NULL) {

+      FreePool (mGlobal->LangCodes);

+    }

+    mGlobal->LangCodes = AllocateRuntimeCopyPool (DataSize, Data);

+    ASSERT (mGlobal->LangCodes != NULL);

+  }

+

+  if (SetLanguageCodes 

+      && (mGlobal->PlatformLangCodes != NULL)

+      && (mGlobal->LangCodes != NULL)) {

+    //

+    // Update Lang if PlatformLang is already set

+    // Update PlatformLang if Lang is already set

+    //

+    Status = FindVariable (L"PlatformLang", &gEfiGlobalVariableGuid, &Variable);

+    if (!EFI_ERROR (Status)) {

+      //

+      // Update Lang

+      //

+      VariableName = L"PlatformLang";

+      Data         = GetVariableDataPtr (Variable.CurrPtr);

+      DataSize     = Variable.CurrPtr->DataSize;

+    } else {

+      Status = FindVariable (L"Lang", &gEfiGlobalVariableGuid, &Variable);

+      if (!EFI_ERROR (Status)) {

+        //

+        // Update PlatformLang

+        //

+        VariableName = L"Lang";

+        Data         = GetVariableDataPtr (Variable.CurrPtr);

+        DataSize     = Variable.CurrPtr->DataSize;

+      } else {

+        //

+        // Neither PlatformLang nor Lang is set, directly return

+        //

+        return;

+      }

+    }

+  }

+  

+  //

   // According to UEFI spec, "Lang" and "PlatformLang" is NV|BS|RT attributions.

   //

   Attributes = EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS;

 

-  if (StrCmp (VariableName, L"PlatformLangCodes") == 0) {

+  if (StrCmp (VariableName, L"PlatformLang") == 0) {

     //

-    // According to UEFI spec, PlatformLangCodes is only set once in firmware initialization, and is read-only

-    // Therefore, in variable driver, only store the original value for other use.

+    // Update Lang when PlatformLangCodes/LangCodes were set.

     //

-    AsciiStrnCpy (mGlobal->PlatformLangCodes, Data, DataSize);

-  } else if (StrCmp (VariableName, L"LangCodes") == 0) {

-    //

-    // According to UEFI spec, LangCodes is only set once in firmware initialization, and is read-only

-    // Therefore, in variable driver, only store the original value for other use.

-    //

-    AsciiStrnCpy (mGlobal->LangCodes, Data, DataSize);

-  } else if (StrCmp (VariableName, L"PlatformLang") == 0) {

-    ASSERT (AsciiStrLen (mGlobal->PlatformLangCodes) != 0);

+    if ((mGlobal->PlatformLangCodes != NULL) && (mGlobal->LangCodes != NULL)) {

+      //

+      // When setting PlatformLang, firstly get most matched language string from supported language codes.

+      //

+      BestPlatformLang = VariableGetBestLanguage (mGlobal->PlatformLangCodes, FALSE, Data, NULL);

+      if (BestPlatformLang != NULL) {

+        //

+        // Get the corresponding index in language codes.

+        //

+        Index = GetIndexFromSupportedLangCodes (mGlobal->PlatformLangCodes, BestPlatformLang, FALSE);

 

-    //

-    // When setting PlatformLang, firstly get most matched language string from supported language codes.

-    //

-    BestPlatformLang = GetBestLanguage(mGlobal->PlatformLangCodes, FALSE, Data, NULL);

+        //

+        // Get the corresponding ISO639 language tag according to RFC4646 language tag.

+        //

+        BestLang = GetLangFromSupportedLangCodes (mGlobal->LangCodes, Index, TRUE);

 

-    //

-    // Get the corresponding index in language codes.

-    //

-    Index = GetIndexFromSupportedLangCodes(mGlobal->PlatformLangCodes, BestPlatformLang, FALSE);

+        //

+        // Successfully convert PlatformLang to Lang, and set the BestLang value into Lang variable simultaneously.

+        //

+        FindVariable(L"Lang", &gEfiGlobalVariableGuid, &Variable);

 

-    //

-    // Get the corresponding ISO639 language tag according to RFC4646 language tag.

-    //

-    BestLang = GetLangFromSupportedLangCodes(mGlobal->LangCodes, Index, TRUE);

+        Status = UpdateVariable (L"Lang", &gEfiGlobalVariableGuid, BestLang, ISO_639_2_ENTRY_SIZE + 1, Attributes, &Variable);

 

-    //

-    // Successfully convert PlatformLang to Lang, and set the BestLang value into Lang variable simultaneously.

-    //

-    FindVariable(L"Lang", &gEfiGlobalVariableGuid, &Variable);

+        DEBUG ((EFI_D_INFO, "Variable Driver Auto Update PlatformLang, PlatformLang:%a, Lang:%a\n", BestPlatformLang, BestLang));

 

-    Status = UpdateVariable(L"Lang", &gEfiGlobalVariableGuid, 

-                    BestLang, ISO_639_2_ENTRY_SIZE + 1, Attributes, &Variable);

+        ASSERT_EFI_ERROR(Status);

+      }

+    }

 

-    DEBUG((EFI_D_INFO, "Variable Driver Auto Update PlatformLang, PlatformLang:%a, Lang:%a\n", BestPlatformLang, BestLang));

-

-    ASSERT_EFI_ERROR(Status);

-    

   } else if (StrCmp (VariableName, L"Lang") == 0) {

-    ASSERT (AsciiStrLen (mGlobal->LangCodes) != 0);

+    //

+    // Update PlatformLang when PlatformLangCodes/LangCodes were set.

+    //

+    if ((mGlobal->PlatformLangCodes != NULL) && (mGlobal->LangCodes != NULL)) {

+      //

+      // When setting Lang, firstly get most matched language string from supported language codes.

+      //

+      BestLang = VariableGetBestLanguage (mGlobal->LangCodes, TRUE, Data, NULL);

+      if (BestLang != NULL) {

+        //

+        // Get the corresponding index in language codes.

+        //

+        Index = GetIndexFromSupportedLangCodes (mGlobal->LangCodes, BestLang, TRUE);

 

-    //

-    // When setting Lang, firstly get most matched language string from supported language codes.

-    //

-    BestLang = GetBestLanguage(mGlobal->LangCodes, TRUE, Data, NULL);

+        //

+        // Get the corresponding RFC4646 language tag according to ISO639 language tag.

+        //

+        BestPlatformLang = GetLangFromSupportedLangCodes (mGlobal->PlatformLangCodes, Index, FALSE);

 

-    //

-    // Get the corresponding index in language codes.

-    //

-    Index = GetIndexFromSupportedLangCodes(mGlobal->LangCodes, BestLang, TRUE);

+        //

+        // Successfully convert Lang to PlatformLang, and set the BestPlatformLang value into PlatformLang variable simultaneously.

+        //

+        FindVariable(L"PlatformLang", &gEfiGlobalVariableGuid, &Variable);

 

-    //

-    // Get the corresponding RFC4646 language tag according to ISO639 language tag.

-    //

-    BestPlatformLang = GetLangFromSupportedLangCodes(mGlobal->PlatformLangCodes, Index, FALSE);

+        Status = UpdateVariable (L"PlatformLang", &gEfiGlobalVariableGuid, BestPlatformLang, 

+                                 AsciiStrSize (BestPlatformLang), Attributes, &Variable);

 

-    //

-    // Successfully convert Lang to PlatformLang, and set the BestPlatformLang value into PlatformLang variable simultaneously.

-    //

-    FindVariable(L"PlatformLang", &gEfiGlobalVariableGuid, &Variable);

-

-    Status = UpdateVariable(L"PlatformLang", &gEfiGlobalVariableGuid, 

-                    BestPlatformLang, AsciiStrSize (BestPlatformLang), Attributes, &Variable);

-

-    DEBUG((EFI_D_INFO, "Variable Driver Auto Update Lang, Lang:%a, PlatformLang:%a\n", BestLang, BestPlatformLang));

-    ASSERT_EFI_ERROR(Status);

+        DEBUG ((EFI_D_INFO, "Variable Driver Auto Update Lang, Lang:%a, PlatformLang:%a\n", BestLang, BestPlatformLang));

+        ASSERT_EFI_ERROR (Status);

+      }

+    }

   }

-  return EFI_SUCCESS;

 }

 

 /**

@@ -1708,6 +1931,9 @@
     EfiConvertPointer (0, (VOID**) &mGlobal->VariableStore[Index]);

     EfiConvertPointer (0, &mGlobal->VariableBase[Index]);

   }

+  EfiConvertPointer (0, (VOID **) &mGlobal->PlatformLangCodes);

+  EfiConvertPointer (0, (VOID **) &mGlobal->LangCodes);

+  EfiConvertPointer (0, (VOID **) &mGlobal->PlatformLang);

   EfiConvertPointer (0, &mGlobal->Scratch);

   EfiConvertPointer (0, (VOID**) &mGlobal);

 }

diff --git a/DuetPkg/FSVariable/FSVariable.h b/DuetPkg/FSVariable/FSVariable.h
index 2abec3e..f01ae64 100644
--- a/DuetPkg/FSVariable/FSVariable.h
+++ b/DuetPkg/FSVariable/FSVariable.h
@@ -1,6 +1,6 @@
 /*++

 

-Copyright (c) 2006 - 2007, Intel Corporation                                                         

+Copyright (c) 2006 - 2012, Intel Corporation                                                         

 All rights reserved. This program and the accompanying materials                          

 are licensed and made available under the terms and conditions of the BSD License         

 which accompanies this distribution.  The full text of the license may be found at        

@@ -28,6 +28,7 @@
 #include <Library/BaseLib.h>

 #include <Library/PcdLib.h>

 #include <Library/BaseMemoryLib.h>

+#include <Library/MemoryAllocationLib.h>

 #include <Library/UefiBootServicesTableLib.h>

 #include <Library/UefiRuntimeLib.h>

 #include <Library/DebugLib.h>

@@ -91,10 +92,10 @@
   VOID               *Scratch;                      // Buffer used during reclaim

   UINTN              CommonVariableTotalSize;

   UINTN              HwErrVariableTotalSize;

-  CHAR8              PlatformLangCodes[256]; //Pre-allocate 256 bytes space to accommodate the PlatformlangCodes.

-  CHAR8              LangCodes[256];         //Pre-allocate 256 bytes space to accommodate the langCodes.

-  CHAR8              PlatformLang[8];        //Pre-allocate 8 bytes space to accommodate the Platformlang variable.

-  CHAR8              Lang[4];                //Pre-allocate 4 bytes space to accommodate the lang variable.

+  CHAR8              *PlatformLangCodes;

+  CHAR8              *LangCodes;

+  CHAR8              *PlatformLang;

+  CHAR8              Lang[ISO_639_2_ENTRY_SIZE + 1];

 } VARIABLE_GLOBAL;

 

 //

diff --git a/DuetPkg/FSVariable/FSVariable.inf b/DuetPkg/FSVariable/FSVariable.inf
index a5c0c31..8c61292 100644
--- a/DuetPkg/FSVariable/FSVariable.inf
+++ b/DuetPkg/FSVariable/FSVariable.inf
@@ -1,6 +1,6 @@
 #/*++

 #

-# Copyright (c) 2006 - 2007, Intel Corporation                                                         

+# Copyright (c) 2006 - 2012, Intel Corporation                                                         

 # All rights reserved. This program and the accompanying materials                          

 # are licensed and made available under the terms and conditions of the BSD License         

 # which accompanies this distribution.  The full text of the license may be found at        

@@ -53,6 +53,7 @@
   DxeServicesTableLib

   DevicePathLib

   UefiDriverEntryPoint

+  MemoryAllocationLib

 

 [Guids]

   gEfiHobListGuid

diff --git a/MdeModulePkg/Universal/Variable/EmuRuntimeDxe/EmuVariable.c b/MdeModulePkg/Universal/Variable/EmuRuntimeDxe/EmuVariable.c
index dddc143..0138e68 100644
--- a/MdeModulePkg/Universal/Variable/EmuRuntimeDxe/EmuVariable.c
+++ b/MdeModulePkg/Universal/Variable/EmuRuntimeDxe/EmuVariable.c
@@ -3,7 +3,7 @@
   Emulation Variable services operate on the runtime volatile memory.

   The nonvolatile variable space doesn't exist.

 

-Copyright (c) 2006 - 2008, Intel Corporation

+Copyright (c) 2006 - 2012, Intel Corporation

 All rights reserved. This program and the accompanying materials

 are licensed and made available under the terms and conditions of the BSD License

 which accompanies this distribution.  The full text of the license may be found at

@@ -338,7 +338,6 @@
 

 **/

 UINTN

-EFIAPI

 GetIndexFromSupportedLangCodes(

   IN  CHAR8            *SupportedLang,

   IN  CHAR8            *Lang,

@@ -346,13 +345,11 @@
   ) 

 {

   UINTN    Index;

-  UINT32   CompareLength;

-  CHAR8    *Supported;

+  UINTN    CompareLength;

+  UINTN    LanguageLength;

 

-  Index = 0;

-  Supported = SupportedLang;

   if (Iso639Language) {

-    CompareLength = 3;

+    CompareLength = ISO_639_2_ENTRY_SIZE;

     for (Index = 0; Index < AsciiStrLen (SupportedLang); Index += CompareLength) {

       if (AsciiStrnCmp (Lang, SupportedLang + Index, CompareLength) == 0) {

         //

@@ -368,20 +365,26 @@
     //

     // Compare RFC4646 language code

     //

-    while (*Supported != '\0') {

+    Index = 0;

+    for (LanguageLength = 0; Lang[LanguageLength] != '\0'; LanguageLength++);

+

+    for (Index = 0; *SupportedLang != '\0'; Index++, SupportedLang += CompareLength) {

       //

-      // take semicolon as delimitation, sequentially traverse supported language codes.

+      // Skip ';' characters in SupportedLang

       //

-      for (CompareLength = 0; *Supported != ';' && *Supported != '\0'; CompareLength++) {

-        Supported++;

-      }

-      if (AsciiStrnCmp (Lang, Supported - CompareLength, CompareLength) == 0) {

+      for (; *SupportedLang != '\0' && *SupportedLang == ';'; SupportedLang++);

+      //

+      // Determine the length of the next language code in SupportedLang

+      //

+      for (CompareLength = 0; SupportedLang[CompareLength] != '\0' && SupportedLang[CompareLength] != ';'; CompareLength++);

+      

+      if ((CompareLength == LanguageLength) && 

+          (AsciiStrnCmp (Lang, SupportedLang, CompareLength) == 0)) {

         //

         // Successfully find the index of Lang string in SupportedLang string.

         //

         return Index;

       }

-      Index++;

     }

     ASSERT (FALSE);

     return 0;

@@ -415,7 +418,6 @@
 

 **/

 CHAR8 *

-EFIAPI

 GetLangFromSupportedLangCodes (

   IN  CHAR8            *SupportedLang,

   IN  UINTN            Index,

@@ -423,7 +425,7 @@
 )

 {

   UINTN    SubIndex;

-  UINT32   CompareLength;

+  UINTN    CompareLength;

   CHAR8    *Supported;

 

   SubIndex  = 0;

@@ -434,10 +436,10 @@
     // As this code will be invoked in RUNTIME, therefore there is not memory allocate/free operation.

     // In driver entry, it pre-allocates a runtime attribute memory to accommodate this string.

     //

-    CompareLength = 3;

-    SetMem (mVariableModuleGlobal->Lang, sizeof(mVariableModuleGlobal->Lang), 0);

+    CompareLength = ISO_639_2_ENTRY_SIZE;

+    mVariableModuleGlobal->Lang[CompareLength] = '\0';

     return CopyMem (mVariableModuleGlobal->Lang, SupportedLang + Index * CompareLength, CompareLength);

-      

+

   } else {

     while (TRUE) {

       //

@@ -460,15 +462,151 @@
         // As this code will be invoked in RUNTIME, therefore there is not memory allocate/free operation.

         // In driver entry, it pre-allocates a runtime attribute memory to accommodate this string.

         //

-        SetMem (mVariableModuleGlobal->PlatformLang, sizeof (mVariableModuleGlobal->PlatformLang), 0);

+        mVariableModuleGlobal->PlatformLang[CompareLength] = '\0';

         return CopyMem (mVariableModuleGlobal->PlatformLang, Supported - CompareLength, CompareLength);

       }

-      SubIndex++; 			 

+      SubIndex++;

+      

+      //

+      // Skip ';' characters in Supported

+      //

+      for (; *Supported != '\0' && *Supported == ';'; Supported++);

     }

   }

 }

 

 /**

+  Returns a pointer to an allocated buffer that contains the best matching language 

+  from a set of supported languages.  

+  

+  This function supports both ISO 639-2 and RFC 4646 language codes, but language 

+  code types may not be mixed in a single call to this function. This function

+  supports a variable argument list that allows the caller to pass in a prioritized

+  list of language codes to test against all the language codes in SupportedLanguages.

+

+  If SupportedLanguages is NULL, then ASSERT().

+

+  @param[in]  SupportedLanguages  A pointer to a Null-terminated ASCII string that

+                                  contains a set of language codes in the format 

+                                  specified by Iso639Language.

+  @param[in]  Iso639Language      If TRUE, then all language codes are assumed to be

+                                  in ISO 639-2 format.  If FALSE, then all language

+                                  codes are assumed to be in RFC 4646 language format

+  @param[in]  ...                 A variable argument list that contains pointers to 

+                                  Null-terminated ASCII strings that contain one or more

+                                  language codes in the format specified by Iso639Language.

+                                  The first language code from each of these language

+                                  code lists is used to determine if it is an exact or

+                                  close match to any of the language codes in 

+                                  SupportedLanguages.  Close matches only apply to RFC 4646

+                                  language codes, and the matching algorithm from RFC 4647

+                                  is used to determine if a close match is present.  If 

+                                  an exact or close match is found, then the matching

+                                  language code from SupportedLanguages is returned.  If

+                                  no matches are found, then the next variable argument

+                                  parameter is evaluated.  The variable argument list 

+                                  is terminated by a NULL.

+

+  @retval NULL   The best matching language could not be found in SupportedLanguages.

+  @retval NULL   There are not enough resources available to return the best matching 

+                 language.

+  @retval Other  A pointer to a Null-terminated ASCII string that is the best matching 

+                 language in SupportedLanguages.

+

+**/

+CHAR8 *

+EFIAPI

+VariableGetBestLanguage (

+  IN CONST CHAR8  *SupportedLanguages, 

+  IN BOOLEAN      Iso639Language,

+  ...

+  )

+{

+  VA_LIST      Args;

+  CHAR8        *Language;

+  UINTN        CompareLength;

+  UINTN        LanguageLength;

+  CONST CHAR8  *Supported;

+  CHAR8        *Buffer;

+

+  ASSERT (SupportedLanguages != NULL);

+

+  VA_START (Args, Iso639Language);

+  while ((Language = VA_ARG (Args, CHAR8 *)) != NULL) {

+    //

+    // Default to ISO 639-2 mode

+    //

+    CompareLength  = 3;

+    LanguageLength = MIN (3, AsciiStrLen (Language));

+

+    //

+    // If in RFC 4646 mode, then determine the length of the first RFC 4646 language code in Language

+    //

+    if (!Iso639Language) {

+      for (LanguageLength = 0; Language[LanguageLength] != 0 && Language[LanguageLength] != ';'; LanguageLength++);

+    }

+

+    //

+    // Trim back the length of Language used until it is empty

+    //

+    while (LanguageLength > 0) {

+      //

+      // Loop through all language codes in SupportedLanguages

+      //

+      for (Supported = SupportedLanguages; *Supported != '\0'; Supported += CompareLength) {

+        //

+        // In RFC 4646 mode, then Loop through all language codes in SupportedLanguages

+        //

+        if (!Iso639Language) {

+          //

+          // Skip ';' characters in Supported

+          //

+          for (; *Supported != '\0' && *Supported == ';'; Supported++);

+          //

+          // Determine the length of the next language code in Supported

+          //

+          for (CompareLength = 0; Supported[CompareLength] != 0 && Supported[CompareLength] != ';'; CompareLength++);

+          //

+          // If Language is longer than the Supported, then skip to the next language

+          //

+          if (LanguageLength > CompareLength) {

+            continue;

+          }

+        }

+        //

+        // See if the first LanguageLength characters in Supported match Language

+        //

+        if (AsciiStrnCmp (Supported, Language, LanguageLength) == 0) {

+          VA_END (Args);

+

+          Buffer = Iso639Language ? mVariableModuleGlobal->Lang : mVariableModuleGlobal->PlatformLang;

+          Buffer[CompareLength] = '\0';

+          return CopyMem (Buffer, Supported, CompareLength);

+        }

+      }

+

+      if (Iso639Language) {

+        //

+        // If ISO 639 mode, then each language can only be tested once

+        //

+        LanguageLength = 0;

+      } else {

+        //

+        // If RFC 4646 mode, then trim Language from the right to the next '-' character 

+        //

+        for (LanguageLength--; LanguageLength > 0 && Language[LanguageLength] != '-'; LanguageLength--);

+      }

+    }

+  }

+  VA_END (Args);

+

+  //

+  // No matches were found 

+  //

+  return NULL;

+}

+

+/**

   Hook the operations in PlatformLangCodes, LangCodes, PlatformLang and Lang.

 

   When setting Lang/LangCodes, simultaneously update PlatformLang/PlatformLangCodes.

@@ -482,101 +620,186 @@
 

   @param[in] DataSize           Size of data. 0 means delete

 

-  @retval EFI_SUCCESS  auto update operation is successful.

-

 **/

-EFI_STATUS

-EFIAPI

+VOID

 AutoUpdateLangVariable(

   IN  CHAR16             *VariableName,

   IN  VOID               *Data,

   IN  UINTN              DataSize

   )

 {

-  EFI_STATUS     Status;

-  CHAR8          *BestPlatformLang;

-  CHAR8          *BestLang;

-  UINTN          Index;

-  UINT32         Attributes;

+  EFI_STATUS             Status;

+  CHAR8                  *BestPlatformLang;

+  CHAR8                  *BestLang;

+  UINTN                  Index;

+  UINT32                 Attributes;

   VARIABLE_POINTER_TRACK Variable;

+  BOOLEAN                SetLanguageCodes;

 

   //

+  // Don't do updates for delete operation

+  //

+  if (DataSize == 0) {

+    return;

+  }

+

+  SetLanguageCodes = FALSE;

+

+  if (StrCmp (VariableName, L"PlatformLangCodes") == 0) {

+    //

+    // PlatformLangCodes is a volatile variable, so it can not be updated at runtime.

+    //

+    if (EfiAtRuntime ()) {

+      return;

+    }

+

+    SetLanguageCodes = TRUE;

+

+    //

+    // According to UEFI spec, PlatformLangCodes is only set once in firmware initialization, and is read-only

+    // Therefore, in variable driver, only store the original value for other use.

+    //

+    if (mVariableModuleGlobal->PlatformLangCodes != NULL) {

+      FreePool (mVariableModuleGlobal->PlatformLangCodes);

+    }

+    mVariableModuleGlobal->PlatformLangCodes = AllocateRuntimeCopyPool (DataSize, Data);

+    ASSERT (mVariableModuleGlobal->PlatformLangCodes != NULL);

+

+    //

+    // PlatformLang holds a single language from PlatformLangCodes, 

+    // so the size of PlatformLangCodes is enough for the PlatformLang.

+    //

+    if (mVariableModuleGlobal->PlatformLang != NULL) {

+      FreePool (mVariableModuleGlobal->PlatformLang);

+    }

+    mVariableModuleGlobal->PlatformLang = AllocateRuntimePool (DataSize);

+    ASSERT (mVariableModuleGlobal->PlatformLang != NULL);

+

+  } else if (StrCmp (VariableName, L"LangCodes") == 0) {

+    //

+    // LangCodes is a volatile variable, so it can not be updated at runtime.

+    //

+    if (EfiAtRuntime ()) {

+      return;

+    }

+

+    SetLanguageCodes = TRUE;

+

+    //

+    // According to UEFI spec, LangCodes is only set once in firmware initialization, and is read-only

+    // Therefore, in variable driver, only store the original value for other use.

+    //

+    if (mVariableModuleGlobal->LangCodes != NULL) {

+      FreePool (mVariableModuleGlobal->LangCodes);

+    }

+    mVariableModuleGlobal->LangCodes = AllocateRuntimeCopyPool (DataSize, Data);

+    ASSERT (mVariableModuleGlobal->LangCodes != NULL);

+  }

+

+  if (SetLanguageCodes 

+      && (mVariableModuleGlobal->PlatformLangCodes != NULL)

+      && (mVariableModuleGlobal->LangCodes != NULL)) {

+    //

+    // Update Lang if PlatformLang is already set

+    // Update PlatformLang if Lang is already set

+    //

+    Status = FindVariable (L"PlatformLang", &gEfiGlobalVariableGuid, &Variable, (VARIABLE_GLOBAL *) mVariableModuleGlobal);

+    if (!EFI_ERROR (Status)) {

+      //

+      // Update Lang

+      //

+      VariableName = L"PlatformLang";

+      Data         = GetVariableDataPtr (Variable.CurrPtr);

+      DataSize     = Variable.CurrPtr->DataSize;

+    } else {

+      Status = FindVariable (L"Lang", &gEfiGlobalVariableGuid, &Variable, (VARIABLE_GLOBAL *) mVariableModuleGlobal);

+      if (!EFI_ERROR (Status)) {

+        //

+        // Update PlatformLang

+        //

+        VariableName = L"Lang";

+        Data         = GetVariableDataPtr (Variable.CurrPtr);

+        DataSize     = Variable.CurrPtr->DataSize;

+      } else {

+        //

+        // Neither PlatformLang nor Lang is set, directly return

+        //

+        return;

+      }

+    }

+  }

+  

+  //

   // According to UEFI spec, "Lang" and "PlatformLang" is NV|BS|RT attributions.

   //

   Attributes = EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS;

 

-  if (StrCmp (VariableName, L"PlatformLangCodes") == 0) {

+  if (StrCmp (VariableName, L"PlatformLang") == 0) {

     //

-    // According to UEFI spec, PlatformLangCodes is only set once in firmware initialization, and is read-only

-    // Therefore, in variable driver, only store the original value for other use.

+    // Update Lang when PlatformLangCodes/LangCodes were set.

     //

-    AsciiStrnCpy (mVariableModuleGlobal->PlatformLangCodes, Data, DataSize);

-  } else if (StrCmp (VariableName, L"LangCodes") == 0) {

-    //

-    // According to UEFI spec, LangCodes is only set once in firmware initialization, and is read-only

-    // Therefore, in variable driver, only store the original value for other use.

-    //

-    AsciiStrnCpy (mVariableModuleGlobal->LangCodes, Data, DataSize);

-  } else if (StrCmp (VariableName, L"PlatformLang") == 0) {

-    ASSERT (AsciiStrLen (mVariableModuleGlobal->PlatformLangCodes) != 0);

+    if ((mVariableModuleGlobal->PlatformLangCodes != NULL) && (mVariableModuleGlobal->LangCodes != NULL)) {

+      //

+      // When setting PlatformLang, firstly get most matched language string from supported language codes.

+      //

+      BestPlatformLang = VariableGetBestLanguage (mVariableModuleGlobal->PlatformLangCodes, FALSE, Data, NULL);

+      if (BestPlatformLang != NULL) {

+        //

+        // Get the corresponding index in language codes.

+        //

+        Index = GetIndexFromSupportedLangCodes (mVariableModuleGlobal->PlatformLangCodes, BestPlatformLang, FALSE);

 

-    //

-    // When setting PlatformLang, firstly get most matched language string from supported language codes.

-    //

-    BestPlatformLang = GetBestLanguage(mVariableModuleGlobal->PlatformLangCodes, FALSE, Data, NULL);

+        //

+        // Get the corresponding ISO639 language tag according to RFC4646 language tag.

+        //

+        BestLang = GetLangFromSupportedLangCodes (mVariableModuleGlobal->LangCodes, Index, TRUE);

 

-    //

-    // Get the corresponding index in language codes.

-    //

-    Index = GetIndexFromSupportedLangCodes(mVariableModuleGlobal->PlatformLangCodes, BestPlatformLang, FALSE);

+        //

+        // Successfully convert PlatformLang to Lang, and set the BestLang value into Lang variable simultaneously.

+        //

+        FindVariable (L"Lang", &gEfiGlobalVariableGuid, &Variable, (VARIABLE_GLOBAL *)mVariableModuleGlobal);

 

-    //

-    // Get the corresponding ISO639 language tag according to RFC4646 language tag.

-    //

-    BestLang = GetLangFromSupportedLangCodes(mVariableModuleGlobal->LangCodes, Index, TRUE);

+        Status = UpdateVariable (L"Lang", &gEfiGlobalVariableGuid, BestLang, ISO_639_2_ENTRY_SIZE + 1, Attributes, &Variable);

 

-    //

-    // Successfully convert PlatformLang to Lang, and set the BestLang value into Lang variable simultaneously.

-    //

-    FindVariable(L"Lang", &gEfiGlobalVariableGuid, &Variable, (VARIABLE_GLOBAL *)mVariableModuleGlobal);

+        DEBUG ((EFI_D_INFO, "Variable Driver Auto Update PlatformLang, PlatformLang:%a, Lang:%a\n", BestPlatformLang, BestLang));

 

-    Status = UpdateVariable(L"Lang", &gEfiGlobalVariableGuid, 

-                    BestLang, ISO_639_2_ENTRY_SIZE + 1, Attributes, &Variable);

-

-    DEBUG((EFI_D_INFO, "Variable Driver Auto Update PlatformLang, PlatformLang:%a, Lang:%a\n", BestPlatformLang, BestLang));

-

-    ASSERT_EFI_ERROR(Status);

+        ASSERT_EFI_ERROR(Status);

+      }

+    }

 

   } else if (StrCmp (VariableName, L"Lang") == 0) {

-    ASSERT (AsciiStrLen (mVariableModuleGlobal->LangCodes) != 0);

+    //

+    // Update PlatformLang when PlatformLangCodes/LangCodes were set.

+    //

+    if ((mVariableModuleGlobal->PlatformLangCodes != NULL) && (mVariableModuleGlobal->LangCodes != NULL)) {

+      //

+      // When setting Lang, firstly get most matched language string from supported language codes.

+      //

+      BestLang = VariableGetBestLanguage (mVariableModuleGlobal->LangCodes, TRUE, Data, NULL);

+      if (BestLang != NULL) {

+        //

+        // Get the corresponding index in language codes.

+        //

+        Index = GetIndexFromSupportedLangCodes (mVariableModuleGlobal->LangCodes, BestLang, TRUE);

 

-    //

-    // When setting Lang, firstly get most matched language string from supported language codes.

-    //

-    BestLang = GetBestLanguage(mVariableModuleGlobal->LangCodes, TRUE, Data, NULL);

+        //

+        // Get the corresponding RFC4646 language tag according to ISO639 language tag.

+        //

+        BestPlatformLang = GetLangFromSupportedLangCodes (mVariableModuleGlobal->PlatformLangCodes, Index, FALSE);

 

-    //

-    // Get the corresponding index in language codes.

-    //

-    Index = GetIndexFromSupportedLangCodes(mVariableModuleGlobal->LangCodes, BestLang, TRUE);

+        //

+        // Successfully convert Lang to PlatformLang, and set the BestPlatformLang value into PlatformLang variable simultaneously.

+        //

+        FindVariable (L"PlatformLang", &gEfiGlobalVariableGuid, &Variable, (VARIABLE_GLOBAL *)mVariableModuleGlobal);

 

-    //

-    // Get the corresponding RFC4646 language tag according to ISO639 language tag.

-    //

-    BestPlatformLang = GetLangFromSupportedLangCodes(mVariableModuleGlobal->PlatformLangCodes, Index, FALSE);

+        Status = UpdateVariable (L"PlatformLang", &gEfiGlobalVariableGuid, BestPlatformLang, 

+                                 AsciiStrSize (BestPlatformLang), Attributes, &Variable);

 

-    //

-    // Successfully convert Lang to PlatformLang, and set the BestPlatformLang value into PlatformLang variable simultaneously.

-    //

-    FindVariable(L"PlatformLang", &gEfiGlobalVariableGuid, &Variable, (VARIABLE_GLOBAL *)mVariableModuleGlobal);

-

-    Status = UpdateVariable(L"PlatformLang", &gEfiGlobalVariableGuid, 

-                    BestPlatformLang, AsciiStrSize (BestPlatformLang), Attributes, &Variable);

-

-    DEBUG((EFI_D_INFO, "Variable Driver Auto Update Lang, Lang:%a, PlatformLang:%a\n", BestLang, BestPlatformLang));

-    ASSERT_EFI_ERROR(Status);

+        DEBUG ((EFI_D_INFO, "Variable Driver Auto Update Lang, Lang:%a, PlatformLang:%a\n", BestLang, BestPlatformLang));

+        ASSERT_EFI_ERROR (Status);

+      }

+    }

   }

-  return EFI_SUCCESS;

 }

 

 /**

diff --git a/MdeModulePkg/Universal/Variable/EmuRuntimeDxe/InitVariable.c b/MdeModulePkg/Universal/Variable/EmuRuntimeDxe/InitVariable.c
index b4ecf86..08ded46 100644
--- a/MdeModulePkg/Universal/Variable/EmuRuntimeDxe/InitVariable.c
+++ b/MdeModulePkg/Universal/Variable/EmuRuntimeDxe/InitVariable.c
@@ -3,7 +3,7 @@
   Implment all four UEFI runtime variable services and 

   install variable architeture protocol.

   

-Copyright (c) 2006 - 2008, Intel Corporation

+Copyright (c) 2006 - 2012, Intel Corporation

 All rights reserved. This program and the accompanying materials

 are licensed and made available under the terms and conditions of the BSD License

 which accompanies this distribution.  The full text of the license may be found at

@@ -178,6 +178,9 @@
   IN VOID             *Context

   )

 {

+  EfiConvertPointer (0x0, (VOID **) &mVariableModuleGlobal->PlatformLangCodes);

+  EfiConvertPointer (0x0, (VOID **) &mVariableModuleGlobal->LangCodes);

+  EfiConvertPointer (0x0, (VOID **) &mVariableModuleGlobal->PlatformLang);

   EfiConvertPointer (

     0x0,

     (VOID **) &mVariableModuleGlobal->VariableGlobal[Physical].NonVolatileVariableBase

diff --git a/MdeModulePkg/Universal/Variable/EmuRuntimeDxe/Variable.h b/MdeModulePkg/Universal/Variable/EmuRuntimeDxe/Variable.h
index cc5803d..c235679 100644
--- a/MdeModulePkg/Universal/Variable/EmuRuntimeDxe/Variable.h
+++ b/MdeModulePkg/Universal/Variable/EmuRuntimeDxe/Variable.h
@@ -3,7 +3,7 @@
   The internal header file includes the common header files, defines

   internal structure and functions used by EmuVariable module.

 

-Copyright (c) 2006 - 2008, Intel Corporation

+Copyright (c) 2006 - 2012, Intel Corporation

 All rights reserved. This program and the accompanying materials

 are licensed and made available under the terms and conditions of the BSD License

 which accompanies this distribution.  The full text of the license may be found at

@@ -38,6 +38,11 @@
 

 #define GET_VARIABLE_NAME_PTR(a)  (CHAR16 *) ((UINTN) (a) + sizeof (VARIABLE_HEADER))

 

+///

+/// The size of a 3 character ISO639 language code.

+///

+#define ISO_639_2_ENTRY_SIZE    3

+

 typedef enum {

   Physical,

   Virtual

@@ -62,10 +67,10 @@
   UINTN           NonVolatileLastVariableOffset;

   UINTN           CommonVariableTotalSize;

   UINTN           HwErrVariableTotalSize;

-  CHAR8           PlatformLangCodes[256]; //Pre-allocate 256 bytes space to accommodate the PlatformlangCodes.

-  CHAR8           LangCodes[256]; //Pre-allocate 256 bytes space to accommodate the langCodes.

-  CHAR8           PlatformLang[8]; //Pre-allocate 8 bytes space to accommodate the Platformlang variable.

-  CHAR8           Lang[4]; //Pre-allocate 4 bytes space to accommodate the lang variable.

+  CHAR8           *PlatformLangCodes;

+  CHAR8           *LangCodes;

+  CHAR8           *PlatformLang;

+  CHAR8           Lang[ISO_639_2_ENTRY_SIZE + 1];

 } ESAL_VARIABLE_GLOBAL;

 

 ///

diff --git a/MdeModulePkg/Universal/Variable/RuntimeDxe/Variable.c b/MdeModulePkg/Universal/Variable/RuntimeDxe/Variable.c
index aadda4b..585ea43 100644
--- a/MdeModulePkg/Universal/Variable/RuntimeDxe/Variable.c
+++ b/MdeModulePkg/Universal/Variable/RuntimeDxe/Variable.c
@@ -3,7 +3,7 @@
   Implement all four UEFI Runtime Variable services for the nonvolatile

   and volatile storage space and install variable architecture protocol.

   

-Copyright (c) 2006 - 2009, Intel Corporation                                                         

+Copyright (c) 2006 - 2012, Intel Corporation                                                         

 All rights reserved. This program and the accompanying materials                          

 are licensed and made available under the terms and conditions of the BSD License         

 which accompanies this distribution.  The full text of the license may be found at        

@@ -19,10 +19,6 @@
 VARIABLE_MODULE_GLOBAL  *mVariableModuleGlobal;

 EFI_EVENT   mVirtualAddressChangeEvent = NULL;

 EFI_HANDLE  mHandle = NULL;

-///

-/// The size of a 3 character ISO639 language code.

-///

-#define ISO_639_2_ENTRY_SIZE    3

 

 ///

 /// The current Hii implementation accesses this variable many times on every boot.

@@ -951,7 +947,7 @@
   @retval EFI_INVALID_PARAMETER       If VariableName is not an empty string, while

                                       VendorGuid is NULL

   @retval EFI_SUCCESS                 Variable successfully found

-  @retval EFI_INVALID_PARAMETER       Variable not found

+  @retval EFI_NOT_FOUND               Variable not found

 

 **/

 EFI_STATUS

@@ -1075,7 +1071,6 @@
 

 **/

 UINTN

-EFIAPI

 GetIndexFromSupportedLangCodes(

   IN  CHAR8            *SupportedLang,

   IN  CHAR8            *Lang,

@@ -1083,13 +1078,11 @@
   ) 

 {

   UINTN    Index;

-  UINT32   CompareLength;

-  CHAR8    *Supported;

+  UINTN    CompareLength;

+  UINTN    LanguageLength;

 

-  Index = 0;

-  Supported = SupportedLang;

   if (Iso639Language) {

-    CompareLength = 3;

+    CompareLength = ISO_639_2_ENTRY_SIZE;

     for (Index = 0; Index < AsciiStrLen (SupportedLang); Index += CompareLength) {

       if (AsciiStrnCmp (Lang, SupportedLang + Index, CompareLength) == 0) {

         //

@@ -1105,20 +1098,26 @@
     //

     // Compare RFC4646 language code

     //

-    while (*Supported != '\0') {

+    Index = 0;

+    for (LanguageLength = 0; Lang[LanguageLength] != '\0'; LanguageLength++);

+

+    for (Index = 0; *SupportedLang != '\0'; Index++, SupportedLang += CompareLength) {

       //

-      // take semicolon as delimitation, sequentially traverse supported language codes.

+      // Skip ';' characters in SupportedLang

       //

-      for (CompareLength = 0; *Supported != ';' && *Supported != '\0'; CompareLength++) {

-        Supported++;

-      }

-      if (AsciiStrnCmp (Lang, Supported - CompareLength, CompareLength) == 0) {

+      for (; *SupportedLang != '\0' && *SupportedLang == ';'; SupportedLang++);

+      //

+      // Determine the length of the next language code in SupportedLang

+      //

+      for (CompareLength = 0; SupportedLang[CompareLength] != '\0' && SupportedLang[CompareLength] != ';'; CompareLength++);

+      

+      if ((CompareLength == LanguageLength) && 

+          (AsciiStrnCmp (Lang, SupportedLang, CompareLength) == 0)) {

         //

         // Successfully find the index of Lang string in SupportedLang string.

         //

         return Index;

       }

-      Index++;

     }

     ASSERT (FALSE);

     return 0;

@@ -1152,7 +1151,6 @@
 

 **/

 CHAR8 *

-EFIAPI

 GetLangFromSupportedLangCodes (

   IN  CHAR8            *SupportedLang,

   IN  UINTN            Index,

@@ -1160,7 +1158,7 @@
 )

 {

   UINTN    SubIndex;

-  UINT32   CompareLength;

+  UINTN    CompareLength;

   CHAR8    *Supported;

 

   SubIndex  = 0;

@@ -1171,10 +1169,10 @@
     // As this code will be invoked in RUNTIME, therefore there is not memory allocate/free operation.

     // In driver entry, it pre-allocates a runtime attribute memory to accommodate this string.

     //

-    CompareLength = 3;

-    SetMem (mVariableModuleGlobal->Lang, sizeof(mVariableModuleGlobal->Lang), 0);

+    CompareLength = ISO_639_2_ENTRY_SIZE;

+    mVariableModuleGlobal->Lang[CompareLength] = '\0';

     return CopyMem (mVariableModuleGlobal->Lang, SupportedLang + Index * CompareLength, CompareLength);

-      

+

   } else {

     while (TRUE) {

       //

@@ -1197,15 +1195,151 @@
         // As this code will be invoked in RUNTIME, therefore there is not memory allocate/free operation.

         // In driver entry, it pre-allocates a runtime attribute memory to accommodate this string.

         //

-        SetMem (mVariableModuleGlobal->PlatformLang, sizeof (mVariableModuleGlobal->PlatformLang), 0);

+        mVariableModuleGlobal->PlatformLang[CompareLength] = '\0';

         return CopyMem (mVariableModuleGlobal->PlatformLang, Supported - CompareLength, CompareLength);

       }

       SubIndex++;

+      

+      //

+      // Skip ';' characters in Supported

+      //

+      for (; *Supported != '\0' && *Supported == ';'; Supported++);

     }

   }

 }

 

 /**

+  Returns a pointer to an allocated buffer that contains the best matching language 

+  from a set of supported languages.  

+  

+  This function supports both ISO 639-2 and RFC 4646 language codes, but language 

+  code types may not be mixed in a single call to this function. This function

+  supports a variable argument list that allows the caller to pass in a prioritized

+  list of language codes to test against all the language codes in SupportedLanguages.

+

+  If SupportedLanguages is NULL, then ASSERT().

+

+  @param[in]  SupportedLanguages  A pointer to a Null-terminated ASCII string that

+                                  contains a set of language codes in the format 

+                                  specified by Iso639Language.

+  @param[in]  Iso639Language      If TRUE, then all language codes are assumed to be

+                                  in ISO 639-2 format.  If FALSE, then all language

+                                  codes are assumed to be in RFC 4646 language format

+  @param[in]  ...                 A variable argument list that contains pointers to 

+                                  Null-terminated ASCII strings that contain one or more

+                                  language codes in the format specified by Iso639Language.

+                                  The first language code from each of these language

+                                  code lists is used to determine if it is an exact or

+                                  close match to any of the language codes in 

+                                  SupportedLanguages.  Close matches only apply to RFC 4646

+                                  language codes, and the matching algorithm from RFC 4647

+                                  is used to determine if a close match is present.  If 

+                                  an exact or close match is found, then the matching

+                                  language code from SupportedLanguages is returned.  If

+                                  no matches are found, then the next variable argument

+                                  parameter is evaluated.  The variable argument list 

+                                  is terminated by a NULL.

+

+  @retval NULL   The best matching language could not be found in SupportedLanguages.

+  @retval NULL   There are not enough resources available to return the best matching 

+                 language.

+  @retval Other  A pointer to a Null-terminated ASCII string that is the best matching 

+                 language in SupportedLanguages.

+

+**/

+CHAR8 *

+EFIAPI

+VariableGetBestLanguage (

+  IN CONST CHAR8  *SupportedLanguages, 

+  IN BOOLEAN      Iso639Language,

+  ...

+  )

+{

+  VA_LIST      Args;

+  CHAR8        *Language;

+  UINTN        CompareLength;

+  UINTN        LanguageLength;

+  CONST CHAR8  *Supported;

+  CHAR8        *Buffer;

+

+  ASSERT (SupportedLanguages != NULL);

+

+  VA_START (Args, Iso639Language);

+  while ((Language = VA_ARG (Args, CHAR8 *)) != NULL) {

+    //

+    // Default to ISO 639-2 mode

+    //

+    CompareLength  = 3;

+    LanguageLength = MIN (3, AsciiStrLen (Language));

+

+    //

+    // If in RFC 4646 mode, then determine the length of the first RFC 4646 language code in Language

+    //

+    if (!Iso639Language) {

+      for (LanguageLength = 0; Language[LanguageLength] != 0 && Language[LanguageLength] != ';'; LanguageLength++);

+    }

+

+    //

+    // Trim back the length of Language used until it is empty

+    //

+    while (LanguageLength > 0) {

+      //

+      // Loop through all language codes in SupportedLanguages

+      //

+      for (Supported = SupportedLanguages; *Supported != '\0'; Supported += CompareLength) {

+        //

+        // In RFC 4646 mode, then Loop through all language codes in SupportedLanguages

+        //

+        if (!Iso639Language) {

+          //

+          // Skip ';' characters in Supported

+          //

+          for (; *Supported != '\0' && *Supported == ';'; Supported++);

+          //

+          // Determine the length of the next language code in Supported

+          //

+          for (CompareLength = 0; Supported[CompareLength] != 0 && Supported[CompareLength] != ';'; CompareLength++);

+          //

+          // If Language is longer than the Supported, then skip to the next language

+          //

+          if (LanguageLength > CompareLength) {

+            continue;

+          }

+        }

+        //

+        // See if the first LanguageLength characters in Supported match Language

+        //

+        if (AsciiStrnCmp (Supported, Language, LanguageLength) == 0) {

+          VA_END (Args);

+

+          Buffer = Iso639Language ? mVariableModuleGlobal->Lang : mVariableModuleGlobal->PlatformLang;

+          Buffer[CompareLength] = '\0';

+          return CopyMem (Buffer, Supported, CompareLength);

+        }

+      }

+

+      if (Iso639Language) {

+        //

+        // If ISO 639 mode, then each language can only be tested once

+        //

+        LanguageLength = 0;

+      } else {

+        //

+        // If RFC 4646 mode, then trim Language from the right to the next '-' character 

+        //

+        for (LanguageLength--; LanguageLength > 0 && Language[LanguageLength] != '-'; LanguageLength--);

+      }

+    }

+  }

+  VA_END (Args);

+

+  //

+  // No matches were found 

+  //

+  return NULL;

+}

+

+/**

   Hook the operations in PlatformLangCodes, LangCodes, PlatformLang and Lang.

 

   When setting Lang/LangCodes, simultaneously update PlatformLang/PlatformLangCodes.

@@ -1219,101 +1353,186 @@
 

   @param[in] DataSize           Size of data. 0 means delete

 

-  @retval EFI_SUCCESS  auto update operation is successful.

-

 **/

-EFI_STATUS

-EFIAPI

+VOID

 AutoUpdateLangVariable(

   IN  CHAR16             *VariableName,

   IN  VOID               *Data,

   IN  UINTN              DataSize

   )

 {

-  EFI_STATUS     Status;

-  CHAR8          *BestPlatformLang;

-  CHAR8          *BestLang;

-  UINTN          Index;

-  UINT32         Attributes;

+  EFI_STATUS             Status;

+  CHAR8                  *BestPlatformLang;

+  CHAR8                  *BestLang;

+  UINTN                  Index;

+  UINT32                 Attributes;

   VARIABLE_POINTER_TRACK Variable;

+  BOOLEAN                SetLanguageCodes;

 

   //

+  // Don't do updates for delete operation

+  //

+  if (DataSize == 0) {

+    return;

+  }

+

+  SetLanguageCodes = FALSE;

+

+  if (StrCmp (VariableName, L"PlatformLangCodes") == 0) {

+    //

+    // PlatformLangCodes is a volatile variable, so it can not be updated at runtime.

+    //

+    if (EfiAtRuntime ()) {

+      return;

+    }

+

+    SetLanguageCodes = TRUE;

+

+    //

+    // According to UEFI spec, PlatformLangCodes is only set once in firmware initialization, and is read-only

+    // Therefore, in variable driver, only store the original value for other use.

+    //

+    if (mVariableModuleGlobal->PlatformLangCodes != NULL) {

+      FreePool (mVariableModuleGlobal->PlatformLangCodes);

+    }

+    mVariableModuleGlobal->PlatformLangCodes = AllocateRuntimeCopyPool (DataSize, Data);

+    ASSERT (mVariableModuleGlobal->PlatformLangCodes != NULL);

+

+    //

+    // PlatformLang holds a single language from PlatformLangCodes, 

+    // so the size of PlatformLangCodes is enough for the PlatformLang.

+    //

+    if (mVariableModuleGlobal->PlatformLang != NULL) {

+      FreePool (mVariableModuleGlobal->PlatformLang);

+    }

+    mVariableModuleGlobal->PlatformLang = AllocateRuntimePool (DataSize);

+    ASSERT (mVariableModuleGlobal->PlatformLang != NULL);

+

+  } else if (StrCmp (VariableName, L"LangCodes") == 0) {

+    //

+    // LangCodes is a volatile variable, so it can not be updated at runtime.

+    //

+    if (EfiAtRuntime ()) {

+      return;

+    }

+

+    SetLanguageCodes = TRUE;

+

+    //

+    // According to UEFI spec, LangCodes is only set once in firmware initialization, and is read-only

+    // Therefore, in variable driver, only store the original value for other use.

+    //

+    if (mVariableModuleGlobal->LangCodes != NULL) {

+      FreePool (mVariableModuleGlobal->LangCodes);

+    }

+    mVariableModuleGlobal->LangCodes = AllocateRuntimeCopyPool (DataSize, Data);

+    ASSERT (mVariableModuleGlobal->LangCodes != NULL);

+  }

+

+  if (SetLanguageCodes 

+      && (mVariableModuleGlobal->PlatformLangCodes != NULL)

+      && (mVariableModuleGlobal->LangCodes != NULL)) {

+    //

+    // Update Lang if PlatformLang is already set

+    // Update PlatformLang if Lang is already set

+    //

+    Status = FindVariable (L"PlatformLang", &gEfiGlobalVariableGuid, &Variable, (VARIABLE_GLOBAL *) mVariableModuleGlobal);

+    if (!EFI_ERROR (Status)) {

+      //

+      // Update Lang

+      //

+      VariableName = L"PlatformLang";

+      Data         = GetVariableDataPtr (Variable.CurrPtr);

+      DataSize     = Variable.CurrPtr->DataSize;

+    } else {

+      Status = FindVariable (L"Lang", &gEfiGlobalVariableGuid, &Variable, (VARIABLE_GLOBAL *) mVariableModuleGlobal);

+      if (!EFI_ERROR (Status)) {

+        //

+        // Update PlatformLang

+        //

+        VariableName = L"Lang";

+        Data         = GetVariableDataPtr (Variable.CurrPtr);

+        DataSize     = Variable.CurrPtr->DataSize;

+      } else {

+        //

+        // Neither PlatformLang nor Lang is set, directly return

+        //

+        return;

+      }

+    }

+  }

+  

+  //

   // According to UEFI spec, "Lang" and "PlatformLang" is NV|BS|RT attributions.

   //

   Attributes = EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS;

 

-  if (StrCmp (VariableName, L"PlatformLangCodes") == 0) {

+  if (StrCmp (VariableName, L"PlatformLang") == 0) {

     //

-    // According to UEFI spec, PlatformLangCodes is only set once in firmware initialization, and is read-only

-    // Therefore, in variable driver, only store the original value for other use.

+    // Update Lang when PlatformLangCodes/LangCodes were set.

     //

-    AsciiStrnCpy (mVariableModuleGlobal->PlatformLangCodes, Data, DataSize);

-  } else if (StrCmp (VariableName, L"LangCodes") == 0) {

-    //

-    // According to UEFI spec, LangCodes is only set once in firmware initialization, and is read-only

-    // Therefore, in variable driver, only store the original value for other use.

-    //

-    AsciiStrnCpy (mVariableModuleGlobal->LangCodes, Data, DataSize);

-  } else if (StrCmp (VariableName, L"PlatformLang") == 0) {

-    ASSERT (AsciiStrLen (mVariableModuleGlobal->PlatformLangCodes) != 0);

+    if ((mVariableModuleGlobal->PlatformLangCodes != NULL) && (mVariableModuleGlobal->LangCodes != NULL)) {

+      //

+      // When setting PlatformLang, firstly get most matched language string from supported language codes.

+      //

+      BestPlatformLang = VariableGetBestLanguage (mVariableModuleGlobal->PlatformLangCodes, FALSE, Data, NULL);

+      if (BestPlatformLang != NULL) {

+        //

+        // Get the corresponding index in language codes.

+        //

+        Index = GetIndexFromSupportedLangCodes (mVariableModuleGlobal->PlatformLangCodes, BestPlatformLang, FALSE);

 

-    //

-    // When setting PlatformLang, firstly get most matched language string from supported language codes.

-    //

-    BestPlatformLang = GetBestLanguage(mVariableModuleGlobal->PlatformLangCodes, FALSE, Data, NULL);

+        //

+        // Get the corresponding ISO639 language tag according to RFC4646 language tag.

+        //

+        BestLang = GetLangFromSupportedLangCodes (mVariableModuleGlobal->LangCodes, Index, TRUE);

 

-    //

-    // Get the corresponding index in language codes.

-    //

-    Index = GetIndexFromSupportedLangCodes(mVariableModuleGlobal->PlatformLangCodes, BestPlatformLang, FALSE);

+        //

+        // Successfully convert PlatformLang to Lang, and set the BestLang value into Lang variable simultaneously.

+        //

+        FindVariable (L"Lang", &gEfiGlobalVariableGuid, &Variable, (VARIABLE_GLOBAL *)mVariableModuleGlobal);

 

-    //

-    // Get the corresponding ISO639 language tag according to RFC4646 language tag.

-    //

-    BestLang = GetLangFromSupportedLangCodes(mVariableModuleGlobal->LangCodes, Index, TRUE);

+        Status = UpdateVariable (L"Lang", &gEfiGlobalVariableGuid, BestLang, ISO_639_2_ENTRY_SIZE + 1, Attributes, &Variable);

 

-    //

-    // Successfully convert PlatformLang to Lang, and set the BestLang value into Lang variable simultaneously.

-    //

-    FindVariable(L"Lang", &gEfiGlobalVariableGuid, &Variable, (VARIABLE_GLOBAL *)mVariableModuleGlobal);

+        DEBUG ((EFI_D_INFO, "Variable Driver Auto Update PlatformLang, PlatformLang:%a, Lang:%a\n", BestPlatformLang, BestLang));

 

-    Status = UpdateVariable(L"Lang", &gEfiGlobalVariableGuid, 

-                    BestLang, ISO_639_2_ENTRY_SIZE + 1, Attributes, &Variable);

+        ASSERT_EFI_ERROR(Status);

+      }

+    }

 

-    DEBUG((EFI_D_INFO, "Variable Driver Auto Update PlatformLang, PlatformLang:%a, Lang:%a\n", BestPlatformLang, BestLang));

-

-    ASSERT_EFI_ERROR(Status);

-    

   } else if (StrCmp (VariableName, L"Lang") == 0) {

-    ASSERT (AsciiStrLen (mVariableModuleGlobal->LangCodes) != 0);

+    //

+    // Update PlatformLang when PlatformLangCodes/LangCodes were set.

+    //

+    if ((mVariableModuleGlobal->PlatformLangCodes != NULL) && (mVariableModuleGlobal->LangCodes != NULL)) {

+      //

+      // When setting Lang, firstly get most matched language string from supported language codes.

+      //

+      BestLang = VariableGetBestLanguage (mVariableModuleGlobal->LangCodes, TRUE, Data, NULL);

+      if (BestLang != NULL) {

+        //

+        // Get the corresponding index in language codes.

+        //

+        Index = GetIndexFromSupportedLangCodes (mVariableModuleGlobal->LangCodes, BestLang, TRUE);

 

-    //

-    // When setting Lang, firstly get most matched language string from supported language codes.

-    //

-    BestLang = GetBestLanguage(mVariableModuleGlobal->LangCodes, TRUE, Data, NULL);

+        //

+        // Get the corresponding RFC4646 language tag according to ISO639 language tag.

+        //

+        BestPlatformLang = GetLangFromSupportedLangCodes (mVariableModuleGlobal->PlatformLangCodes, Index, FALSE);

 

-    //

-    // Get the corresponding index in language codes.

-    //

-    Index = GetIndexFromSupportedLangCodes(mVariableModuleGlobal->LangCodes, BestLang, TRUE);

+        //

+        // Successfully convert Lang to PlatformLang, and set the BestPlatformLang value into PlatformLang variable simultaneously.

+        //

+        FindVariable (L"PlatformLang", &gEfiGlobalVariableGuid, &Variable, (VARIABLE_GLOBAL *)mVariableModuleGlobal);

 

-    //

-    // Get the corresponding RFC4646 language tag according to ISO639 language tag.

-    //

-    BestPlatformLang = GetLangFromSupportedLangCodes(mVariableModuleGlobal->PlatformLangCodes, Index, FALSE);

+        Status = UpdateVariable (L"PlatformLang", &gEfiGlobalVariableGuid, BestPlatformLang, 

+                                 AsciiStrSize (BestPlatformLang), Attributes, &Variable);

 

-    //

-    // Successfully convert Lang to PlatformLang, and set the BestPlatformLang value into PlatformLang variable simultaneously.

-    //

-    FindVariable(L"PlatformLang", &gEfiGlobalVariableGuid, &Variable, (VARIABLE_GLOBAL *)mVariableModuleGlobal);

-

-    Status = UpdateVariable(L"PlatformLang", &gEfiGlobalVariableGuid, 

-                    BestPlatformLang, AsciiStrSize (BestPlatformLang), Attributes, &Variable);

-

-    DEBUG((EFI_D_INFO, "Variable Driver Auto Update Lang, Lang:%a, PlatformLang:%a\n", BestLang, BestPlatformLang));

-    ASSERT_EFI_ERROR(Status);

+        DEBUG ((EFI_D_INFO, "Variable Driver Auto Update Lang, Lang:%a, PlatformLang:%a\n", BestLang, BestPlatformLang));

+        ASSERT_EFI_ERROR (Status);

+      }

+    }

   }

-  return EFI_SUCCESS;

 }

 

 /**

@@ -2424,6 +2643,9 @@
   EfiConvertPointer (0x0, (VOID **) &mVariableModuleGlobal->FvbInstance->Write);

   EfiConvertPointer (0x0, (VOID **) &mVariableModuleGlobal->FvbInstance->EraseBlocks);

   EfiConvertPointer (0x0, (VOID **) &mVariableModuleGlobal->FvbInstance);

+  EfiConvertPointer (0x0, (VOID **) &mVariableModuleGlobal->PlatformLangCodes);

+  EfiConvertPointer (0x0, (VOID **) &mVariableModuleGlobal->LangCodes);

+  EfiConvertPointer (0x0, (VOID **) &mVariableModuleGlobal->PlatformLang);

   EfiConvertPointer (

     0x0,

     (VOID **) &mVariableModuleGlobal->VariableGlobal.NonVolatileVariableBase

diff --git a/MdeModulePkg/Universal/Variable/RuntimeDxe/Variable.h b/MdeModulePkg/Universal/Variable/RuntimeDxe/Variable.h
index 9c3b43f..ef63f53 100644
--- a/MdeModulePkg/Universal/Variable/RuntimeDxe/Variable.h
+++ b/MdeModulePkg/Universal/Variable/RuntimeDxe/Variable.h
@@ -3,7 +3,7 @@
   The internal header file includes the common header files, defines

   internal structure and functions used by RuntimeVariable module.

 

-Copyright (c) 2006 - 2008, Intel Corporation

+Copyright (c) 2006 - 2012, Intel Corporation

 All rights reserved. This program and the accompanying materials

 are licensed and made available under the terms and conditions of the BSD License

 which accompanies this distribution.  The full text of the license may be found at

@@ -39,6 +39,11 @@
 

 #define VARIABLE_RECLAIM_THRESHOLD (1024)

 

+///

+/// The size of a 3 character ISO639 language code.

+///

+#define ISO_639_2_ENTRY_SIZE    3

+

 typedef struct {

   VARIABLE_HEADER *CurrPtr;

   VARIABLE_HEADER *EndPtr;

@@ -59,10 +64,10 @@
   UINTN           NonVolatileLastVariableOffset;

   UINTN           CommonVariableTotalSize;

   UINTN           HwErrVariableTotalSize;

-  CHAR8           PlatformLangCodes[256]; //Pre-allocate 256 bytes space to accommodate the PlatformlangCodes.

-  CHAR8           LangCodes[256]; //Pre-allocate 256 bytes space to accommodate the langCodes.

-  CHAR8           PlatformLang[8]; //Pre-allocate 8 bytes space to accommodate the Platformlang variable.

-  CHAR8           Lang[4]; //Pre-allocate 4 bytes space to accommodate the lang variable.

+  CHAR8           *PlatformLangCodes;

+  CHAR8           *LangCodes;

+  CHAR8           *PlatformLang;

+  CHAR8           Lang[ISO_639_2_ENTRY_SIZE + 1];

   EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL *FvbInstance;

 } VARIABLE_MODULE_GLOBAL;