Eric,

I do not see how system firmware can reliably support multiple RegEx 
implementations using a single Regular_Expression_Protocol instance. That was 
definitely not the intention of, nor was it called for in the UEFI 2.5 
specification.

The library was just to allow someone to easily replace a single RegEx 
implementation with another. If that is not seen as important, we can easily 
drop the library, and keep a single driver implementation that produces a 
single instance of the protocol with a single RegEx implementation. Other 
drivers (most likely not in system firmware) can implement other flavors with 
new instances of Regular Expression Protocol.

Does this sound reasonable?




-----Original Message-----
From: Dong, Eric [mailto:eric.d...@intel.com] 
Sent: Wednesday, May 27, 2015 12:05 AM
To: El-Haj-Mahmoud, Samer; edk2-devel@lists.sourceforge.net; Doman, Jonathan
Cc: Rothman, Michael A; Gao, Liming; Ni, Ruiyu
Subject: RE: [edk2] [PATCH] MdeModulePkg: Regular expression protocol

Samer & Jonathan,

Add my comments below. 

Thanks,
Eric

-----Original Message-----
From: El-Haj-Mahmoud, Samer [mailto:samer.el-haj-mahm...@hp.com] 
Sent: Wednesday, May 27, 2015 4:39 AM
To: edk2-devel@lists.sourceforge.net; Dong, Eric
Subject: RE: [edk2] [PATCH] MdeModulePkg: Regular expression protocol

Eric,

The original design from UEFI 2.5 (as discussed in USWG) is to allow multiple 
implementations of the EFI_REGULAR_EXPRESSION_PROTOCOL by multiple drivers. 
This includes the ability for a UEFI driver, say from an IHV provided card 
firmware, extend the capabilities of the base driver supplied by the system 
firmware. That architecture (multiple RegEx protocols from different drivers) 
does not need the EDK2 router library design. The language in the UEFI spec 
(and the code in the HII Browser) is clearly expecting this design (looping 
through all RegEx protocol handles and trying them out one by one).
[[[Eric]]] yes, agreed.

I see that BIOS will provide only 1 RegEx implementation (there is REALLY no 
need for multiple implementations in BIOS). Other implementations can be 
provided by ISVs and IHVs by installing new instances of the RegEx protocol.
[[[Eric]]] I don't know the direction now whether the bios need to support only 
one RegEx or more. If the bios only need  to provide one RegEx implementation, 
I think we don't need the library, just add these code to the driver is enough. 
 If we add the library to support later add more regex support, I think my 
design is more flexibility and has the capability add more regex support later.

Hope this helps clarify the intention behind this implementation.

Thanks,
--Samer

-----Original Message-----
From: Doman, Jonathan 
Sent: Tuesday, May 26, 2015 12:41 PM
To: Dong, Eric; edk2-devel@lists.sourceforge.net
Subject: Re: [edk2] [PATCH] MdeModulePkg: Regular expression protocol

I don't quite understand why the extra indirection layer is useful. The driver 
can be connected to a specific library B in the dsc file. If you later want to 
switch to a library C that provides more features, then update the dsc along 
with the syntax guids in the driver code. I think this is sufficient, and a 
little simpler, but I will consider your suggestion.
[[[Eric]]] If follow your design, later when others provide another regex 
support, this design can't support both library at same time.  Or it must copy 
all your code and add his new code to support more. But if follow my design, he 
just need to register his new regex(in library C) to library A and the system 
can support both library B and library C. It has the capability to accept more 
regex without change current code infrastructure.
________________________________________
From: Dong, Eric [eric.d...@intel.com]
Sent: Monday, May 25, 2015 03:21
To: edk2-devel@lists.sourceforge.net; Doman, Jonathan
Subject: RE: [edk2] [PATCH] MdeModulePkg: Regular expression protocol

Doman,

I think this infrastructure don't have the flexibility to add more regex syntax 
support later. I think we need to enhance the design. Maybe we need to add two 
libraries for RegularExpressionDxe driver. One library (Library A) is the 
router library and used by RegularExpressionDxe driver. This other library 
(Library B) provide Slre regex implementation, and just register itself to the 
library A.  later we can add library C provide another regex support and also 
register in library A.
Edkii already has similar design for TPM2, we can reference it. The sample code 
in Edk2\SecurityPkg\Library\Tpm2DeviceLibRouter\Tpm2DeviceLibRouterDxe.inf and 
Edk2\SecurityPkg\Library\Tpm2DeviceLibDTpm\ Tpm2InstanceLibDTpm.inf.  
Tpm2DeviceLibRouter is library A and Tpm2DeviceLibDTpm is library B.  What do 
you think?

Thanks,
Eric

-----Original Message-----
From: Jonathan Doman [mailto:jonathan.do...@hp.com]
Sent: Thursday, May 21, 2015 1:57 AM
To: edk2-devel@lists.sourceforge.net
Subject: [edk2] [PATCH] MdeModulePkg: Regular expression protocol

Add RegularExpressionDxe driver. Add RegExLib library header and sample
implementation SlreRegExLib, based on open-source SLRE library (old
version with permissive license).

Contributed-under: TianoCore Contribution Agreement 1.0
Signed-off-by: Jonathan Doman <jonathan.do...@hp.com>
---
 MdeModulePkg/Include/Library/RegExLib.h            | 165 +++++
 MdeModulePkg/Library/SlreRegExLib/SLRE/License.txt |   9 +
 .../Library/SlreRegExLib/SLRE/SlreUefiPort.h       |  31 +
 MdeModulePkg/Library/SlreRegExLib/SLRE/slre.c      | 684 +++++++++++++++++++++
 MdeModulePkg/Library/SlreRegExLib/SLRE/slre.h      | 104 ++++
 MdeModulePkg/Library/SlreRegExLib/SlreRegExLib.c   | 301 +++++++++
 MdeModulePkg/Library/SlreRegExLib/SlreRegExLib.inf |  38 ++
 MdeModulePkg/MdeModulePkg.dec                      |   3 +
 MdeModulePkg/MdeModulePkg.dsc                      |   2 +
 .../RegularExpressionDxe/RegularExpressionDxe.c    | 306 +++++++++
 .../RegularExpressionDxe/RegularExpressionDxe.inf  |  44 ++
 11 files changed, 1687 insertions(+)
 create mode 100644 MdeModulePkg/Include/Library/RegExLib.h
 create mode 100644 MdeModulePkg/Library/SlreRegExLib/SLRE/License.txt
 create mode 100644 MdeModulePkg/Library/SlreRegExLib/SLRE/SlreUefiPort.h
 create mode 100644 MdeModulePkg/Library/SlreRegExLib/SLRE/slre.c
 create mode 100644 MdeModulePkg/Library/SlreRegExLib/SLRE/slre.h
 create mode 100644 MdeModulePkg/Library/SlreRegExLib/SlreRegExLib.c
 create mode 100644 MdeModulePkg/Library/SlreRegExLib/SlreRegExLib.inf
 create mode 100644 
MdeModulePkg/Universal/RegularExpressionDxe/RegularExpressionDxe.c
 create mode 100644 
MdeModulePkg/Universal/RegularExpressionDxe/RegularExpressionDxe.inf

