1# Copyright (C) 2021-2022 Intel Corporation. 2# 3# SPDX-License-Identifier: BSD-3-Clause 4# 5 6import ctypes 7 8import inspectorlib.cdata as cdata 9import inspectorlib.unpack as unpack 10 11# 6.4.2 Small Resource Data Type 12 13class SmallResourceDataTag(cdata.Struct): 14 _pack_ = 1 15 _fields_ = [ 16 ('length', ctypes.c_uint8, 3), 17 ('name', ctypes.c_uint8, 4), 18 ('type', ctypes.c_uint8, 1), 19 ] 20 21SMALL_RESOURCE_ITEM_IRQ_FORMAT = 0x04 22SMALL_RESOURCE_ITEM_DMA_FORMAT = 0x05 23SMALL_RESOURCE_ITEM_START_DEPENDENT_FUNCTIONS = 0x06 24SMALL_RESOURCE_ITEM_END_DEPENDENT_FUNCTIONS = 0x07 25SMALL_RESOURCE_ITEM_IO_PORT = 0x08 26SMALL_RESOURCE_ITEM_FIXED_LOCATION_IO_PORT = 0x09 27SMALL_RESOURCE_ITEM_FIXED_DMA = 0x0A 28SMALL_RESOURCE_ITEM_VENDOR_DEFINED = 0x0E 29SMALL_RESOURCE_ITEM_END_TAG = 0x0F 30 31# 6.4.2.1 IRQ Descriptor 32 33def SmallResourceItemIRQ_factory(_len=2): 34 class SmallResourceItemIRQ(cdata.Struct): 35 _pack_ = 1 36 _fields_ = SmallResourceDataTag._fields_ + [ 37 ('_INT', ctypes.c_uint16), 38 ] + ([ 39 ('_HE', ctypes.c_uint8, 1), 40 ('ingored', ctypes.c_uint8, 2), 41 ('_LL', ctypes.c_uint8, 1), 42 ('_SHR', ctypes.c_uint8, 1), 43 ('_WKC', ctypes.c_uint8, 1), 44 ('reserved', ctypes.c_uint8, 2), 45 ] if (_len > 2) else []) 46 47 @property 48 def irqs(self): 49 return [i for i in range(0, 16) if ((self._INT & (1 << i)) != 0)] 50 return SmallResourceItemIRQ 51 52# 6.4.2.2 DMA Descriptor 53 54class SmallResourceItemDMA(cdata.Struct): 55 _pack_ = 1 56 _fields_ = SmallResourceDataTag._fields_ + [ 57 ('_DMA', ctypes.c_uint8), 58 ('_SIZ', ctypes.c_uint8, 2), 59 ('_BM', ctypes.c_uint8, 1), 60 ('ignored', ctypes.c_uint8, 2), 61 ('_TYP', ctypes.c_uint8, 2), 62 ('reserved', ctypes.c_uint8, 1), 63 ] 64 65# 6.4.2.3 Start Dependent Functions Descriptor 66 67def SmallResourceItemStartDependentFunctions_factory(_len): 68 class SmallResourceItemStartDependentFunctions(cdata.Struct): 69 _pack_ = 1 70 _fields_ = SmallResourceDataTag._fields_ + ([ 71 ('compatibility', ctypes.c_uint8, 2), 72 ('performance', ctypes.c_uint8, 2), 73 ('reserved', ctypes.c_uint8, 4), 74 ] if (_len > 0) else []) 75 return SmallResourceItemStartDependentFunctions 76 77# 6.4.2.4 End Dependent Functions Descriptor 78 79class SmallResourceItemEndDependentFunctions(cdata.Struct): 80 _pack_ = 1 81 _fields_ = SmallResourceDataTag._fields_ 82 83# 6.4.2.5 I/O Port Descriptor 84 85io_port_decoding = { 86 0b0: 'Decodes bits[9:0]', 87 0b1: 'Decodes bits[15:0]', 88} 89 90class SmallResourceItemIOPort(cdata.Struct): 91 _pack_ = 1 92 _fields_ = SmallResourceDataTag._fields_ + [ 93 ('_DEC', ctypes.c_uint8, 1), 94 ('reserved', ctypes.c_uint8, 7), 95 ('_MIN', ctypes.c_uint16), 96 ('_MAX', ctypes.c_uint16), 97 ('_ALN', ctypes.c_uint8), 98 ('_LEN', ctypes.c_uint8), 99 ] 100 _formats = { 101 '_DEC': unpack.format_table("{}", io_port_decoding) 102 } 103 104# 6.4.2.6 Fixed Location I/O Port Descriptor 105 106class SmallResourceItemFixedLocationIOPort(cdata.Struct): 107 _pack_ = 1 108 _fields_ = SmallResourceDataTag._fields_ + [ 109 ('_BAS', ctypes.c_uint16), 110 ('_LEN', ctypes.c_uint8), 111 ] 112 113# 6.4.2.7 Fixed DMA Descriptor 114 115class SmallResourceItemFixedDMA(cdata.Struct): 116 _pack_ = 1 117 _fields_ = SmallResourceDataTag._fields_ + [ 118 ('_DMA', ctypes.c_uint16), 119 ('_TYP', ctypes.c_uint16), 120 ('_SIZ', ctypes.c_uint8), 121 ] 122 123# 6.4.2.8 Vendor-Defined Descriptor, Type 0 124 125def SmallResourceItemVendorDefined_factory(_len): 126 class SmallResourceItemVendorDefined(cdata.Struct): 127 _pack_ = 1 128 _fields_ = SmallResourceDataTag._fields_ + [ 129 ('data', ctypes.c_uint8 * _len), 130 ] 131 return SmallResourceItemVendorDefined 132 133# 6.4.2.9 End Tag 134 135class SmallResourceItemEndTag(cdata.Struct): 136 _pack_ = 1 137 _fields_ = SmallResourceDataTag._fields_ + [ 138 ('checksum', ctypes.c_uint8) 139 ] 140 141# 6.4.3 Large Resource Data Type 142 143class LargeResourceDataTag(cdata.Struct): 144 _pack_ = 1 145 _fields_ = [ 146 ('name', ctypes.c_uint8, 7), 147 ('type', ctypes.c_uint8, 1), 148 ('length', ctypes.c_uint16), 149 ] 150 151LARGE_RESOURCE_ITEM_24BIT_MEMORY_RANGE = 0x01 152LARGE_RESOURCE_ITEM_GENERIC_REGISTER = 0x02 153LARGE_RESOURCE_ITEM_VENDOR_DEFINED = 0x04 154LARGE_RESOURCE_ITEM_32BIT_MEMORY_RANGE = 0x05 155LARGE_RESOURCE_ITEM_32BIT_FIXED_MEMORY_RANGE = 0x06 156LARGE_RESOURCE_ITEM_ADDRESS_SPACE_RESOURCE = 0x07 157LARGE_RESOURCE_ITEM_WORD_ADDRESS_SPACE = 0x08 158LARGE_RESOURCE_ITEM_EXTENDED_INTERRUPT = 0x09 159LARGE_RESOURCE_ITEM_QWORD_ADDRESS_SPACE = 0x0A 160LARGE_RESOURCE_ITEM_EXTENDED_ADDRESS_SPACE = 0x0B 161LARGE_RESOURCE_ITEM_GPIO_CONNECTION = 0x0C 162LARGE_RESOURCE_ITEM_PIN_FUNCTION = 0x0D 163LARGE_RESOURCE_ITEM_GENERIC_SERIAL_BUS_CONNECTION = 0x0E 164LARGE_RESOURCE_ITEM_PIN_CONFIGURATION = 0x0F 165LARGE_RESOURCE_ITEM_PIN_GROUP = 0x10 166LARGE_RESOURCE_ITEM_PIN_GROUP_FUNCTION = 0x11 167LARGE_RESOURCE_ITEM_PIN_GROUP_CONFIGURATION = 0x12 168 169# 6.4.3.1 24-Bit Memory Range Descriptor 170 171class LargeResourceItem24BitMemoryRange(cdata.Struct): 172 _pack_ = 1 173 _fields_ = LargeResourceDataTag._fields_ + [ 174 ('_RW', ctypes.c_uint8, 1), 175 ('ignored', ctypes.c_uint8, 7), 176 ('_MIN', ctypes.c_uint16), 177 ('_MAX', ctypes.c_uint16), 178 ('_ALN', ctypes.c_uint16), 179 ('_LEN', ctypes.c_uint16), 180 ] 181 182# 6.4.3.2 Vendor-Defined Descriptor, Type 1 183 184def LargeResourceItemVendorDefined_factory(_len): 185 class LargeResourceItemVendorDefined(cdata.Struct): 186 _pack_ = 1 187 _fields_ = SmallResourceDataTag._fields_ + [ 188 ('subtype', ctypes.c_uint8), 189 ('UUID', ctypes.c_uint8 * 16), 190 ('data', ctypes.c_uint8 * (_len - 17)), 191 ] 192 return LargeResourceItemVendorDefined 193 194# 6.4.3.3 32-Bit Memory Range Descriptor 195 196class LargeResourceItem32BitMemoryRange(cdata.Struct): 197 _pack_ = 1 198 _fields_ = LargeResourceDataTag._fields_ + [ 199 ('_RW', ctypes.c_uint8, 1), 200 ('ignored', ctypes.c_uint8, 7), 201 ('_MIN', ctypes.c_uint32), 202 ('_MAX', ctypes.c_uint32), 203 ('_ALN', ctypes.c_uint32), 204 ('_LEN', ctypes.c_uint32), 205 ] 206 207# 6.4.3.4 32-Bit Fixed Memory Range Descriptor 208 209class LargeResourceItem32BitFixedMemoryRange(cdata.Struct): 210 _pack_ = 1 211 _fields_ = LargeResourceDataTag._fields_ + [ 212 ('_RW', ctypes.c_uint8, 1), 213 ('ignored', ctypes.c_uint8, 7), 214 ('_BAS', ctypes.c_uint32), 215 ('_LEN', ctypes.c_uint32), 216 ] 217 218# 6.4.3.5 Address Space Resource Descriptors 219 220resource_type = { 221 0x00: 'Memory range', 222 0x01: 'I/O range', 223 0x02: 'Bus number', 224} 225 226decode_type = { 227 0b0: 'This bridge positively decodes this address', 228 0b1: 'This bridge subtractively decodes this address', 229} 230 231min_address_fixed = { 232 0b0: 'The specified minimum address is not fixed', 233 0b1: 'The specified minimum address is fixed', 234} 235 236max_address_fixed = { 237 0b0: 'The specified maximum address is not fixed', 238 0b1: 'The specified maximum address is fixed', 239} 240 241# 6.4.3.5.1 QWord Address Space Descriptor 242 243def LargeResourceItemQWordAddressSpace_factory(_len=43): 244 class LargeResourceItemQWordAddressSpace(cdata.Struct): 245 _pack_ = 1 246 _fields_ = LargeResourceDataTag._fields_ + [ 247 ('_TYP', ctypes.c_uint8), 248 ('ignored', ctypes.c_uint8, 1), 249 ('_DEC', ctypes.c_uint8, 1), 250 ('_MIF', ctypes.c_uint8, 1), 251 ('_MAF', ctypes.c_uint8, 1), 252 ('reserved1', ctypes.c_uint8, 4), 253 ('flags', ctypes.c_uint8), 254 ('_GRA', ctypes.c_uint64), 255 ('_MIN', ctypes.c_uint64), 256 ('_MAX', ctypes.c_uint64), 257 ('_TRA', ctypes.c_uint64), 258 ('_LEN', ctypes.c_uint64), 259 ] + ([ 260 ('reserved2', ctypes.c_uint8) 261 ] if (_len > 43) else []) + ([ 262 ('resource_source_opt', ctypes.c_char * (_len - 44)) 263 ] if (_len > 44) else []) 264 _formats = { 265 '_TYP': unpack.format_table("{}", resource_type), 266 '_DEC': unpack.format_table("{}", decode_type), 267 '_MIF': unpack.format_table("{}", min_address_fixed), 268 '_MAF': unpack.format_table("{}", max_address_fixed), 269 } 270 271 @property 272 def resource_source(self): 273 return getattr(self, "resource_source_opt", None) 274 275 return LargeResourceItemQWordAddressSpace 276 277# 6.4.3.5.2 DWord Address Space Descriptor 278 279def LargeResourceItemDWordAddressSpace_factory(_len=23): 280 class LargeResourceItemDWordAddressSpace(cdata.Struct): 281 _pack_ = 1 282 _fields_ = LargeResourceDataTag._fields_ + [ 283 ('_TYP', ctypes.c_uint8), 284 ('ignored', ctypes.c_uint8, 1), 285 ('_DEC', ctypes.c_uint8, 1), 286 ('_MIF', ctypes.c_uint8, 1), 287 ('_MAF', ctypes.c_uint8, 1), 288 ('reserved1', ctypes.c_uint8, 4), 289 ('flags', ctypes.c_uint8), 290 ('_GRA', ctypes.c_uint32), 291 ('_MIN', ctypes.c_uint32), 292 ('_MAX', ctypes.c_uint32), 293 ('_TRA', ctypes.c_uint32), 294 ('_LEN', ctypes.c_uint32), 295 ] + ([ 296 ('reserved2', ctypes.c_uint8) 297 ] if (_len > 23) else []) + ([ 298 ('resource_source_opt', ctypes.c_char * (_len - 24)) 299 ] if (_len > 24) else []) 300 _formats = { 301 '_TYP': unpack.format_table("{}", resource_type), 302 '_DEC': unpack.format_table("{}", decode_type), 303 '_MIF': unpack.format_table("{}", min_address_fixed), 304 '_MAF': unpack.format_table("{}", max_address_fixed), 305 } 306 307 @property 308 def resource_source(self): 309 return getattr(self, "resource_source_opt", None) 310 311 return LargeResourceItemDWordAddressSpace 312 313# 6.4.3.5.3 Word Address Space Descriptor 314 315def LargeResourceItemWordAddressSpace_factory(_len=13): 316 class LargeResourceItemWordAddressSpace(cdata.Struct): 317 _pack_ = 1 318 _fields_ = LargeResourceDataTag._fields_ + [ 319 ('_TYP', ctypes.c_uint8), 320 ('ignored', ctypes.c_uint8, 1), 321 ('_DEC', ctypes.c_uint8, 1), 322 ('_MIF', ctypes.c_uint8, 1), 323 ('_MAF', ctypes.c_uint8, 1), 324 ('reserved1', ctypes.c_uint8, 4), 325 ('flags', ctypes.c_uint8), 326 ('_GRA', ctypes.c_uint16), 327 ('_MIN', ctypes.c_uint16), 328 ('_MAX', ctypes.c_uint16), 329 ('_TRA', ctypes.c_uint16), 330 ('_LEN', ctypes.c_uint16), 331 ] + ([ 332 ('reserved2', ctypes.c_uint8) 333 ] if (_len > 13) else []) + ([ 334 ('resource_source_opt', ctypes.c_char * (_len - 14)) 335 ] if (_len > 14) else []) 336 _formats = { 337 '_TYP': unpack.format_table("{}", resource_type), 338 '_DEC': unpack.format_table("{}", decode_type), 339 '_MIF': unpack.format_table("{}", min_address_fixed), 340 '_MAF': unpack.format_table("{}", max_address_fixed), 341 } 342 343 @property 344 def resource_source(self): 345 return getattr(self, "resource_source_opt", None) 346 347 return LargeResourceItemWordAddressSpace 348 349# 6.4.3.5.4 Extended Address Space Descriptor 350 351class LargeResourceItemExtendedAddressSpace(cdata.Struct): 352 _pack_ = 1 353 _fields_ = LargeResourceDataTag._fields_ + [ 354 ('_TYP', ctypes.c_uint8), 355 ('ignored', ctypes.c_uint8, 1), 356 ('_DEC', ctypes.c_uint8, 1), 357 ('_MIF', ctypes.c_uint8, 1), 358 ('_MAF', ctypes.c_uint8, 1), 359 ('reserved1', ctypes.c_uint8, 4), 360 ('flags', ctypes.c_uint8), 361 ('revision', ctypes.c_uint8), 362 ('reserved2', ctypes.c_uint8), 363 ('_GRA', ctypes.c_uint64), 364 ('_MIN', ctypes.c_uint64), 365 ('_MAX', ctypes.c_uint64), 366 ('_TRA', ctypes.c_uint64), 367 ('_LEN', ctypes.c_uint64), 368 ('_ATT', ctypes.c_uint64), 369 ] 370 _formats = { 371 '_TYP': unpack.format_table("{}", resource_type), 372 '_DEC': unpack.format_table("{}", decode_type), 373 '_MIF': unpack.format_table("{}", min_address_fixed), 374 '_MAF': unpack.format_table("{}", max_address_fixed), 375 } 376 377# 6.4.3.6 Extended Interrupt Descriptor 378 379def LargeResourceItemExtendedInterrupt_factory(_addr): 380 class LargeResourceItemExtendedInterruptLayout(cdata.Struct): 381 _pack_ = 1 382 _fields_ = LargeResourceDataTag._fields_ + [ 383 ('flags', ctypes.c_uint8), 384 ('_LEN', ctypes.c_uint8), 385 ] 386 387 def aux(layout): 388 class LargeResourceItemExtendedInterrupt(cdata.Struct): 389 _pack_ = 1 390 _fields_ = LargeResourceDataTag._fields_ + [ 391 ('_CP', ctypes.c_uint8, 1), 392 ('_HE', ctypes.c_uint8, 1), 393 ('_LL', ctypes.c_uint8, 1), 394 ('_SHR', ctypes.c_uint8, 1), 395 ('_WKC', ctypes.c_uint8, 1), 396 ('reserved1', ctypes.c_uint8, 3), 397 ('_LEN', ctypes.c_uint8), 398 ('_INT', ctypes.c_uint32 * layout._LEN), 399 ] + ([ 400 ('reserved2', ctypes.c_uint8), 401 ] if (layout.length > 2 + layout._LEN * 4) else []) + ([ 402 ('resource_source_opt', ctypes.c_char * (layout.length - layout._LEN * 4 - 3)) 403 ] if (layout.length > 2 + layout._LEN * 4 + 1) else []) 404 405 @property 406 def resource_source(self): 407 return getattr(self, "resource_source_opt", None) 408 409 return LargeResourceItemExtendedInterrupt 410 411 return aux(LargeResourceItemExtendedInterruptLayout.from_address(_addr)) 412 413# 6.4.3.7 Generic Register Descriptor 414 415class LargeResourceItemGenericRegister(cdata.Struct): 416 _pack_ = 1 417 _fields_ = LargeResourceDataTag._fields_ + [ 418 ('_ASI', ctypes.c_uint8), 419 ('_RBW', ctypes.c_uint8), 420 ('_RBO', ctypes.c_uint8), 421 ('_ASZ', ctypes.c_uint8), 422 ('_ADR', ctypes.c_uint64), 423 ] 424 425# 6.4.3.8.1 GPIO Connection Descriptor 426 427def LargeResourceItemGPIOConnection_factory(_addr): 428 class LargeResourceItemGPIOConnectionLayout(cdata.Struct): 429 _pack_ = 1 430 _fields_ = LargeResourceDataTag._fields_ + [ 431 ('revision_id', ctypes.c_uint8), 432 ('connection_type', ctypes.c_uint8), 433 # Byte 5 to 13 (both inclusive) are not involved in detecting the layout of the descriptor 434 ('data1', ctypes.c_uint8 * 9), 435 ('pin_table_offset', ctypes.c_uint16), 436 ('data2', ctypes.c_uint8), 437 ('resource_source_name_offset', ctypes.c_uint16), 438 ('vendor_data_offset', ctypes.c_uint16), 439 ('vendor_data_length', ctypes.c_uint16), 440 ] 441 442 def aux(layout): 443 if layout.connection_type == 0: # Interrupt connection 444 interrupt_and_io_flags_fields = [ 445 ('_MOD', ctypes.c_uint16, 1), 446 ('_POL', ctypes.c_uint16, 2), 447 ('_SHR', ctypes.c_uint16, 1), 448 ('_WKC', ctypes.c_uint16, 1), 449 ('reserved2', ctypes.c_uint16, 11), 450 ] 451 elif layout.connection_type == 1: # I/O connection 452 interrupt_and_io_flags_fields = [ 453 ('_IOR', ctypes.c_uint16, 1), 454 ('reserved2_1', ctypes.c_uint16, 2), 455 ('_SHR', ctypes.c_uint16, 1), 456 ('reserved2_2', ctypes.c_uint16, 12), 457 ] 458 else: 459 interrupt_and_io_flags_fields = [('interrupt_and_io_flags', ctypes.c_uint16)] 460 461 pre_pin_table_length = layout.pin_table_offset - 23 462 pin_count = (layout.resource_source_name_offset - layout.pin_table_offset) // 2 463 resource_source_name_length = layout.vendor_data_offset - layout.resource_source_name_offset 464 465 class LargeResourceItemGPIOConnection(cdata.Struct): 466 _pack_ = 1 467 _fields_ = LargeResourceDataTag._fields_ + [ 468 ('revision_id', ctypes.c_uint8), 469 ('connection_type', ctypes.c_uint8), 470 ('consumer_producer', ctypes.c_uint16, 1), 471 ('reserved1', ctypes.c_uint16, 15), 472 ] + interrupt_and_io_flags_fields + [ 473 ('_PPI', ctypes.c_uint8), 474 ('_DRS', ctypes.c_uint16), 475 ('_DBT', ctypes.c_uint16), 476 ('pin_table_offset', ctypes.c_uint16), 477 ('resource_source_index', ctypes.c_uint8), 478 ('resource_source_name_offset', ctypes.c_uint16), 479 ('vendor_data_offset', ctypes.c_uint16), 480 ('vendor_data_length', ctypes.c_uint16), 481 ] + ([ 482 ('reserved3', ctypes.c_uint8 * pre_pin_table_length), 483 ] if pre_pin_table_length > 0 else []) + [ 484 ('pin_numbers', ctypes.c_uint16 * pin_count), 485 ('resource_source', ctypes.c_char * resource_source_name_length) 486 ] + ([ 487 ('_VEN', ctypes.c_uint8 * layout.vendor_data_length) 488 ] if layout.vendor_data_length > 0 else []) 489 490 return LargeResourceItemGPIOConnection 491 492 return aux(LargeResourceItemGPIOConnectionLayout.from_address(_addr)) 493 494# 6.4.3.8.2 GenericSerialBus Connection Descriptors 495 496def LargeResourceItemGenericSerialBusConnection_factory(_addr): 497 class LargeResourceItemGenericSerialBusConnectionLayout(cdata.Struct): 498 _pack_ = 1 499 _fields_ = LargeResourceDataTag._fields_ + [ 500 # Byte 3 to 9 (both inclusive) are not involved in detecting the layout of the descriptor 501 ('data', ctypes.c_uint8 * 7), 502 ('type_data_length', ctypes.c_uint16), 503 ] 504 505 def aux(layout): 506 class LargeResourceItemGenericSerialBusConnection(cdata.Struct): 507 _pack_ = 1 508 _fields_ = LargeResourceDataTag._fields_ + [ 509 ('revision_id', ctypes.c_uint8), 510 ('resource_source_index', ctypes.c_uint8), 511 ('serial_bus_type', ctypes.c_uint8), 512 ('_SLV', ctypes.c_uint8, 1), 513 ('consumer_producer', ctypes.c_uint8, 1), 514 ('_SHR', ctypes.c_uint8, 1), 515 ('reserved', ctypes.c_uint8, 5), 516 ('type_specific_flags', ctypes.c_uint16), 517 ('type_specific_revision_id', ctypes.c_uint8), 518 ('type_data_length', ctypes.c_uint16), 519 ('type_specific_data', ctypes.c_uint8 * layout.type_data_length), 520 ('resource_source', ctypes.c_char * (layout.length - 9 - layout.type_data_length)), 521 ] 522 523 return LargeResourceItemGenericSerialBusConnection 524 525 return aux(LargeResourceItemGenericSerialBusConnectionLayout.from_address(_addr)) 526 527# 6.4.3.9 Pin Function Descriptor 528 529def LargeResourceItemPinFunction_factory(_len): 530 class LargeResourceItemPinFunction(cdata.Struct): 531 _pack_ = 1 532 _fields_ = LargeResourceDataTag._fields_ + [ 533 ('_REV', ctypes.c_uint8), 534 ('_SHR', ctypes.c_uint8, 1), 535 ('reserved1', ctypes.c_uint16, 15), 536 ('_PPC', ctypes.c_uint8), 537 ('_FUN', ctypes.c_uint16), 538 ('_PTO', ctypes.c_uint16), 539 ('reserved2', ctypes.c_uint8), 540 ('_RNI', ctypes.c_uint16), 541 ('_VDO', ctypes.c_uint16), 542 ('_VDL', ctypes.c_uint16), 543 ('data', ctypes.c_uint8 * (_len - 18)), 544 ] 545 return LargeResourceItemPinFunction 546 547# 6.4.3.10 Pin Configuration Descriptor 548 549def LargeResourceItemPinConfiguration_factory(_len): 550 class LargeResourceItemPinConfiguration(cdata.Struct): 551 _pack_ = 1 552 _fields_ = LargeResourceDataTag._fields_ + [ 553 ('_REV', ctypes.c_uint8), 554 ('_SHR', ctypes.c_uint8, 1), 555 ('_CP', ctypes.c_uint8, 1), 556 ('reserved1', ctypes.c_uint16, 14), 557 ('_TYP', ctypes.c_uint8), 558 ('_VAL', ctypes.c_uint32), 559 ('_PTO', ctypes.c_uint16), 560 ('reserved2', ctypes.c_uint8), 561 ('_RNO', ctypes.c_uint16), 562 ('_VDO', ctypes.c_uint16), 563 ('_VDL', ctypes.c_uint16), 564 ('data', ctypes.c_uint8 * (_len - 20)), 565 ] 566 return LargeResourceItemPinConfiguration 567 568# 6.4.3.11 Pin Group Descriptor 569 570def LargeResourceItemPinGroup_factory(_len): 571 class LargeResourceItemPinGroup(cdata.Struct): 572 _pack_ = 1 573 _fields_ = LargeResourceDataTag._fields_ + [ 574 ('_REV', ctypes.c_uint8), 575 ('_CP', ctypes.c_uint8, 1), 576 ('reserved1', ctypes.c_uint16, 15), 577 ('_PTO', ctypes.c_uint16), 578 ('_RLO', ctypes.c_uint16), 579 ('_VDO', ctypes.c_uint16), 580 ('_VDL', ctypes.c_uint16), 581 ('data', ctypes.c_uint8 * (_len - 14)), 582 ] 583 return LargeResourceItemPinGroup 584 585# 6.4.3.12 Pin Group Function Descriptor 586 587def LargeResourceItemPinGroupFunction_factory(_len): 588 class LargeResourceItemPinGroupFunction(cdata.Struct): 589 _pack_ = 1 590 _fields_ = LargeResourceDataTag._fields_ + [ 591 ('_REV', ctypes.c_uint8), 592 ('_SHR', ctypes.c_uint8, 1), 593 ('_CP', ctypes.c_uint8, 1), 594 ('reserved1', ctypes.c_uint16, 14), 595 ('_FUN', ctypes.c_uint16), 596 ('reserved2', ctypes.c_uint8), 597 ('_RNI', ctypes.c_uint16), 598 ('_RLO', ctypes.c_uint16), 599 ('_VDO', ctypes.c_uint16), 600 ('_VDL', ctypes.c_uint16), 601 ('data', ctypes.c_uint8 * (_len - 17)), 602 ] 603 return LargeResourceItemPinGroupFunction 604 605# 6.4.3.13 Pin Group Configuration Descriptor 606 607def LargeResourceItemPinGroupConfiguration_factory(_len): 608 class LargeResourceItemPinGroupConfiguration(cdata.Struct): 609 _pack_ = 1 610 _fields_ = LargeResourceDataTag._fields_ + [ 611 ('_REV', ctypes.c_uint8), 612 ('_SHR', ctypes.c_uint8, 1), 613 ('_CP', ctypes.c_uint8, 1), 614 ('reserved1', ctypes.c_uint16, 14), 615 ('_TYP', ctypes.c_uint8), 616 ('_VAL', ctypes.c_uint32), 617 ('reserved2', ctypes.c_uint8), 618 ('_RNO', ctypes.c_uint16), 619 ('_RLO', ctypes.c_uint16), 620 ('_VDO', ctypes.c_uint16), 621 ('_VDL', ctypes.c_uint16), 622 ('data', ctypes.c_uint8 * (_len - 20)), 623 ] 624 return LargeResourceItemPinGroupConfiguration 625 626# The parser 627 628def rdt_item_list(addr, length): 629 end = addr + length 630 field_list = list() 631 item_num = 0 632 while addr < end: 633 item_num += 1 634 tag = SmallResourceDataTag.from_address(addr) 635 if tag.type == 0: # Small type 636 if tag.name == SMALL_RESOURCE_ITEM_IRQ_FORMAT: 637 cls = SmallResourceItemIRQ_factory(tag.length) 638 elif tag.name == SMALL_RESOURCE_ITEM_DMA_FORMAT: 639 cls = SmallResourceItemDMA 640 elif tag.name == SMALL_RESOURCE_ITEM_START_DEPENDENT_FUNCTIONS: 641 cls = SmallResourceItemStartDependentFunctions_factory(tag.length) 642 elif tag.name == SMALL_RESOURCE_ITEM_END_DEPENDENT_FUNCTIONS: 643 cls = SmallResourceItemEndDependentFunctions 644 elif tag.name == SMALL_RESOURCE_ITEM_IO_PORT: 645 cls = SmallResourceItemIOPort 646 elif tag.name == SMALL_RESOURCE_ITEM_FIXED_LOCATION_IO_PORT: 647 cls = SmallResourceItemFixedLocationIOPort 648 elif tag.name == SMALL_RESOURCE_ITEM_FIXED_DMA: 649 cls = SmallResourceItemFixedDMA 650 elif tag.name == SMALL_RESOURCE_ITEM_VENDOR_DEFINED: 651 cls = SmallResourceItemVendorDefined_factory(tag.length) 652 elif tag.name == SMALL_RESOURCE_ITEM_END_TAG: 653 cls = SmallResourceItemEndTag 654 else: 655 raise NotImplementedError(f"Unknown small resource item name: {tag.name}, offset {addr}") 656 size = ctypes.sizeof(cls) 657 assert size == tag.length + 1, f"{cls}: {size} != {tag.length} + 1" 658 addr += size 659 else: # Large type 660 tag = LargeResourceDataTag.from_address(addr) 661 if tag.name == LARGE_RESOURCE_ITEM_24BIT_MEMORY_RANGE: 662 cls = LargeResourceItem24BitMemoryRange 663 elif tag.name == LARGE_RESOURCE_ITEM_GENERIC_REGISTER: 664 cls = LargeResourceItemGenericRegister 665 elif tag.name == LARGE_RESOURCE_ITEM_VENDOR_DEFINED: 666 cls = LargeResourceItemVendorDefined_factory(tag.length) 667 elif tag.name == LARGE_RESOURCE_ITEM_32BIT_MEMORY_RANGE: 668 cls = LargeResourceItem32BitMemoryRange 669 elif tag.name == LARGE_RESOURCE_ITEM_32BIT_FIXED_MEMORY_RANGE: 670 cls = LargeResourceItem32BitFixedMemoryRange 671 elif tag.name == LARGE_RESOURCE_ITEM_ADDRESS_SPACE_RESOURCE: 672 cls = LargeResourceItemDWordAddressSpace_factory(tag.length) 673 elif tag.name == LARGE_RESOURCE_ITEM_WORD_ADDRESS_SPACE: 674 cls = LargeResourceItemWordAddressSpace_factory(tag.length) 675 elif tag.name == LARGE_RESOURCE_ITEM_EXTENDED_INTERRUPT: 676 cls = LargeResourceItemExtendedInterrupt_factory(addr) 677 elif tag.name == LARGE_RESOURCE_ITEM_QWORD_ADDRESS_SPACE: 678 cls = LargeResourceItemQWordAddressSpace_factory(tag.length) 679 elif tag.name == LARGE_RESOURCE_ITEM_EXTENDED_ADDRESS_SPACE: 680 cls = LargeResourceItemExtendedAddressSpace 681 elif tag.name == LARGE_RESOURCE_ITEM_GPIO_CONNECTION: 682 cls = LargeResourceItemGPIOConnection_factory(addr) 683 elif tag.name == LARGE_RESOURCE_ITEM_PIN_FUNCTION: 684 cls = LargeResourceItemPinFunction_factory(tag.length) 685 elif tag.name == LARGE_RESOURCE_ITEM_GENERIC_SERIAL_BUS_CONNECTION: 686 cls = LargeResourceItemGenericSerialBusConnection_factory(addr) 687 elif tag.name == LARGE_RESOURCE_ITEM_PIN_CONFIGURATION: 688 cls = LargeResourceItemPinConfiguration_factory(tag.length) 689 elif tag.name == LARGE_RESOURCE_ITEM_PIN_GROUP: 690 cls = LargeResourceItemPinGroup_factory(tag.length) 691 elif tag.name == LARGE_RESOURCE_ITEM_PIN_GROUP_FUNCTION: 692 cls = LargeResourceItemPinGroupFunction_factory(tag.length) 693 elif tag.name == LARGE_RESOURCE_ITEM_PIN_GROUP_CONFIGURATION: 694 cls = LargeResourceItemPinGroupConfiguration_factory(tag.length) 695 else: 696 raise NotImplementedError(f"Unknown Large resource item name: {tag.name}, offset {addr}") 697 size = ctypes.sizeof(cls) 698 assert size == tag.length + 3, f"{cls}: {size} != {tag.length} + 3" 699 addr += size 700 field_list.append((f'item{item_num}', cls)) 701 return field_list 702 703def rdt_factory(field_list): 704 705 class items(cdata.Struct): 706 _pack_ = 1 707 _fields_ = field_list 708 709 def __iter__(self): 710 for f in self._fields_: 711 yield getattr(self, f[0]) 712 713 def __getitem__(self, index): 714 return getattr(self, self._fields_[index][0]) 715 716 class ResourceData(cdata.Struct): 717 _pack_ = 1 718 _fields_ = [ 719 ('items', items) 720 ] 721 return ResourceData 722 723def parse_resource_data(data): 724 """Parse ACPI resource data types returned by _CRS, _PRS and _SRS control methods.""" 725 buf = ctypes.create_string_buffer(bytes(data), len(data)) 726 addr = ctypes.addressof(buf) 727 item_list = rdt_item_list(addr, len(data)) 728 return rdt_factory(item_list).from_buffer_copy(data) 729