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

Reply via email to