diff --git a/MdeModulePkg/Include/Library/RegExLib.h 
b/MdeModulePkg/Include/Library/RegExLib.h
new file mode 100644
index 0000000..75c930d
--- /dev/null
+++ b/MdeModulePkg/Include/Library/RegExLib.h
@@ -0,0 +1,165 @@
+/** @file
+
+  Regular Expression Library Class
+
+  Copyright (c) 2014-2015, Hewlett-Packard Development Company, L.P.
+
+  This program and the accompanying materials are licensed and made available
+  under the terms and conditions of the BSD License that accompanies this
+  distribution.  The full text of the license may be found at
+  http://opensource.org/licenses/bsd-license.php.
+
+  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, WITHOUT
+  WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+**/
+#ifndef REG_EX_LIB_H
+#define REG_EX_LIB_H
+
+#include <Uefi.h>
+
+typedef VOID* REG_EX_HANDLE;
+
+/**
+  Container for returning information about subexpression captures resulting
+  from successful matches.
+**/
+typedef struct {
+  CONST CHAR8 *Ptr;   ///< Beginning of captured subexpression within matched 
string.
+  INT32       Length; ///< Length of captured subexpression.
+} REG_EX_CAPTURE;
+
+/**
+  Compile a regular expression in preparation for matching with RegExMatch.
+  A call to RegExFree is always required to free resources regardless of
+  whether compilation was successful.
+
+  @param[out]   Handle    Pointer to RegExHandle to initialize. Must be freed
+                          with a call to RegExFree when no longer needed.
+  @param[in]    Pattern   Pointer to null-terminated ASCII string containing
+                          the desired regular expression.
+
+  @return   EFI_SUCCESS             Operation was successful.
+            EFI_ABORTED             Pattern could not be compiled. More 
information
+                                    may be found through RegExErrorMessage.
+            EFI_INVALID_PARAMETER   A required parameter was NULL.
+            EFI_OUT_OF_RESOURCES    Memory allocation failed.
+**/
+EFI_STATUS
+EFIAPI
+RegExCompile (
+  OUT       REG_EX_HANDLE *Handle,
+  IN  CONST CHAR8         *Pattern
+  );
+
+/**
+  Search the input string for anything that matches the regular expression.
+
+  Be aware that the specific implementation of this library class may not
+  support all regular expression syntax, which could lead to unexpected 
results.
+
+  If no match is found, the contents of Captures is undefined (i.e. it may be
+  overwritten with invalid data).
+
+  @param[in]  Handle      The compiled regular expression.
+  @param[in]  String      Pointer to null-terminated ASCII string to match
+                          against the regular expression.
+  @param[out] Captures    Pointer to array of REG_EX_CAPTURE objects to receive
+                          the captured groups in the event of a match. 
According
+                          to convention, the full (sub-)string match is put in
+                          Captures[0], and the results of N capturing groups 
are
+                          put in Captures[1:N]. The caller must allocate the
+                          appropriate sized array (N+1). This parameter is 
optional
+                          and may be NULL.
+  @param[in]  NumCaptures Number of elements in the Captures array. If Captures
+                          is NULL, this should be zero.
+
+  @return   TRUE    Match was found.
+            FALSE   No match was found.
+**/
+BOOLEAN
+EFIAPI
+RegExMatch (
+  IN        REG_EX_HANDLE   Handle,
+  IN  CONST CHAR8           *String,
+  OUT       REG_EX_CAPTURE  Captures[], OPTIONAL
+  IN        INT32           NumCaptures
+  );
+
+/**
+  Free any resources associated with this regular expression when it's no
+  longer needed.
+
+  @param[in]  Handle  Handle to regular expression to be freed.
+**/
+VOID
+EFIAPI
+RegExFree (
+  IN  REG_EX_HANDLE Handle
+  );
+
+/**
+  When compilation fails, the internal implementation may generate an error
+  string which can be read with this function. However, there may not always
+  be an error message when it seems like there should be, as this depends
+  on the specific implementation.
+
+  @param[in]  Handle  Handle to regular expression.
+
+  @return   Pointer to null-terminated ASCII error message. May be NULL or
+            an empty string if there is no applicable error.
+**/
+CONST CHAR8*
+EFIAPI
+RegExErrorMessage (
+  IN REG_EX_HANDLE Handle
+  );
+
+/**
+  Helper function. Match the string against a regex pattern.
+
+  @param[in]    String      The string to check.
+  @param[in]    Pattern     The regex pattern.
+
+  @retval TRUE     The string matches the pattern.
+  @retval FALSE    The string does not match the pattern.
+**/
+BOOLEAN
+RegExMatchString (
+  IN CONST CHAR16 *String,
+  IN CONST CHAR8  *AsciiPattern
+ );
+
+/**
+  Match the string against a regex pattern.
+
+  @param[in]    AnsiString      The string to check.
+  @param[in]    AnsiPattern     The regex pattern.
+
+  @retval TRUE     The string matches the pattern.
+  @retval FALSE    The string does not match the pattern.
+**/
+BOOLEAN
+RegExMatchStringAscii (
+  IN CONST CHAR8 *AsciiString,
+  IN CONST CHAR8 *AsciiPattern
+ );
+
+/**
+  Match the string against a regex pattern.
+
+  If you happen to have a UCS-2 pattern string, this helper function will do
+  the ASCII conversion for you.
+
+  @param[in]    String      The string to check.
+  @param[in]    Pattern     The regex pattern.
+
+  @retval TRUE     The string matches the pattern.
+  @retval FALSE    The string does not match the pattern.
+**/
+BOOLEAN
+RegExMatchStringUnicode (
+  IN  CONST CHAR16  *String,
+  IN  CONST CHAR16  *Pattern
+  );
+
+#endif // !REG_EX_LIB_H
diff --git a/MdeModulePkg/Library/SlreRegExLib/SLRE/License.txt 
b/MdeModulePkg/Library/SlreRegExLib/SLRE/License.txt
new file mode 100644
index 0000000..fb0df8f
--- /dev/null
+++ b/MdeModulePkg/Library/SlreRegExLib/SLRE/License.txt
@@ -0,0 +1,9 @@
+http://slre.sourceforge.net/
+
+Copyright (c) 2004-2005 Sergey Lyubka <vale...@gmail.com>
+All rights reserved
+
+"THE BEER-WARE LICENSE" (Revision 42):
+Sergey Lyubka wrote this file.  As long as you retain this notice you
+can do whatever you want with this stuff. If we meet some day, and you think
+this stuff is worth it, you can buy me a beer in return.
diff --git a/MdeModulePkg/Library/SlreRegExLib/SLRE/SlreUefiPort.h 
b/MdeModulePkg/Library/SlreRegExLib/SLRE/SlreUefiPort.h
new file mode 100644
index 0000000..e7389d8
--- /dev/null
+++ b/MdeModulePkg/Library/SlreRegExLib/SLRE/SlreUefiPort.h
@@ -0,0 +1,31 @@
+/**
+  @file
+
+  Header to rewrite stdlib references within slre
+
+  Copyright (c) 2014-2015, Hewlett-Packard Development Company, L.P.<BR>
+
+  This program and the accompanying materials are licensed and made available
+  under the terms and conditions of the BSD License that accompanies this
+  distribution.  The full text of the license may be found at
+  http://opensource.org/licenses/bsd-license.php.
+
+  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, WITHOUT
+  WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+**/
+#ifndef SLRE_UEFI_PORT_H
+#define SLRE_UEFI_PORT_H
+
+#include <Library/DebugLib.h>
+#include <Library/BaseMemoryLib.h>
+
+#define assert(x)  ASSERT(x);
+#define strchr(str,c) ScanMem8(str,sizeof(str),c)
+#define memmove(dest,src,len)  CopyMem(dest,src,len)
+#define memcmp(dest,src,len)  CompareMem(dest,src,len)
+#define printf(...)
+
+#define isdigit(c) ((c) >= '0' && (c) <= '9')
+#define isspace(c) ((c) == '\t' || (c) == '\n' || (c) == '\v' || (c) == 0xc  
|| (c) == '\r' || (c) == ' ')
+
+#endif // !SLRE_UEFI_PORT_H
diff --git a/MdeModulePkg/Library/SlreRegExLib/SLRE/slre.c 
b/MdeModulePkg/Library/SlreRegExLib/SLRE/slre.c
new file mode 100644
index 0000000..ecb3d30
--- /dev/null
+++ b/MdeModulePkg/Library/SlreRegExLib/SLRE/slre.c
@@ -0,0 +1,684 @@
+/**
+  Copyright (c) 2014-2015, Hewlett-Packard Development Company, L.P.<BR>
+
+  This program and the accompanying materials are licensed and made available
+  under the terms and conditions of the BSD License that accompanies this
+  distribution.  The full text of the license may be found at
+  http://opensource.org/licenses/bsd-license.php.
+
+  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, WITHOUT
+  WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+  Copyright (c) 2004-2005 Sergey Lyubka <vale...@gmail.com>
+  All rights reserved
+
+  "THE BEER-WARE LICENSE" (Revision 42):
+  Sergey Lyubka wrote this file.  As long as you retain this notice you
+  can do whatever you want with this stuff. If we meet some day, and you think
+  this stuff is worth it, you can buy me a beer in return.
+**/
+
+#if 0
+#include <stdio.h>
+#include <assert.h>
+#include <ctype.h>
+#include <stdlib.h>
+#include <string.h>
+#include <errno.h>
+#endif
+
+#include "slre.h"
+
+enum {END, BRANCH, ANY, EXACT, ANYOF, ANYBUT, OPEN, CLOSE, BOL, EOL,
+       STAR, PLUS, STARQ, PLUSQ, QUEST, SPACE, NONSPACE, DIGIT};
+
+#if 0
+static struct {
+       const char      *name;
+       int             narg;
+       const char      *flags;
+} opcodes[] = {
+       {"END",         0, ""},         /* End of code block or program */
+       {"BRANCH",      2, "oo"},       /* Alternative operator, "|"    */
+       {"ANY",         0, ""},         /* Match any character, "."     */
+       {"EXACT",       2, "d"},        /* Match exact string           */
+       {"ANYOF",       2, "D"},        /* Match any from set, "[]"     */
+       {"ANYBUT",      2, "D"},        /* Match any but from set, "[^]"*/
+       {"OPEN ",       1, "i"},        /* Capture start, "("           */
+       {"CLOSE",       1, "i"},        /* Capture end, ")"             */
+       {"BOL",         0, ""},         /* Beginning of string, "^"     */
+       {"EOL",         0, ""},         /* End of string, "$"           */
+       {"STAR",        1, "o"},        /* Match zero or more times "*" */
+       {"PLUS",        1, "o"},        /* Match one or more times, "+" */
+       {"STARQ",       1, "o"},        /* Non-greedy STAR,  "*?"       */
+       {"PLUSQ",       1, "o"},        /* Non-greedy PLUS, "+?"        */
+       {"QUEST",       1, "o"},        /* Match zero or one time, "?"  */
+       {"SPACE",       0, ""},         /* Match whitespace, "\s"       */
+       {"NONSPACE",    0, ""},         /* Match non-space, "\S"        */
+       {"DIGIT",       0, ""}          /* Match digit, "\d"            */
+};
+#endif
+
+/*
+ * Commands and operands are all unsigned char (1 byte long). All code offsets
+ * are relative to current address, and positive (always point forward). Data
+ * offsets are absolute. Commands with operands:
+ *
+ * BRANCH offset1 offset2
+ *     Try to match the code block that follows the BRANCH instruction
+ *     (code block ends with END). If no match, try to match code block that
+ *     starts at offset1. If either of these match, jump to offset2.
+ *
+ * EXACT data_offset data_length
+ *     Try to match exact string. String is recorded in data section from
+ *     data_offset, and has length data_length.
+ *
+ * OPEN capture_number
+ * CLOSE capture_number
+ *     If the user have passed 'struct cap' array for captures, OPEN
+ *     records the beginning of the matched substring (cap->ptr), CLOSE
+ *     sets the length (cap->len) for respective capture_number.
+ *
+ * STAR code_offset
+ * PLUS code_offset
+ * QUEST code_offset
+ *     *, +, ?, respectively. Try to gobble as much as possible from the
+ *     matched buffer, until code block that follows these instructions
+ *     matches. When the longest possible string is matched,
+ *     jump to code_offset
+ *
+ * STARQ, PLUSQ are non-greedy versions of STAR and PLUS.
+ */
+
+static const char *meta_chars = "|.^$*+?()[\\";
+
+#if 0
+static void
+print_character_set(FILE *fp, const unsigned char *p, int len)
+{
+       int     i;
+
+       for (i = 0; i < len; i++) {
+               if (i > 0)
+                       (void) fputc(',', fp);
+               if (p[i] == 0) {
+                       i++;
+                       if (p[i] == 0)
+                               (void) fprintf(fp, "\\x%02x", p[i]);
+                       else
+                               (void) fprintf(fp, "%s", opcodes[p[i]].name);
+               } else if (isprint(p[i])) {
+                       (void) fputc(p[i], fp);
+               } else {
+                       (void) fprintf(fp,"\\x%02x", p[i]);
+               }
+       }
+}
+
+void
+slre_dump(const struct slre *r, FILE *fp)
+{
+       int     i, j, ch, op, pc;
+
+       for (pc = 0; pc < r->code_size; pc++) {
+
+               op = r->code[pc];
+               (void) fprintf(fp, "%3d %s ", pc, opcodes[op].name);
+
+               for (i = 0; opcodes[op].flags[i] != '\0'; i++)
+                       switch (opcodes[op].flags[i]) {
+                       case 'i':
+                               (void) fprintf(fp, "%d ", r->code[pc + 1]);
+                               pc++;
+                               break;
+                       case 'o':
+                               (void) fprintf(fp, "%d ",
+                                   pc + r->code[pc + 1] - i);
+                               pc++;
+                               break;
+                       case 'D':
+                               print_character_set(fp, r->data +
+                                   r->code[pc + 1], r->code[pc + 2]);
+                               pc += 2;
+                               break;
+                       case 'd':
+                               (void) fputc('"', fp);
+                               for (j = 0; j < r->code[pc + 2]; j++) {
+                                       ch = r->data[r->code[pc + 1] + j];
+                                       if (isprint(ch))
+                                               (void) fputc(ch, fp);
+                                       else
+                                               (void) fprintf(fp,"\\x%02x",ch);
+                               }
+                               (void) fputc('"', fp);
+                               pc += 2;
+                               break;
+                       }
+
+               (void) fputc('\n', fp);
+       }
+}
+#endif
+
+static void
+set_jump_offset(struct slre *r, int pc, int offset)
+{
+       assert(offset < r->code_size);
+
+       if (r->code_size - offset > 0xff) {
+               r->err_str = "Jump offset is too big";
+       } else {
+               r->code[pc] = (unsigned char) (r->code_size - offset);
+       }
+}
+
+static void
+emit(struct slre *r, int code)
+{
+       if (r->code_size >= (int) (sizeof(r->code) / sizeof(r->code[0])))
+               r->err_str = "RE is too long (code overflow)";
+       else
+               r->code[r->code_size++] = (unsigned char) code;
+}
+
+static void
+store_char_in_data(struct slre *r, int ch)
+{
+       if (r->data_size >= (int) sizeof(r->data))
+               r->err_str = "RE is too long (data overflow)";
+       else
+               r->data[r->data_size++] = (unsigned char)ch;
+}
+
+static void
+exact(struct slre *r, const char **re)
+{
+       int     old_data_size = r->data_size;
+
+       while (**re != '\0' && (strchr(meta_chars, **re)) == NULL)
+               store_char_in_data(r, *(*re)++);
+
+       emit(r, EXACT);
+       emit(r, old_data_size);
+       emit(r, r->data_size - old_data_size);
+}
+
+static int
+get_escape_char(const char **re)
+{
+       int     res;
+
+       switch (*(*re)++) {
+       case 'n':       res = '\n';             break;
+       case 'r':       res = '\r';             break;
+       case 't':       res = '\t';             break;
+       case '0':       res = 0;                break;
+       case 'S':       res = NONSPACE << 8;    break;
+       case 's':       res = SPACE << 8;       break;
+       case 'd':       res = DIGIT << 8;       break;
+       default:        res = (*re)[-1];        break;
+       }
+
+       return (res);
+}
+
+static void
+anyof(struct slre *r, const char **re)
+{
+       int     esc, old_data_size = r->data_size, op = ANYOF;
+
+       if (**re == '^') {
+               op = ANYBUT;
+               (*re)++;
+       }
+
+       while (**re != '\0')
+
+               switch (*(*re)++) {
+               case ']':
+                       emit(r, op);
+                       emit(r, old_data_size);
+                       emit(r, r->data_size - old_data_size);
+                       return;
+                       /* NOTREACHED */
+                       break;
+               case '\\':
+                       esc = get_escape_char(re);
+                       if ((esc & 0xff) == 0) {
+                               store_char_in_data(r, 0);
+                               store_char_in_data(r, esc >> 8);
+                       } else {
+                               store_char_in_data(r, esc);
+                       }
+                       break;
+               default:
+                       store_char_in_data(r, (*re)[-1]);
+                       break;
+               }
+
+       r->err_str = "No closing ']' bracket";
+}
+
+static void
+relocate(struct slre *r, int begin, int shift)
+{
+       emit(r, END);
+       memmove(r->code + begin + shift, r->code + begin, r->code_size - begin);
+       r->code_size += shift;
+}
+
+static void
+quantifier(struct slre *r, int prev, int op)
+{
+       if (r->code[prev] == EXACT && r->code[prev + 2] > 1) {
+               r->code[prev + 2]--;
+               emit(r, EXACT);
+               emit(r, r->code[prev + 1] + r->code[prev + 2]);
+               emit(r, 1);
+               prev = r->code_size - 3;
+       }
+       relocate(r, prev, 2);
+       r->code[prev] = (unsigned char)op;
+       set_jump_offset(r, prev + 1, prev);
+}
+
+static void
+exact_one_char(struct slre *r, int ch)
+{
+       emit(r, EXACT);
+       emit(r, r->data_size);
+       emit(r, 1);
+       store_char_in_data(r, ch);
+}
+
+static void
+fixup_branch(struct slre *r, int fixup)
+{
+       if (fixup > 0) {
+               emit(r, END);
+               set_jump_offset(r, fixup, fixup - 2);
+       }
+}
+
+static void
+compile(struct slre *r, const char **re)
+{
+       int     op, esc, branch_start, last_op, fixup, cap_no, level;
+
+       fixup = 0;
+       level = r->num_caps;
+       branch_start = last_op = r->code_size;
+
+       for (;;)
+               switch (*(*re)++) {
+               case '\0':
+                       (*re)--;
+                       return;
+                       /* NOTREACHED */
+                       break;
+               case '^':
+                       emit(r, BOL);
+                       break;
+               case '$':
+                       emit(r, EOL);
+                       break;
+               case '.':
+                       last_op = r->code_size;
+                       emit(r, ANY);
+                       break;
+               case '[':
+                       last_op = r->code_size;
+                       anyof(r, re);
+                       break;
+               case '\\':
+                       last_op = r->code_size;
+                       esc = get_escape_char(re);
+                       if (esc & 0xff00) {
+                               emit(r, esc >> 8);
+                       } else {
+                               exact_one_char(r, esc);
+                       }
+                       break;
+               case '(':
+                       last_op = r->code_size;
+                       cap_no = ++r->num_caps;
+                       emit(r, OPEN);
+                       emit(r, cap_no);
+
+                       compile(r, re);
+                       if (*(*re)++ != ')') {
+                               r->err_str = "No closing bracket";
+                               return;
+                       }
+
+                       emit(r, CLOSE);
+                       emit(r, cap_no);
+                       break;
+               case ')':
+                       (*re)--;
+                       fixup_branch(r, fixup);
+                       if (level == 0) {
+                               r->err_str = "Unbalanced brackets";
+                               return;
+                       }
+                       return;
+                       /* NOTREACHED */
+                       break;
+               case '+':
+               case '*':
+                       op = (*re)[-1] == '*' ? STAR: PLUS;
+                       if (**re == '?') {
+                               (*re)++;
+                               op = op == STAR ? STARQ : PLUSQ;
+                       }
+                       quantifier(r, last_op, op);
+                       break;
+               case '?':
+                       quantifier(r, last_op, QUEST);
+                       break;
+               case '|':
+                       fixup_branch(r, fixup);
+                       relocate(r, branch_start, 3);
+                       r->code[branch_start] = BRANCH;
+                       set_jump_offset(r, branch_start + 1, branch_start);
+                       fixup = branch_start + 2;
+                       r->code[fixup] = 0xff;
+                       break;
+               default:
+                       (*re)--;
+                       last_op = r->code_size;
+                       exact(r, re);
+                       break;
+               }
+}
+
+int
+slre_compile(struct slre *r, const char *re)
+{
+       r->err_str = NULL;
+       r->code_size = r->data_size = r->num_caps = r->anchored = 0;
+
+       if (*re == '^')
+               r->anchored++;
+
+       emit(r, OPEN);  /* This will capture what matches full RE */
+       emit(r, 0);
+
+       while (*re != '\0')
+               compile(r, &re);
+
+       if (r->code[2] == BRANCH)
+               fixup_branch(r, 4);
+
+       emit(r, CLOSE);
+       emit(r, 0);
+       emit(r, END);
+
+       return (r->err_str == NULL ? 1 : 0);
+}
+
+static int match(const struct slre *, int,
+               const char *, int, int *, struct cap *);
+
+static void
+loop_greedy(const struct slre *r, int pc, const char *s, int len, int *ofs)
+{
+       int     saved_offset, matched_offset;
+
+       saved_offset = matched_offset = *ofs;
+
+       while (match(r, pc + 2, s, len, ofs, NULL)) {
+               saved_offset = *ofs;
+               if (match(r, pc + r->code[pc + 1], s, len, ofs, NULL))
+                       matched_offset = saved_offset;
+               *ofs = saved_offset;
+       }
+
+       *ofs = matched_offset;
+}
+
+static void
+loop_non_greedy(const struct slre *r, int pc, const char *s,int len, int *ofs)
+{
+       int     saved_offset = *ofs;
+
+       while (match(r, pc + 2, s, len, ofs, NULL)) {
+               saved_offset = *ofs;
+               if (match(r, pc + r->code[pc + 1], s, len, ofs, NULL))
+                       break;
+       }
+
+       *ofs = saved_offset;
+}
+
+static int
+is_any_of(const unsigned char *p, int len, const char *s, int *ofs)
+{
+       int     i, ch;
+
+       ch = s[*ofs];
+
+       for (i = 0; i < len; i++)
+               if (p[i] == ch) {
+                       (*ofs)++;
+                       return (1);
+               }
+
+       return (0);
+}
+
+static int
+is_any_but(const unsigned char *p, int len, const char *s, int *ofs)
+{
+       int     i, ch;
+
+       ch = s[*ofs];
+
+       for (i = 0; i < len; i++)
+               if (p[i] == ch)
+                       return (0);
+
+       (*ofs)++;
+       return (1);
+}
+
+static int
+match(const struct slre *r, int pc, const char *s, int len,
+               int *ofs, struct cap *caps)
+{
+       int     n, saved_offset, res = 1;
+
+       while (res && r->code[pc] != END) {
+
+               assert(pc < r->code_size);
+               assert(pc < (int) (sizeof(r->code) / sizeof(r->code[0])));
+
+               switch (r->code[pc]) {
+               case BRANCH:
+                       saved_offset = *ofs;
+                       res = match(r, pc + 3, s, len, ofs, caps);
+                       if (res == 0) {
+                               *ofs = saved_offset;
+                               res = match(r, pc + r->code[pc + 1],
+                                   s, len, ofs, caps);
+                       }
+                       pc += r->code[pc + 2];
+                       break;
+               case EXACT:
+                       res = 0;
+                       n = r->code[pc + 2];    /* String length */
+                       if (n <= len - *ofs && !memcmp(s + *ofs, r->data +
+                           r->code[pc + 1], n)) {
+                               (*ofs) += n;
+                               res = 1;
+                       }
+                       pc += 3;
+                       break;
+               case QUEST:
+                       res = 1;
+                       saved_offset = *ofs;
+                       if (!match(r, pc + 2, s, len, ofs, caps))
+                               *ofs = saved_offset;
+                       pc += r->code[pc + 1];
+                       break;
+               case STAR:
+                       res = 1;
+                       loop_greedy(r, pc, s, len, ofs);
+                       pc += r->code[pc + 1];
+                       break;
+               case STARQ:
+                       res = 1;
+                       loop_non_greedy(r, pc, s, len, ofs);
+                       pc += r->code[pc + 1];
+                       break;
+               case PLUS:
+                       if ((res = match(r, pc + 2, s, len, ofs, caps)) == 0)
+                               break;
+
+                       loop_greedy(r, pc, s, len, ofs);
+                       pc += r->code[pc + 1];
+                       break;
+               case PLUSQ:
+                       if ((res = match(r, pc + 2, s, len, ofs, caps)) == 0)
+                               break;
+
+                       loop_non_greedy(r, pc, s, len, ofs);
+                       pc += r->code[pc + 1];
+                       break;
+               case SPACE:
+                       res = 0;
+                       if (*ofs < len && isspace(((unsigned char *)s)[*ofs])) {
+                               (*ofs)++;
+                               res = 1;
+                       }
+                       pc++;
+                       break;
+               case NONSPACE:
+                       res = 0;
+                       if (*ofs <len && !isspace(((unsigned char *)s)[*ofs])) {
+                               (*ofs)++;
+                               res = 1;
+                       }
+                       pc++;
+                       break;
+               case DIGIT:
+                       res = 0;
+                       if (*ofs < len && isdigit(((unsigned char *)s)[*ofs])) {
+                               (*ofs)++;
+                               res = 1;
+                       }
+                       pc++;
+                       break;
+               case ANY:
+                       res = 0;
+                       if (*ofs < len) {
+                               (*ofs)++;
+                               res = 1;
+                       }
+                       pc++;
+                       break;
+               case ANYOF:
+                       res = 0;
+                       if (*ofs < len)
+                               res = is_any_of(r->data + r->code[pc + 1],
+                                       r->code[pc + 2], s, ofs);
+                       pc += 3;
+                       break;
+               case ANYBUT:
+                       res = 0;
+                       if (*ofs < len)
+                               res = is_any_but(r->data + r->code[pc + 1],
+                                       r->code[pc + 2], s, ofs);
+                       pc += 3;
+                       break;
+               case BOL:
+                       res = *ofs == 0 ? 1 : 0;
+                       pc++;
+                       break;
+               case EOL:
+                       res = *ofs == len ? 1 : 0;
+                       pc++;
+                       break;
+               case OPEN:
+                       if (caps != NULL)
+                               caps[r->code[pc + 1]].ptr = s + *ofs;
+                       pc += 2;
+                       break;
+               case CLOSE:
+                       if (caps != NULL)
+                               caps[r->code[pc + 1]].len = (int)((s + *ofs) - 
caps[r->code[pc + 1]].ptr);
+                       pc += 2;
+                       break;
+               case END:
+                       pc++;
+                       break;
+               default:
+                       printf("unknown cmd (%d) at %d\n", r->code[pc], pc);
+                       assert(0);
+                       break;
+               }
+       }
+
+       return (res);
+}
+
+int
+slre_match(const struct slre *r, const char *buf, int len,
+               struct cap *caps)
+{
+       int     i, ofs = 0, res = 0;
+
+       if (r->anchored) {
+               res = match(r, 0, buf, len, &ofs, caps);
+       } else {
+               for (i = 0; i < len && res == 0; i++) {
+                       ofs = i;
+                       res = match(r, 0, buf, len, &ofs, caps);
+               }
+       }
+
+       return (res);
+}
+
+#if 0
+#ifdef TEST
+int main(int argc, char *argv[])
+{
+       struct slre     slre;
+       struct cap      caps[20];
+       char            data[1 * 1024 * 1024];
+       FILE            *fp;
+       int             i, count, res, len;
+
+       if (argc < 3) {
+               printf("Usage: %s 'slre' <file> [count]\n", argv[0]);
+       } else if ((fp = fopen(argv[2], "rb")) == NULL) {
+               printf("Error: cannot open %s:%s\n", argv[2], strerror(errno));
+       } else if (!slre_compile(&slre, argv[1])) {
+               printf("Error compiling slre: %s\n", slre.err_str);
+       } else {
+               slre_dump(&slre, stderr);
+
+               (void) memset(caps, 0, sizeof(caps));
+
+               /* Read first 128K of file */
+               len = fread(data, 1, sizeof(data), fp);
+               (void) fclose(fp);
+
+               res = 0;
+               count = argc > 3 ? atoi(argv[3]) : 1;
+               for (i = 0; i < count; i++)
+                       res = slre_match(&slre, data, len, caps);
+
+               printf("Result: %d\n", res);
+
+               for (i = 0; i < 20; i++)
+                       if (caps[i].len > 0)
+                               printf("Substring %d: [%.*s]\n", i,
+                                   caps[i].len, caps[i].ptr);
+       }
+
+       return (0);
+}
+#endif /* TEST */
+#endif
diff --git a/MdeModulePkg/Library/SlreRegExLib/SLRE/slre.h 
b/MdeModulePkg/Library/SlreRegExLib/SLRE/slre.h
new file mode 100644
index 0000000..9aecdd5
--- /dev/null
+++ b/MdeModulePkg/Library/SlreRegExLib/SLRE/slre.h
@@ -0,0 +1,104 @@
+/**
+  Copyright (c) 2014-2015, Hewlett-Packard Development Company, L.P.<BR>
+
+  This program and the accompanying materials are licensed and made available
+  under the terms and conditions of the BSD License that accompanies this
+  distribution.  The full text of the license may be found at
+  http://opensource.org/licenses/bsd-license.php.
+
+  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, WITHOUT
+  WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+  Copyright (c) 2004-2005 Sergey Lyubka <vale...@gmail.com>
+  All rights reserved
+
+  "THE BEER-WARE LICENSE" (Revision 42):
+  Sergey Lyubka wrote this file.  As long as you retain this notice you
+  can do whatever you want with this stuff. If we meet some day, and you think
+  this stuff is worth it, you can buy me a beer in return.
+**/
+
+/*
+ * This is a regular expression library that implements a subset of Perl RE.
+ * Please refer to http://slre.sourceforge.net for detailed description.
+ *
+ * Usage example (parsing HTTP request):
+ *
+ * struct slre slre;
+ * struct cap  captures[4 + 1];  // Number of braket pairs + 1
+ * ...
+ *
+ * slre_compile(&slre,"^(GET|POST) (\S+) HTTP/(\S+?)\r\n");
+ *
+ * if (slre_match(&slre, buf, len, captures)) {
+ *     printf("Request line length: %d\n", captures[0].len);
+ *     printf("Method: %.*s\n", captures[1].len, captures[1].ptr);
+ *     printf("URI: %.*s\n", captures[2].len, captures[2].ptr);
+ * }
+ *
+ * Supported syntax:
+ *     ^               Match beginning of a buffer
+ *     $               Match end of a buffer
+ *     ()              Grouping and substring capturing
+ *     [...]           Match any character from set
+ *     [^...]          Match any character but ones from set
+ *     \s              Match whitespace
+ *     \S              Match non-whitespace
+ *     \d              Match decimal digit
+ *     \r              Match carriage return
+ *     \n              Match newline
+ *     +               Match one or more times (greedy)
+ *     +?              Match one or more times (non-greedy)
+ *     *               Match zero or more times (greedy)
+ *     *?              Match zero or more times (non-greedy)
+ *     ?               Match zero or once
+ *     \xDD            Match byte with hex value 0xDD
+ *     \meta           Match one of the meta character: ^$().[*+?\
+ */
+
+#ifndef SLRE_HEADER_DEFINED
+#define        SLRE_HEADER_DEFINED
+
+#include "SlreUefiPort.h"
+
+/*
+ * Compiled regular expression
+ */
+struct slre {
+       unsigned char   code[256];
+       unsigned char   data[256];
+       int             code_size;
+       int             data_size;
+       int             num_caps;       /* Number of bracket pairs      */
+       int             anchored;       /* Must match from string start */
+       const char      *err_str;       /* Error string                 */
+};
+
+/*
+ * Captured substring
+ */
+struct cap {
+       const char      *ptr;           /* Pointer to the substring     */
+       int             len;            /* Substring length             */
+};
+
+/*
+ * Compile regular expression. If success, 1 is returned.
+ * If error, 0 is returned and slre.err_str points to the error message.
+ */
+int slre_compile(struct slre *, const char *re);
+
+/*
+ * Return 1 if match, 0 if no match.
+ * If `captured_substrings' array is not NULL, then it is filled with the
+ * values of captured substrings. captured_substrings[0] element is always
+ * a full matched substring. The round bracket captures start from
+ * captured_substrings[1].
+ * It is assumed that the size of captured_substrings array is enough to
+ * hold all captures. The caller function must make sure it is! So, the
+ * array_size = number_of_round_bracket_pairs + 1
+ */
+int slre_match(const struct slre *, const char *buf, int buf_len,
+       struct cap *captured_substrings);
+
+#endif /* SLRE_HEADER_DEFINED */
diff --git a/MdeModulePkg/Library/SlreRegExLib/SlreRegExLib.c 
b/MdeModulePkg/Library/SlreRegExLib/SlreRegExLib.c
new file mode 100644
index 0000000..a912595
--- /dev/null
+++ b/MdeModulePkg/Library/SlreRegExLib/SlreRegExLib.c
@@ -0,0 +1,301 @@
+/**
+  @file
+
+  RegExLib implementation using SLRE
+
+  Copyright (c) 2014-2015, Hewlett-Packard Development Company, L.P.<BR>
+
+  This program and the accompanying materials are licensed and made available
+  under the terms and conditions of the BSD License that accompanies this
+  distribution.  The full text of the license may be found at
+  http://opensource.org/licenses/bsd-license.php.
+
+  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, WITHOUT
+  WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+**/
+
+#include "SLRE/slre.h"
+
+#include <Uefi.h>
+
+#include <Library/RegExLib.h>
+#include <Library/MemoryAllocationLib.h>
+#include <Library/BaseLib.h>
+#include <Library/DebugLib.h>
+
+typedef struct {
+  struct slre SlreState;
+  struct cap  *SlreCaptures;
+  INT32       NumCaptures;
+} SLRE_REG_EX_STATE;
+
+/**
+  Compile a regular expression in preparation for matching with RegExMatch.
+  A call to RegExFree is always required to free resources regardless of
+  whether compilation was successful.
+
+  @param[out]   Handle    Pointer to RegExHandle to initialize. Must be freed
+                          with a call to RegExFree when no longer needed.
+  @param[in]    Pattern   Pointer to null-terminated ASCII string containing
+                          the desired regular expression.
+
+  @return   EFI_SUCCESS             Operation was successful.
+            EFI_ABORTED             Pattern could not be compiled. More 
information
+                                    may be found through RegExErrorMessage.
+            EFI_INVALID_PARAMETER   A required parameter was NULL.
+            EFI_OUT_OF_RESOURCES    Memory allocation failed.
+**/
+EFI_STATUS
+EFIAPI
+RegExCompile (
+  OUT       REG_EX_HANDLE *Handle,
+  IN  CONST CHAR8         *Pattern
+  )
+{
+  INT32             Result;
+  SLRE_REG_EX_STATE *SlreRegEx;
+
+  if (Handle == NULL || Pattern == NULL) {
+    return EFI_INVALID_PARAMETER;
+  }
+
+  *Handle = AllocatePool (sizeof(SLRE_REG_EX_STATE));
+  if (*Handle == NULL) {
+    return EFI_OUT_OF_RESOURCES;
+  }
+
+  SlreRegEx = *Handle;
+  SlreRegEx->SlreCaptures = NULL;
+  SlreRegEx->NumCaptures  = 0;
+
+  Result = slre_compile (&SlreRegEx->SlreState, Pattern);
+
+  return (Result == 1) ? EFI_SUCCESS : EFI_ABORTED;
+}
+
+/**
+  Search the input string for anything that matches the regular expression.
+
+  Be aware that the specific implementation of this library class may not
+  support all regular expression syntax, which could lead to unexpected 
results.
+
+  If no match is found, the contents of Captures is undefined (i.e. it may be
+  overwritten with invalid data).
+
+  @param[in]  Handle      The compiled regular expression.
+  @param[in]  String      Pointer to null-terminated ASCII string to match
+                          against the regular expression.
+  @param[out] Captures    Pointer to array of REG_EX_CAPTURE objects to receive
+                          the captured groups in the event of a match. 
According
+                          to convention, the full (sub-)string match is put in
+                          Captures[0], and the results of N capturing groups 
are
+                          put in Captures[1:N]. The caller must allocate the
+                          appropriate sized array (N+1). This parameter is 
optional
+                          and may be NULL.
+  @param[in]  NumCaptures Number of elements in the Captures array. If Captures
+                          is NULL, this should be zero.
+
+  @return   TRUE    Match was found.
+            FALSE   No match was found.
+**/
+BOOLEAN
+EFIAPI
+RegExMatch (
+  IN        REG_EX_HANDLE   Handle,
+  IN  CONST CHAR8           *String,
+  OUT       REG_EX_CAPTURE  Captures[],  OPTIONAL
+  IN        INT32           NumCaptures
+  )
+{
+  SLRE_REG_EX_STATE *SlreHandle;
+  INT32             Return;
+  INT32             Index;
+  struct cap        *SlreCaptures;
+
+  SlreHandle = Handle;
+
+  //
+  // Allocate internal captures buffer, same size as caller-provided buffer.
+  // Reuse across calls when possible.
+  //
+  if (Captures != NULL) {
+    if (SlreHandle->SlreCaptures != NULL && NumCaptures > 
SlreHandle->NumCaptures) {
+      FreePool (SlreHandle->SlreCaptures);
+      SlreHandle->SlreCaptures = NULL;
+    }
+    if (SlreHandle->SlreCaptures == NULL) {
+      SlreHandle->SlreCaptures = AllocateZeroPool (NumCaptures * sizeof(struct 
cap));
+      ASSERT (SlreHandle->SlreCaptures != NULL);
+    }
+    SlreHandle->NumCaptures = NumCaptures;
+    SlreCaptures = SlreHandle->SlreCaptures;
+  } else {
+    ASSERT (NumCaptures == 0);
+    SlreCaptures = NULL;
+  }
+
+  Return = slre_match (&SlreHandle->SlreState, String, (INT32)AsciiStrLen 
(String), SlreCaptures);
+
+  //
+  // Translate internal captures into RegExLib standard captures
+  //
+  if (Return == 1) {
+    for (Index = 0; Index < NumCaptures; ++Index) {
+      Captures[Index].Ptr    = SlreHandle->SlreCaptures[Index].ptr;
+      Captures[Index].Length = SlreHandle->SlreCaptures[Index].len;
+    }
+  }
+
+  return (Return == 1);
+}
+
+/**
+  Free any resources associated with this regular expression when it's no
+  longer needed.
+
+  @param[in]  Handle  Handle to regular expression to be freed.
+**/
+VOID
+EFIAPI
+RegExFree (
+  IN  REG_EX_HANDLE Handle
+  )
+{
+  SLRE_REG_EX_STATE *SlreHandle;
+
+  SlreHandle = Handle;
+
+  if (SlreHandle != NULL) {
+    if (SlreHandle->SlreCaptures != NULL) {
+      FreePool (SlreHandle->SlreCaptures);
+    }
+    FreePool (Handle);
+  }
+}
+
+/**
+  When compilation fails, the internal implementation may generate an error
+  string which can be read with this function. However, there may not always
+  be an error message when it seems like there should be, as this depends
+  on the specific implementation.
+
+  @param[in]  Handle  Handle to regular expression.
+
+  @return   Pointer to null-terminated ASCII error message. May be NULL or
+            an empty string if there is no applicable error.
+**/
+CONST CHAR8*
+EFIAPI
+RegExErrorMessage (
+  IN REG_EX_HANDLE Handle
+  )
+{
+  return ((SLRE_REG_EX_STATE*)Handle)->SlreState.err_str;
+}
+
+/**
+  Match the string against a regex pattern.
+
+  @param[in]    AnsiString      The string to check.
+  @param[in]    AnsiPattern     The regex pattern.
+
+  @retval TRUE     The string matches the pattern.
+  @retval FALSE    The string does not match the pattern.
+**/
+BOOLEAN
+RegExMatchStringAscii (
+  IN CONST CHAR8 *AnsiString,
+  IN CONST CHAR8 *AnsiPattern
+ )
+{
+  REG_EX_HANDLE RegExHandle;
+  EFI_STATUS    Status;
+  BOOLEAN       Result;
+
+  if ((AnsiString == NULL) || (AnsiPattern == NULL)) {
+    return FALSE;
+  }
+
+  Status = RegExCompile (&RegExHandle, AnsiPattern);
+  if (EFI_ERROR (Status)) {
+    DEBUG ((DEBUG_ERROR, "SLRE RegEx Compile failed: %r, %a\n", Status, 
RegExErrorMessage (RegExHandle)));
+    Result = FALSE;
+  } else {
+    Result = RegExMatch (RegExHandle, AnsiString, NULL, 0);
+  }
+
+  RegExFree (RegExHandle);
+
+  return Result;
+}
+
+/**
+  Match the string against a regex pattern.
+
+  @param[in]    String      The string to check.
+  @param[in]    Pattern     The regex pattern.
+
+  @retval TRUE     The string matches the pattern.
+  @retval FALSE    The string does not match the pattern.
+**/
+BOOLEAN
+RegExMatchString (
+  IN CONST CHAR16 *String,
+  IN CONST CHAR8  *Pattern
+ )
+{
+  BOOLEAN       Result;
+  CHAR8         *AnsiStr;
+
+  if ((String == NULL) || (Pattern == NULL)) {
+    return FALSE;
+  }
+
+  AnsiStr = (CHAR8 *) AllocatePool ((StrLen (String) + 1) * sizeof (CHAR8));
+  if (AnsiStr == NULL) {
+    return FALSE;
+  }
+
+  UnicodeStrToAsciiStr (String, AnsiStr);
+  Result = RegExMatchStringAscii (AnsiStr, Pattern);
+
+  FreePool (AnsiStr);
+
+  return Result;
+}
+
+/**
+  Match the string against a regex pattern.
+
+  If you happen to have a UCS-2 pattern string, this helper function will do
+  the ASCII conversion for you.
+
+  @param[in]    String      The string to check.
+  @param[in]    Pattern     The regex pattern.
+
+  @retval TRUE     The string matches the pattern.
+  @retval FALSE    The string does not match the pattern.
+**/
+BOOLEAN
+RegExMatchStringUnicode (
+  IN  CONST CHAR16  *String,
+  IN  CONST CHAR16  *Pattern
+  )
+{
+  CHAR8   *AsciiPattern;
+  BOOLEAN Match;
+
+  Match = FALSE;
+
+  AsciiPattern = AllocatePool (StrLen (Pattern) + 1);
+  if (AsciiPattern == NULL) {
+    return FALSE;
+  }
+  UnicodeStrToAsciiStr (Pattern, AsciiPattern);
+
+  Match = RegExMatchString (String, AsciiPattern);
+
+  FreePool (AsciiPattern);
+
+  return Match;
+}
diff --git a/MdeModulePkg/Library/SlreRegExLib/SlreRegExLib.inf 
b/MdeModulePkg/Library/SlreRegExLib/SlreRegExLib.inf
new file mode 100644
index 0000000..a8a6710
--- /dev/null
+++ b/MdeModulePkg/Library/SlreRegExLib/SlreRegExLib.inf
@@ -0,0 +1,38 @@
+##
+#  @file
+#
+#  RegExLib implementation using SLRE
+#
+#  Copyright (c) 2014-2015, Hewlett-Packard Development Company, L.P.<BR>
+#
+#  This program and the accompanying materials are licensed and made available
+#  under the terms and conditions of the BSD License that accompanies this
+#  distribution.  The full text of the license may be found at
+#  http://opensource.org/licenses/bsd-license.php.
+#
+#  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, 
WITHOUT
+#  WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+##
+
+[Defines]
+  INF_VERSION     = 0x00010017
+  BASE_NAME       = SlreRegExLib
+  FILE_GUID       = 985CB64D-620A-4E45-B84D-E39C5536D76F
+  MODULE_TYPE     = BASE
+  VERSION_STRING  = 1.0
+  LIBRARY_CLASS   = RegExLib
+
+[Sources]
+  SlreRegExLib.c
+  SLRE/SlreUefiPort.h
+  SLRE/slre.h
+  SLRE/slre.c
+
+[Packages]
+  MdePkg/MdePkg.dec
+  MdeModulePkg/MdeModulePkg.dec
+
+[LibraryClasses]
+  BaseLib
+  DebugLib
+  BaseMemoryLib
diff --git a/MdeModulePkg/MdeModulePkg.dec b/MdeModulePkg/MdeModulePkg.dec
index 93ae120..6b5d1ba 100644
--- a/MdeModulePkg/MdeModulePkg.dec
+++ b/MdeModulePkg/MdeModulePkg.dec
@@ -111,6 +111,9 @@
   ## @libraryclass   Provides core boot manager functions
   PlatformBootManagerLib|Include/Library/PlatformBootManagerLib.h

