Add Fii oem command

Signed-off-by: mohaimen alsamarai <mohaimen.alsamarai@fii-na.com>
Change-Id: I1b9113367f71d9484688b3d7fe4a923007fe31e2
diff --git a/generate-whitelist.py b/generate-whitelist.py
new file mode 100755
index 0000000..c732726
--- /dev/null
+++ b/generate-whitelist.py
@@ -0,0 +1,107 @@
+#!/usr/bin/env python3
+
+import re, sys, os.path
+
+def usage():
+    sys.stderr.write("Usage: $0 whitelist-config-in whitelist-header-out\n")
+    sys.stderr.write("    Reads in whitelist config, sorting the contents\n")
+    sys.stderr.write("    and outputs a header file\n")
+    sys.exit(-1)
+
+class Error(Exception):
+    pass
+
+class DuplicateEntry(Error):
+    def __init__(self, e):
+        super(Error, self).__init__(
+             "Multiple entries with matching netfn/cmd found ({})".format(e))
+
+class ParseError(Error):
+    def __init__(self, d):
+        super(Error, self).__init__("Parse error at: '{}'".format(d))
+
+class entry:
+    linere = re.compile(
+            r'(0x[0-9a-f]{2}):(0x[0-9a-f]{2})((:(0x[0-9a-f]{4}))?)\s*((//\s*(.*))?)',
+            re.I
+        )
+    def __init__(self, data):
+        # parse data line into values:
+        # type 1, two values: netfn, cmd
+        # type 2, three values: netfn, cmd, channels
+        try:
+            m = self.linere.fullmatch(data).groups()
+        except:
+            raise ParseError(data)
+        self.netfn = int(m[0], 16)
+        self.cmd = int(m[1], 16)
+        if m[4] is not None:
+            self.channels = int(m[4], 16)
+        else:
+            # if no channel was provided, default to previous behavior, which
+            # is allow all interfaces, including the system interface (ch 15)
+            self.channels = 0xffff
+        if m[6] is not None:
+            self.comment = "// " + m[7]
+        else:
+            self.comment = "//"
+    def __str__(self):
+        return " ".join([ '{',
+            "0x{0.netfn:02x},".format(self),
+            "0x{0.cmd:02x},".format(self),
+            "0x{0.channels:04x}".format(self),
+            "},",
+            "{0.comment}".format(self),
+        ])
+    def __lt__(self, other):
+        if self.netfn == other.netfn:
+            return self.cmd < other.cmd
+        return self.netfn < other.netfn
+    def match(self, other):
+        return (self.netfn == other.netfn) and (self.cmd == other.cmd)
+
+def parse(config):
+    entries = []
+    with open(config) as f:
+        for line in f:
+            line = line.strip()
+            if len(line) == 0 or line[0] == '#':
+                continue
+            e = entry(line)
+            if any([e.match(item) for item in entries]):
+                d = DuplicateEntry(e)
+                sys.stderr.write("WARNING: {}\n".format(d))
+            else:
+                entries.append(e)
+    entries.sort()
+    return entries
+
+def output(entries, hppfile):
+    lines = [
+            "#pragma once",
+            "",
+            "// AUTOGENERATED FILE; DO NOT MODIFY",
+            "",
+            "#include <array>",
+            "#include <tuple>",
+            "",
+            "using netfncmd_tuple = std::tuple<unsigned char, unsigned char, unsigned short>;",
+            "",
+            "constexpr const std::array<netfncmd_tuple, {}> whitelist = ".format(
+                    len(entries)),
+            "{{"
+            ]
+    lines.extend(['    {}'.format(e) for e in entries])
+    lines.append("}};\n");
+
+    with open(hppfile, "w") as hpp:
+        hpp.write("\n".join(lines))
+
+
+if __name__ == "__main__":
+    if len(sys.argv) != 3:
+        usage()
+    config = sys.argv[1]
+    header = sys.argv[2]
+    entries = parse(config)
+    output(entries, header)