1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130
|
#
# Copyright (C) 2023 Advanced Micro Devices. All rights reserved.
#
# Permission is hereby granted, free of charge, to any person obtaining a copy of
# this software and associated documentation files (the "Software"), to deal in
# the Software without restriction, including without limitation the rights to
# use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
# the Software, and to permit persons to whom the Software is furnished to do so,
# subject to the following conditions:
#
# The above copyright notice and this permission notice shall be included in all
# copies or substantial portions of the Software.
#
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
# FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
# COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
# IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
# CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
#
import logging
import re
class BDF():
""" BDF Class to cast and compare BDF objects using built-in python comparators
Useful for validating a BDF string and converting it to a BDF object
This allows us to handle BDF objects in a pythonic way
Attributes:
__eq__: The equals comparator
__: An integer count of the eggs we have laid.
"""
def __init__(self, bdf):
"""Init a BDF object"""
if isinstance(bdf, BDF):
self.segment, self.bus, self.device, self.function = tuple(bdf)
else:
if bdf.startswith("BDF("):
bdf = bdf.replace('BDF(', '').replace(')', '')
try:
bdf_components = [int(x, 16) for x in re.split('[:.]', bdf)]
except self.BDFError as e:
logging.error(f"Invalid string passed: {bdf}")
raise e
self.segment = bdf_components[0] if len(bdf_components) == 4 else 0
self.bus, self.device, self.function = bdf_components[-3:]
if self.segment > 65535:
raise self.BDFError("Segment can't be greater than 65535")
if self.bus > 255:
raise self.BDFError("Bus can't be greater than 255")
if self.device > 31:
raise self.BDFError("Device can't be greater than 31")
if self.function > 7:
raise self.BDFError("Function can't be greater than 7")
class BDFError(Exception):
"""BDF Class Error"""
def __eq__(self, passed_bdf):
"""Overrides the == operator and allows for BDF objects to be compared to BDF strings"""
# Only accept strings and BDF objects
if isinstance(passed_bdf, str):
if passed_bdf == '':
return False
passed_bdf = BDF(passed_bdf)
elif not isinstance(passed_bdf, BDF):
return False
if self.segment == passed_bdf.segment and \
self.bus == passed_bdf.bus and \
self.device == passed_bdf.device and \
self.function == passed_bdf.function:
return True
else:
return False
def __ne__(self, passed_bdf):
"""Overrides the != operator and allows for BDF objects to be compared to BDF strings"""
# Since we overrided the == operator we can use that to make this simple
return not self == passed_bdf
def __add__(self, passed_bdf):
"""Overrides the + operator and allows for string concatenation"""
return str(self) + passed_bdf
def __radd__(self, passed_bdf):
"""Overrides the + operator and allows for string concatenation"""
return passed_bdf + str(self)
def __str__(self):
"""Cast BDF object to a string"""
return "{:04X}:{:02X}:{:02X}:{}".format(self.segment, self.bus, self.device, self.function)
def __repr__(self):
"""How the BDF object is represented"""
return f"BDF({self})"
def __hash__(self):
"""Allow the BDF object to be hashable"""
return hash(str(self))
def __iter__(self):
"""Make the BDF object iterable over its 4 values"""
yield from (self.segment, self.bus, self.device, self.function)
def __contains__(self, passed_bdf):
"""Overrided the 'in' comparator in python"""
passed_bdf = str(BDF(passed_bdf))
bdf_regex = "(?:[0-6]?[0-9a-fA-F]{1,4}:)?[0-2]?[0-9a-fA-F]{1,2}:[0-9a-fA-F]{1,2}\\.[0-7]"
for match in re.findall(bdf_regex, passed_bdf):
if self == match:
return True
return False
|