xref: /openbmc/intel-ipmi-oem/generate-allowlist.py (revision 844f8fc10d58fd183f958f0609d851033b504183)
18b7c156eSVernon Mauery#!/usr/bin/env python3
28b7c156eSVernon Mauery
3*844f8fc1SPatrick Williamsimport re
4*844f8fc1SPatrick Williamsimport sys
5*844f8fc1SPatrick Williams
68b7c156eSVernon Mauery
78b7c156eSVernon Mauerydef usage():
88b7c156eSVernon Mauery    sys.stderr.write("Usage: $0 allowlist-config-in allowlist-header-out\n")
98b7c156eSVernon Mauery    sys.stderr.write("    Reads in allowlist config, sorting the contents\n")
108b7c156eSVernon Mauery    sys.stderr.write("    and outputs a header file\n")
118b7c156eSVernon Mauery    sys.exit(-1)
128b7c156eSVernon Mauery
13*844f8fc1SPatrick Williams
148b7c156eSVernon Maueryclass Error(Exception):
158b7c156eSVernon Mauery    pass
168b7c156eSVernon Mauery
17*844f8fc1SPatrick Williams
188b7c156eSVernon Maueryclass DuplicateEntry(Error):
198b7c156eSVernon Mauery    def __init__(self, e):
208b7c156eSVernon Mauery        super(Error, self).__init__(
21*844f8fc1SPatrick Williams            "Multiple entries with matching netfn/cmd found ({})".format(e)
22*844f8fc1SPatrick Williams        )
23*844f8fc1SPatrick Williams
248b7c156eSVernon Mauery
258b7c156eSVernon Maueryclass ParseError(Error):
268b7c156eSVernon Mauery    def __init__(self, d):
278b7c156eSVernon Mauery        super(Error, self).__init__("Parse error at: '{}'".format(d))
288b7c156eSVernon Mauery
29*844f8fc1SPatrick Williams
308b7c156eSVernon Maueryclass entry:
318b7c156eSVernon Mauery    linere = re.compile(
32*844f8fc1SPatrick Williams        r"(0x[0-9a-f]{2}):(0x[0-9a-f]{2})((:(0x[0-9a-f]{4}))?)\s*((//\s*(.*))?)",  # noqa: E501
33*844f8fc1SPatrick Williams        re.I,
348b7c156eSVernon Mauery    )
35*844f8fc1SPatrick Williams
368b7c156eSVernon Mauery    def __init__(self, data):
378b7c156eSVernon Mauery        # parse data line into values:
388b7c156eSVernon Mauery        # type 1, two values: netfn, cmd
398b7c156eSVernon Mauery        # type 2, three values: netfn, cmd, channels
408b7c156eSVernon Mauery        try:
418b7c156eSVernon Mauery            m = self.linere.fullmatch(data).groups()
42*844f8fc1SPatrick Williams        except Exception:
438b7c156eSVernon Mauery            raise ParseError(data)
448b7c156eSVernon Mauery        self.netfn = int(m[0], 16)
458b7c156eSVernon Mauery        self.cmd = int(m[1], 16)
468b7c156eSVernon Mauery        if m[4] is not None:
478b7c156eSVernon Mauery            self.channels = int(m[4], 16)
488b7c156eSVernon Mauery        else:
498b7c156eSVernon Mauery            # if no channel was provided, default to previous behavior, which
508b7c156eSVernon Mauery            # is allow all interfaces, including the system interface (ch 15)
51*844f8fc1SPatrick Williams            self.channels = 0xFFFF
528b7c156eSVernon Mauery        if m[6] is not None:
538b7c156eSVernon Mauery            self.comment = "// " + m[7]
548b7c156eSVernon Mauery        else:
558b7c156eSVernon Mauery            self.comment = "//"
56*844f8fc1SPatrick Williams
578b7c156eSVernon Mauery    def __str__(self):
58*844f8fc1SPatrick Williams        return " ".join(
59*844f8fc1SPatrick Williams            [
60*844f8fc1SPatrick Williams                "{",
618b7c156eSVernon Mauery                "0x{0.netfn:02x},".format(self),
628b7c156eSVernon Mauery                "0x{0.cmd:02x},".format(self),
638b7c156eSVernon Mauery                "0x{0.channels:04x}".format(self),
648b7c156eSVernon Mauery                "},",
658b7c156eSVernon Mauery                "{0.comment}".format(self),
66*844f8fc1SPatrick Williams            ]
67*844f8fc1SPatrick Williams        )
68*844f8fc1SPatrick Williams
698b7c156eSVernon Mauery    def __lt__(self, other):
708b7c156eSVernon Mauery        if self.netfn == other.netfn:
718b7c156eSVernon Mauery            return self.cmd < other.cmd
728b7c156eSVernon Mauery        return self.netfn < other.netfn
73*844f8fc1SPatrick Williams
748b7c156eSVernon Mauery    def match(self, other):
758b7c156eSVernon Mauery        return (self.netfn == other.netfn) and (self.cmd == other.cmd)
768b7c156eSVernon Mauery
77*844f8fc1SPatrick Williams
788b7c156eSVernon Mauerydef parse(config):
798b7c156eSVernon Mauery    entries = []
808b7c156eSVernon Mauery    with open(config) as f:
818b7c156eSVernon Mauery        for line in f:
828b7c156eSVernon Mauery            line = line.strip()
83*844f8fc1SPatrick Williams            if len(line) == 0 or line[0] == "#":
848b7c156eSVernon Mauery                continue
858b7c156eSVernon Mauery            e = entry(line)
868b7c156eSVernon Mauery            if any([e.match(item) for item in entries]):
878b7c156eSVernon Mauery                d = DuplicateEntry(e)
888b7c156eSVernon Mauery                sys.stderr.write("WARNING: {}\n".format(d))
898b7c156eSVernon Mauery            else:
908b7c156eSVernon Mauery                entries.append(e)
918b7c156eSVernon Mauery    entries.sort()
928b7c156eSVernon Mauery    return entries
938b7c156eSVernon Mauery
94*844f8fc1SPatrick Williams
958b7c156eSVernon Mauerydef output(entries, hppfile):
968b7c156eSVernon Mauery    lines = [
978b7c156eSVernon Mauery        "#pragma once",
988b7c156eSVernon Mauery        "",
998b7c156eSVernon Mauery        "// AUTOGENERATED FILE; DO NOT MODIFY",
1008b7c156eSVernon Mauery        "",
1018b7c156eSVernon Mauery        "#include <array>",
1028b7c156eSVernon Mauery        "#include <tuple>",
1038b7c156eSVernon Mauery        "",
104*844f8fc1SPatrick Williams        (
105*844f8fc1SPatrick Williams            "using netfncmd_tuple = std::tuple<unsigned char, unsigned char,"
106*844f8fc1SPatrick Williams            " unsigned short>;"
107*844f8fc1SPatrick Williams        ),
1088b7c156eSVernon Mauery        "",
1098b7c156eSVernon Mauery        "constexpr const std::array<netfncmd_tuple, {}> allowlist = ".format(
110*844f8fc1SPatrick Williams            len(entries)
111*844f8fc1SPatrick Williams        ),
112*844f8fc1SPatrick Williams        "{{",
1138b7c156eSVernon Mauery    ]
114*844f8fc1SPatrick Williams    lines.extend(["    {}".format(e) for e in entries])
115*844f8fc1SPatrick Williams    lines.append("}};\n")
1168b7c156eSVernon Mauery
1178b7c156eSVernon Mauery    with open(hppfile, "w") as hpp:
1188b7c156eSVernon Mauery        hpp.write("\n".join(lines))
1198b7c156eSVernon Mauery
1208b7c156eSVernon Mauery
1218b7c156eSVernon Maueryif __name__ == "__main__":
1228b7c156eSVernon Mauery    if len(sys.argv) != 3:
1238b7c156eSVernon Mauery        usage()
1248b7c156eSVernon Mauery    config = sys.argv[1]
1258b7c156eSVernon Mauery    header = sys.argv[2]
1268b7c156eSVernon Mauery    entries = parse(config)
1278b7c156eSVernon Mauery    output(entries, header)
128