Add example of Name/Value pair var store to DriverSample
[efi/edk2/.git] / edk2 / MdeModulePkg / Universal / DriverSampleDxe / DriverSample.c
index 3912946..52d9b83 100644 (file)
@@ -301,6 +301,38 @@ SetPassword (
   return Status;\r
 }\r
 \r
+/**\r
+ Update names of Name/Value storage to current language.\r
+\r
+ @param PrivateData   Points to the driver private data.\r
+\r
+ @retval EFI_SUCCESS   All names are successfully updated.\r
+ @retval EFI_NOT_FOUND Failed to get Name from HII database.\r
+\r
+**/\r
+EFI_STATUS\r
+LoadNameValueNames (\r
+  IN DRIVER_SAMPLE_PRIVATE_DATA      *PrivateData\r
+  )\r
+{\r
+  UINTN      Index;\r
+\r
+  //\r
+  // Get Name/Value name string of current language\r
+  //\r
+  for (Index = 0; Index < NAME_VALUE_NAME_NUMBER; Index++) {\r
+    PrivateData->NameValueName[Index] = HiiGetString (\r
+                                         PrivateData->HiiHandle[0],\r
+                                         PrivateData->NameStringId[Index],\r
+                                         NULL\r
+                                         );\r
+    if (PrivateData->NameValueName[Index] == NULL) {\r
+      return EFI_NOT_FOUND;\r
+    }\r
+  }\r
+\r
+  return EFI_SUCCESS;\r
+}\r
 \r
 /**\r
   This function allows a caller to extract the current configuration for one\r
@@ -344,6 +376,11 @@ ExtractConfig (
   EFI_STRING                       ConfigRequest;\r
   EFI_STRING                       ConfigRequestHdr;\r
   UINTN                            Size;\r
+  EFI_STRING                       Value;\r
+  UINTN                            ValueStrLen;\r
+  CHAR16                           BackupChar;\r
+  CHAR16                           *StrPointer;\r
+\r
 \r
   if (Progress == NULL || Results == NULL || Request == NULL) {\r
     return EFI_INVALID_PARAMETER;\r
@@ -394,10 +431,96 @@ ExtractConfig (
     // Check routing data in <ConfigHdr>.\r
     // Note: if only one Storage is used, then this checking could be skipped.\r
     //\r
-    if (!HiiIsConfigHdrMatch (Request, &mFormSetGuid, VariableName)) {\r
+    if (!HiiIsConfigHdrMatch (Request, &mFormSetGuid, NULL)) {\r
       return EFI_NOT_FOUND;\r
     }\r
     ConfigRequest = Request;\r
+\r
+    //\r
+    // Check if requesting Name/Value storage\r
+    //\r
+    if (StrStr (Request, L"OFFSET") == NULL) {\r
+      //\r
+      // Update Name/Value storage Names\r
+      //\r
+      Status = LoadNameValueNames (PrivateData);\r
+      if (EFI_ERROR (Status)) {\r
+        return Status;\r
+      }\r
+\r
+      //\r
+      // Allocate memory for <ConfigResp>, e.g. Name0=0x11, Name1=0x1234, Name2="ABCD"\r
+      // <Request>   ::=<ConfigHdr>&Name0&Name1&Name2\r
+      // <ConfigResp>::=<ConfigHdr>&Name0=11&Name1=1234&Name2=0041004200430044\r
+      //\r
+      BufferSize = (StrLen (Request) +\r
+        1 + sizeof (PrivateData->Configuration.NameValueVar0) * 2 +\r
+        1 + sizeof (PrivateData->Configuration.NameValueVar1) * 2 +\r
+        1 + sizeof (PrivateData->Configuration.NameValueVar2) * 2 + 1) * sizeof (CHAR16);\r
+      *Results = AllocateZeroPool (BufferSize);\r
+      ASSERT (*Results != NULL);\r
+      StrCpy (*Results, Request);\r
+      Value = *Results;\r
+\r
+      //\r
+      // Append value of NameValueVar0, type is UINT8\r
+      //\r
+      if ((Value = StrStr (*Results, PrivateData->NameValueName[0])) != NULL) {\r
+        Value += StrLen (PrivateData->NameValueName[0]);\r
+        ValueStrLen = ((sizeof (PrivateData->Configuration.NameValueVar0) * 2) + 1);\r
+        CopyMem (Value + ValueStrLen, Value, StrSize (Value));\r
+\r
+        BackupChar = Value[ValueStrLen];\r
+        *Value++   = L'=';\r
+        Value += UnicodeValueToString (\r
+                   Value, \r
+                   PREFIX_ZERO | RADIX_HEX, \r
+                   PrivateData->Configuration.NameValueVar0, \r
+                   sizeof (PrivateData->Configuration.NameValueVar0) * 2\r
+                   );\r
+        *Value = BackupChar;\r
+      }\r
+\r
+      //\r
+      // Append value of NameValueVar1, type is UINT16\r
+      //\r
+      if ((Value = StrStr (*Results, PrivateData->NameValueName[1])) != NULL) {\r
+        Value += StrLen (PrivateData->NameValueName[1]);\r
+        ValueStrLen = ((sizeof (PrivateData->Configuration.NameValueVar1) * 2) + 1);\r
+        CopyMem (Value + ValueStrLen, Value, StrSize (Value));\r
+\r
+        BackupChar = Value[ValueStrLen];\r
+        *Value++   = L'=';\r
+        Value += UnicodeValueToString (\r
+                  Value, \r
+                  PREFIX_ZERO | RADIX_HEX, \r
+                  PrivateData->Configuration.NameValueVar1, \r
+                  sizeof (PrivateData->Configuration.NameValueVar1) * 2\r
+                  );\r
+        *Value = BackupChar;\r
+      }\r
+\r
+      //\r
+      // Append value of NameValueVar2, type is CHAR16 *\r
+      //\r
+      if ((Value = StrStr (*Results, PrivateData->NameValueName[2])) != NULL) {\r
+        Value += StrLen (PrivateData->NameValueName[2]);\r
+        ValueStrLen = StrLen (PrivateData->Configuration.NameValueVar2) * 4 + 1;\r
+        CopyMem (Value + ValueStrLen, Value, StrSize (Value));\r
+\r
+        *Value++ = L'=';\r
+        //\r
+        // Convert Unicode String to Config String, e.g. "ABCD" => "0041004200430044"\r
+        //\r
+        StrPointer = (CHAR16 *) PrivateData->Configuration.NameValueVar2;\r
+        for (; *StrPointer != L'\0'; StrPointer++) {\r
+          Value += UnicodeValueToString (Value, PREFIX_ZERO | RADIX_HEX, *StrPointer, 4);\r
+        }\r
+      }\r
+\r
+      Progress = (EFI_STRING *) Request + StrLen (Request);\r
+      return EFI_SUCCESS;\r
+    }\r
   }\r
 \r
   //\r
@@ -451,6 +574,13 @@ RouteConfig (
   UINTN                            BufferSize;\r
   DRIVER_SAMPLE_PRIVATE_DATA       *PrivateData;\r
   EFI_HII_CONFIG_ROUTING_PROTOCOL  *HiiConfigRouting;\r
+  CHAR16                           *Value;\r
+  CHAR16                           *StrPtr;\r
+  CHAR16                           TemStr[5];\r
+  UINT8                            *DataBuffer;\r
+  UINT8                            DigitUint8;\r
+  UINTN                            Index;\r
+  CHAR16                           *StrBuffer;\r
 \r
   if (Configuration == NULL || Progress == NULL) {\r
     return EFI_INVALID_PARAMETER;\r
@@ -464,7 +594,7 @@ RouteConfig (
   // Check routing data in <ConfigHdr>.\r
   // Note: if only one Storage is used, then this checking could be skipped.\r
   //\r
-  if (!HiiIsConfigHdrMatch (Configuration, &mFormSetGuid, VariableName)) {\r
+  if (!HiiIsConfigHdrMatch (Configuration, &mFormSetGuid, NULL)) {\r
     return EFI_NOT_FOUND;\r
   }\r
 \r
@@ -483,6 +613,125 @@ RouteConfig (
     return Status;\r
   }\r
 \r
+  //\r
+  // Check if configuring Name/Value storage\r
+  //\r
+  if (StrStr (Configuration, L"OFFSET") == NULL) {\r
+    //\r
+    // Update Name/Value storage Names\r
+    //\r
+    Status = LoadNameValueNames (PrivateData);\r
+    if (EFI_ERROR (Status)) {\r
+      return Status;\r
+    }\r
+\r
+    //\r
+    // Convert value for NameValueVar0\r
+    //\r
+    if ((Value = StrStr (Configuration, PrivateData->NameValueName[0])) != NULL) {\r
+      //\r
+      // Skip "Name="\r
+      //\r
+      Value += StrLen (PrivateData->NameValueName[0]);\r
+      Value++;\r
+      //\r
+      // Get Value String\r
+      //\r
+      StrPtr = StrStr (Value, L"&");\r
+      if (StrPtr == NULL) {\r
+        StrPtr = Value + StrLen (Value);\r
+      }\r
+      //\r
+      // Convert Value to Buffer data\r
+      //\r
+      DataBuffer = (UINT8 *) &PrivateData->Configuration.NameValueVar0;\r
+      ZeroMem (TemStr, sizeof (TemStr));\r
+      for (Index = 0, StrPtr --; StrPtr >= Value; StrPtr --, Index ++) {\r
+        TemStr[0] = *StrPtr;\r
+        DigitUint8 = (UINT8) StrHexToUint64 (TemStr);\r
+        if ((Index & 1) == 0) {\r
+          DataBuffer [Index/2] = DigitUint8;\r
+        } else {\r
+          DataBuffer [Index/2] = (UINT8) ((UINT8) (DigitUint8 << 4) + DataBuffer [Index/2]);\r
+        }\r
+      }\r
+    }\r
+\r
+    //\r
+    // Convert value for NameValueVar1\r
+    //\r
+    if ((Value = StrStr (Configuration, PrivateData->NameValueName[1])) != NULL) {\r
+      //\r
+      // Skip "Name="\r
+      //\r
+      Value += StrLen (PrivateData->NameValueName[1]);\r
+      Value++;\r
+      //\r
+      // Get Value String\r
+      //\r
+      StrPtr = StrStr (Value, L"&");\r
+      if (StrPtr == NULL) {\r
+        StrPtr = Value + StrLen (Value);\r
+      }\r
+      //\r
+      // Convert Value to Buffer data\r
+      //\r
+      DataBuffer = (UINT8 *) &PrivateData->Configuration.NameValueVar1;\r
+      ZeroMem (TemStr, sizeof (TemStr));\r
+      for (Index = 0, StrPtr --; StrPtr >= Value; StrPtr --, Index ++) {\r
+        TemStr[0] = *StrPtr;\r
+        DigitUint8 = (UINT8) StrHexToUint64 (TemStr);\r
+        if ((Index & 1) == 0) {\r
+          DataBuffer [Index/2] = DigitUint8;\r
+        } else {\r
+          DataBuffer [Index/2] = (UINT8) ((UINT8) (DigitUint8 << 4) + DataBuffer [Index/2]);\r
+        }\r
+      }\r
+    }\r
+\r
+    //\r
+    // Convert value for NameValueVar2\r
+    //\r
+    if ((Value = StrStr (Configuration, PrivateData->NameValueName[2])) != NULL) {\r
+      //\r
+      // Skip "Name="\r
+      //\r
+      Value += StrLen (PrivateData->NameValueName[2]);\r
+      Value++;\r
+      //\r
+      // Get Value String\r
+      //\r
+      StrPtr = StrStr (Value, L"&");\r
+      if (StrPtr == NULL) {\r
+        StrPtr = Value + StrLen (Value);\r
+      }\r
+      //\r
+      // Convert Config String to Unicode String, e.g "0041004200430044" => "ABCD"\r
+      //\r
+      StrBuffer = (CHAR16 *) PrivateData->Configuration.NameValueVar2;\r
+      ZeroMem (TemStr, sizeof (TemStr));\r
+      while (Value < StrPtr) {\r
+        StrnCpy (TemStr, Value, 4);\r
+        *(StrBuffer++) = (CHAR16) StrHexToUint64 (TemStr);\r
+        Value += 4;\r
+      }\r
+      *StrBuffer = L'\0';\r
+    }\r
+\r
+    //\r
+    // Store Buffer Storage back to EFI variable\r
+    //\r
+    Status = gRT->SetVariable(\r
+      VariableName,\r
+      &mFormSetGuid,\r
+      EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS,\r
+      sizeof (DRIVER_SAMPLE_CONFIGURATION),\r
+      &PrivateData->Configuration\r
+      );\r
+\r
+    return Status;\r
+  }\r
+\r
   //\r
   // Convert <ConfigResp> to buffer data by helper function ConfigToBlock()\r
   //\r
@@ -1035,6 +1284,7 @@ DriverSampleInit (
                    NULL\r
                    );\r
   if (HiiHandle[1] == NULL) {\r
+    DriverSampleUnload (ImageHandle);\r
     return EFI_OUT_OF_RESOURCES;\r
   }\r
 \r
@@ -1047,9 +1297,19 @@ DriverSampleInit (
   NewString = L"700 Mhz";\r
 \r
   if (HiiSetString (HiiHandle[0], STRING_TOKEN (STR_CPU_STRING2), NewString, NULL) == 0) {\r
+    DriverSampleUnload (ImageHandle);\r
     return EFI_OUT_OF_RESOURCES;\r
   }\r
 \r
+  HiiSetString (HiiHandle[0], 0, NewString, NULL);\r
+\r
+  //\r
+  // Initialize Name/Value name String ID\r
+  //\r
+  PrivateData->NameStringId[0] = STR_NAME_VALUE_VAR_NAME0;\r
+  PrivateData->NameStringId[1] = STR_NAME_VALUE_VAR_NAME1;\r
+  PrivateData->NameStringId[2] = STR_NAME_VALUE_VAR_NAME2;\r
+\r
   //\r
   // Initialize configuration data\r
   //\r
@@ -1138,6 +1398,7 @@ DriverSampleUnload (
   IN EFI_HANDLE  ImageHandle\r
   )\r
 {\r
+  UINTN Index;\r
   if (DriverHandle[0] != NULL) {\r
     gBS->UninstallMultipleProtocolInterfaces (\r
             DriverHandle[0],\r
@@ -1169,6 +1430,11 @@ DriverSampleUnload (
   }\r
 \r
   if (PrivateData != NULL) {\r
+    for (Index = 0; Index < NAME_VALUE_NAME_NUMBER; Index++) {\r
+      if (PrivateData->NameValueName[Index] != NULL) {\r
+        FreePool (PrivateData->NameValueName[Index]);\r
+      }\r
+    }\r
     FreePool (PrivateData);\r
     PrivateData = NULL;\r
   }\r