1# Copyright (C) 2021-2022 Intel Corporation. 2# 3# SPDX-License-Identifier: BSD-3-Clause 4# 5 6import ctypes 7import copy 8 9import inspectorlib.cdata as cdata 10import inspectorlib.unpack as unpack 11from acpiparser._utils import TableHeader, GAS 12 13_preferred_pm_profile = { 14 0: 'Unspecified', 15 1: 'Desktop', 16 2: 'Mobile', 17 3: 'Workstation', 18 4: 'Enterprise Server', 19 5: 'SOHO Server', 20 6: 'Appliance PC', 21 7: 'Performance Server', 22 8: 'Tablet' 23} 24 25class facp_flags_bits_v1(cdata.Struct): 26 _pack_ = 1 27 _fields_ = [ 28 ('wbinvd', ctypes.c_uint32, 1), 29 ('wbinvd_flush', ctypes.c_uint32, 1), 30 ('proc_c1', ctypes.c_uint32, 1), 31 ('p_lvl2_up', ctypes.c_uint32, 1), 32 ('pwr_button', ctypes.c_uint32, 1), 33 ('slp_button', ctypes.c_uint32, 1), 34 ('fix_rtc', ctypes.c_uint32, 1), 35 ('rtc_s4', ctypes.c_uint32, 1), 36 ('tmr_val_ext', ctypes.c_uint32, 1), 37 ('dck_cap', ctypes.c_uint32, 1), 38 ] 39 40class facp_flags_v1(cdata.Union): 41 _pack_ = 1 42 _anonymous_ = ("bits",) 43 _fields_ = [ 44 ('data', ctypes.c_uint32), 45 ('bits', facp_flags_bits_v1), 46 ] 47 48class FACP_v1(cdata.Struct): 49 _pack_ = 1 50 _fields_ = [ 51 ('header', TableHeader), 52 ('firmware_ctrl', ctypes.c_uint32), 53 ('dsdt', ctypes.c_uint32), 54 ('int_model', ctypes.c_uint8), 55 ('reserved0', ctypes.c_uint8), 56 ('sci_int', ctypes.c_uint16), 57 ('smi_cmd', ctypes.c_uint32), 58 ('acpi_enable', ctypes.c_uint8), 59 ('acpi_disable', ctypes.c_uint8), 60 ('s4bios_req', ctypes.c_uint8), 61 ('reserved1', ctypes.c_uint8), 62 ('pm1a_evt_blk', ctypes.c_uint32), 63 ('pm1b_evt_blk', ctypes.c_uint32), 64 ('pm1a_cnt_blk', ctypes.c_uint32), 65 ('pm1b_cnt_blk', ctypes.c_uint32), 66 ('pm2_cnt_blk', ctypes.c_uint32), 67 ('pm_tmr_blk', ctypes.c_uint32), 68 ('gpe0_blk', ctypes.c_uint32), 69 ('gpe1_blk', ctypes.c_uint32), 70 ('pm1_evt_len', ctypes.c_uint8), 71 ('pm1_cnt_len', ctypes.c_uint8), 72 ('pm2_cnt_len', ctypes.c_uint8), 73 ('pm_tmr_len', ctypes.c_uint8), 74 ('gpe0_blk_len', ctypes.c_uint8), 75 ('gpe1_blk_len', ctypes.c_uint8), 76 ('gpe1_base', ctypes.c_uint8), 77 ('reserved2', ctypes.c_uint8), 78 ('p_lvl2_lat', ctypes.c_uint16), 79 ('p_lvl3_lat', ctypes.c_uint16), 80 ('flush_size', ctypes.c_uint16), 81 ('flush_stride', ctypes.c_uint16), 82 ('duty_offset', ctypes.c_uint8), 83 ('duty_width', ctypes.c_uint8), 84 ('day_alrm', ctypes.c_uint8), 85 ('mon_alrm', ctypes.c_uint8), 86 ('century', ctypes.c_uint8), 87 ('reserved3', ctypes.c_uint8 * 3), 88 ('flags', facp_flags_v1), 89 ] 90 91class facp_flags_bits_v3(cdata.Struct): 92 _pack_ = 1 93 _fields_ = copy.copy(facp_flags_bits_v1._fields_) + [ 94 ('reset_reg_sup', ctypes.c_uint32, 1), 95 ('sealed_case', ctypes.c_uint32, 1), 96 ('headless', ctypes.c_uint32, 1), 97 ('cpu_sw_slp', ctypes.c_uint32, 1), 98 ('pci_exp_wak', ctypes.c_uint32, 1), 99 ('use_platform_clock', ctypes.c_uint32, 1), 100 ('s4_rtc_sts_valid', ctypes.c_uint32, 1), 101 ('remote_power_on_capable', ctypes.c_uint32, 1), 102 ('force_apic_cluster_mode', ctypes.c_uint32, 1), 103 ('force_apic_physical_destination_mode', ctypes.c_uint32, 1), 104 ] 105 106class facp_flags_v3(cdata.Union): 107 _pack_ = 1 108 _anonymous_ = ("bits",) 109 _fields_ = [ 110 ('data', ctypes.c_uint32), 111 ('bits', facp_flags_bits_v3), 112 ] 113 114class facp_iapc_arch_bits_v3(cdata.Struct): 115 _pack_ = 1 116 _fields_ = [ 117 ('legacy_devices', ctypes.c_uint16, 1), 118 ('8042', ctypes.c_uint16, 1), 119 ('vga_not_present', ctypes.c_uint16, 1), 120 ('msi_not_supported', ctypes.c_uint16, 1), 121 ] 122 123class facp_iapc_arch_v3(cdata.Union): 124 _pack_ = 1 125 _anonymous_ = ("bits",) 126 _fields_ = [ 127 ('data', ctypes.c_uint16), 128 ('bits', facp_iapc_arch_bits_v3), 129 ] 130 131class FACP_v3(cdata.Struct): 132 _pack_ = 1 133 _fields_ = [ 134 ('header', TableHeader), 135 ('firmware_ctrl', ctypes.c_uint32), 136 ('dsdt', ctypes.c_uint32), 137 ('reserved0', ctypes.c_uint8), 138 ('preferred_pm_profile', ctypes.c_uint8), 139 ('sci_int', ctypes.c_uint16), 140 ('smi_cmd', ctypes.c_uint32), 141 ('acpi_enable', ctypes.c_uint8), 142 ('acpi_disable', ctypes.c_uint8), 143 ('s4bios_req', ctypes.c_uint8), 144 ('pstate_cnt', ctypes.c_uint8), 145 ('pm1a_evt_blk', ctypes.c_uint32), 146 ('pm1b_evt_blk', ctypes.c_uint32), 147 ('pm1a_cnt_blk', ctypes.c_uint32), 148 ('pm1b_cnt_blk', ctypes.c_uint32), 149 ('pm2_cnt_blk', ctypes.c_uint32), 150 ('pm_tmr_blk', ctypes.c_uint32), 151 ('gpe0_blk', ctypes.c_uint32), 152 ('gpe1_blk', ctypes.c_uint32), 153 ('pm1_evt_len', ctypes.c_uint8), 154 ('pm1_cnt_len', ctypes.c_uint8), 155 ('pm2_cnt_len', ctypes.c_uint8), 156 ('pm_tmr_len', ctypes.c_uint8), 157 ('gpe0_blk_len', ctypes.c_uint8), 158 ('gpe1_blk_len', ctypes.c_uint8), 159 ('gpe1_base', ctypes.c_uint8), 160 ('cst_cnt', ctypes.c_uint8), 161 ('p_lvl2_lat', ctypes.c_uint16), 162 ('p_lvl3_lat', ctypes.c_uint16), 163 ('flush_size', ctypes.c_uint16), 164 ('flush_stride', ctypes.c_uint16), 165 ('duty_offset', ctypes.c_uint8), 166 ('duty_width', ctypes.c_uint8), 167 ('day_alrm', ctypes.c_uint8), 168 ('mon_alrm', ctypes.c_uint8), 169 ('century', ctypes.c_uint8), 170 ('iapc_boot_arch', facp_iapc_arch_v3), 171 ('reserved1', ctypes.c_uint8), 172 ('flags', facp_flags_v3), 173 ('reset_reg', GAS), 174 ('reset_value', ctypes.c_uint8), 175 ('reserved2', ctypes.c_uint8 * 3), 176 ('x_firmware_ctrl', ctypes.c_uint64), 177 ('x_dsdt', ctypes.c_uint64), 178 ('x_pm1a_evt_blk', GAS), 179 ('x_pm1b_evt_blk', GAS), 180 ('x_pm1a_cnt_blk', GAS), 181 ('x_pm1b_cnt_blk', GAS), 182 ('x_pm2_cnt_blk', GAS), 183 ('x_pm_tmr_blk', GAS), 184 ('x_gpe0_blk', GAS), 185 ('x_gpe1_blk', GAS), 186 ] 187 188 _formats = { 189 'preferred_pm_profile': unpack.format_table("{}", _preferred_pm_profile), 190 } 191 192class facp_iapc_arch_bits_v4(cdata.Struct): 193 _pack_ = 1 194 _fields_ = copy.copy(facp_iapc_arch_bits_v3._fields_) + [ 195 ('pcie_aspm_controls', ctypes.c_uint16, 1), 196 ] 197 198class facp_iapc_arch_v4(cdata.Union): 199 _pack_ = 1 200 _anonymous_ = ("bits",) 201 _fields_ = [ 202 ('data', ctypes.c_uint16), 203 ('bits', facp_iapc_arch_bits_v4), 204 ] 205 206class FACP_v4(cdata.Struct): 207 _pack_ = 1 208 _fields_ = [ 209 ('header', TableHeader), 210 ('firmware_ctrl', ctypes.c_uint32), 211 ('dsdt', ctypes.c_uint32), 212 ('reserved0', ctypes.c_uint8), 213 ('preferred_pm_profile', ctypes.c_uint8), 214 ('sci_int', ctypes.c_uint16), 215 ('smi_cmd', ctypes.c_uint32), 216 ('acpi_enable', ctypes.c_uint8), 217 ('acpi_disable', ctypes.c_uint8), 218 ('s4bios_req', ctypes.c_uint8), 219 ('pstate_cnt', ctypes.c_uint8), 220 ('pm1a_evt_blk', ctypes.c_uint32), 221 ('pm1b_evt_blk', ctypes.c_uint32), 222 ('pm1a_cnt_blk', ctypes.c_uint32), 223 ('pm1b_cnt_blk', ctypes.c_uint32), 224 ('pm2_cnt_blk', ctypes.c_uint32), 225 ('pm_tmr_blk', ctypes.c_uint32), 226 ('gpe0_blk', ctypes.c_uint32), 227 ('gpe1_blk', ctypes.c_uint32), 228 ('pm1_evt_len', ctypes.c_uint8), 229 ('pm1_cnt_len', ctypes.c_uint8), 230 ('pm2_cnt_len', ctypes.c_uint8), 231 ('pm_tmr_len', ctypes.c_uint8), 232 ('gpe0_blk_len', ctypes.c_uint8), 233 ('gpe1_blk_len', ctypes.c_uint8), 234 ('gpe1_base', ctypes.c_uint8), 235 ('cst_cnt', ctypes.c_uint8), 236 ('p_lvl2_lat', ctypes.c_uint16), 237 ('p_lvl3_lat', ctypes.c_uint16), 238 ('flush_size', ctypes.c_uint16), 239 ('flush_stride', ctypes.c_uint16), 240 ('duty_offset', ctypes.c_uint8), 241 ('duty_width', ctypes.c_uint8), 242 ('day_alrm', ctypes.c_uint8), 243 ('mon_alrm', ctypes.c_uint8), 244 ('century', ctypes.c_uint8), 245 ('iapc_boot_arch', facp_iapc_arch_v4), 246 ('reserved1', ctypes.c_uint8), 247 ('flags', facp_flags_v3), 248 ('reset_reg', GAS), 249 ('reset_value', ctypes.c_uint8), 250 ('reserved2', ctypes.c_uint8 * 3), 251 ('x_firmware_ctrl', ctypes.c_uint64), 252 ('x_dsdt', ctypes.c_uint64), 253 ('x_pm1a_evt_blk', GAS), 254 ('x_pm1b_evt_blk', GAS), 255 ('x_pm1a_cnt_blk', GAS), 256 ('x_pm1b_cnt_blk', GAS), 257 ('x_pm2_cnt_blk', GAS), 258 ('x_pm_tmr_blk', GAS), 259 ('x_gpe0_blk', GAS), 260 ('x_gpe1_blk', GAS), 261 ] 262 263 _formats = { 264 'preferred_pm_profile': unpack.format_table("{}", _preferred_pm_profile), 265 } 266 267class facp_flags_bits_v5(cdata.Struct): 268 _pack_ = 1 269 _fields_ = copy.copy(facp_flags_bits_v3._fields_) + [ 270 ('hw_reduced_acpi', ctypes.c_uint32, 1), 271 ('low_power_s0_idle_capable', ctypes.c_uint32, 1), 272 ] 273 274class facp_flags_v5(cdata.Union): 275 _pack_ = 1 276 _anonymous_ = ("bits",) 277 _fields_ = [ 278 ('data', ctypes.c_uint32), 279 ('bits', facp_flags_bits_v5), 280 ] 281 282class facp_iapc_arch_bits_v5(cdata.Struct): 283 _pack_ = 1 284 _fields_ = copy.copy(facp_iapc_arch_bits_v4._fields_) + [ 285 ('cmos_rtc_not_present', ctypes.c_uint16, 1), 286 ] 287 288class facp_iapc_arch_v5(cdata.Union): 289 _pack_ = 1 290 _anonymous_ = ("bits",) 291 _fields_ = [ 292 ('data', ctypes.c_uint16), 293 ('bits', facp_iapc_arch_bits_v5), 294 ] 295 296class FACP_v5(cdata.Struct): 297 _pack_ = 1 298 _fields_ = [ 299 ('header', TableHeader), 300 ('firmware_ctrl', ctypes.c_uint32), 301 ('dsdt', ctypes.c_uint32), 302 ('reserved0', ctypes.c_uint8), 303 ('preferred_pm_profile', ctypes.c_uint8), 304 ('sci_int', ctypes.c_uint16), 305 ('smi_cmd', ctypes.c_uint32), 306 ('acpi_enable', ctypes.c_uint8), 307 ('acpi_disable', ctypes.c_uint8), 308 ('s4bios_req', ctypes.c_uint8), 309 ('pstate_cnt', ctypes.c_uint8), 310 ('pm1a_evt_blk', ctypes.c_uint32), 311 ('pm1b_evt_blk', ctypes.c_uint32), 312 ('pm1a_cnt_blk', ctypes.c_uint32), 313 ('pm1b_cnt_blk', ctypes.c_uint32), 314 ('pm2_cnt_blk', ctypes.c_uint32), 315 ('pm_tmr_blk', ctypes.c_uint32), 316 ('gpe0_blk', ctypes.c_uint32), 317 ('gpe1_blk', ctypes.c_uint32), 318 ('pm1_evt_len', ctypes.c_uint8), 319 ('pm1_cnt_len', ctypes.c_uint8), 320 ('pm2_cnt_len', ctypes.c_uint8), 321 ('pm_tmr_len', ctypes.c_uint8), 322 ('gpe0_blk_len', ctypes.c_uint8), 323 ('gpe1_blk_len', ctypes.c_uint8), 324 ('gpe1_base', ctypes.c_uint8), 325 ('cst_cnt', ctypes.c_uint8), 326 ('p_lvl2_lat', ctypes.c_uint16), 327 ('p_lvl3_lat', ctypes.c_uint16), 328 ('flush_size', ctypes.c_uint16), 329 ('flush_stride', ctypes.c_uint16), 330 ('duty_offset', ctypes.c_uint8), 331 ('duty_width', ctypes.c_uint8), 332 ('day_alrm', ctypes.c_uint8), 333 ('mon_alrm', ctypes.c_uint8), 334 ('century', ctypes.c_uint8), 335 ('iapc_boot_arch', facp_iapc_arch_v5), 336 ('reserved1', ctypes.c_uint8), 337 ('flags', facp_flags_v5), 338 ('reset_reg', GAS), 339 ('reset_value', ctypes.c_uint8), 340 ('reserved2', ctypes.c_uint8 * 3), 341 ('x_firmware_ctrl', ctypes.c_uint64), 342 ('x_dsdt', ctypes.c_uint64), 343 ('x_pm1a_evt_blk', GAS), 344 ('x_pm1b_evt_blk', GAS), 345 ('x_pm1a_cnt_blk', GAS), 346 ('x_pm1b_cnt_blk', GAS), 347 ('x_pm2_cnt_blk', GAS), 348 ('x_pm_tmr_blk', GAS), 349 ('x_gpe0_blk', GAS), 350 ('x_gpe1_blk', GAS), 351 ('sleep_control_reg', GAS), 352 ('sleep_status_reg', GAS), 353 ] 354 355 _formats = { 356 'preferred_pm_profile': unpack.format_table("{}", _preferred_pm_profile), 357 } 358 359def FACP(val): 360 """Create class based on decode of an FACP table from filename.""" 361 data = open(val, mode='rb').read() 362 buf = ctypes.create_string_buffer(data, len(data)) 363 addr = ctypes.addressof(buf) 364 hdr = TableHeader.from_address(addr) 365 if hdr.revision < 3: 366 cls = FACP_v1 367 elif hdr.revision == 3: 368 cls = FACP_v3 369 elif hdr.revision == 4: 370 cls = FACP_v4 371 else: 372 cls = FACP_v5 373 return cls.from_buffer_copy(data) 374