+  ## @libraryclass   Regular expression matching
+  RegExLib|Include/Library/RegExLib.h
+
 [Guids]
   ## MdeModule package token space guid
   # Include/Guid/MdeModulePkgTokenSpace.h
diff --git a/MdeModulePkg/MdeModulePkg.dsc b/MdeModulePkg/MdeModulePkg.dsc
index d0832bc..94ebbd8 100644
--- a/MdeModulePkg/MdeModulePkg.dsc
+++ b/MdeModulePkg/MdeModulePkg.dsc
@@ -95,6 +95,7 @@
   
S3BootScriptLib|MdeModulePkg/Library/PiDxeS3BootScriptLib/DxeS3BootScriptLib.inf
   
CpuExceptionHandlerLib|MdeModulePkg/Library/CpuExceptionHandlerLibNull/CpuExceptionHandlerLibNull.inf
   
PlatformBootManagerLib|MdeModulePkg/Library/PlatformBootManagerLibNull/PlatformBootManagerLibNull.inf
+  RegExLib|MdeModulePkg/Library/SlreRegExLib/SlreRegExLib.inf

 [LibraryClasses.EBC.PEIM]
   IoLib|MdePkg/Library/PeiIoLibCpuIo/PeiIoLibCpuIo.inf
@@ -298,6 +299,7 @@
   
