MdeModulePkg: Add match2 opcode support in SetupBrowserDxe and sample code in DriverS...
[mirror_edk2.git] / MdeModulePkg / Universal / SetupBrowserDxe / Expression.c
index e8829c1855fcbe50ca683893452345f6204e21b2..6c179c445f864d287e282050daba9a984541c04a 100644 (file)
@@ -1,7 +1,7 @@
 /** @file\r
 Utility functions for expression evaluation.\r
 \r
-Copyright (c) 2007 - 2014, Intel Corporation. All rights reserved.<BR>\r
+Copyright (c) 2007 - 2015, Intel Corporation. All rights reserved.<BR>\r
 This program and the accompanying materials\r
 are licensed and made available under the terms and conditions of the BSD License\r
 which accompanies this distribution.  The full text of the license may be found at\r
@@ -1475,6 +1475,177 @@ Done:
   return Status;\r
 }\r
 \r
+/**\r
+  Evaluate opcode EFI_IFR_MATCH2.\r
+\r
+  @param  FormSet                Formset which contains this opcode.\r
+  @param  SyntaxType             Syntax type for match2.\r
+  @param  Result                 Evaluation result for this opcode.\r
+\r
+  @retval EFI_SUCCESS            Opcode evaluation success.\r
+  @retval Other                  Opcode evaluation failed.\r
+\r
+**/\r
+EFI_STATUS\r
+IfrMatch2 (\r
+  IN FORM_BROWSER_FORMSET  *FormSet,\r
+  IN EFI_GUID              *SyntaxType,\r
+  OUT  EFI_HII_VALUE       *Result\r
+  )\r
+{\r
+  EFI_STATUS                       Status;\r
+  EFI_HII_VALUE                    Value[2];\r
+  CHAR16                           *String[2];\r
+  UINTN                            Index;\r
+  UINTN                            GuidIndex;\r
+  EFI_HANDLE                       *HandleBuffer;\r
+  UINTN                            BufferSize;\r
+  EFI_REGULAR_EXPRESSION_PROTOCOL  *RegularExpressionProtocol;\r
+  UINTN                            RegExSyntaxTypeListSize;\r
+  EFI_REGEX_SYNTAX_TYPE            *RegExSyntaxTypeList;\r
+  UINTN                            CapturesCount;\r
+\r
+  //\r
+  // String[0] - The string to search\r
+  // String[1] - pattern\r
+  //\r
+  String[0] = NULL;\r
+  String[1] = NULL;\r
+  HandleBuffer = NULL;\r
+  RegExSyntaxTypeList = NULL;\r
+  Status = EFI_SUCCESS;\r
+  ZeroMem (Value, sizeof (Value));\r
+\r
+  Status = PopExpression (&Value[0]);\r
+  if (EFI_ERROR (Status)) {\r
+    goto Done;\r
+  }\r
+\r
+  Status = PopExpression (&Value[1]);\r
+  if (EFI_ERROR (Status)) {\r
+    goto Done;\r
+  }\r
+\r
+  for (Index = 0; Index < 2; Index++) {\r
+    if (Value[Index].Type != EFI_IFR_TYPE_STRING) {\r
+      Result->Type = EFI_IFR_TYPE_UNDEFINED;\r
+      Status = EFI_SUCCESS;\r
+      goto Done;\r
+    }\r
+\r
+    String[Index] = GetToken (Value[Index].Value.string, FormSet->HiiHandle);\r
+    if (String [Index] == NULL) {\r
+      Status = EFI_NOT_FOUND;\r
+      goto Done;\r
+    }\r
+  }\r
+\r
+  BufferSize    = 0;\r
+  HandleBuffer  = NULL;\r
+  Status = gBS->LocateHandle(\r
+                      ByProtocol,\r
+                      &gEfiRegularExpressionProtocolGuid,\r
+                      NULL,\r
+                      &BufferSize,\r
+                      HandleBuffer);\r
+  if (Status == EFI_BUFFER_TOO_SMALL) {\r
+    HandleBuffer = AllocateZeroPool(BufferSize);\r
+    if (HandleBuffer == NULL) {\r
+      Status = EFI_OUT_OF_RESOURCES;\r
+      goto Done;\r
+    }\r
+    Status = gBS->LocateHandle(\r
+                        ByProtocol,\r
+                        &gEfiRegularExpressionProtocolGuid,\r
+                        NULL,\r
+                        &BufferSize,\r
+                        HandleBuffer);\r
+\r
+  } else if (EFI_ERROR (Status)) {\r
+    Value->Type = EFI_IFR_TYPE_UNDEFINED;\r
+    Status = EFI_SUCCESS;\r
+    goto Done;\r
+  }\r
+\r
+  for ( Index = 0; Index < BufferSize / sizeof(EFI_HANDLE); Index ++) {\r
+    Status = gBS->HandleProtocol (\r
+                  HandleBuffer[Index],\r
+                  &gEfiRegularExpressionProtocolGuid,\r
+                  (VOID**)&RegularExpressionProtocol\r
+                 );\r
+    if (EFI_ERROR (Status)) {\r
+      goto Done;\r
+    }\r
+\r
+    RegExSyntaxTypeListSize = 0;\r
+    RegExSyntaxTypeList = NULL;\r
+\r
+    Status = RegularExpressionProtocol->GetInfo (\r
+                                          RegularExpressionProtocol, \r
+                                          &RegExSyntaxTypeListSize, \r
+                                          RegExSyntaxTypeList\r
+                                          );\r
+    if (Status == EFI_BUFFER_TOO_SMALL) {\r
+      RegExSyntaxTypeList = AllocateZeroPool(RegExSyntaxTypeListSize);\r
+      if (RegExSyntaxTypeList == NULL) {\r
+        Status = EFI_OUT_OF_RESOURCES;\r
+        goto Done;\r
+      }\r
+      Status = RegularExpressionProtocol->GetInfo (\r
+                                            RegularExpressionProtocol, \r
+                                            &RegExSyntaxTypeListSize, \r
+                                            RegExSyntaxTypeList\r
+                                            );\r
+    } else if (EFI_ERROR (Status)) {\r
+      goto Done;\r
+    }\r
+\r
+    for (GuidIndex = 0; GuidIndex < RegExSyntaxTypeListSize / sizeof(EFI_GUID); GuidIndex++) {\r
+      if (CompareGuid (&RegExSyntaxTypeList[GuidIndex], SyntaxType)) {\r
+        //\r
+        // Find the match type, return the value.\r
+        //\r
+        Result->Type = EFI_IFR_TYPE_BOOLEAN;\r
+        Status = RegularExpressionProtocol->MatchString (\r
+                                              RegularExpressionProtocol, \r
+                                              String[0],\r
+                                              String[1],\r
+                                              SyntaxType,\r
+                                              &Result->Value.b,\r
+                                              NULL,\r
+                                              &CapturesCount\r
+                                              );\r
+        goto Done;\r
+      }\r
+    }\r
+\r
+    if (RegExSyntaxTypeList != NULL) {\r
+      FreePool (RegExSyntaxTypeList);\r
+    }\r
+  }\r
+\r
+  //\r
+  // Type specified by SyntaxType is not supported \r
+  // in any of the EFI_REGULAR_EXPRESSION_PROTOCOL instances.\r
+  //\r
+  Value->Type = EFI_IFR_TYPE_UNDEFINED;\r
+  Status = EFI_SUCCESS;\r
+\r
+Done:\r
+  if (String[0] != NULL) {\r
+    FreePool (String[0]);\r
+  }\r
+  if (String[1] != NULL) {\r
+    FreePool (String[1]);\r
+  }\r
+  if (RegExSyntaxTypeList != NULL) {\r
+    FreePool (RegExSyntaxTypeList);\r
+  }\r
+  if (HandleBuffer != NULL) {\r
+    FreePool (HandleBuffer);\r
+  }\r
+  return Status;\r
+}\r
 \r
 /**\r
   Evaluate opcode EFI_IFR_FIND.\r
@@ -3267,6 +3438,10 @@ EvaluateExpression (
       Status = IfrMatch (FormSet, Value);\r
       break;\r
 \r
+    case EFI_IFR_MATCH2_OP:\r
+      Status = IfrMatch2 (FormSet, &OpCode->Guid, Value);\r
+      break;\r
+\r
     case EFI_IFR_CATENATE_OP:\r
       Status = IfrCatenate (FormSet, Value);\r
       break;\r