--- /dev/null
+/**\r
+ @file\r
+\r
+ EFI_REGULAR_EXPRESSION_PROTOCOL Implementation\r
+\r
+ Copyright (c) 2015, Hewlett Packard Enterprise Development, L.P.<BR>\r
+\r
+ This program and the accompanying materials are licensed and made available\r
+ under the terms and conditions of the BSD License that accompanies this\r
+ distribution. The full text of the license may be found at\r
+ http://opensource.org/licenses/bsd-license.php.\r
+\r
+ THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, WITHOUT\r
+ WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
+**/\r
+\r
+#include "RegularExpressionDxe.h"\r
+\r
+STATIC\r
+EFI_REGEX_SYNTAX_TYPE * CONST mSupportedSyntaxes[] = {\r
+ &gEfiRegexSyntaxTypePosixExtendedGuid,\r
+ &gEfiRegexSyntaxTypePerlGuid\r
+};\r
+\r
+STATIC\r
+EFI_REGULAR_EXPRESSION_PROTOCOL mProtocolInstance = {\r
+ RegularExpressionMatch,\r
+ RegularExpressionGetInfo\r
+};\r
+\r
+\r
+\r
+#define CHAR16_ENCODING ONIG_ENCODING_UTF16_LE\r
+\r
+/**\r
+ Call the Oniguruma regex match API.\r
+\r
+ Same parameters as RegularExpressionMatch, except SyntaxType is required.\r
+\r
+ @retval EFI_SUCCESS Regex compilation and match completed successfully.\r
+ @retval EFI_DEVICE_ERROR Regex compilation failed.\r
+**/\r
+STATIC\r
+EFI_STATUS\r
+OnigurumaMatch (\r
+ IN CHAR16 *String,\r
+ IN CHAR16 *Pattern,\r
+ IN EFI_REGEX_SYNTAX_TYPE *SyntaxType,\r
+ OUT BOOLEAN *Result,\r
+ OUT EFI_REGEX_CAPTURE **Captures, OPTIONAL\r
+ OUT UINTN *CapturesCount\r
+ )\r
+{\r
+ regex_t *OnigRegex;\r
+ OnigSyntaxType *OnigSyntax;\r
+ OnigRegion *Region;\r
+ INT32 OnigResult;\r
+ OnigErrorInfo ErrorInfo;\r
+ CHAR8 ErrorMessage[ONIG_MAX_ERROR_MESSAGE_LEN];\r
+ UINT32 Index;\r
+ OnigUChar *Start;\r
+\r
+ //\r
+ // Detemine the internal syntax type\r
+ //\r
+ OnigSyntax = ONIG_SYNTAX_DEFAULT;\r
+ if (CompareGuid (SyntaxType, &gEfiRegexSyntaxTypePosixExtendedGuid)) {\r
+ OnigSyntax = ONIG_SYNTAX_POSIX_EXTENDED;\r
+ } else if (CompareGuid (SyntaxType, &gEfiRegexSyntaxTypePerlGuid)) {\r
+ OnigSyntax = ONIG_SYNTAX_PERL;\r
+ } else {\r
+ DEBUG ((DEBUG_ERROR, "Unsupported regex syntax - using default\n"));\r
+ ASSERT (FALSE);\r
+ }\r
+\r
+ //\r
+ // Compile pattern\r
+ //\r
+ Start = (OnigUChar*)Pattern;\r
+ OnigResult = onig_new (\r
+ &OnigRegex,\r
+ Start,\r
+ Start + onigenc_str_bytelen_null (CHAR16_ENCODING, Start),\r
+ ONIG_OPTION_DEFAULT,\r
+ CHAR16_ENCODING,\r
+ OnigSyntax,\r
+ &ErrorInfo\r
+ );\r
+\r
+ if (OnigResult != ONIG_NORMAL) {\r
+ onig_error_code_to_str (ErrorMessage, OnigResult, &ErrorInfo);\r
+ DEBUG ((DEBUG_ERROR, "Regex compilation failed: %a\n", ErrorMessage));\r
+ return EFI_DEVICE_ERROR;\r
+ }\r
+\r
+ //\r
+ // Try to match\r
+ //\r
+ Start = (OnigUChar*)String;\r
+ Region = onig_region_new ();\r
+ OnigResult = onig_search (\r
+ OnigRegex,\r
+ Start,\r
+ Start + onigenc_str_bytelen_null (CHAR16_ENCODING, Start),\r
+ Start,\r
+ Start + onigenc_str_bytelen_null (CHAR16_ENCODING, Start),\r
+ Region,\r
+ ONIG_OPTION_NONE\r
+ );\r
+ if (OnigResult >= 0) {\r
+ *Result = TRUE;\r
+ } else {\r
+ *Result = FALSE;\r
+ if (OnigResult != ONIG_MISMATCH) {\r
+ onig_error_code_to_str (ErrorMessage, OnigResult);\r
+ DEBUG ((DEBUG_ERROR, "Regex match failed: %a\n", ErrorMessage));\r
+ }\r
+ }\r
+\r
+ //\r
+ // If successful, copy out the region (capture) information\r
+ //\r
+ if (*Result && Captures != NULL) {\r
+ *CapturesCount = Region->num_regs;\r
+ *Captures = AllocatePool (*CapturesCount * sizeof(**Captures));\r
+ if (*Captures != NULL) {\r
+ for (Index = 0; Index < *CapturesCount; ++Index) {\r
+ //\r
+ // Region beg/end values represent bytes, not characters\r
+ //\r
+ (*Captures)[Index].CapturePtr = (CHAR16*)((UINTN)String + Region->beg[Index]);\r
+ (*Captures)[Index].Length = (Region->end[Index] - Region->beg[Index]) / sizeof(CHAR16);\r
+ }\r
+ }\r
+ }\r
+\r
+ onig_region_free (Region, 1);\r
+ onig_free (OnigRegex);\r
+\r
+ return EFI_SUCCESS;\r
+}\r
+\r
+/**\r
+ Returns information about the regular expression syntax types supported\r
+ by the implementation.\r
+\r
+ This A pointer to the EFI_REGULAR_EXPRESSION_PROTOCOL\r
+ instance.\r
+\r
+ RegExSyntaxTypeListSize On input, the size in bytes of RegExSyntaxTypeList.\r
+ On output with a return code of EFI_SUCCESS, the\r
+ size in bytes of the data returned in\r
+ RegExSyntaxTypeList. On output with a return code\r
+ of EFI_BUFFER_TOO_SMALL, the size of\r
+ RegExSyntaxTypeList required to obtain the list.\r
+\r
+ RegExSyntaxTypeList A caller-allocated memory buffer filled by the\r
+ driver with one EFI_REGEX_SYNTAX_TYPE element\r
+ for each supported Regular expression syntax\r
+ type. The list must not change across multiple\r
+ calls to the same driver. The first syntax\r
+ type in the list is the default type for the\r
+ driver.\r
+\r
+ @retval EFI_SUCCESS The regular expression syntax types list\r
+ was returned successfully.\r
+ @retval EFI_UNSUPPORTED The service is not supported by this driver.\r
+ @retval EFI_DEVICE_ERROR The list of syntax types could not be\r
+ retrieved due to a hardware or firmware error.\r
+ @retval EFI_BUFFER_TOO_SMALL The buffer RegExSyntaxTypeList is too small\r
+ to hold the result.\r
+ @retval EFI_INVALID_PARAMETER RegExSyntaxTypeListSize is NULL\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+RegularExpressionGetInfo (\r
+ IN EFI_REGULAR_EXPRESSION_PROTOCOL *This,\r
+ IN OUT UINTN *RegExSyntaxTypeListSize,\r
+ OUT EFI_REGEX_SYNTAX_TYPE *RegExSyntaxTypeList\r
+ )\r
+{\r
+ UINTN SyntaxSize;\r
+ UINTN Index;\r
+\r
+ if (This == NULL || RegExSyntaxTypeListSize == NULL) {\r
+ return EFI_INVALID_PARAMETER;\r
+ }\r
+\r
+ if (*RegExSyntaxTypeListSize != 0 && RegExSyntaxTypeList == NULL) {\r
+ return EFI_INVALID_PARAMETER;\r
+ }\r
+\r
+ SyntaxSize = ARRAY_SIZE (mSupportedSyntaxes) * sizeof(**mSupportedSyntaxes);\r
+\r
+ if (*RegExSyntaxTypeListSize < SyntaxSize) {\r
+ *RegExSyntaxTypeListSize = SyntaxSize;\r
+ return EFI_BUFFER_TOO_SMALL;\r
+ }\r
+\r
+ for (Index = 0; Index < ARRAY_SIZE (mSupportedSyntaxes); ++Index) {\r
+ CopyMem (&RegExSyntaxTypeList[Index], mSupportedSyntaxes[Index], sizeof(**mSupportedSyntaxes));\r
+ }\r
+ *RegExSyntaxTypeListSize = SyntaxSize;\r
+\r
+ return EFI_SUCCESS;\r
+}\r
+\r
+/**\r
+ Checks if the input string matches to the regular expression pattern.\r
+\r
+ This A pointer to the EFI_REGULAR_EXPRESSION_PROTOCOL instance.\r
+ Type EFI_REGULAR_EXPRESSION_PROTOCOL is defined in Section\r
+ XYZ.\r
+\r
+ String A pointer to a NULL terminated string to match against the\r
+ regular expression string specified by Pattern.\r
+\r
+ Pattern A pointer to a NULL terminated string that represents the\r
+ regular expression.\r
+\r
+ SyntaxType A pointer to the EFI_REGEX_SYNTAX_TYPE that identifies the\r
+ regular expression syntax type to use. May be NULL in which\r
+ case the function will use its default regular expression\r
+ syntax type.\r
+\r
+ Result On return, points to TRUE if String fully matches against\r
+ the regular expression Pattern using the regular expression\r
+ SyntaxType. Otherwise, points to FALSE.\r
+\r
+ Captures A Pointer to an array of EFI_REGEX_CAPTURE objects to receive\r
+ the captured groups in the event of a match. The full\r
+ sub-string match is put in Captures[0], and the results of N\r
+ capturing groups are put in Captures[1:N]. If Captures is\r
+ NULL, then this function doesn't allocate the memory for the\r
+ array and does not build up the elements. It only returns the\r
+ number of matching patterns in CapturesCount. If Captures is\r
+ not NULL, this function returns a pointer to an array and\r
+ builds up the elements in the array. CapturesCount is also\r
+ updated to the number of matching patterns found. It is the\r
+ caller's responsibility to free the memory pool in Captures\r
+ and in each CapturePtr in the array elements.\r
+\r
+ CapturesCount On output, CapturesCount is the number of matching patterns\r
+ found in String. Zero means no matching patterns were found\r
+ in the string.\r
+\r
+ @retval EFI_SUCCESS The regular expression string matching\r
+ completed successfully.\r
+ @retval EFI_UNSUPPORTED The regular expression syntax specified by\r
+ SyntaxType is not supported by this driver.\r
+ @retval EFI_DEVICE_ERROR The regular expression string matching\r
+ failed due to a hardware or firmware error.\r
+ @retval EFI_INVALID_PARAMETER String, Pattern, Result, or CapturesCountis\r
+ NULL.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+RegularExpressionMatch (\r
+ IN EFI_REGULAR_EXPRESSION_PROTOCOL *This,\r
+ IN CHAR16 *String,\r
+ IN CHAR16 *Pattern,\r
+ IN EFI_REGEX_SYNTAX_TYPE *SyntaxType, OPTIONAL\r
+ OUT BOOLEAN *Result,\r
+ OUT EFI_REGEX_CAPTURE **Captures, OPTIONAL\r
+ OUT UINTN *CapturesCount\r
+ )\r
+{\r
+ EFI_STATUS Status;\r
+ UINT32 Index;\r
+ BOOLEAN Supported;\r
+\r
+ if (This == NULL || String == NULL || Pattern == NULL || Result == NULL || CapturesCount == NULL) {\r
+ return EFI_INVALID_PARAMETER;\r
+ }\r
+\r
+ //\r
+ // Figure out which syntax to use\r
+ //\r
+ if (SyntaxType == NULL) {\r
+ SyntaxType = mSupportedSyntaxes[0];\r
+ } else {\r
+ Supported = FALSE;\r
+ for (Index = 0; Index < ARRAY_SIZE (mSupportedSyntaxes); ++Index) {\r
+ if (CompareGuid (SyntaxType, mSupportedSyntaxes[Index])) {\r
+ Supported = TRUE;\r
+ break;\r
+ }\r
+ }\r
+ if (!Supported) {\r
+ return EFI_UNSUPPORTED;\r
+ }\r
+ }\r
+\r
+ Status = OnigurumaMatch (String, Pattern, SyntaxType, Result, Captures, CapturesCount);\r
+\r
+ return Status;\r
+}\r
+\r
+/**\r
+ Entry point for RegularExpressionDxe.\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+RegularExpressionDxeEntry (\r
+ IN EFI_HANDLE ImageHandle,\r
+ IN EFI_SYSTEM_TABLE *SystemTable\r
+ )\r
+{\r
+ EFI_STATUS Status;\r
+\r
+ Status = gBS->InstallMultipleProtocolInterfaces (\r
+ &ImageHandle,\r
+ &gEfiRegularExpressionProtocolGuid,\r
+ &mProtocolInstance,\r
+ NULL\r
+ );\r
+\r
+ return Status;\r
+}\r