1# Copyright (C) 2019-2022 Intel Corporation. 2# 3# SPDX-License-Identifier: BSD-3-Clause 4# 5 6import logging 7 8import board_cfg_lib 9import acrn_config_utilities 10 11PLATFORM_HEADER = r"""/* DO NOT MODIFY THIS FILE UNLESS YOU KNOW WHAT YOU ARE DOING! 12 */ 13 14#ifndef PLATFORM_ACPI_INFO_H 15#define PLATFORM_ACPI_INFO_H 16""" 17 18PLATFORM_END_HEADER = "#endif /* PLATFORM_ACPI_INFO_H */" 19 20 21class OverridAccessSize(): 22 """ The Pm access size which are needed to redefine """ 23 def __init__(self): 24 self.pm1a_cnt_ac_sz = True 25 self.pm1b_cnt_ac_sz = True 26 self.pm1b_evt_ac_sz = True 27 28 def style_check_1(self): 29 """ Style check if have public method """ 30 self.pm1a_cnt_ac_sz = True 31 32 def style_check_2(self): 33 """ Style check if have public method """ 34 self.pm1a_cnt_ac_sz = True 35 36 37def multi_parser(line, s_line, pm_ac_sz, config): 38 """ 39 Multi parse the line 40 :param line: it is a line read from default_acpi_info.h 41 :param s_line: it is a line read from board information file 42 :param pm_ac_sz: it is a class for access size which would be override 43 :param config: it is a file pointer to write acpi information 44 """ 45 addr = ['PM1A_EVT_ADDRESS', 'PM1B_EVT_ADDRESS', 'PM1A_CNT_ADDRESS', 'PM1B_CNT_ADDRESS'] 46 space_id = ['PM1A_EVT_SPACE_ID', 'PM1B_EVT_SPACE_ID', 'PM1A_CNT_SPACE_ID', 'PM1B_CNT_SPACE_ID'] 47 48 if line.split()[1] in space_id and line.split()[1] == s_line.split()[1]: 49 if line.split()[2] != s_line.split()[2]: 50 print("#undef {}".format(s_line.split()[1]), file=config) 51 print("{}".format(s_line.strip()), file=config) 52 return 53 54 if line.split()[1] in addr and line.split()[1] == s_line.split()[1]: 55 if int(line.split()[2].strip('UL'), 16) != \ 56 int(s_line.split()[2].strip('UL'), 16) and \ 57 int(s_line.split()[2].strip('UL'), 16) != 0: 58 print("#undef {}".format(s_line.split()[1]), file=config) 59 print("{}".format(s_line.strip()), file=config) 60 else: 61 if "PM1B_EVT" in line.split()[1]: 62 pm_ac_sz.pm1b_evt_ac_sz = False 63 if "PM1B_CNT" in line.split()[1]: 64 pm_ac_sz.pm1b_cnt_ac_sz = False 65 66 return 67 68 if line.split()[1] == s_line.split()[1]: 69 if "PM1B_EVT" in line.split()[1] and not pm_ac_sz.pm1b_evt_ac_sz: 70 return 71 72 if "PM1B_CNT" in line.split()[1] and not pm_ac_sz.pm1b_cnt_ac_sz: 73 return 74 75 if "PM1A_CNT" in line.split()[1] and not pm_ac_sz.pm1a_cnt_ac_sz: 76 return 77 78 if int(line.split()[2].strip('U'), 16) != int(s_line.split()[2].strip('U'), 16): 79 print("#undef {}".format(s_line.split()[1]), file=config) 80 print("{}".format(s_line.strip()), file=config) 81 82 83def multi_info_parser(config, default_platform, msg_s, msg_e): 84 """ 85 Parse multi information 86 :param config: it is a file pointer to write acpi information 87 :param default_platform: it is the default_acpi_info.h in acrn-hypervisor 88 :param msg_s: it is a pattern of key stings what start to match from board information 89 :param msg_e: it is a pattern of key stings what end to match from board information 90 """ 91 write_direct = ['PM1A_EVT_ACCESS_SIZE', 'PM1A_EVT_ADDRESS', 'PM1A_CNT_ADDRESS'] 92 93 pm_ac_sz = OverridAccessSize() 94 multi_lines = board_cfg_lib.get_info(acrn_config_utilities.BOARD_INFO_FILE, msg_s, msg_e) 95 96 msg_name = msg_s.split('_')[0].strip('<') 97 98 # Set defaults for PM1A registers if not present in target xml file 99 if not multi_lines and msg_name in ("PM1A"): 100 print("#define PM1A_EVT_ACCESS_SIZE\t0U", file=config) 101 print("#define PM1A_EVT_ADDRESS\t0UL", file=config) 102 print("#define PM1A_CNT_ADDRESS\t0UL", file=config) 103 return 104 105 # S3/S5 not supported by BIOS 106 if not multi_lines and msg_name in ("S3", "S5"): 107 print("/* {} is not supported by BIOS */".format(msg_name), file=config) 108 return 109 110 for s_line in multi_lines: 111 # parse the commend line 112 if '/*' in s_line: 113 print("{}".format(s_line), file=config) 114 continue 115 116 if s_line.split()[1] in write_direct: 117 if "PM1A_CNT" in s_line.split()[1] and int(s_line.split()[2].strip('UL'), 16) == 0: 118 pm_ac_sz.pm1a_cnt_ac_sz = False 119 120 print("{}".format(s_line.strip()), file=config) 121 continue 122 123 with open(default_platform, 'r') as default: 124 while True: 125 line = default.readline() 126 127 if not line: 128 break 129 130 if len(line.split()) < 2: 131 continue 132 133 multi_parser(line, s_line, pm_ac_sz, config) 134 135 136def write_direct_info_parser(config, msg_s, msg_e): 137 """ 138 Direct to write 139 :param config: it is a file pointer to write acpi information 140 :param msg_s: it is a pattern of key stings what start to match from board information 141 :param msg_e: it is a pattern of key stings what end to match from board information 142 """ 143 vector_lines = board_cfg_lib.get_info(acrn_config_utilities.BOARD_INFO_FILE, msg_s, msg_e) 144 msg_name = msg_s.split('_')[0].strip('<') 145 146 # Set defaults if not present in target xml file 147 if not vector_lines and msg_name in ("WAKE"): 148 print("\n#define WAKE_VECTOR_32\t\t0UL", file=config) 149 print("#define WAKE_VECTOR_64\t\t0UL", file=config) 150 return 151 152 if not vector_lines and msg_name in ("RESET"): 153 print("\n#define RESET_REGISTER_ADDRESS\t0UL", file=config) 154 print("#define RESET_REGISTER_VALUE\t0UL", file=config) 155 print("#define RESET_REGISTER_SPACE_ID\t0UL", file=config) 156 return 157 158 if not vector_lines and msg_name in ("MMCFG"): 159 print("\n#define DEFAULT_PCI_MMCFG_BASE\t0UL", file=config) 160 return 161 162 if msg_name in ("IOMEM"): 163 if vector_lines: 164 for vector in vector_lines: 165 if "MMCONFIG" in vector: 166 try: 167 bus_list = vector.split("bus")[1].strip().split("-") 168 start_bus_number = int(bus_list[0].strip(), 16) 169 end_bus_number = int(bus_list[1].strip("]"), 16) 170 print("/* PCI mmcfg bus number of MCFG */", file=config) 171 print("#define DEFAULT_PCI_MMCFG_START_BUS \t 0x{:X}U".format(start_bus_number), file=config) 172 print("#define DEFAULT_PCI_MMCFG_END_BUS \t 0x{:X}U\n".format(end_bus_number), file=config) 173 print("", file=config) 174 return 175 except: 176 pass 177 178 print("/* PCI mmcfg bus number of MCFG */", file=config) 179 print("#define DEFAULT_PCI_MMCFG_START_BUS\t0U", file=config) 180 print("#define DEFAULT_PCI_MMCFG_END_BUS\t0U", file=config) 181 print("", file=config) 182 return 183 184 for vector in vector_lines: 185 print("{}".format(vector.strip()), file=config) 186 187 print("", file=config) 188 189 190def drhd_info_parser(config): 191 """ 192 Parse DRHD information 193 :param config: it is a file pointer to write acpi information 194 """ 195 has_drhd_max_devscope_count = False 196 197 drhd_lines = board_cfg_lib.get_info( 198 acrn_config_utilities.BOARD_INFO_FILE, "<DRHD_INFO>", "</DRHD_INFO>") 199 200 # write DRHD 201 print("/* DRHD of DMAR */", file=config) 202 203 if not drhd_lines: 204 print("\n#define DRHD_COUNT\t\t8U", file=config) 205 print("\n#define DRHD_MAX_DEVSCOPE_COUNT\t16U", file=config) 206 return 207 208 for drhd in drhd_lines: 209 if "DRHD_MAX_DEVSCOPE_COUNT" in drhd: 210 has_drhd_max_devscope_count = True 211 break 212 213 if not has_drhd_max_devscope_count: 214 logging.warning("DRHD_MAX_DEVSCOPE_COUNT is not defined in board.xml, using default 16U. " 215 "Generate board.xml with latest board inspector to remove this warning.") 216 print("\n#define DRHD_MAX_DEVSCOPE_COUNT\t16U", file=config) 217 218 for drhd in drhd_lines: 219 print(drhd.strip(), file=config) 220 221 222def platform_info_parser(config, default_platform): 223 """ 224 Parse ACPI information 225 :param config: it is a file pointer to write acpi information 226 :param default_platform: it is the default_acpi_info.h in acrn-hypervisor 227 """ 228 print("\n/* pm sstate data */", file=config) 229 multi_info_parser(config, default_platform, "<PM_INFO>", "</PM_INFO>") 230 multi_info_parser(config, default_platform, "<S3_INFO>", "</S3_INFO>") 231 multi_info_parser(config, default_platform, "<S5_INFO>", "</S5_INFO>") 232 print("", file=config) 233 234 write_direct_info_parser(config, "<WAKE_VECTOR_INFO>", "</WAKE_VECTOR_INFO>") 235 write_direct_info_parser(config, "<RESET_REGISTER_INFO>", "</RESET_REGISTER_INFO>") 236 drhd_info_parser(config) 237 write_direct_info_parser(config, "<MMCFG_BASE_INFO>", "</MMCFG_BASE_INFO>") 238 write_direct_info_parser(config, "<IOMEM_INFO>", "</IOMEM_INFO>") 239 240 241def generate_file(config, default_platform): 242 """ 243 write board_name_acpi_info.h 244 :param config: it is a file pointer to write acpi information 245 :param default_platform: it is the default_acpi_info.h in acrn-hypervisor 246 """ 247 print("{}".format(board_cfg_lib.HEADER_LICENSE), file=config) 248 249 print("{}".format(PLATFORM_HEADER), file=config) 250 251 board_cfg_lib.handle_bios_info(config) 252 # parse for the platform info 253 platform_info_parser(config, default_platform) 254 255 print("{}".format(PLATFORM_END_HEADER), file=config) 256