MdeModulePkg/Universal/MonotonicCounterRuntimeDxe/MonotonicCounterRuntimeDxe.inf
   MdeModulePkg/Universal/ResetSystemRuntimeDxe/ResetSystemRuntimeDxe.inf
   MdeModulePkg/Universal/SmbiosDxe/SmbiosDxe.inf
+  MdeModulePkg/Universal/RegularExpressionDxe/RegularExpressionDxe.inf

   MdeModulePkg/Universal/Network/ArpDxe/ArpDxe.inf
   MdeModulePkg/Universal/Network/Dhcp4Dxe/Dhcp4Dxe.inf
diff --git a/MdeModulePkg/Universal/RegularExpressionDxe/RegularExpressionDxe.c 
b/MdeModulePkg/Universal/RegularExpressionDxe/RegularExpressionDxe.c
new file mode 100644
index 0000000..57558c9
--- /dev/null
+++ b/MdeModulePkg/Universal/RegularExpressionDxe/RegularExpressionDxe.c
@@ -0,0 +1,306 @@
+/**
+  @file
+
+  EFI_REGULAR_EXPRESSION_PROTOCOL Implementation
+
+  Copyright (c) 2015, Hewlett-Packard Development Company, L.P.<BR>
+
+  This program and the accompanying materials are licensed and made available
+  under the terms and conditions of the BSD License that accompanies this
+  distribution.  The full text of the license may be found at
+  http://opensource.org/licenses/bsd-license.php.
+
+  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, WITHOUT
+  WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+**/
+
+#include <Uefi.h>
+#include <Protocol/RegularExpressionProtocol.h>
+#include <Library/UefiBootServicesTableLib.h>
+#include <Library/BaseMemoryLib.h>
+#include <Library/RegExLib.h>
+#include <Library/MemoryAllocationLib.h>
+#include <Library/DebugLib.h>
+#include <Library/BaseLib.h>
+
+#define ARRAY_SIZE(Array) (sizeof(Array) / sizeof(*Array))
+
+STATIC
+EFI_REGEX_SYNTAX_TYPE * CONST mSupportedSyntaxes[] = {
+  &gEfiRegexSyntaxTypePosixExtendedGuid
+};
+
+/**
+  POSIX Extended regex syntax implementation.
+
+  @ref RegularExpressionMatch
+**/
+STATIC
+EFI_STATUS
+PosixExtendedMatch (
+  IN  CHAR16              *String,
+  IN  CHAR16              *Pattern,
+  OUT BOOLEAN             *Result,
+  OUT EFI_REGEX_CAPTURE   **Captures,     OPTIONAL
+  OUT UINTN               *CapturesCount
+  )
+{
+  REG_EX_HANDLE Regex;
+  CHAR8         *AsciiString;
+  CHAR8         *AsciiPattern;
+  EFI_STATUS    Status;
+
+  ASSERT (String != NULL);
+  ASSERT (Pattern != NULL);
+  ASSERT (Result != NULL);
+  ASSERT (CapturesCount != NULL);
+
+  //
+  // Our POSIX Extended library only supports ASCII input
+  //
+  AsciiString = AllocatePool (StrLen (String) + 1);
+  if (AsciiString == NULL) {
+    return EFI_OUT_OF_RESOURCES;
+  }
+  UnicodeStrToAsciiStr (String, AsciiString);
+
+  AsciiPattern = AllocatePool (StrLen (Pattern) + 1);
+  if (AsciiPattern == NULL) {
+    FreePool (AsciiString);
+    return EFI_OUT_OF_RESOURCES;
+  }
+  UnicodeStrToAsciiStr (Pattern, AsciiPattern);
+
+  //
+  // Compile and run the regex
+  //
+  Status = RegExCompile (&Regex, AsciiPattern);
+
+  if (!EFI_ERROR (Status)) {
+    *Result = RegExMatch (Regex, AsciiString, NULL, 0);
+  } else {
+    *Result = FALSE;
+  }
+
+  //
+  // Write out the results
+  //
+  if (!*Result) {
+    if (Captures != NULL) {
+      *Captures = NULL;
+    }
+    *CapturesCount = 0;
+  } else {
+    //
+    // Doesn't support sub-expression capture groups yet
+    //
+    if (Captures != NULL) {
+      *Captures = AllocatePool (sizeof(EFI_REGEX_CAPTURE));
+      (*Captures)[0].CapturePtr = String;
+      (*Captures)[0].Length = StrLen (String);
+    }
+    *CapturesCount = 1;
+  }
+
+  RegExFree (Regex);
+
+  FreePool (AsciiPattern);
+  FreePool (AsciiString);
+
+  return Status;
+}
+
+/**
+  Returns information about the regular expression syntax types supported
+  by the implementation.
+
+  This                     A pointer to the EFI_REGULAR_EXPRESSION_PROTOCOL
+                           instance.
+
+  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.
+
+  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 || 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.
+
+  This          A pointer to the EFI_REGULAR_EXPRESSION_PROTOCOL instance.
+                Type EFI_REGULAR_EXPRESSION_PROTOCOL is defined in Section
+                XYZ.
+
+  String        A pointer to a NULL terminated string to match against the
+                regular expression string specified by Pattern.
+
+  Pattern       A pointer to a NULL terminated string that represents the
+                regular expression.
+
+  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.
+
+  Result        On return, points to TRUE if String fully matches against
+                the regular expression Pattern using the regular expression
+                SyntaxType. Otherwise, points to FALSE.
+
+  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.
+
+  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;
+    }
+  }
+
+  //
+  // Here is where we determine which underlying library can handle the
+  // requested syntax. (Or possibly one library can implement all the
+  // protocols.)
+  //
+  if (CompareGuid (SyntaxType, &gEfiRegexSyntaxTypePosixExtendedGuid)) {
+    Status = PosixExtendedMatch (String, Pattern, Result, Captures, 
CapturesCount);
+  } else {
+    ASSERT (FALSE);
+    DEBUG ((DEBUG_ERROR, "Regex Syntax %g is supported but unimplemented\n", 
SyntaxType));
+    Status = EFI_DEVICE_ERROR;
+  }
+
+  return Status;
+}
+
+/**
+  Entry point for RegularExpressionDxe.
+**/
+EFI_STATUS
+EFIAPI
+RegularExpressionDxeEntry (
+  IN  EFI_HANDLE        ImageHandle,
+  IN  EFI_SYSTEM_TABLE  *SystemTable
+  )
+{
+  EFI_STATUS  Status;
+
+  STATIC
+  CONST EFI_REGULAR_EXPRESSION_PROTOCOL ProtocolInstance = {
+    RegularExpressionMatch,
+    RegularExpressionGetInfo
+  };
+
+  (VOID)SystemTable;
+
+  Status = gBS->InstallMultipleProtocolInterfaces (
+                  &ImageHandle,
+                  &gEfiRegularExpressionProtocolGuid,
+                  &ProtocolInstance,
+                  NULL
+                  );
+
+  return Status;
+}
diff --git 
a/MdeModulePkg/Universal/RegularExpressionDxe/RegularExpressionDxe.inf 
b/MdeModulePkg/Universal/RegularExpressionDxe/RegularExpressionDxe.inf
new file mode 100644
index 0000000..b83f105
--- /dev/null
+++ b/MdeModulePkg/Universal/RegularExpressionDxe/RegularExpressionDxe.inf
@@ -0,0 +1,44 @@
+##
+#  @file
+#
+#  EFI_REGULAR_EXPRESSION_PROTOCOL Implementation
+#
+#  Copyright (c) 2015, Hewlett-Packard Development Company, L.P.<BR>
+#
+#  This program and the accompanying materials are licensed and made available
+#  under the terms and conditions of the BSD License that accompanies this
+#  distribution.  The full text of the license may be found at
+#  http://opensource.org/licenses/bsd-license.php.
+#
+#  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, 
WITHOUT
+#  WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+##
+
+[Defines]
+  INF_VERSION     = 0x00010018
+  BASE_NAME       = RegularExpressionDxe
+  FILE_GUID       = 3E197E9C-D8DC-42D3-89CE-B04FA9833756
+  MODULE_TYPE     = UEFI_DRIVER
+  VERSION_STRING  = 1.0
+  ENTRY_POINT     = RegularExpressionDxeEntry
+
+[Sources]
+  RegularExpressionDxe.c
+
+[Packages]
+  MdePkg/MdePkg.dec
+  MdeModulePkg/MdeModulePkg.dec
+
+[LibraryClasses]
+  UefiBootServicesTableLib
+  UefiDriverEntryPoint
+  MemoryAllocationLib
+  BaseMemoryLib
+  DebugLib
+  RegExLib
+
+[Guids]
+  gEfiRegexSyntaxTypePosixExtendedGuid
+
+[Protocols]
+  gEfiRegularExpressionProtocolGuid
--
2.4.1


------------------------------------------------------------------------------
One dashboard for servers and applications across Physical-Virtual-Cloud
Widest out-of-the-box monitoring support with 50+ applications
Performance metrics, stats and reports that give you Actionable Insights
Deep dive visibility with transaction tracing using APM Insight.
http://ad.doubleclick.net/ddm/clk/290420510;117567292;y
_______________________________________________
edk2-devel mailing list
edk2-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/edk2-devel

------------------------------------------------------------------------------
One dashboard for servers and applications across Physical-Virtual-Cloud 
Widest out-of-the-box monitoring support with 50+ applications
Performance metrics, stats and reports that give you Actionable Insights
Deep dive visibility with transaction tracing using APM Insight.
http://ad.doubleclick.net/ddm/clk/290420510;117567292;y
_______________________________________________
edk2-devel mailing list
edk2-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/edk2-devel


------------------------------------------------------------------------------
_______________________________________________
edk2-devel mailing list
edk2-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/edk2-devel

Reply via email to