diff --git a/tdx-compliance/auto_gen.py b/tdx-compliance/auto_gen.py new file mode 100644 index 00000000..ad772cd0 --- /dev/null +++ b/tdx-compliance/auto_gen.py @@ -0,0 +1,151 @@ + + +# related filepath +import csv +import sys + +import pandas +import math +import json +version = "1.5" +class GetPath: + def __init__(self, config_path): + # 初始化成员变量 + self.config_path = config_path + self.csv_path = None + self.header_path = None + self.vdetail = None + self.vtype = None + self.bias = 0 + + def read_config_csv(self, ptype): + try: + with open(self.config_path, 'r') as config_file: + config_data = json.load(config_file) + self.csv_path = config_data.get(ptype, {}).get('csv_path', None) + self.header_path = config_data.get(ptype, {}).get('header_path', None) + self.vdetail = config_data.get(ptype, {}).get('vdetail', None) + self.vtype = config_data.get(ptype, {}).get('vtype', None) + self.bias = config_data.get(ptype, {}).get('bias', 0) + return 0 + except: + return -1 + +class CsvData: + def __init__(self, bias=0, vdetail='Virtualization Details', vtype='Bit or Field Virtualization Type'): + # 初始化成员变量,ans 为一个空数组 + self.ans = [] + self.bias = bias + self.vdetail=vdetail + self.vtype=vtype + self.body = [] + + def parse_csv(self, csv_path): + self.ans = [] + try: + df = pandas.read_csv(csv_path, skiprows=range(int(self.bias))) + columns = df.columns.tolist() + column_indices = {column: index for index, column in enumerate(columns)} + except: + return -1 + + for index, row in df.iterrows(): + virtualization_type = row[columns[column_indices[self.vtype]]] + + # if "Bit or Field Virtualization Type"="Fixed" + if virtualization_type == 'Fixed': + entry = [] + leaf = row[columns[column_indices['Leaf']]] + sl_from = row[columns[column_indices['Sub-Leaf From']]] + sl_to = row[columns[column_indices['Sub-Leaf To']]] + if isinstance(sl_from, float) and math.isnan(sl_from): + sl_from = 0x0 + sl_to = 0x0 + else: + sl_from = int(sl_from, 16) + sl_to = int(sl_to, 16) + reg = row[columns[column_indices['Reg.']]] + msb = int(row[columns[column_indices['MSB']]]) + lsb = int(row[columns[column_indices['LSB']]]) + field_size = int(row[columns[column_indices['Field Size']]]) + virtualization_details = str(row[columns[column_indices[self.vdetail]]]) + field_name = row[columns[column_indices['Field Name']]] + + for i in range(sl_from, sl_to + 1): + subleaf = str(hex(i)) + entry = [leaf, subleaf, reg, msb, lsb, field_size, field_name, virtualization_details] + self.ans.append(entry) + return 0 + + def get_body(self): + self.body = [] + for entry in self.ans: + leaf = entry[0] + subleaf = entry[1] + reg = entry[2] + msb = entry[3] + lsb = entry[4] + size = entry[5] + name = entry[6] + val = entry[7] + if entry[5] == 32: + self.body.append("EXP_CPUID_BYTE(%s, %s, %s, %s, %s);\t//%s" % ( \ + leaf, subleaf, reg, val, version, name)) + + elif entry[5] == 1: + self.body.append("EXP_CPUID_BIT(%s, %s, %s, %s, %s, %s);\t//%s" % ( \ + leaf, subleaf, reg, msb, val, version, name)) + else: + self.body.append("EXP_CPUID_RES_BITS(%s, %s, %s, %s, %s, %s);\t//%s" % ( \ + leaf, subleaf, reg, lsb, msb, version, name)) + +def write2header(path, list, ptype, funcName="initial_cpuid"): + """ + gen a header file + :param path: + :param list: stores the generated statements for all cases. + :param funcName: the initial-func name defined in header file. + :return: if -1 is returned, it means the write failed + """ + function_name = f"void {funcName}(void)" + ptype = ptype.upper() + try: + with open(path, 'w') as header_file: + header_file.write(f"#define AUTOGEN_{ptype}\n\n") + header_file.write(f"{function_name} {{\n") + + for line in list: + header_file.write('\t' + line + '\n') + header_file.write("}\n") + return 0 + except: + return -1 + +if __name__ == '__main__': + + # init all params + config_path = 'config.json' + ptype = "cpuid" + path_info = GetPath(config_path) + if path_info.read_config_csv(ptype) == -1: + print("Failed to read config. Exiting program.") + sys.exit(1) + + + # parse to a list + get_csv = CsvData(path_info.bias) + get_csv.parse_csv(path_info.csv_path) + if get_csv.ans == []: + print("Failed to parse csv. Exiting program.") + sys.exit(1) + #assert get_csv.ans, "ans is empty. Exiting program." + get_csv.get_body() + + #gen a header file + write2header(path_info.header_path, get_csv.body, ptype) + + + + + + diff --git a/tdx-compliance/config.json b/tdx-compliance/config.json new file mode 100644 index 00000000..fec02bde --- /dev/null +++ b/tdx-compliance/config.json @@ -0,0 +1,23 @@ +{ + "cpuid":{ + "csv_path": "aa.csv", + "header_path": "cpuid_case.h", + "vdetail": "", + "vtype": "", + "bias": "2" + }, + "cr":{ + "csv_path": "", + "header_path": "", + "vdetail": "", + "vtype": "", + "bias": "2" + }, + "msr":{ + "csv_path": "", + "header_path": "msr_case.h", + "vdetail": "", + "vtype": "", + "bias": "2" + } +} \ No newline at end of file diff --git a/tdx-compliance/tdx-compliance-cpuid.h b/tdx-compliance/tdx-compliance-cpuid.h index a951a12f..161378cd 100644 --- a/tdx-compliance/tdx-compliance-cpuid.h +++ b/tdx-compliance/tdx-compliance-cpuid.h @@ -47,6 +47,9 @@ list_add_tail(&t->list, &cpuid_list); \ } while (0) +#ifdef AUTOGEN_CPUID +extern void initial_cpuid(void); +#else void initial_cpuid(void) { /* CPUID(0x0) */ @@ -540,3 +543,4 @@ void initial_cpuid(void) /* CPUID(0x80000008).EDX */ EXP_CPUID_RES_BITS(0x80000008, 0x0, edx, 0, 31, VER1_0); //Reserved } +#endif