[Device] Correctly parse device's resources

This commit is contained in:
lucasg
2020-04-15 16:02:28 +02:00
committed by hakril
parent 5aa181c4cf
commit 7652f597f3
+234 -7
View File
@@ -1,3 +1,6 @@
import struct
import ctypes
from ctypes import wintypes
import windows
from windows import winproxy
@@ -27,6 +30,153 @@ BOOT_LOG_CONF = 0x00000003 # boot configuration information.
FORCED_LOG_CONF = 0x00000004 # forced configuration information.
OVERRIDE_LOG_CONF = 0x00000005 # override configuration information.
class _IO_DES(ctypes.Structure):
"""
The IO_DES structure is used for specifying either a resource list or a resource requirements list that describes I/O port usage for a device instance.
Source : https://docs.microsoft.com/en-gb/windows/win32/api/cfgmgr32/ns-cfgmgr32-io_des
"""
_fields_ = [
('IOD_Count', gdef.DWORD),
('IOD_Type', gdef.DWORD),
('IOD_Alloc_Base', gdef.UINT64),
('IOD_Alloc_End', gdef.UINT64),
('IOD_DesFlags', gdef.DWORD),
]
IO_DES = _IO_DES
PIO_DES = ctypes.POINTER(_IO_DES)
class _IO_RANGE(ctypes.Structure):
"""
The IO_RANGE structure specifies a resource requirements list that describes I/O port usage for a device instance.
Source : https://docs.microsoft.com/en-gb/windows/win32/api/cfgmgr32/ns-cfgmgr32-io_range
"""
_fields_ = [
('IOR_Align', gdef.UINT64),
('IOR_nPorts', gdef.DWORD),
('IOR_Min', gdef.UINT64),
('IOR_Max', gdef.UINT64),
('IOR_RangeFlags', gdef.DWORD),
('IOR_Alias', gdef.UINT64),
]
IO_RANGE = _IO_RANGE
PIO_RANGE = ctypes.POINTER(_IO_RANGE)
class _MEM_DES(ctypes.Structure):
"""
The MEM_DES structure is used for specifying either a resource list or a resource requirements list that describes memory usage for a device instance.
Source : https://docs.microsoft.com/en-gb/windows/win32/api/cfgmgr32/ns-cfgmgr32-mem_des
"""
_fields_ = [
('MD_Count', gdef.DWORD),
('MD_Type', gdef.DWORD),
('MD_Alloc_Base', gdef.UINT64),
('MD_Alloc_End', gdef.UINT64),
('MD_DesFlags', gdef.DWORD),
]
MEM_DES = _MEM_DES
PMEM_DES = ctypes.POINTER(_MEM_DES)
class _MEM_RANGE(ctypes.Structure):
"""
The MEM_RANGE structure specifies a resource requirements list that describes memory usage for a device instance.
Source : https://docs.microsoft.com/en-gb/windows/win32/api/cfgmgr32/ns-cfgmgr32-mem_range
"""
_fields_ = [
('MR_Align', gdef.UINT64),
('MR_nBytes', gdef.ULONG),
('MR_Min', gdef.UINT64),
('MR_Max', gdef.UINT64),
('MR_Flags', gdef.DWORD),
('MR_Reserved', gdef.DWORD),
]
MEM_RANGE = _MEM_RANGE
PMEM_RANGE = ctypes.POINTER(_MEM_RANGE)
class _DMA_DES(ctypes.Structure):
"""
The DMA_DES structure is used for specifying either a resource list or a resource requirements list that describes direct memory access (DMA) channel usage for a device instance.
Source : https://docs.microsoft.com/en-gb/windows/win32/api/cfgmgr32/ns-cfgmgr32-dma_des
"""
_fields_ = [
('DD_Count', gdef.DWORD),
('DD_Type', gdef.DWORD),
('DD_Flags', gdef.DWORD),
('DD_Alloc_Chan', gdef.ULONG),
]
DMA_DES = _DMA_DES
PDMA_DES = ctypes.POINTER(_DMA_DES)
class _DMA_RANGE(ctypes.Structure):
"""
The MEM_RANGE structure specifies a resource requirements list that describes memory usage for a device instance.
Source : https://docs.microsoft.com/en-gb/windows/win32/api/cfgmgr32/ns-cfgmgr32-dma_range
"""
_fields_ = [
('DR_Min', gdef.ULONG),
('DR_Max', gdef.ULONG),
('DR_Flags', gdef.ULONG),
]
DMA_RANGE = _DMA_RANGE
PDMA_RANGE = ctypes.POINTER(_DMA_RANGE)
class _IRQ_DES_64(ctypes.Structure):
"""
The IRQ_DES structure is used for specifying either a resource list or a resource requirements list that describes IRQ line usage for a device instance.
Source : https://docs.microsoft.com/en-gb/windows/win32/api/cfgmgr32/ns-cfgmgr32-irq_des_64
"""
_fields_ = [
('IRQD_Count', gdef.DWORD),
('IRQD_Type', gdef.DWORD),
('IRQD_Flags', gdef.DWORD),
('IRQD_Alloc_Num', gdef.ULONG),
('IRQD_Affinity', gdef.ULONG64),
]
IRQ_DES_64 = _IRQ_DES_64
PIRQ_DES_64 = ctypes.POINTER(_IRQ_DES_64)
class _IRQ_DES_32(ctypes.Structure):
"""
The IRQ_DES structure is used for specifying either a resource list or a resource requirements list that describes IRQ line usage for a device instance.
Source : https://docs.microsoft.com/en-gb/windows/win32/api/cfgmgr32/ns-cfgmgr32-irq_des_32
"""
_fields_ = [
('IRQD_Count', gdef.DWORD),
('IRQD_Type', gdef.DWORD),
('IRQD_Flags', gdef.DWORD),
('IRQD_Alloc_Num', gdef.ULONG),
('IRQD_Affinity', gdef.DWORD),
]
IRQ_DES_32 = _IRQ_DES_32
PIRQ_DES_32 = ctypes.POINTER(_IRQ_DES_32)
class _IRQ_RANGE(ctypes.Structure):
"""
The IRQ_RANGE structure specifies a resource requirements list that describes IRQ line usage for a device instance.
Source : https://docs.microsoft.com/en-gb/windows/win32/api/cfgmgr32/ns-cfgmgr32-irq_range
"""
_fields_ = [
('IRQR_Min', gdef.ULONG),
('IRQR_Max', gdef.ULONG),
('IRQR_Flags', gdef.ULONG),
]
IRQ_RANGE = _IRQ_RANGE
PIRQ_RANGE = ctypes.POINTER(_IRQ_RANGE)
class AbstractDeviceResource(object):
""" An abstract Python object representing a setup device resource. """
pass
@@ -34,26 +184,103 @@ class AbstractDeviceResource(object):
class MmioDeviceResource(AbstractDeviceResource):
""" A Python object representing a setup device MMIO resource. """
def __init__(self, data):
pass
def __init__(self, data):
# check before casting into MEM_DES
assert (len(data) >= ctypes.sizeof(MEM_DES))
self.header = MEM_DES()
ctypes.memmove(ctypes.byref(self.header), data, ctypes.sizeof(MEM_DES))
# check before casting into MEM_RANGES
assert (len(data) >= ctypes.sizeof(MEM_DES) + self.header.MD_Count*ctypes.sizeof(MEM_RANGE))
# only for requirements list (not our case)
self.ranges = ()
for i in range(self.header.MD_Count):
mem_range = MEM_RANGE()
ctypes.memmove(ctypes.byref(mem_range), data + ctypes.sizeof(MEM_DES) + i*ctypes.sizeof(MEM_RANGE), ctypes.sizeof(MEM_RANGE))
self.ranges.append(mem_range)
def __str__(self):
return 'MmioDeviceResource : [%016x-%016x]' % (self.header.MD_Alloc_Base, self.header.MD_Alloc_End)
class IoDeviceResource(AbstractDeviceResource):
""" A Python object representing a setup device IO port resource. """
def __init__(self, data):
pass
def __init__(self, data):
# check before casting into IO_DES
assert (len(data) >= ctypes.sizeof(IO_DES))
self.header = IO_DES()
ctypes.memmove(ctypes.byref(self.header), data, ctypes.sizeof(IO_DES))
# check before casting into IO_RANGES
assert (len(data) >= ctypes.sizeof(IO_DES) + self.header.IOD_Count*ctypes.sizeof(IO_RANGE))
# only for requirements list (not our case)
self.ranges = ()
for i in range(self.header.IOD_Count):
io_range = IO_RANGE()
ctypes.memmove(ctypes.byref(io_range), data + ctypes.sizeof(IO_DES) + i*ctypes.sizeof(IO_RANGE), ctypes.sizeof(IO_RANGE))
self.ranges.append(io_range)
def __str__(self):
return 'IoDeviceResource : [%016x-%016x]' % (self.header.IOD_Alloc_Base, self.header.IOD_Alloc_End)
class DmaDeviceResource(AbstractDeviceResource):
""" A Python object representing a setup device DMA resource. """
def __init__(self, data):
pass
def __init__(self, data):
# check before casting into DMA_DES
assert (len(data) >= ctypes.sizeof(DMA_DES))
self.header = DMA_DES()
ctypes.memmove(ctypes.byref(self.header), data, ctypes.sizeof(DMA_DES))
# check before casting into MEM_RANGES
assert (len(data) >= ctypes.sizeof(DMA_DES) + self.header.DD_Count*ctypes.sizeof(DMA_RANGE))
# only for requirements list (not our case)
self.ranges = ()
for i in range(self.header.DD_Count):
dma_range = DMA_RANGE()
ctypes.memmove(ctypes.byref(mem_range), data + ctypes.sizeof(DMA_DES) + i*ctypes.sizeof(DMA_RANGE), ctypes.sizeof(DMA_RANGE))
self.ranges.append(dma_range)
def __str__(self):
return 'DmaDeviceResource : [%016x]' % (self.header.DD_Alloc_Chan)
class IrqDeviceResource(AbstractDeviceResource):
""" A Python object representing a setup device Irq resource. """
def __init__(self, data):
pass
# TODO : check 32/64 bitness before casting
# check before casting into IRQ_DES_64
assert (len(data) >= ctypes.sizeof(IRQ_DES_64))
self.header = IRQ_DES_64()
ctypes.memmove(ctypes.byref(self.header), data, ctypes.sizeof(IRQ_DES_64))
# check before casting into MEM_RANGES
assert (len(data) >= ctypes.sizeof(IRQ_DES_64) + self.header.IRQD_Count*ctypes.sizeof(IRQ_RANGE))
# only for requirements list (not our case)
self.ranges = ()
for i in range(self.header.IRQD_Count):
irq_range = IRQ_RANGE()
ctypes.memmove(ctypes.byref(mem_range), data + ctypes.sizeof(IRQ_DES_64) + i*ctypes.sizeof(IRQ_RANGE), ctypes.sizeof(DMA_RANGE))
self.ranges.append(irq_range)
def __str__(self):
return 'IrqDeviceResource : [%016x]' % (self.header.IRQD_Alloc_Num)
class DeviceResource(object):
""" A Python object representing a setup device resource. """