From af1a266670d040d2f4083ff309d732d648afba2a Mon Sep 17 00:00:00 2001 From: Angelos Mouzakitis Date: Tue, 10 Oct 2023 14:33:42 +0000 Subject: Add submodule dependency files Change-Id: Iaf8d18082d3991dec7c0ebbea540f092188eb4ec --- .../RegularExpressionDxe/RegularExpressionDxe.c | 381 +++++++++++++++++++++ 1 file changed, 381 insertions(+) create mode 100644 roms/edk2/MdeModulePkg/Universal/RegularExpressionDxe/RegularExpressionDxe.c (limited to 'roms/edk2/MdeModulePkg/Universal/RegularExpressionDxe/RegularExpressionDxe.c') diff --git a/roms/edk2/MdeModulePkg/Universal/RegularExpressionDxe/RegularExpressionDxe.c b/roms/edk2/MdeModulePkg/Universal/RegularExpressionDxe/RegularExpressionDxe.c new file mode 100644 index 000000000..d1324c135 --- /dev/null +++ b/roms/edk2/MdeModulePkg/Universal/RegularExpressionDxe/RegularExpressionDxe.c @@ -0,0 +1,381 @@ +/** @file + + EFI_REGULAR_EXPRESSION_PROTOCOL Implementation + + (C) Copyright 2015-2016 Hewlett Packard Enterprise Development LP
+ + SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#include "RegularExpressionDxe.h" + +STATIC +EFI_REGEX_SYNTAX_TYPE * CONST mSupportedSyntaxes[] = { + &gEfiRegexSyntaxTypePosixExtendedGuid, + &gEfiRegexSyntaxTypePerlGuid +}; + +STATIC +EFI_REGULAR_EXPRESSION_PROTOCOL mProtocolInstance = { + RegularExpressionMatch, + RegularExpressionGetInfo +}; + + + +#define CHAR16_ENCODING ONIG_ENCODING_UTF16_LE + +/** + Call the Oniguruma regex match API. + + Same parameters as RegularExpressionMatch, except SyntaxType is required. + + @param String A pointer to a NULL terminated string to match against the + regular expression string specified by Pattern. + + @param Pattern A pointer to a NULL terminated string that represents the + regular expression. + @param SyntaxType A pointer to the EFI_REGEX_SYNTAX_TYPE that identifies the + regular expression syntax type to use. May be NULL in which + case the function will use its default regular expression + syntax type. + + @param Result On return, points to TRUE if String fully matches against + the regular expression Pattern using the regular expression + SyntaxType. Otherwise, points to FALSE. + + @param Captures A Pointer to an array of EFI_REGEX_CAPTURE objects to receive + the captured groups in the event of a match. The full + sub-string match is put in Captures[0], and the results of N + capturing groups are put in Captures[1:N]. If Captures is + NULL, then this function doesn't allocate the memory for the + array and does not build up the elements. It only returns the + number of matching patterns in CapturesCount. If Captures is + not NULL, this function returns a pointer to an array and + builds up the elements in the array. CapturesCount is also + updated to the number of matching patterns found. It is the + caller's responsibility to free the memory pool in Captures + and in each CapturePtr in the array elements. + + @param CapturesCount On output, CapturesCount is the number of matching patterns + found in String. Zero means no matching patterns were found + in the string. + + @retval EFI_SUCCESS Regex compilation and match completed successfully. + @retval EFI_DEVICE_ERROR Regex compilation failed. + +**/ +STATIC +EFI_STATUS +OnigurumaMatch ( + IN CHAR16 *String, + IN CHAR16 *Pattern, + IN EFI_REGEX_SYNTAX_TYPE *SyntaxType, + OUT BOOLEAN *Result, + OUT EFI_REGEX_CAPTURE **Captures, OPTIONAL + OUT UINTN *CapturesCount + ) +{ + regex_t *OnigRegex; + OnigSyntaxType *OnigSyntax; + OnigRegion *Region; + INT32 OnigResult; + OnigErrorInfo ErrorInfo; + OnigUChar ErrorMessage[ONIG_MAX_ERROR_MESSAGE_LEN]; + UINT32 Index; + OnigUChar *Start; + EFI_STATUS Status; + + + Status = EFI_SUCCESS; + + // + // Detemine the internal syntax type + // + OnigSyntax = ONIG_SYNTAX_DEFAULT; + if (CompareGuid (SyntaxType, &gEfiRegexSyntaxTypePosixExtendedGuid)) { + OnigSyntax = ONIG_SYNTAX_POSIX_EXTENDED; + } else if (CompareGuid (SyntaxType, &gEfiRegexSyntaxTypePerlGuid)) { + OnigSyntax = ONIG_SYNTAX_PERL; + } else { + DEBUG ((DEBUG_ERROR, "Unsupported regex syntax - using default\n")); + return EFI_UNSUPPORTED; + } + + // + // Compile pattern + // + Start = (OnigUChar*)Pattern; + OnigResult = onig_new ( + &OnigRegex, + Start, + Start + onigenc_str_bytelen_null (CHAR16_ENCODING, Start), + ONIG_OPTION_DEFAULT, + CHAR16_ENCODING, + OnigSyntax, + &ErrorInfo + ); + + if (OnigResult != ONIG_NORMAL) { + onig_error_code_to_str (ErrorMessage, OnigResult, &ErrorInfo); + DEBUG ((DEBUG_ERROR, "Regex compilation failed: %a\n", ErrorMessage)); + return EFI_DEVICE_ERROR; + } + + // + // Try to match + // + Start = (OnigUChar*)String; + Region = onig_region_new (); + if (Region == NULL) { + onig_free (OnigRegex); + return EFI_OUT_OF_RESOURCES; + } + OnigResult = onig_search ( + OnigRegex, + Start, + Start + onigenc_str_bytelen_null (CHAR16_ENCODING, Start), + Start, + Start + onigenc_str_bytelen_null (CHAR16_ENCODING, Start), + Region, + ONIG_OPTION_NONE + ); + + if (OnigResult >= 0) { + *Result = TRUE; + } else { + *Result = FALSE; + if (OnigResult != ONIG_MISMATCH) { + onig_error_code_to_str (ErrorMessage, OnigResult); + DEBUG ((DEBUG_ERROR, "Regex match failed: %a\n", ErrorMessage)); + onig_region_free (Region, 1); + onig_free (OnigRegex); + return EFI_DEVICE_ERROR; + } + } + + // + // If successful, copy out the region (capture) information + // + if (*Result && Captures != NULL) { + *CapturesCount = Region->num_regs; + *Captures = AllocateZeroPool (*CapturesCount * sizeof(**Captures)); + if (*Captures != NULL) { + for (Index = 0; Index < *CapturesCount; ++Index) { + // + // Region beg/end values represent bytes, not characters + // + (*Captures)[Index].Length = (Region->end[Index] - Region->beg[Index]) / sizeof(CHAR16); + (*Captures)[Index].CapturePtr = AllocateCopyPool ( + ((*Captures)[Index].Length) * sizeof (CHAR16), + (CHAR16*)((UINTN)String + Region->beg[Index]) + ); + if ((*Captures)[Index].CapturePtr == NULL) { + Status = EFI_OUT_OF_RESOURCES; + break; + } + } + + if (EFI_ERROR (Status)) { + for (Index = 0; Index < *CapturesCount; ++Index) { + if ((*Captures)[Index].CapturePtr != NULL) { + FreePool ((CHAR16*)(*Captures)[Index].CapturePtr); + } + } + FreePool (*Captures); + } + } + } + + onig_region_free (Region, 1); + onig_free (OnigRegex); + + return Status; +} + +/** + Returns information about the regular expression syntax types supported + by the implementation. + + @param This A pointer to the EFI_REGULAR_EXPRESSION_PROTOCOL + instance. + + @param RegExSyntaxTypeListSize On input, the size in bytes of RegExSyntaxTypeList. + On output with a return code of EFI_SUCCESS, the + size in bytes of the data returned in + RegExSyntaxTypeList. On output with a return code + of EFI_BUFFER_TOO_SMALL, the size of + RegExSyntaxTypeList required to obtain the list. + + @param RegExSyntaxTypeList A caller-allocated memory buffer filled by the + driver with one EFI_REGEX_SYNTAX_TYPE element + for each supported Regular expression syntax + type. The list must not change across multiple + calls to the same driver. The first syntax + type in the list is the default type for the + driver. + + @retval EFI_SUCCESS The regular expression syntax types list + was returned successfully. + @retval EFI_UNSUPPORTED The service is not supported by this driver. + @retval EFI_DEVICE_ERROR The list of syntax types could not be + retrieved due to a hardware or firmware error. + @retval EFI_BUFFER_TOO_SMALL The buffer RegExSyntaxTypeList is too small + to hold the result. + @retval EFI_INVALID_PARAMETER RegExSyntaxTypeListSize is NULL + +**/ +EFI_STATUS +EFIAPI +RegularExpressionGetInfo ( + IN EFI_REGULAR_EXPRESSION_PROTOCOL *This, + IN OUT UINTN *RegExSyntaxTypeListSize, + OUT EFI_REGEX_SYNTAX_TYPE *RegExSyntaxTypeList + ) +{ + UINTN SyntaxSize; + UINTN Index; + + if (This == NULL || RegExSyntaxTypeListSize == NULL) { + return EFI_INVALID_PARAMETER; + } + + if (*RegExSyntaxTypeListSize != 0 && RegExSyntaxTypeList == NULL) { + return EFI_INVALID_PARAMETER; + } + + SyntaxSize = ARRAY_SIZE (mSupportedSyntaxes) * sizeof(**mSupportedSyntaxes); + + if (*RegExSyntaxTypeListSize < SyntaxSize) { + *RegExSyntaxTypeListSize = SyntaxSize; + return EFI_BUFFER_TOO_SMALL; + } + + for (Index = 0; Index < ARRAY_SIZE (mSupportedSyntaxes); ++Index) { + CopyMem (&RegExSyntaxTypeList[Index], mSupportedSyntaxes[Index], sizeof(**mSupportedSyntaxes)); + } + *RegExSyntaxTypeListSize = SyntaxSize; + + return EFI_SUCCESS; +} + +/** + Checks if the input string matches to the regular expression pattern. + + @param This A pointer to the EFI_REGULAR_EXPRESSION_PROTOCOL instance. + Type EFI_REGULAR_EXPRESSION_PROTOCOL is defined in Section + XYZ. + + @param String A pointer to a NULL terminated string to match against the + regular expression string specified by Pattern. + + @param Pattern A pointer to a NULL terminated string that represents the + regular expression. + + @param SyntaxType A pointer to the EFI_REGEX_SYNTAX_TYPE that identifies the + regular expression syntax type to use. May be NULL in which + case the function will use its default regular expression + syntax type. + + @param Result On return, points to TRUE if String fully matches against + the regular expression Pattern using the regular expression + SyntaxType. Otherwise, points to FALSE. + + @param Captures A Pointer to an array of EFI_REGEX_CAPTURE objects to receive + the captured groups in the event of a match. The full + sub-string match is put in Captures[0], and the results of N + capturing groups are put in Captures[1:N]. If Captures is + NULL, then this function doesn't allocate the memory for the + array and does not build up the elements. It only returns the + number of matching patterns in CapturesCount. If Captures is + not NULL, this function returns a pointer to an array and + builds up the elements in the array. CapturesCount is also + updated to the number of matching patterns found. It is the + caller's responsibility to free the memory pool in Captures + and in each CapturePtr in the array elements. + + @param CapturesCount On output, CapturesCount is the number of matching patterns + found in String. Zero means no matching patterns were found + in the string. + + @retval EFI_SUCCESS The regular expression string matching + completed successfully. + @retval EFI_UNSUPPORTED The regular expression syntax specified by + SyntaxType is not supported by this driver. + @retval EFI_DEVICE_ERROR The regular expression string matching + failed due to a hardware or firmware error. + @retval EFI_INVALID_PARAMETER String, Pattern, Result, or CapturesCountis + NULL. + +**/ +EFI_STATUS +EFIAPI +RegularExpressionMatch ( + IN EFI_REGULAR_EXPRESSION_PROTOCOL *This, + IN CHAR16 *String, + IN CHAR16 *Pattern, + IN EFI_REGEX_SYNTAX_TYPE *SyntaxType, OPTIONAL + OUT BOOLEAN *Result, + OUT EFI_REGEX_CAPTURE **Captures, OPTIONAL + OUT UINTN *CapturesCount + ) +{ + EFI_STATUS Status; + UINT32 Index; + BOOLEAN Supported; + + if (This == NULL || String == NULL || Pattern == NULL || Result == NULL || CapturesCount == NULL) { + return EFI_INVALID_PARAMETER; + } + + // + // Figure out which syntax to use + // + if (SyntaxType == NULL) { + SyntaxType = mSupportedSyntaxes[0]; + } else { + Supported = FALSE; + for (Index = 0; Index < ARRAY_SIZE (mSupportedSyntaxes); ++Index) { + if (CompareGuid (SyntaxType, mSupportedSyntaxes[Index])) { + Supported = TRUE; + break; + } + } + if (!Supported) { + return EFI_UNSUPPORTED; + } + } + + Status = OnigurumaMatch (String, Pattern, SyntaxType, Result, Captures, CapturesCount); + + return Status; +} + +/** + Entry point for RegularExpressionDxe. + + @param ImageHandle Image handle this driver. + @param SystemTable Pointer to SystemTable. + + @retval Status Whether this function complete successfully. + +**/ +EFI_STATUS +EFIAPI +RegularExpressionDxeEntry ( + IN EFI_HANDLE ImageHandle, + IN EFI_SYSTEM_TABLE *SystemTable + ) +{ + EFI_STATUS Status; + + Status = gBS->InstallMultipleProtocolInterfaces ( + &ImageHandle, + &gEfiRegularExpressionProtocolGuid, + &mProtocolInstance, + NULL + ); + + return Status; +} -- cgit