Merge pull request #1368 from qilingframework/dev

Getting ready for 1.4.6
This commit is contained in:
xwings
2023-08-04 10:49:14 +08:00
committed by GitHub
199 changed files with 13626 additions and 11748 deletions
+1
View File
@@ -18,6 +18,7 @@
- KONG ziqiao (lazymio) <mio_at_lazym_io>
- YU zheng (dataisland) <dataisland_at_outlook_com>
- Eli Cohen Nehemia (elicn) <elichn_at_gmail_com>
- Li Hong Jhe (ucgJhe) <ucg.jhe_at_gamil_com>
#### CI, Website,Documentations, Logo & Swags
+1 -2
View File
@@ -1,7 +1,7 @@
This file details the changelog of Qiling Framework.
------------------------------------
[Version 1.4.5]: December 29th, 2022
[Version 1.4.5]: December 31st, 2022
New features:
- Qdb with PE (#1295)
@@ -41,7 +41,6 @@ Contributors:
- ucgJhe
- aquynh
- owl129
-
------------------------------------
[Version 1.4.4]: September 24th, 2022
+4 -3
View File
@@ -3,17 +3,18 @@
# Cross Platform and Multi Architecture Advanced Binary Emulation Framework
#
from zipfile import ZipFile
import sys
sys.path.append("..")
from zipfile import ZipFile
from qiling import Qiling
from qiling.const import QL_VERBOSE
from qiling.const import QL_ARCH, QL_OS, QL_VERBOSE
if __name__ == "__main__":
with ZipFile("shellcodes/win32_https_download.zip") as zip_reader:
with zip_reader.open('win32_https_download.bin', 'r', b'infected') as f:
sc = f.read()
ql = Qiling(code=sc, archtype="x86", ostype="windows", rootfs="rootfs/x86_windows", verbose=QL_VERBOSE.DEBUG)
ql = Qiling(code=sc, archtype=QL_ARCH.X86, ostype=QL_OS.WINDOWS, rootfs="rootfs/x86_windows", verbose=QL_VERBOSE.DEBUG)
ql.run()
+17 -11
View File
@@ -1,15 +1,22 @@
#!/usr/bin/env python3
#
#
# Cross Platform and Multi Architecture Advanced Binary Emulation Framework
#
import sys, curses, math, struct, string, time
import curses
import math
import string
import time
from struct import pack
import sys
sys.path.append("..")
from qiling import *
from qiling import Qiling
from qiling.const import *
from qiling.os.disk import QlDisk
from qiling.os.dos.utils import BIN2BCD
from struct import pack
# https://stackoverflow.com/questions/9829578/fast-way-of-counting-non-zero-bits-in-positive-integer
@@ -129,9 +136,7 @@ def show_once(ql: Qiling, key):
# In this stage, we show every key.
def third_stage(keys):
# To setup terminal again, we have to restart the whole program.
ql = Qiling(["rootfs/8086/doogie/doogie.DOS_MBR"],
"rootfs/8086",
console=False)
ql = Qiling(["rootfs/8086/doogie/doogie.DOS_MBR"], "rootfs/8086", console=False)
ql.add_fs_mapper(0x80, QlDisk("rootfs/8086/doogie/doogie.DOS_MBR", 0x80))
ql.os.set_api((0x1a, 4), set_required_datetime, QL_INTERCEPT.EXIT)
hk = ql.hook_code(stop, begin=0x8018, end=0x8018)
@@ -170,21 +175,22 @@ def read_until_zero(ql: Qiling, addr):
addr += 1
return buf
def set_required_datetime(ql: Qiling):
ql.log.info("Setting Feburary 06, 1990")
ql.arch.regs.ch = BIN2BCD(19)
ql.arch.regs.cl = BIN2BCD(1990%100)
ql.arch.regs.cl = BIN2BCD(1990 % 100)
ql.arch.regs.dh = BIN2BCD(2)
ql.arch.regs.dl = BIN2BCD(6)
def stop(ql, addr, data):
ql.emu_stop()
# In this stage, we get the encrypted data which xored with the specific date.
def first_stage():
ql = Qiling(["rootfs/8086/doogie/doogie.DOS_MBR"],
"rootfs/8086",
console=False)
ql = Qiling(["rootfs/8086/doogie/doogie.DOS_MBR"], "rootfs/8086", console=False)
ql.add_fs_mapper(0x80, QlDisk("rootfs/8086/doogie/doogie.DOS_MBR", 0x80))
# Doogie suggests that the datetime should be 1990-02-06.
ql.os.set_api((0x1a, 4), set_required_datetime, QL_INTERCEPT.EXIT)
+10 -7
View File
@@ -1,5 +1,5 @@
#!/usr/bin/env python3
#
#
# Cross Platform and Multi Architecture Advanced Binary Emulation Framework
#
@@ -7,14 +7,15 @@
# https://www.anquanke.com/post/id/145520
import sys
sys.path.append("../..")
from qiling import *
from qiling import Qiling
from qiling.const import QL_ARCH
def example_run_evm():
contract = '0x606060405266017dfcdece4000600055341561001a57600080fd5b600160a060020a033316600090815260016020526040902066017dfcdece400090556106eb8061004b6000396000f3006060604052600436106100c45763ffffffff7c010000000000000000000000000000000000000000000000000000000060003504166306fdde0381146100c9578063095ea7b31461015357806318160ddd1461018957806323b872dd146101ae57806327edf097146101d6578063313ce567146101ff578063378dc3dc1461021257806342966c681461022557806370a082311461023b578063771282f61461025a57806395d89b411461026d578063a9059cbb14610280578063dd62ed3e146102a2575b600080fd5b34156100d457600080fd5b6100dc6102c7565b60405160208082528190810183818151815260200191508051906020019080838360005b83811015610118578082015183820152602001610100565b50505050905090810190601f1680156101455780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b341561015e57600080fd5b610175600160a060020a03600435166024356102fe565b604051901515815260200160405180910390f35b341561019457600080fd5b61019c6103a4565b60405190815260200160405180910390f35b34156101b957600080fd5b610175600160a060020a03600435811690602435166044356103aa565b34156101e157600080fd5b6101e9610422565b60405160ff909116815260200160405180910390f35b341561020a57600080fd5b6101e9610427565b341561021d57600080fd5b61019c61042c565b341561023057600080fd5b610175600435610437565b341561024657600080fd5b61019c600160a060020a03600435166104ea565b341561026557600080fd5b61019c6104fc565b341561027857600080fd5b6100dc610502565b341561028b57600080fd5b610175600160a060020a0360043516602435610539565b34156102ad57600080fd5b61019c600160a060020a036004358116906024351661054f565b60408051908101604052600781527f48657861676f6e00000000000000000000000000000000000000000000000000602082015281565b60008115806103305750600160a060020a03338116600090815260026020908152604080832093871683529290522054155b151561033b57600080fd5b600160a060020a03338116600081815260026020908152604080832094881680845294909152908190208590557f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b9259085905190815260200160405180910390a350600192915050565b60005490565b600160a060020a03808416600090815260026020908152604080832033909416835292905290812054829010156103e057600080fd5b600160a060020a038085166000908152600260209081526040808320339094168352929052208054839003905561041884848461056c565b5060019392505050565b600281565b600481565b66017dfcdece400081565b600160a060020a0333166000908152600160205260408120548290101561045d57600080fd5b600160a060020a033316600081815260016020526040808220805486900390558180527fa6eef7e35abe7026729641147f7915573c7e97b47efa546f5f6e3230263bcb4980548601905581548590039091557fcc16f5dbb4873280815c1ee09dbd06736cffcc184412cf7a71a0fdb75d397ca59084905190815260200160405180910390a2506001919050565b60016020526000908152604090205481565b60005481565b60408051908101604052600381527f4858470000000000000000000000000000000000000000000000000000000000602082015281565b600061054633848461056c565b50600192915050565b600260209081526000928352604080842090915290825290205481565b600160a060020a038216151561058157600080fd5b600160a060020a038316600090815260016020526040902054600282019010156105aa57600080fd5b600160a060020a038216600090815260016020526040902054818101116105d057600080fd5b600160a060020a03808416600081815260016020526040808220805460011990879003810190915593861682528082208054860190558180527fa6eef7e35abe7026729641147f7915573c7e97b47efa546f5f6e3230263bcb4980546002908101909155825490940190915590917fcc16f5dbb4873280815c1ee09dbd06736cffcc184412cf7a71a0fdb75d397ca5915160ff909116815260200160405180910390a281600160a060020a031683600160a060020a03167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef8360405190815260200160405180910390a35050505600a165627a7a72305820fbef5b10322242b8659b5de8e24ec1cf5e809831f6f7c08e52112f76daa31aef0029'
ql = Qiling(code=contract, archtype="evm")
ql = Qiling(code=contract, archtype=QL_ARCH.EVM)
user1 = ql.arch.evm.create_account(balance=100*10**18)
user2 = ql.arch.evm.create_account(balance=100*10**18)
@@ -36,9 +37,10 @@ def example_run_evm():
# # SMART CONTRACT DEPENDENT: transform from user1 to user2
call_data = '0xa9059cbb'+ ql.arch.evm.abi.convert(['address'], [user2]) + \
ql.arch.evm.abi.convert(['uint256'], [0xfffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe])
msg1 = ql.arch.evm.create_message(user1, c1, data=call_data)
msg1 = ql.arch.evm.create_message(user1, c1, data=call_data)
result = ql.run(code=msg1)
if int(result.output.hex()[2:], 16) == 1:
if int(result.output.hex()[2:], 16) == 1:
print('User1 transfered Token to User1')
# # SMART CONTRACT DEPENDENT: User1 balance underflow, MAX - 1
@@ -48,5 +50,6 @@ def example_run_evm():
result = check_balance(user2, c1)
print('User2 final balance =', int(result.output.hex()[2:], 16))
if __name__ == "__main__":
example_run_evm()
example_run_evm()
+6 -4
View File
@@ -1,16 +1,18 @@
#!/usr/bin/env python3
#
#
# Cross Platform and Multi Architecture Advanced Binary Emulation Framework
#
import sys
sys.path.append("../..")
from qiling import *
from qiling import Qiling
from qiling.const import QL_ARCH
if __name__ == '__main__':
contract = '0x6060604052341561000f57600080fd5b60405160208061031c833981016040528080519060200190919050508060018190556000803373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000208190555050610299806100836000396000f300606060405260043610610057576000357c0100000000000000000000000000000000000000000000000000000000900463ffffffff16806318160ddd1461005c57806370a0823114610085578063a9059cbb146100d2575b600080fd5b341561006757600080fd5b61006f61012c565b6040518082815260200191505060405180910390f35b341561009057600080fd5b6100bc600480803573ffffffffffffffffffffffffffffffffffffffff16906020019091905050610132565b6040518082815260200191505060405180910390f35b34156100dd57600080fd5b610112600480803573ffffffffffffffffffffffffffffffffffffffff1690602001909190803590602001909190505061017a565b604051808215151515815260200191505060405180910390f35b60015481565b60008060008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020549050919050565b600080826000803373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000205403101515156101cb57600080fd5b816000803373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008282540392505081905550816000808573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000206000828254019250508190555060019050929150505600a165627a7a7230582098f1551a391a3e65b3ce45cfa2b3fa5f91eea9a3e7181a81454e025ea0d7151c0029'
ql = Qiling(code=contract, archtype="evm")
ql = Qiling(code=contract, archtype=QL_ARCH.EVM)
ql.debugger = True
# Add Balance Var to the contract
+8 -7
View File
@@ -1,22 +1,23 @@
#!/usr/bin/env python3
#
#
# Cross Platform and Multi Architecture Advanced Binary Emulation Framework
#
import sys
sys.path.append("../..")
from qiling import *
from qiling import Qiling
from qiling.arch.evm.vm.utils import bytecode_to_bytes, runtime_code_detector
from qiling.arch.evm.vm.vm import BaseVM
from qiling.arch.evm.constants import CREATE_CONTRACT_ADDRESS
from qiling.const import QL_ARCH
if __name__ == '__main__':
# Attack_contract = '0x608060405234801561001057600080fd5b5060405160208061046d83398101806040528101908080519060200190929190505050806000806101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550506103ea806100836000396000f300608060405260043610610057576000357c0100000000000000000000000000000000000000000000000000000000900463ffffffff1680636289d38514610152578063acd2e6e51461015c578063ff11e1db146101b3575b670de0b6b3a76400006000809054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16311115610150576000809054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663155dd5ee670de0b6b3a76400006040518263ffffffff167c010000000000000000000000000000000000000000000000000000000002815260040180828152602001915050600060405180830381600087803b15801561013757600080fd5b505af115801561014b573d6000803e3d6000fd5b505050505b005b61015a6101ca565b005b34801561016857600080fd5b50610171610339565b604051808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390f35b3480156101bf57600080fd5b506101c861035e565b005b670de0b6b3a764000034101515156101e157600080fd5b6000809054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663e2c41dbc670de0b6b3a76400006040518263ffffffff167c01000000000000000000000000000000000000000000000000000000000281526004016000604051808303818588803b15801561026e57600080fd5b505af1158015610282573d6000803e3d6000fd5b50505050506000809054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663155dd5ee670de0b6b3a76400006040518263ffffffff167c010000000000000000000000000000000000000000000000000000000002815260040180828152602001915050600060405180830381600087803b15801561031f57600080fd5b505af1158015610333573d6000803e3d6000fd5b50505050565b6000809054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b3373ffffffffffffffffffffffffffffffffffffffff166108fc3073ffffffffffffffffffffffffffffffffffffffff16319081150290604051600060405180830381858888f193505050501580156103bb573d6000803e3d6000fd5b505600a165627a7a723058204ad3139b1085c12112b76e9eab70c6589942d6e84eb3d8329a644eca757c19d00029'
Attack_contract = '0x608060405234801561001057600080fd5b506040516020806104b883398101806040528101908080519060200190929190505050806000806101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555050610435806100836000396000f30060806040526004361061004c576000357c0100000000000000000000000000000000000000000000000000000000900463ffffffff168063a75e462514610179578063ff11e1db146101e1575b670de0b6b3a76400006000809054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16311115610177576000809054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16600060149054906101000a90047c0100000000000000000000000000000000000000000000000000000000027c01000000000000000000000000000000000000000000000000000000009004670de0b6b3a76400006040518263ffffffff167c0100000000000000000000000000000000000000000000000000000000028152600401808267ffffffffffffffff1681526020019150506000604051808303816000875af192505050505b005b6101df60048036038101908080357bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916906020019092919080357bffffffffffffffffffffffffffffffffffffffffffffffffffffffff191690602001909291905050506101f8565b005b3480156101ed57600080fd5b506101f66103a9565b005b80600060146101000a81548163ffffffff02191690837c010000000000000000000000000000000000000000000000000000000090040217905550670de0b6b3a7640000341015151561024a57600080fd5b6000809054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16670de0b6b3a7640000837c01000000000000000000000000000000000000000000000000000000009004906040518263ffffffff167c010000000000000000000000000000000000000000000000000000000002815260040160006040518083038185885af19350505050506000809054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16817c01000000000000000000000000000000000000000000000000000000009004670de0b6b3a76400006040518263ffffffff167c0100000000000000000000000000000000000000000000000000000000028152600401808267ffffffffffffffff1681526020019150506000604051808303816000875af192505050505050565b3373ffffffffffffffffffffffffffffffffffffffff166108fc3073ffffffffffffffffffffffffffffffffffffffff16319081150290604051600060405180830381858888f19350505050158015610406573d6000803e3d6000fd5b505600a165627a7a723058205aacb19a5864d2c460aed6c844f2aca575d87de6477ac757a72511bb2975b3f80029'
ql = Qiling(code=Attack_contract, archtype="evm")
ql = Qiling(code=Attack_contract, archtype=QL_ARCH.EVM)
vm:BaseVM = ql.arch.evm.vm
C1 = b'\xaa' * 20
@@ -28,9 +29,9 @@ if __name__ == '__main__':
ql.arch.evm.create_account(C2)
ql.arch.evm.create_account(User1, 100*10**18)
ql.arch.evm.create_account(User2, 100*10**18)
EtherStore_contract = '0x6080604052670de0b6b3a764000060005534801561001c57600080fd5b506103b08061002c6000396000f30060806040526004361061006d576000357c0100000000000000000000000000000000000000000000000000000000900463ffffffff1680631031ec3114610072578063155dd5ee146100c957806327e235e3146100f65780637ddfe78d1461014d578063e2c41dbc14610178575b600080fd5b34801561007e57600080fd5b506100b3600480360381019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190505050610182565b6040518082815260200191505060405180910390f35b3480156100d557600080fd5b506100f46004803603810190808035906020019092919050505061019a565b005b34801561010257600080fd5b50610137600480360381019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190505050610317565b6040518082815260200191505060405180910390f35b34801561015957600080fd5b5061016261032f565b6040518082815260200191505060405180910390f35b610180610335565b005b60016020528060005260406000206000915090505481565b80600260003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002054101515156101e857600080fd5b60005481111515156101f957600080fd5b62093a80600160003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000205401421015151561024c57600080fd5b3373ffffffffffffffffffffffffffffffffffffffff168160405160006040518083038185875af192505050151561028357600080fd5b80600260003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000206000828254039250508190555042600160003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000208190555050565b60026020528060005260406000206000915090505481565b60005481565b34600260003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020600082825401925050819055505600a165627a7a72305820707bf0ae11ce52ff7b7846ede3497d41b6fadea29579773fc70e8e61c0f549f10029'
print('Init Victim balance is', vm.state.get_balance(User1)/10**18)
print('Init Attacker balance is', vm.state.get_balance(User2)/10**18)
@@ -66,7 +67,7 @@ if __name__ == '__main__':
res_code = bytecode_to_bytes(res.output)
runtime_code, aux_data, constructor_args = runtime_code_detector(res_code)
rt_code1 = bytecode_to_bytes(runtime_code)
print('\n------ Attacker deposit 1 ETH to DeFi contract, Start Reentrancy Attack')
# 4. User2 pwnEtherStore with 1ETH
call_data = '0xa75e4625' + ql.arch.evm.abi.convert(['bytes4'], [bytecode_to_bytes('0xe2c41dbc')]) + ql.arch.evm.abi.convert(['bytes4'], [bytecode_to_bytes('0x155dd5ee')])
+15 -14
View File
@@ -1,21 +1,22 @@
#!/usr/bin/env python3
#
#
# Cross Platform and Multi Architecture Advanced Binary Emulation Framework
#
import sys
sys.path.append("../..")
from qiling import *
from qiling import Qiling
from qiling.arch.evm.vm.utils import bytecode_to_bytes, runtime_code_detector
from qiling.arch.evm.vm.vm import BaseVM
from qiling.arch.evm.constants import CREATE_CONTRACT_ADDRESS
from qiling.const import QL_ARCH
def template(vic_contract, deposit, withdraw):
Attack_contract = '0x608060405234801561001057600080fd5b506040516020806104b883398101806040528101908080519060200190929190505050806000806101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555050610435806100836000396000f30060806040526004361061004c576000357c0100000000000000000000000000000000000000000000000000000000900463ffffffff168063a75e462514610179578063ff11e1db146101e1575b670de0b6b3a76400006000809054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16311115610177576000809054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16600060149054906101000a90047c0100000000000000000000000000000000000000000000000000000000027c01000000000000000000000000000000000000000000000000000000009004670de0b6b3a76400006040518263ffffffff167c0100000000000000000000000000000000000000000000000000000000028152600401808267ffffffffffffffff1681526020019150506000604051808303816000875af192505050505b005b6101df60048036038101908080357bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916906020019092919080357bffffffffffffffffffffffffffffffffffffffffffffffffffffffff191690602001909291905050506101f8565b005b3480156101ed57600080fd5b506101f66103a9565b005b80600060146101000a81548163ffffffff02191690837c010000000000000000000000000000000000000000000000000000000090040217905550670de0b6b3a7640000341015151561024a57600080fd5b6000809054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16670de0b6b3a7640000837c01000000000000000000000000000000000000000000000000000000009004906040518263ffffffff167c010000000000000000000000000000000000000000000000000000000002815260040160006040518083038185885af19350505050506000809054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16817c01000000000000000000000000000000000000000000000000000000009004670de0b6b3a76400006040518263ffffffff167c0100000000000000000000000000000000000000000000000000000000028152600401808267ffffffffffffffff1681526020019150506000604051808303816000875af192505050505050565b3373ffffffffffffffffffffffffffffffffffffffff166108fc3073ffffffffffffffffffffffffffffffffffffffff16319081150290604051600060405180830381858888f19350505050158015610406573d6000803e3d6000fd5b505600a165627a7a723058205aacb19a5864d2c460aed6c844f2aca575d87de6477ac757a72511bb2975b3f80029'
ql = Qiling(code=Attack_contract, archtype="evm")
ql = Qiling(code=Attack_contract, archtype=QL_ARCH.EVM)
vm:BaseVM = ql.arch.evm.vm
C1 = b'\xaa' * 20
@@ -30,7 +31,7 @@ def template(vic_contract, deposit, withdraw):
EtherStore_contract = vic_contract
print('Init Victim balance is', vm.state.get_balance(User1)/10**18)
print('Init Attacker balance is', vm.state.get_balance(User2)/10**18)
@@ -66,7 +67,7 @@ def template(vic_contract, deposit, withdraw):
res_code = bytecode_to_bytes(res.output)
runtime_code, aux_data, constructor_args = runtime_code_detector(res_code)
rt_code1 = bytecode_to_bytes(runtime_code)
print('\n------ Attacker deposit 1 ETH to DeFi contract, Start Reentrancy Attack')
# 4. User2 pwnEtherStore with 1ETH
call_data = '0xa75e4625' + ql.arch.evm.abi.convert(['bytes4'], [bytecode_to_bytes(deposit)]) + ql.arch.evm.abi.convert(['bytes4'], [bytecode_to_bytes(withdraw)])
@@ -88,7 +89,7 @@ if __name__ == '__main__':
contract_1 = '0x6080604052670de0b6b3a764000060005534801561001c57600080fd5b506103b08061002c6000396000f30060806040526004361061006d576000357c0100000000000000000000000000000000000000000000000000000000900463ffffffff1680631031ec3114610072578063155dd5ee146100c957806327e235e3146100f65780637ddfe78d1461014d578063e2c41dbc14610178575b600080fd5b34801561007e57600080fd5b506100b3600480360381019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190505050610182565b6040518082815260200191505060405180910390f35b3480156100d557600080fd5b506100f46004803603810190808035906020019092919050505061019a565b005b34801561010257600080fd5b50610137600480360381019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190505050610317565b6040518082815260200191505060405180910390f35b34801561015957600080fd5b5061016261032f565b6040518082815260200191505060405180910390f35b610180610335565b005b60016020528060005260406000206000915090505481565b80600260003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002054101515156101e857600080fd5b60005481111515156101f957600080fd5b62093a80600160003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000205401421015151561024c57600080fd5b3373ffffffffffffffffffffffffffffffffffffffff168160405160006040518083038185875af192505050151561028357600080fd5b80600260003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000206000828254039250508190555042600160003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000208190555050565b60026020528060005260406000206000915090505481565b60005481565b34600260003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020600082825401925050819055505600a165627a7a72305820707bf0ae11ce52ff7b7846ede3497d41b6fadea29579773fc70e8e61c0f549f10029'
c1_deposit = '0xe2c41dbc'
c1_withdraw = '0x155dd5ee'
contract_2 = '0x608060405234801561001057600080fd5b5033600160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055506106dc806100616000396000f300608060405260043610610062576000357c0100000000000000000000000000000000000000000000000000000000900463ffffffff1680630c08bf881461014d578063590e1ae314610164578063a9059cbb1461017b578063e42c08f2146101c8575b600080339150349050600060648281151561007957fe5b0614151561008657600080fd5b60648181151561009257fe5b046000808473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020600082825401925050819055507fc848a0bc6fc10f63d456eae535b952f8768bfd21d409b4933f8032cce0432ea48183604051808381526020018273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019250505060405180910390a15050005b34801561015957600080fd5b5061016261021f565b005b34801561017057600080fd5b50610179610312565b005b34801561018757600080fd5b506101c6600480360381019080803573ffffffffffffffffffffffffffffffffffffffff16906020019092919080359060200190929190505050610434565b005b3480156101d457600080fd5b50610209600480360381019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190505050610658565b6040518082815260200191505060405180910390f35b600034111561022d57600080fd5b3373ffffffffffffffffffffffffffffffffffffffff16600160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1614151561028957600080fd5b7fedf2f7451a6c99c99b58baaddbe18df51bec156fe6ae8dd3ea730168326f94cd3073ffffffffffffffffffffffffffffffffffffffff16316040518082815260200191505060405180910390a1600160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16ff5b600080600034111561032357600080fd5b3391506000808373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020549050600081141561037557600080fd5b61038160648202610670565b60008060008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020819055507f658eefd1c566207ffd3fb44f4d9b1e443698a39f8a6f7b134b3fef529e3f3f028183604051808381526020018273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019250505060405180910390a15050565b60008034111561044357600080fd5b339050816000808373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002054101561049157600080fd5b6000808473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002054826000808673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000205401101561051c57600080fd5b816000808373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008282540392505081905550816000808573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020600082825401925050819055507fa25be434081445744d5b297a785f7b7073142ae4bcd91a0e7aa802f802b4e0c7828285604051808481526020018373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020018273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001935050505060405180910390a1505050565b60006020528060005260406000206000915090505481565b60003373ffffffffffffffffffffffffffffffffffffffff168260405160006040518083038185875af19250505090508015156106ac57600080fd5b50505600a165627a7a72305820e5031f476480cd5d80ec7b267c7bf4c672137328294cb6b71bbb631ce9b99fc20029'
c2_deposit = ''
c2_withdraw = '0x590e1ae3'
@@ -103,11 +104,11 @@ if __name__ == '__main__':
# contract Attack {
# address victim;
# bytes4 withdraw_id;
#
# constructor(address addr) {
# victim = addr;
# }
#
# function pwn(bytes4 deposit, bytes4 withdraw) public payable {
# withdraw_id = withdraw;
# // attack to the nearest ether
@@ -115,19 +116,19 @@ if __name__ == '__main__':
# // send eth to the depositFunds() function
# victim.call.value(1 ether)(deposit);
# victim.call(withdraw, 1 ether);
#
# //etherStore.depositFunds.value(1 ether)();
# // start the magic
# //etherStore.withdrawFunds(1 ether);
# }
#
# function collectEther() public {
# msg.sender.transfer(this.balance);
# }
#
# function () payable {
# if (victim.balance > 1 ether) {
# victim.call(withdraw_id,1 ether);
# }
# }
# }
# }
+7 -6
View File
@@ -1,18 +1,19 @@
#!/usr/bin/env python3
#
#
# Cross Platform and Multi Architecture Advanced Binary Emulation Framework
#
import sys
sys.path.append("../..")
from qiling import *
from qiling import Qiling
from qiling.const import QL_ARCH
def example_run_evm():
contract = '0x6060604052341561000f57600080fd5b60405160208061031c833981016040528080519060200190919050508060018190556000803373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000208190555050610299806100836000396000f300606060405260043610610057576000357c0100000000000000000000000000000000000000000000000000000000900463ffffffff16806318160ddd1461005c57806370a0823114610085578063a9059cbb146100d2575b600080fd5b341561006757600080fd5b61006f61012c565b6040518082815260200191505060405180910390f35b341561009057600080fd5b6100bc600480803573ffffffffffffffffffffffffffffffffffffffff16906020019091905050610132565b6040518082815260200191505060405180910390f35b34156100dd57600080fd5b610112600480803573ffffffffffffffffffffffffffffffffffffffff1690602001909190803590602001909190505061017a565b604051808215151515815260200191505060405180910390f35b60015481565b60008060008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020549050919050565b600080826000803373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000205403101515156101cb57600080fd5b816000803373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008282540392505081905550816000808573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000206000828254019250508190555060019050929150505600a165627a7a7230582098f1551a391a3e65b3ce45cfa2b3fa5f91eea9a3e7181a81454e025ea0d7151c0029'
ql = Qiling(code=contract, archtype="evm")
ql = Qiling(code=contract, archtype=QL_ARCH.EVM)
# Add Balance Var to the contract
bal = ql.arch.evm.abi.convert(['uint256'], [20])
@@ -39,7 +40,7 @@ def example_run_evm():
call_data = '0xa9059cbb'+ ql.arch.evm.abi.convert(['address'], [user2]) + \
ql.arch.evm.abi.convert(['uint256'], [21])
# print('Transfer Calldata Code: ' + call_data)
msg1 = ql.arch.evm.create_message(user1, c1, call_data)
msg1 = ql.arch.evm.create_message(user1, c1, call_data)
result = ql.run(code=msg1)
if int(result.output.hex()[2:], 16) == 1:
print('User1 transfered 21 Token to User2')
+7 -5
View File
@@ -1,17 +1,19 @@
#!/usr/bin/env python3
#
#
# Cross Platform and Multi Architecture Advanced Binary Emulation Framework
#
import sys
sys.path.append("../../../..")
from qiling import *
from qiling import Qiling
from qiling.const import QL_ARCH
def underflow(fuzz_balance):
code = '0x6060604052341561000f57600080fd5b60405160208061031c833981016040528080519060200190919050508060018190556000803373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000208190555050610299806100836000396000f300606060405260043610610057576000357c0100000000000000000000000000000000000000000000000000000000900463ffffffff16806318160ddd1461005c57806370a0823114610085578063a9059cbb146100d2575b600080fd5b341561006757600080fd5b61006f61012c565b6040518082815260200191505060405180910390f35b341561009057600080fd5b6100bc600480803573ffffffffffffffffffffffffffffffffffffffff16906020019091905050610132565b6040518082815260200191505060405180910390f35b34156100dd57600080fd5b610112600480803573ffffffffffffffffffffffffffffffffffffffff1690602001909190803590602001909190505061017a565b604051808215151515815260200191505060405180910390f35b60015481565b60008060008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020549050919050565b600080826000803373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000205403101515156101cb57600080fd5b816000803373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008282540392505081905550816000808573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000206000828254019250508190555060019050929150505600a165627a7a7230582098f1551a391a3e65b3ce45cfa2b3fa5f91eea9a3e7181a81454e025ea0d7151c0029'
ql = Qiling(code=code, archtype="evm")
ql = Qiling(code=code, archtype=QL_ARCH.EVM)
# Add Balance Var to the contract
bal = ql.arch.evm.abi.convert(['uint256'], [20])
@@ -36,7 +38,7 @@ def underflow(fuzz_balance):
# SMART CONTRACT DEPENDENT: transform 21 from user1 to user2
call_data = '0xa9059cbb'+ ql.arch.evm.abi.convert(['address'], [user2]) + \
ql.arch.evm.abi.convert(['uint256'], [fuzz_balance])
msg1 = ql.arch.evm.create_message(user1, c1, call_data)
msg1 = ql.arch.evm.create_message(user1, c1, call_data)
result = ql.run(code=msg1)
# SMART CONTRACT DEPENDENT: User1 balance underflow, MAX - 1
+30 -26
View File
@@ -1,37 +1,41 @@
from qiling import *
from future import __annotations__
class QILING_IDA():
def __init__(self):
pass
from typing import TYPE_CHECKING, List
def _show_context(self, ql:Qiling):
registers = [ k for k in ql.arch.regs.register_mapping.keys() if type(k) is str ]
for idx in range(0, len(registers), 3):
regs = registers[idx:idx+3]
s = "\t".join(map(lambda v: f"{v:4}: {ql.arch.regs.__getattr__(v):016x}", regs))
ql.log.info(s)
if TYPE_CHECKING:
from qiling import Qiling
from qiling.core_hooks_types import HookRet
def custom_prepare(self, ql:Qiling):
class QILING_IDA:
def _show_context(self, ql: Qiling):
registers = tuple(ql.arch.regs.register_mapping.keys())
grouping = 4
for idx in range(0, len(registers), grouping):
ql.log.info('\t'.join(f'{r:5s}: {ql.arch.regs.read(r):016x}' for r in registers[idx:idx + grouping]))
def custom_prepare(self, ql: Qiling) -> None:
ql.log.info('Context before starting emulation:')
self._show_context(ql)
def custom_continue(self, ql:Qiling):
ql.log.info('custom_continue hook.')
def custom_continue(self, ql: Qiling) -> List[HookRet]:
ql.log.info('custom_continue hook')
self._show_context(ql)
hook = []
return hook
def custom_step(self, ql:Qiling):
def step_hook(ql, addr, size):
ql.log.info(f"Executing: {hex(addr)}")
return []
def custom_step(self, ql: Qiling) -> List[HookRet]:
def step_hook(ql: Qiling, addr: int, size: int):
ql.log.info(f'Executing: {addr:#x}')
self._show_context(ql)
ql.log.info('custom_step hook')
hook = []
hook.append(ql.hook_code(step_hook))
return hook
def custom_execute_selection(self, ql:Qiling):
ql.log.info('custom execute selection hook')
hook = []
return hook
return [ql.hook_code(step_hook)]
def custom_execute_selection(self, ql: Qiling) -> List[HookRet]:
ql.log.info('custom_execute_selection hook')
return []
+12 -3
View File
@@ -7,7 +7,7 @@ import sys
sys.path.append('..')
from qiling import Qiling
from qiling.const import QL_VERBOSE
from qiling.const import QL_ARCH, QL_OS, QL_VERBOSE
from qiling.extensions.r2 import R2
@@ -15,6 +15,7 @@ def func(ql: Qiling, *args, **kwargs):
ql.os.stdout.write(b"=====hooked main=====!\n")
return
def my_sandbox(path, rootfs):
ql = Qiling(path, rootfs, verbose=QL_VERBOSE.DISASM)
# QL_VERBOSE.DISASM will be monkey-patched when r2 is available
@@ -37,13 +38,21 @@ def my_sandbox(path, rootfs):
# r2.enable_trace()
ql.run()
if __name__ == "__main__":
my_sandbox(["rootfs/x86_windows/bin/x86_hello.exe"], "rootfs/x86_windows")
# test shellcode mode
ARM64_LIN = bytes.fromhex('420002ca210080d2400080d2c81880d2010000d4e60300aa01020010020280d2681980d2010000d4410080d2420002cae00306aa080380d2010000d4210400f165ffff54e0000010420002ca210001caa81b80d2010000d4020004d27f0000012f62696e2f736800')
ARM64_LIN = bytes.fromhex('''
420002ca210080d2400080d2c81880d2010000d4e60300aa01020010020280d2
681980d2010000d4410080d2420002cae00306aa080380d2010000d4210400f1
65ffff54e0000010420002ca210001caa81b80d2010000d4020004d27f000001
2f62696e2f736800
''')
print("\nLinux ARM 64bit Shellcode")
ql = Qiling(code=ARM64_LIN, archtype="arm64", ostype="linux", verbose=QL_VERBOSE.DEBUG)
ql = Qiling(code=ARM64_LIN, archtype=QL_ARCH.ARM64, ostype=QL_OS.LINUX, verbose=QL_VERBOSE.DEBUG)
r2 = R2(ql)
# disassemble 32 instructions
print(r2._cmd('pd 32'))
@@ -4,10 +4,9 @@
#
import sys
sys.path.append("..")
from qiling import *
from qiling import Qiling
from qiling.const import QL_VERBOSE
from qiling.extensions.report import generate_report
+27
View File
@@ -0,0 +1,27 @@
#!/usr/bin/env python3
#
# Cross Platform and Multi Architecture Advanced Binary Emulation Framework
#
from qiling import Qiling
from qiling.const import QL_VERBOSE
from qiling.extensions import trace
ROOTFS = r'examples/rootfs/x8664_linux'
if __name__ == '__main__':
# qiling verbosity should be set to DEBUG to show the trace records
ql = Qiling([fr'{ROOTFS}/bin/x8664_hello'], ROOTFS, verbose=QL_VERBOSE.DEBUG)
# enable full tracing. since full tracing significantly slows down the emulation,
# it may be enabled on demand from a hook, instead
trace.enable_full_trace(ql)
# sometimes all we need is to see the last operations that led to a crash. the history
# method uses less resources compared to full trace, and emits trace records only when
# a crash occurs.
#
# for example, showing last 32 trace records before the crash:
# trace.enable_history_trace(ql, 32)
ql.run()
@@ -1,19 +1,20 @@
#!/usr/bin/env python3
#
#
# Cross Platform and Multi Architecture Advanced Binary Emulation Framework
#
# Everything about the bug and firmware https://www.exploit-db.com/exploits/33863
import os,sys
sys.path.append("../../..")
from qiling import *
from qiling import Qiling
from qiling.const import QL_VERBOSE
from qiling.extensions.afl import ql_afl_fuzz
def main(input_file, enable_trace=False):
env_vars = {
"REQUEST_METHOD": "POST",
"REQUEST_URI": "/hedwig.cgi",
@@ -24,9 +25,8 @@ def main(input_file, enable_trace=False):
}
ql = Qiling(["./rootfs/htdocs/web/hedwig.cgi"], "./rootfs",
verbose=QL_VERBOSE.DEBUG, env=env_vars,
console = True if enable_trace else False)
verbose=QL_VERBOSE.DEBUG, env=env_vars, console=enable_trace)
def place_input_callback(ql: Qiling, input: bytes, _: int):
env_var = ("HTTP_COOKIE=uid=1234&password=").encode()
env_vars = env_var + input + b"\x00" + (ql.path).encode() + b"\x00"
+16 -20
View File
@@ -1,51 +1,47 @@
#!/usr/bin/env python3
#
#
# Cross Platform and Multi Architecture Advanced Binary Emulation Framework
#
import os
from typing import Optional
import sys
from typing import Any, Optional
sys.path.append("../../..")
from qiling.core import Qiling
from qiling.const import QL_VERBOSE
from qiling.const import QL_ARCH, QL_OS, QL_VERBOSE
from qiling.extensions.afl import ql_afl_fuzz_custom
from qiling.extensions.mcu.stm32f4 import stm32f429
from unicorn import UC_ERR_OK, UcError
from unicorn import UC_ERR_OK
def main(input_file: str):
ql = Qiling(["../../rootfs/mcu/stm32f429/bof.elf"],
archtype="cortex_m",
env=stm32f429,
ostype='mcu',
verbose=QL_VERBOSE.DISABLED)
ql = Qiling(["../../rootfs/mcu/stm32f429/bof.elf"],
archtype=QL_ARCH.CORTEX_M, ostype=QL_OS.MCU, env=stm32f429, verbose=QL_VERBOSE.DISABLED)
ql.hw.create('rcc')
ql.hw.create('usart2')
ql.hw.create('usart3')
ql.fast_mode = True
ql.fast_mode = True
def place_input_callback(ql: Qiling, input_bytes: bytes, persistent_round: int) -> Optional[bool]:
"""Called with every newly generated input."""
ql.hw.usart3.send(input_bytes)
return True
def fuzzing_callback(ql: Qiling):
ql.run(end=0x80006d9)
ql.run(end=0x80006d9)
return UC_ERR_OK
ql.uc.ctl_exits_enabled(True)
ql.uc.ctl_set_exits([0x80006d9])
ql_afl_fuzz_custom(ql, input_file, place_input_callback, fuzzing_callback=fuzzing_callback)
ql_afl_fuzz_custom(ql, input_file, place_input_callback, fuzzing_callback=fuzzing_callback, exits=[0x80006d9])
os.exit(0)
@@ -1,5 +1,5 @@
#!/usr/bin/env python3
#
#
# Cross Platform and Multi Architecture Advanced Binary Emulation Framework
#
@@ -11,13 +11,16 @@
# 5. rm -rf webroot && mv webroot_ro webroot
# 5. mv etc_ro etc
import os, pickle, socket, sys, threading
import os
import sys
sys.path.append("../../../")
from qiling import *
from qiling import Qiling
from qiling.const import QL_VERBOSE
from qiling.extensions.afl import ql_afl_fuzz
def patcher(ql):
br0_addr = ql.mem.search("br0".encode() + b'\x00')
for addr in br0_addr:
@@ -44,14 +47,14 @@ def main(input_file, enable_trace=False):
ql_afl_fuzz(_ql, input_file=input_file, place_input_callback=place_input_callback, exits=[ql.os.exit_point])
ql.hook_address(callback=start_afl, address=0x10930+8)
try:
ql.run(begin = 0x10930+4, end = 0x7a0cc+4)
os._exit(0)
except:
if enable_trace:
print("\nFuzzer Went Shit")
os._exit(0)
os._exit(0)
if __name__ == "__main__":
if len(sys.argv) == 1:
+4 -3
View File
@@ -7,9 +7,10 @@ import sys
sys.path.append("..")
from qiling.core import Qiling
from qiling.const import QL_VERBOSE
from qiling.const import QL_ARCH, QL_OS, QL_VERBOSE
from qiling.os.const import STRING
def get_kaimendaji_password():
def my_getenv(ql: Qiling):
env = {
@@ -56,11 +57,10 @@ def get_kaimendaji_password():
ql.arch.regs.r2 = 2
ql.arch.regs.r3 = argv_ptr
with open("../examples/rootfs/blob/u-boot.bin.img", "rb") as f:
uboot_code = f.read()
ql = Qiling(code=uboot_code[0x40:], archtype="arm", ostype="blob", profile="uboot_bin.ql", verbose=QL_VERBOSE.OFF)
ql = Qiling(code=uboot_code[0x40:], archtype=QL_ARCH.ARM, ostype=QL_OS.BLOB, profile="uboot_bin.ql", verbose=QL_VERBOSE.OFF)
image_base_addr = ql.loader.load_address
ql.hook_address(my_getenv, image_base_addr + 0x13AC0)
@@ -70,5 +70,6 @@ def get_kaimendaji_password():
ql.run(image_base_addr + 0x486B4, image_base_addr + 0x48718)
if __name__ == "__main__":
get_kaimendaji_password()
+7 -3
View File
@@ -1,5 +1,5 @@
#!/usr/bin/env python3
#
#
# Cross Platform and Multi Architecture Advanced Binary Emulation Framework
#
@@ -9,9 +9,11 @@ sys.path.append("../..")
from qiling.core import Qiling
from qiling.const import QL_VERBOSE
from qiling.extensions.mcu.gd32vf1 import gd32vf103
from qiling.const import QL_ARCH, QL_OS
ql = Qiling(['../rootfs/mcu/gd32vf103/blink.hex'], archtype="riscv64", ostype="mcu",
env=gd32vf103, verbose=QL_VERBOSE.DEBUG)
ql = Qiling(['../rootfs/mcu/gd32vf103/blink.hex'], archtype=QL_ARCH.RISCV64, ostype=QL_OS.MCU,
env=gd32vf103, verbose=QL_VERBOSE.DEBUG)
ql.hw.create('rcu')
ql.hw.create('gpioa').watch()
@@ -20,9 +22,11 @@ ql.hw.create('gpioc').watch()
delay_cycles_begin = 0x800015c
delay_cycles_end = 0x800018c
def skip_delay(ql):
ql.arch.regs.pc = delay_cycles_end
ql.hook_address(skip_delay, delay_cycles_begin)
ql.hw.gpioc.hook_set(13, lambda : print('Set PC13'))
+2 -1
View File
@@ -10,10 +10,11 @@ from qiling.core import Qiling
from qiling.const import QL_VERBOSE
from qiling.extensions.mcu.stm32f4 import stm32f407
from qiling.hw.external_device.oled.ssd1306 import PyGameSSD1306Spi
from qiling.const import QL_ARCH, QL_OS
ql = Qiling(["../rootfs/mcu/stm32f407/ai-sine-test.elf"],
archtype="cortex_m", ostype="mcu", env=stm32f407, verbose=QL_VERBOSE.DEFAULT)
archtype=QL_ARCH.CORTEX_M, ostype=QL_OS.MCU, env=stm32f407, verbose=QL_VERBOSE.DEFAULT)
ql.hw.create('rcc')
ql.hw.create('pwr')
+8 -8
View File
@@ -1,17 +1,15 @@
#!/usr/bin/env python3
#
#
# Cross Platform and Multi Architecture Advanced Binary Emulation Framework
#
from multiprocessing import Pool
import sys
from multiprocessing import Pool
from multiprocessing import Process
sys.path.append("../..")
from qiling.core import Qiling
from qiling.const import QL_VERBOSE
from qiling.const import QL_ARCH, QL_OS, QL_VERBOSE
from qiling.extensions.mcu.stm32f4 import stm32f407
@@ -24,11 +22,12 @@ def dicts():
for x in range(1, 20):
yield str((a*x*x + b*x + c) % M)
# Cracking the passwd of lock
def crack(passwd):
ql = Qiling(["../../examples/rootfs/mcu/stm32f407/backdoorlock.hex"],
archtype="cortex_m", ostype="mcu", env=stm32f407, verbose=QL_VERBOSE.DISABLED)
ql = Qiling(["../../examples/rootfs/mcu/stm32f407/backdoorlock.hex"],
archtype=QL_ARCH.CORTEX_M, ostype=QL_OS.MCU, env=stm32f407, verbose=QL_VERBOSE.DISABLED)
ql.hw.create('spi2')
ql.hw.create('gpioe')
ql.hw.create('gpiof')
@@ -55,6 +54,7 @@ def crack(passwd):
del ql
pool = Pool()
for passwd in dicts():
pool.apply_async(crack, args=(passwd,))
+2 -2
View File
@@ -7,13 +7,13 @@ import sys
sys.path.append("../..")
from qiling.core import Qiling
from qiling.const import QL_VERBOSE
from qiling.const import QL_ARCH, QL_OS, QL_VERBOSE
from qiling.extensions.mcu.stm32f4 import stm32f407
from qiling.hw.external_device.oled.ssd1306 import PyGameSSD1306Spi
ql = Qiling(["../rootfs/mcu/stm32f407/mnist.bin", 0x8000000],
archtype="cortex_m", ostype="mcu", env=stm32f407, verbose=QL_VERBOSE.DEFAULT)
archtype=QL_ARCH.CORTEX_M, ostype=QL_OS.MCU, env=stm32f407, verbose=QL_VERBOSE.DEFAULT)
ql.hw.create('rcc')
ql.hw.create('gpiod')
+9 -7
View File
@@ -1,5 +1,5 @@
#!/usr/bin/env python3
#
#
# Cross Platform and Multi Architecture Advanced Binary Emulation Framework
#
@@ -7,12 +7,13 @@ import sys
sys.path.append("../..")
from qiling.core import Qiling
from qiling.const import QL_VERBOSE
from qiling.const import QL_ARCH, QL_OS, QL_VERBOSE
from qiling.extensions.mcu.stm32f4 import stm32f411
def stm32f411_dma():
ql = Qiling(["../rootfs/mcu/stm32f411/dma-clock.hex"],
archtype="cortex_m", ostype="mcu", env=stm32f411, verbose=QL_VERBOSE.DEBUG)
ql = Qiling(["../rootfs/mcu/stm32f411/dma-clock.hex"],
archtype=QL_ARCH.CORTEX_M, ostype=QL_OS.MCU, env=stm32f411, verbose=QL_VERBOSE.DEBUG)
ql.hw.create('usart2').watch()
ql.hw.create('dma1').watch()
@@ -21,10 +22,11 @@ def stm32f411_dma():
ql.run(count=200000)
buf = ql.hw.usart2.recv()
## check timestamp
# check timestamp
tick = [int(x) for x in buf.split()]
for i in range(1, len(tick)):
assert(4 <= tick[i] - tick[i - 1] <= 6)
assert (4 <= tick[i] - tick[i - 1] <= 6)
if __name__ == "__main__":
stm32f411_dma()
stm32f411_dma()
+7 -6
View File
@@ -1,5 +1,5 @@
#!/usr/bin/env python3
#
#
# Cross Platform and Multi Architecture Advanced Binary Emulation Framework
#
@@ -7,20 +7,21 @@ import sys
sys.path.append("../..")
from qiling.core import Qiling
from qiling.const import QL_VERBOSE
from qiling.const import QL_ARCH, QL_OS, QL_VERBOSE
from qiling.extensions.mcu.stm32f4 import stm32f411
def stm32f411_freertos():
ql = Qiling(["../rootfs/mcu/stm32f411/os-demo.hex"],
archtype="cortex_m", ostype="mcu", env=stm32f411, verbose=QL_VERBOSE.DEBUG)
ql = Qiling(["../rootfs/mcu/stm32f411/os-demo.hex"],
archtype=QL_ARCH.CORTEX_M, ostype=QL_OS.MCU, env=stm32f411, verbose=QL_VERBOSE.DEBUG)
ql.hw.create('usart2').watch()
ql.hw.create('gpioa').watch()
ql.hw.create('rcc')
ql.hw.create('rcc')
ql.hw.systick.set_ratio(100)
ql.run(count=200000)
if __name__ == "__main__":
stm32f411_freertos()
stm32f411_freertos()
+6 -5
View File
@@ -1,5 +1,5 @@
#!/usr/bin/env python3
#
#
# Cross Platform and Multi Architecture Advanced Binary Emulation Framework
#
@@ -7,22 +7,23 @@ import sys
sys.path.append("../..")
from qiling.core import Qiling
from qiling.const import QL_VERBOSE
from qiling.const import QL_ARCH, QL_OS, QL_VERBOSE
from qiling.extensions.mcu.stm32f4 import stm32f411
def test_mcu_gpio_stm32f411():
ql = Qiling(["../../examples/rootfs/mcu/stm32f411/hello_gpioA.hex"],
archtype="cortex_m", ostype="mcu", env=stm32f411, verbose=QL_VERBOSE.DEBUG)
ql = Qiling(["../../examples/rootfs/mcu/stm32f411/hello_gpioA.hex"],
archtype=QL_ARCH.CORTEX_M, ostype=QL_OS.MCU, env=stm32f411, verbose=QL_VERBOSE.DEBUG)
ql.hw.create('usart2').watch()
ql.hw.create('rcc').watch()
ql.hw.create('gpioa').watch()
ql.hw.gpioa.hook_set(5, lambda: print('LED light up'))
ql.hw.gpioa.hook_reset(5, lambda: print('LED light off'))
ql.run(count=10000)
if __name__ == "__main__":
test_mcu_gpio_stm32f411()
+15 -13
View File
@@ -1,5 +1,5 @@
#!/usr/bin/env python3
#
#
# Cross Platform and Multi Architecture Advanced Binary Emulation Framework
#
@@ -8,37 +8,39 @@ import sys
sys.path.append("../..")
from qiling.core import Qiling
from qiling.const import QL_VERBOSE
from qiling.const import QL_ARCH, QL_OS, QL_VERBOSE
from qiling.hw.external_device.lcd.lcd1602 import PyGameLCD1602
from qiling.extensions.mcu.stm32f4 import stm32f411
def create(path, lcd):
ql = Qiling([path], archtype="cortex_m", ostype="mcu", env=stm32f411, verbose=QL_VERBOSE.DEBUG)
ql = Qiling([path], archtype=QL_ARCH.CORTEX_M, ostype=QL_OS.MCU, env=stm32f411, verbose=QL_VERBOSE.DEBUG)
ql.hw.create('i2c1')
ql.hw.create('rcc')
ql.hw.create('gpioa')
ql.hw.create('gpiob')
ql.hw.create('gpiob')
ql.hw.i2c1.watch()
ql.hw.i2c1.connect(lcd)
ql.hw.i2c1.connect(lcd)
ql.hw.systick.set_ratio(100)
return ql
if __name__ == "__main__":
lcd = PyGameLCD1602()
## Example 1
lcd = PyGameLCD1602()
# Example 1
create("../rootfs/mcu/stm32f411/i2c-lcd.hex", lcd).run(count=50000)
## Example 2
# Example 2
create("../rootfs/mcu/stm32f411/lcd-plus.hex", lcd).run(count=100000)
## Example 3
# Example 3
ql = create("../rootfs/mcu/stm32f411/i2cit-lcd.hex", lcd)
delay_start = 0x8002936
delay_end = 0x8002955
def skip_delay(ql):
+9 -9
View File
@@ -1,22 +1,22 @@
#!/usr/bin/env python3
#
#
# Cross Platform and Multi Architecture Advanced Binary Emulation Framework
#
import sys
sys.path.append("../..")
import time
import threading
import sys
sys.path.append("../..")
from qiling.core import Qiling
from qiling.const import QL_VERBOSE
from qiling.const import QL_ARCH, QL_OS, QL_VERBOSE
from qiling.extensions.mcu.stm32f4 import stm32f411
ql = Qiling(["../../examples/rootfs/mcu/stm32f411/md5_server.hex"],
archtype="cortex_m", ostype="mcu", env=stm32f411, verbose=QL_VERBOSE.OFF)
ql = Qiling(["../../examples/rootfs/mcu/stm32f411/md5_server.hex"],
archtype=QL_ARCH.CORTEX_M, ostype=QL_OS.MCU, env=stm32f411, verbose=QL_VERBOSE.OFF)
ql.hw.create('usart2')
ql.hw.create('rcc')
@@ -25,8 +25,8 @@ threading.Thread(target=lambda : ql.run(count=-1)).start()
while True:
message = input('>> ').encode()
ql.hw.usart2.send(message + b'\n')
time.sleep(0.8)
print(ql.hw.usart2.recv())
+5 -4
View File
@@ -1,5 +1,5 @@
#!/usr/bin/env python3
#
#
# Cross Platform and Multi Architecture Advanced Binary Emulation Framework
#
@@ -7,12 +7,13 @@ import sys
sys.path.append("../..")
from qiling.core import Qiling
from qiling.const import QL_VERBOSE
from qiling.const import QL_ARCH, QL_OS, QL_VERBOSE
from qiling.extensions.mcu.stm32f4 import stm32f411
from qiling.hw.external_device.oled.ssd1306 import PyGameSSD1306Spi
ql = Qiling(['../rootfs/mcu/stm32f411/oled12864.hex'],
archtype="cortex_m", ostype="mcu", env=stm32f411, verbose=QL_VERBOSE.DEFAULT)
ql = Qiling(['../rootfs/mcu/stm32f411/oled12864.hex'],
archtype=QL_ARCH.CORTEX_M, ostype=QL_OS.MCU, env=stm32f411, verbose=QL_VERBOSE.DEFAULT)
ql.hw.create('rcc')
ql.hw.create('gpioa')
+104
View File
@@ -0,0 +1,104 @@
#!/usr/bin/env python3
#
# Cross Platform and Multi Architecture Advanced Binary Emulation Framework
#
# Setup:
# - Unpack firmware rootfs (assumed hereby: 'rootfs/netgear_r6220')
# - The firmware expects '/dev/mtdblock11' to exist and be functional, otherwise it crashes
# - cd rootfs/netgear_r6220/dev
# - dd if=/dev/zero of=mtdblock11 bs=1024 count=129030
# - mkfs.ext4 mtdblock11
#
# Run:
# $ PYTHONPATH=/path/to/qiling ROOTFS=/path/to/netgear_rootfs python3 netgear_6220.py
#
# Emulation:
# Soon after Qiling starts emulating the firmware it will look like it is done running, but actually it
# isn't. During the emulation a few OS child processes are spawned, waiting for connection. To see them
# run 'ps | grep python3'.
#
# Once a connection is established on 127.0.0.1:8080, more child processes will be spawned. Note that in
# case a child process dies with an exception, it turns into a zombie process. To kill the spawned child
# processes, run 'pkill python3'
from typing import List
import logging
import os
import sys
sys.path.append("..")
from qiling import Qiling
from qiling.const import QL_INTERCEPT, QL_VERBOSE
from qiling.log import QlColoredFormatter, QlBaseFormatter
# user may set 'ROOTFS' environment variable to use as rootfs
ROOTFS = os.environ.get('ROOTFS', r'./rootfs/netgear_r6220')
def __onexit_fork(ql: Qiling, retval: int) -> None:
# as the emulated binary forks more and more child processes, it becomes hard to keep track
# of their log entries and tell them apart. here we intercept the 'fork' system call on-exit
# (i.e. after it was already simulated, but before resuming emulation) and modify the newly
# created qiling instance's logger to show the os child processes id as part of the logs.
#
# note: os process id should not be confused with the internal qiling thread id, which does
# not exist here since we do not use qiling multithreading feature.
# fork returns 0 on the newly created child process
if retval == 0:
GREEN = '\033[92m'
DEFAULT = '\033[39m'
def __add_color(s: str) -> str:
"""Colorize text.
"""
return f'{GREEN}{s}{DEFAULT}'
def __do_nothing(s: str) -> str:
"""Use text as-is.
"""
return s
# patch current logger instance handlers to show the process id
for h in ql.log.handlers:
formatter = h.formatter
if isinstance(formatter, QlColoredFormatter):
fmt = __add_color
elif isinstance(formatter, QlBaseFormatter):
fmt = __do_nothing
else:
raise RuntimeError('unexpected formatter class')
style = logging.PercentStyle(f'%(levelname)s {fmt(f"[{os.getpid():4d}]")} %(message)s')
formatter._style = style
formatter._fmt = style._fmt
def my_sandbox(path: List[str], rootfs: str) -> None:
ql = Qiling(path, rootfs, profile='netgear_6220.ql', verbose=QL_VERBOSE.DEBUG)
ql.add_fs_mapper(r'/proc', r'/proc')
ql.os.set_syscall('fork', __onexit_fork, QL_INTERCEPT.EXIT)
ql.run()
if __name__ == '__main__':
argv = [
f'{ROOTFS}/bin/mini_httpd',
'-d', '/www',
'-r', 'NETGEAR R6220',
'-c', '**.cgi',
'-t', '300'
]
my_sandbox(argv, ROOTFS)
-75
View File
@@ -1,75 +0,0 @@
#!/usr/bin/env python3
#
# Cross Platform and Multi Architecture Advanced Binary Emulation Framework
#
# After mapping /proc there will be a /dev/mtdblock11 missing and crash
# To fix this,
# - cd $yourfirmware_rootfs/dev
# - dd if=/dev/zero of=mtdblock11 bs=1024 count=129030
# - mkfs.ext4 mtdblock11
#
# This firmware will more or less alive now.
from colorama import Back
import struct
import sys
sys.path.append("..")
from qiling import Qiling
from qiling.const import QL_INTERCEPT, QL_VERBOSE
from qiling.os.posix import syscall
from qiling.os.const import UINT, POINTER
def my_syscall_write(ql, write_fd, write_buf, write_count, *rest):
if write_fd == 2 and ql.os.fd[2].__class__.__name__ == 'ql_pipe':
return -1
else:
return syscall.ql_syscall_write(ql, write_fd, write_buf, write_count, *rest)
def my_bind(ql: Qiling):
params = ql.os.resolve_fcall_params({
'fd': UINT,
'addr': POINTER,
'addrlen': UINT
})
bind_fd = params['fd']
bind_addr = params['addr']
bind_addrlen = params['addrlen']
print(Back.GREEN + f'Hijack bind({bind_fd}, {bind_addr:#x}, {bind_addrlen})' + Back.RESET)
# read from memory (start_address, len)
data = ql.mem.read(bind_addr, bind_addrlen)
# custom unpack (your own ql.unpack) of a C struct from memory
# https://linux.die.net/man/7/ip -> struct
sin_family = struct.unpack("<h", data[:2])[0] or ql.os.fd[bind_fd].family
# little-endian short -> format_string -> https://docs.python.org/3/library/struct.html#format-strings
port, host = struct.unpack(">HI", data[2:8])
# big-endian unsigned short, unsigned int -> format_string
print(Back.RED + f'[*] Socket Infos:' + Back.RESET)
print(f'''
Family: {sin_family}
Port: {port} (no root: +8000)
Host-interface?: {host}
''')
return 0 # from syscall.ql_syscall_bind(ql, bind_fd, bind_addr, bind_addrlen)
def my_netgear(path, rootfs):
ql = Qiling(path, rootfs, verbose=QL_VERBOSE.DEBUG, profile="netgear_6220.ql", multithread=False)
ql.os.root = False
ql.add_fs_mapper('/proc', '/proc')
ql.os.set_syscall(4004, my_syscall_write)
ql.os.set_api('bind', my_bind, QL_INTERCEPT.ENTER) # intercepting the bind call on enter
ql.run()
if __name__ == "__main__":
my_netgear(["rootfs/netgear_r6220/bin/mini_httpd",
"-d", "/www",
"-r", "NETGEAR R6220",
"-c", "**.cgi",
"-t", "300"],
"rootfs/netgear_r6220")
+9
View File
@@ -4,6 +4,13 @@
:: Create the emulated Windows directory structure and registry ::
::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
:: Test for Admin privileges
NET SESSIONS > NUL 2>&1
IF %ERRORLEVEL% NEQ 0 (
ECHO Error: This script requires administrative privileges.
EXIT /B 1
)
:: Host system directories
SET SYSDIR32="%WINDIR%\SysWOW64"
SET SYSDIR64="%WINDIR%\System32"
@@ -118,6 +125,8 @@ CALL :collect_dll64 shlwapi.dll
CALL :collect_dll64 user32.dll
CALL :collect_dll64 vcruntime140.dll
CALL :collect_dll64 vcruntime140d.dll
CALL :collect_dll64 vcruntime140_1.dll
CALL :collect_dll64 vcruntime140_1d.dll
CALL :collect_dll64 win32u.dll
CALL :collect_dll64 winhttp.dll
CALL :collect_dll64 wininet.dll
+47 -45
View File
@@ -1,19 +1,25 @@
#!/usr/bin/env python3
#
#
# Cross Platform and Multi Architecture Advanced Binary Emulation Framework
#
# 1. Download AC15 Firmware from https://down.tenda.com.cn/uploadfile/AC15/US_AC15V1.0BR_V15.03.05.19_multi_TD01.zip
# 2. unzip
# 3. binwalk -e US_AC15V1.0BR_V15.03.05.19_multi_TD01.bin
# 4. locate squashfs-root
# 5. rm -rf webroot && mv webroot_ro webroot
# Setup:
# - Unpack firmware rootfs (assumed hereby: 'rootfs/tendaac15')
# - AC15 firmware may be acquired from https://down.tenda.com.cn/uploadfile/AC15/US_AC15V1.0BR_V15.03.05.19_multi_TD01.zip
# - Refresh webroot directory:
# - Enter the 'squashfs-root' directory
# - rm -rf webroot
# - mv webroot_ro webroot
# - Set network device
# - Open "qiling/profiles/linux.ql"
# - Set 'ifrname_override' to your hosting system network device name (e.g. eth0, lo, etc.)
#
# notes: we are using rootfs in this example, so rootfs = squashfs-root
#
# Run:
# $ PYTHONPATH=/path/to/qiling ROOTFS=/path/to/tenda_rootfs python3 tendaac1518_httpd.py
import os, socket, threading
import os
import socket
import threading
import sys
sys.path.append("..")
@@ -21,66 +27,62 @@ sys.path.append("..")
from qiling import Qiling
from qiling.const import QL_VERBOSE
def patcher(ql: Qiling):
br0_addr = ql.mem.search("br0".encode() + b'\x00')
for addr in br0_addr:
ql.mem.write(addr, b'lo\x00')
# user may set 'ROOTFS' environment variable to use as rootfs
ROOTFS = os.environ.get('ROOTFS', r'./rootfs/tendaac15')
def nvram_listener():
server_address = 'rootfs/var/cfm_socket'
data = ""
server_address = fr'{ROOTFS}/var/cfm_socket'
try:
if os.path.exists(server_address):
os.unlink(server_address)
except OSError:
if os.path.exists(server_address):
raise
# Create UDS socket
sock = socket.socket(socket.AF_UNIX,socket.SOCK_STREAM)
sock = socket.socket(socket.AF_UNIX, socket.SOCK_STREAM)
sock.bind(server_address)
sock.listen(1)
while True:
connection, _ = sock.accept()
data = bytearray()
try:
while True:
data += str(connection.recv(1024))
with open('cfm_socket.log', 'wb') as ofile:
while True:
connection, _ = sock.accept()
if "lan.webiplansslen" in data:
connection.send('192.168.170.169'.encode())
else:
break
try:
while True:
data += connection.recv(1024)
data = ""
finally:
connection.close()
if b'lan.webiplansslen' not in data:
break
def myvfork(ql: Qiling):
regreturn = 0
ql.log.info("vfork() = %d" % regreturn)
connection.send(b'192.168.170.169')
ofile.write(data)
data.clear()
finally:
connection.close()
return regreturn
def my_sandbox(path, rootfs):
ql = Qiling(path, rootfs, verbose=QL_VERBOSE.DEBUG)
ql.add_fs_mapper("/dev/urandom","/dev/urandom")
ql.hook_address(patcher, ql.loader.elf_entry)
ql.add_fs_mapper(r'/dev/urandom', r'/dev/urandom')
# $ gdb-multiarch -q rootfs/bin/httpd
# $ gdb-multiarch -q rootfs/tendaac15/bin/httpd
# gdb> set remotetimeout 100
# gdb> target remote localhost:9999
ql.debugger = False
if ql.debugger == True:
ql.os.set_syscall("vfork", myvfork)
if ql.debugger:
def __vfork(ql: Qiling):
return 0
ql.os.set_syscall('vfork', __vfork)
ql.run()
if __name__ == "__main__":
if __name__ == '__main__':
nvram_listener_therad = threading.Thread(target=nvram_listener, daemon=True)
nvram_listener_therad.start()
my_sandbox(["rootfs/bin/httpd"], "rootfs")
my_sandbox([fr'{ROOTFS}/bin/httpd'], ROOTFS)
+17 -9
View File
@@ -3,7 +3,7 @@
# Cross Platform and Multi Architecture Advanced Binary Emulation Framework
#
from functools import cached_property
from functools import cached_property, lru_cache
from unicorn import Uc, UC_ARCH_ARM, UC_MODE_ARM, UC_MODE_THUMB, UC_MODE_BIG_ENDIAN
from capstone import Cs, CS_ARCH_ARM, CS_MODE_ARM, CS_MODE_THUMB, CS_MODE_BIG_ENDIAN
@@ -70,11 +70,15 @@ class QlArchARM(QlArch):
# append 1 to pc if in thumb mode, or 0 otherwise
return self.regs.pc | int(self.is_thumb)
@lru_cache(maxsize=4)
def __cached_disasm(self, mode: int) -> Cs:
return Cs(CS_ARCH_ARM, mode)
@property
def disassembler(self) -> Cs:
# note: we do not cache the disassembler instance; rather we refresh it
# each time to make sure current endianess and thumb mode are taken into
# account
# note: since endianess and thumb mode might change during execution, we cannot
# cache the disassembler instance directly; rather we pick the appropriate cached
# instance
mode = CS_MODE_ARM
@@ -84,13 +88,17 @@ class QlArchARM(QlArch):
if self.is_thumb:
mode += CS_MODE_THUMB
return Cs(CS_ARCH_ARM, mode)
return self.__cached_disasm(mode)
@lru_cache(maxsize=4)
def __cached_asm(self, mode: int) -> Ks:
return Ks(KS_ARCH_ARM, mode)
@property
def assembler(self) -> Ks:
# note: we do not cache the assembler instance; rather we refresh it
# each time to make sure current endianess and thumb mode are taken into
# account
# note: since endianess and thumb mode might change during execution, we cannot
# cache the assembler instance directly; rather we pick the appropriate cached
# instance
mode = KS_MODE_ARM
@@ -100,7 +108,7 @@ class QlArchARM(QlArch):
if self.is_thumb:
mode += KS_MODE_THUMB
return Ks(KS_ARCH_ARM, mode)
return self.__cached_asm(mode)
def enable_vfp(self) -> None:
# set full access to cp10 and cp11
+13 -13
View File
@@ -14,20 +14,20 @@ from .vm import BaseVM
from .utils import bytecode_to_bytes, runtime_code_detector
from ..abi import QlArchEVMABI
# Code name Release date Release block Opcode supported
# Code name Release date Release block Opcode supported
# Frontier 2015-07-30 0 Yes
# Ice Age 2015-09-08 200,000 -
# Homestead 2016-03-15 1,150,000 Yes
# DAO Fork (unplanned) 2016-07-20 1,920,000 -
# Tangerine Whistle (unplanned) 2016-10-18 2,463,000 Yes
# Spurious Dragon 2016-11-23 2,675,000 Yes
# Byzantium 2017-10-16 4,370,000 Yes
# Constantinople 2019-02-28 7,280,000 Yes
# Petersburg (unplanned) 2019-02-28 7,280,000 Yes
# Istanbul 2019-12-08 9,069,000 Yes
# Muir Glacier 2020-01-01 9,200,000 Yes
# Berlin TBD TBD Yes
# Frontier 2015-07-30 0 Yes
# Ice Age 2015-09-08 200,000 -
# Homestead 2016-03-15 1,150,000 Yes
# DAO Fork (unplanned) 2016-07-20 1,920,000 -
# Tangerine Whistle (unplanned) 2016-10-18 2,463,000 Yes
# Spurious Dragon 2016-11-23 2,675,000 Yes
# Byzantium 2017-10-16 4,370,000 Yes
# Constantinople 2019-02-28 7,280,000 Yes
# Petersburg (unplanned) 2019-02-28 7,280,000 Yes
# Istanbul 2019-12-08 9,069,000 Yes
# Muir Glacier 2020-01-01 9,200,000 Yes
# Berlin TBD TBD Yes
father_VMs = {
+27 -25
View File
@@ -5,34 +5,38 @@
from unicorn.x86_const import *
QL_X86_F_GRANULARITY = 0x8
QL_X86_F_PROT_32 = 0x4
QL_X86_F_LONG = 0x2
QL_X86_F_AVAILABLE = 0x1
# segment descriptor bits [47:40]
QL_X86_A_DATA_A = (1 << 0)
QL_X86_A_DATA_W = (1 << 1)
QL_X86_A_DATA_E = (1 << 2)
QL_X86_A_DATA = (0 << 3)
QL_X86_A_PRESENT = 0x80
QL_X86_A_CODE_A = (1 << 0)
QL_X86_A_CODE_R = (1 << 1)
QL_X86_A_CODE_C = (1 << 2)
QL_X86_A_CODE = (1 << 3)
QL_X86_A_PRIV_3 = 0x60
QL_X86_A_PRIV_2 = 0x40
QL_X86_A_PRIV_1 = 0x20
QL_X86_A_PRIV_0 = 0x0
QL_X86_A_DESC_SYSTEM = (0 << 4) # S
QL_X86_A_DESC_CODE = (1 << 4)
QL_X86_A_DESC_DATA = (1 << 4)
QL_X86_A_CODE = 0x10
QL_X86_A_DATA = 0x10
QL_X86_A_TSS = 0x0
QL_X86_A_GATE = 0x0
QL_X86_A_EXEC = 0x8
QL_X86_A_PRIV_0 = (0b00 << 5) # DPL
QL_X86_A_PRIV_1 = (0b01 << 5)
QL_X86_A_PRIV_2 = (0b10 << 5)
QL_X86_A_PRIV_3 = (0b11 << 5)
QL_X86_A_DATA_WRITABLE = 0x2
QL_X86_A_CODE_READABLE = 0x2
QL_X86_A_DIR_CON_BIT = 0x4
QL_X86_A_PRESENT = (1 << 7)
QL_X86_S_GDT = 0x0
QL_X86_S_LDT = 0x4
QL_X86_S_PRIV_3 = 0x3
QL_X86_S_PRIV_2 = 0x2
QL_X86_S_PRIV_1 = 0x1
QL_X86_S_PRIV_0 = 0x0
# segment descriptor bits [55:52]
QL_X86_F_AVAILABLE = (1 << 0) # AVL
QL_X86_F_LONG = (1 << 1) # L
QL_X86_F_OPSIZE_32 = (1 << 2) # D/B
QL_X86_F_GRANULARITY = (1 << 3) # G
# segment selector bits
QL_X86_SEGSEL_RPL_MASK = 0b11
QL_X86_SEGSEL_TI_GDT = (0 << 2)
QL_X86_SEGSEL_TI_LDT = (1 << 2)
QL_X86_GDT_ADDR = 0x30000
QL_X86_GDT_LIMIT = 0x1000
@@ -43,8 +47,6 @@ IA32_FS_BASE_MSR = 0xC0000100
IA32_GS_BASE_MSR = 0xC0000101
IA32_APIC_BASE_MSR = 0x1B
# WINDOWS SETUP VALUE
# Linux also needs these
GS_SEGMENT_ADDR = 0x6000000
GS_SEGMENT_SIZE = (20 << 20) # 20 MB
+9 -9
View File
@@ -88,12 +88,12 @@ class GDTManager:
@staticmethod
def make_selector(idx: int, rpl: int) -> int:
assert rpl & ~0b11 == 0
assert rpl & ~QL_X86_SEGSEL_RPL_MASK == 0
return (idx << 3) | QL_X86_S_GDT | rpl
return (idx << 3) | QL_X86_SEGSEL_TI_GDT | rpl
def register_gdt_segment(self, index: int, seg_base: int, seg_limit: int, access: int) -> int:
flags = QL_X86_F_PROT_32
flags = QL_X86_F_OPSIZE_32
# is this a huge segment?
if seg_limit > (1 << 16):
@@ -139,7 +139,7 @@ class SegmentManager:
class SegmentManager86(SegmentManager):
def setup_cs_ds_ss_es(self, base: int, size: int) -> None:
# While debugging the linux kernel segment, the cs segment was found on the third segment of gdt.
access = QL_X86_A_PRESENT | QL_X86_A_CODE | QL_X86_A_CODE_READABLE | QL_X86_A_PRIV_3 | QL_X86_A_EXEC | QL_X86_A_DIR_CON_BIT
access = QL_X86_A_PRESENT | QL_X86_A_PRIV_3 | QL_X86_A_DESC_CODE | QL_X86_A_CODE | QL_X86_A_CODE_C | QL_X86_A_CODE_R
selector = self.gdtm.register_gdt_segment(3, base, size - 1, access)
self.arch.regs.cs = selector
@@ -147,7 +147,7 @@ class SegmentManager86(SegmentManager):
# TODO : The section permission here should be QL_X86_A_PRIV_3, but I do n’t know why it can only be set to QL_X86_A_PRIV_0.
# While debugging the Linux kernel segment, I found that the three segments DS, SS, and ES all point to the same location in the GDT table.
# This position is the fifth segment table of GDT.
access = QL_X86_A_PRESENT | QL_X86_A_DATA | QL_X86_A_DATA_WRITABLE | QL_X86_A_PRIV_0 | QL_X86_A_DIR_CON_BIT
access = QL_X86_A_PRESENT | QL_X86_A_PRIV_0 | QL_X86_A_DESC_DATA | QL_X86_A_DATA | QL_X86_A_DATA_E | QL_X86_A_DATA_W
selector = self.gdtm.register_gdt_segment(5, base, size - 1, access)
self.arch.regs.ds = selector
@@ -155,13 +155,13 @@ class SegmentManager86(SegmentManager):
self.arch.regs.es = selector
def setup_fs(self, base: int, size: int) -> None:
access = QL_X86_A_PRESENT | QL_X86_A_DATA | QL_X86_A_DATA_WRITABLE | QL_X86_A_PRIV_3 | QL_X86_A_DIR_CON_BIT
access = QL_X86_A_PRESENT | QL_X86_A_PRIV_3 | QL_X86_A_DESC_DATA | QL_X86_A_DATA | QL_X86_A_DATA_E | QL_X86_A_DATA_W
selector = self.gdtm.register_gdt_segment(14, base, size - 1, access)
self.arch.regs.fs = selector
def setup_gs(self, base: int, size: int) -> None:
access = QL_X86_A_PRESENT | QL_X86_A_DATA | QL_X86_A_DATA_WRITABLE | QL_X86_A_PRIV_3 | QL_X86_A_DIR_CON_BIT
access = QL_X86_A_PRESENT | QL_X86_A_PRIV_3 | QL_X86_A_DESC_DATA | QL_X86_A_DATA | QL_X86_A_DATA_E | QL_X86_A_DATA_W
selector = self.gdtm.register_gdt_segment(15, base, size - 1, access)
self.arch.regs.gs = selector
@@ -170,14 +170,14 @@ class SegmentManager86(SegmentManager):
class SegmentManager64(SegmentManager):
def setup_cs_ds_ss_es(self, base: int, size: int) -> None:
# While debugging the linux kernel segment, the cs segment was found on the sixth segment of gdt.
access = QL_X86_A_PRESENT | QL_X86_A_CODE | QL_X86_A_CODE_READABLE | QL_X86_A_PRIV_3 | QL_X86_A_EXEC | QL_X86_A_DIR_CON_BIT
access = QL_X86_A_PRESENT | QL_X86_A_PRIV_3 | QL_X86_A_DESC_CODE | QL_X86_A_CODE | QL_X86_A_CODE_C | QL_X86_A_CODE_R
selector = self.gdtm.register_gdt_segment(6, base, size - 1, access)
self.arch.regs.cs = selector
# TODO : The section permission here should be QL_X86_A_PRIV_3, but I do n’t know why it can only be set to QL_X86_A_PRIV_0.
# When I debug the Linux kernel, I find that only the SS is set to the fifth segment table, and the rest are not set.
access = QL_X86_A_PRESENT | QL_X86_A_DATA | QL_X86_A_DATA_WRITABLE | QL_X86_A_PRIV_0 | QL_X86_A_DIR_CON_BIT
access = QL_X86_A_PRESENT | QL_X86_A_PRIV_0 | QL_X86_A_DESC_DATA | QL_X86_A_DATA | QL_X86_A_DATA_E | QL_X86_A_DATA_W
selector = self.gdtm.register_gdt_segment(5, base, size - 1, access)
# self.arch.regs.ds = selector
+114 -114
View File
@@ -7,171 +7,171 @@ from typing import Callable, Sequence, Tuple
from qiling.arch.arch import QlArch
class QlCC:
"""Calling convention base class.
"""
"""Calling convention base class.
"""
def __init__(self, arch: QlArch) -> None:
"""Initialize a calling convention instance.
def __init__(self, arch: QlArch) -> None:
"""Initialize a calling convention instance.
Args:
arch: underlying architecture instance
"""
Args:
arch: underlying architecture instance
"""
self.arch = arch
self.arch = arch
@staticmethod
def getNumSlots(argbits: int) -> int:
"""Get the number of slots allocated for an argument of width `argbits`.
"""
@staticmethod
def getNumSlots(argbits: int) -> int:
"""Get the number of slots allocated for an argument of width `argbits`.
"""
raise NotImplementedError
raise NotImplementedError
def getRawParam(self, slot: int, argbits: int = 0) -> int:
"""Read a value of native size from the specified argument slot.
def getRawParam(self, slot: int, argbits: int = 0) -> int:
"""Read a value of native size from the specified argument slot.
Note that argument slots and argument indexes are not the same. Though they often correlate
to each other, some implementations might use more than one slot to represent a sigle argument.
Note that argument slots and argument indexes are not the same. Though they often correlate
to each other, some implementations might use more than one slot to represent a sigle argument.
Args:
slot: argument slot to access
argbits: argument size in bits (default: arch native size)
Args:
slot: argument slot to access
argbits: argument size in bits (default: arch native size)
Returns: raw value
"""
Returns: raw value
"""
raise NotImplementedError
raise NotImplementedError
def setRawParam(self, slot: int, value: int, argbits: int = 0) -> None:
"""Replace the value in the specified argument slot.
def setRawParam(self, slot: int, value: int, argbits: int = 0) -> None:
"""Replace the value in the specified argument slot.
Note that argument slots and argument indexes are not the same. Though they often correlate
to each other, some implementations might use more than one slot to represent a sigle argument.
Note that argument slots and argument indexes are not the same. Though they often correlate
to each other, some implementations might use more than one slot to represent a sigle argument.
Args:
slot: argument slot to access
value: new raw value to write
argbits: argument size in bits (default: arch native size)
"""
Args:
slot: argument slot to access
value: new raw value to write
argbits: argument size in bits (default: arch native size)
"""
raise NotImplementedError
raise NotImplementedError
def getReturnValue(self) -> int:
"""Get function return value.
"""
def getReturnValue(self) -> int:
"""Get function return value.
"""
raise NotImplementedError
raise NotImplementedError
def setReturnValue(self, val: int) -> None:
"""Set function return value.
def setReturnValue(self, val: int) -> None:
"""Set function return value.
Args:
val: a value to set
"""
Args:
val: a value to set
"""
raise NotImplementedError
raise NotImplementedError
def setReturnAddress(self, addr: int) -> None:
"""Set function return address.
def setReturnAddress(self, addr: int) -> None:
"""Set function return address.
Args:
addr: return address to set
"""
Args:
addr: return address to set
"""
raise NotImplementedError
raise NotImplementedError
def reserve(self, nslots: int) -> None:
"""Reserve slots for function arguments.
def reserve(self, nslots: int) -> None:
"""Reserve slots for function arguments.
This may be used to stage a new frame before executing a native function.
This may be used to stage a new frame before executing a native function.
Args:
nslots: number of arg slots to reserve
"""
Args:
nslots: number of arg slots to reserve
"""
raise NotImplementedError
raise NotImplementedError
def unwind(self, nslots: int) -> int:
"""Unwind frame and return from function call.
def unwind(self, nslots: int) -> int:
"""Unwind frame and return from function call.
Args:
nslots: number of arg slots used
Args:
nslots: number of arg slots used
Returns: return address
"""
Returns: return address
"""
raise NotImplementedError
raise NotImplementedError
class QlCommonBaseCC(QlCC):
"""Calling convention base class that implements parameters access through both
registers and the stack. The extending class is resopnsible to implement the rest
of the QlCC interface.
"""
"""Calling convention base class that implements parameters access through both
registers and the stack. The extending class is resopnsible to implement the rest
of the QlCC interface.
"""
_retreg: int
_argregs: Sequence
_shadow = 0
_retaddr_on_stack = True
_retreg: int
_argregs: Sequence
_shadow = 0
_retaddr_on_stack = True
def __init__(self, arch: QlArch):
super().__init__(arch)
def __init__(self, arch: QlArch):
super().__init__(arch)
# native address size in bytes
self._asize = self.arch.pointersize
# native address size in bytes
self._asize = self.arch.pointersize
def __access_param(self, index: int, stack_access: Callable, reg_access: Callable) -> Tuple[Callable, int]:
"""[private] Generic accessor to function call parameters by their index.
def __access_param(self, index: int, stack_access: Callable, reg_access: Callable) -> Tuple[Callable, int]:
"""[private] Generic accessor to function call parameters by their index.
This method will determine whether the parameter should be accessed on the stack or in a
register, and return the appropriate accessor along with the location to access (either a
register id or stack address)
This method will determine whether the parameter should be accessed on the stack or in a
register, and return the appropriate accessor along with the location to access (either a
register id or stack address)
Args:
index: parameter index to access
stack_access: stack accessor method (either read or write)
reg_access: regs accessor method (either read or write)
Args:
index: parameter index to access
stack_access: stack accessor method (either read or write)
reg_access: regs accessor method (either read or write)
Returns: a tuple of the accessor method to use and the location to access
"""
Returns: a tuple of the accessor method to use and the location to access
"""
if index >= len(self._argregs):
raise IndexError(f'tried to access arg {index}, but only {len(self._argregs) - 1} args are supported')
if index >= len(self._argregs):
raise IndexError(f'tried to access arg {index}, but only {len(self._argregs) - 1} args are supported')
reg = self._argregs[index]
reg = self._argregs[index]
# should arg be read from a reg or the stack?
if reg is None:
# get matching stack item
si = index - self._argregs.index(None)
# should arg be read from a reg or the stack?
if reg is None:
# get matching stack item
si = index - self._argregs.index(None)
# skip return address and shadow space
return stack_access, (self._retaddr_on_stack + self._shadow + si) * self._asize
else:
return reg_access, reg
# skip return address and shadow space
return stack_access, (self._retaddr_on_stack + self._shadow + si) * self._asize
else:
return reg_access, reg
def getRawParam(self, index: int, argbits: int = 0) -> int:
read, loc = self.__access_param(index, self.arch.stack_read, self.arch.regs.read)
def getRawParam(self, index: int, argbits: int = 0) -> int:
read, loc = self.__access_param(index, self.arch.stack_read, self.arch.regs.read)
mask = (argbits and (1 << argbits)) - 1
mask = (argbits and (1 << argbits)) - 1
return read(loc) & mask
return read(loc) & mask
def setRawParam(self, index: int, value: int, argbits: int = 0) -> None:
write, loc = self.__access_param(index, self.arch.stack_write, self.arch.regs.write)
def setRawParam(self, index: int, value: int, argbits: int = 0) -> None:
write, loc = self.__access_param(index, self.arch.stack_write, self.arch.regs.write)
mask = (argbits and (1 << argbits)) - 1
mask = (argbits and (1 << argbits)) - 1
write(loc, value & mask)
write(loc, value & mask)
def getReturnValue(self) -> int:
return self.arch.regs.read(self._retreg)
def getReturnValue(self) -> int:
return self.arch.regs.read(self._retreg)
def setReturnValue(self, value: int) -> None:
self.arch.regs.write(self._retreg, value)
def setReturnValue(self, value: int) -> None:
self.arch.regs.write(self._retreg, value)
def reserve(self, nslots: int) -> None:
assert nslots < len(self._argregs), 'too many slots'
def reserve(self, nslots: int) -> None:
assert nslots < len(self._argregs), 'too many slots'
# count how many slots should be reserved on the stack
si = self._argregs[:nslots].count(None)
# count how many slots should be reserved on the stack
si = self._argregs[:nslots].count(None)
self.arch.regs.arch_sp -= (self._shadow + si) * self._asize
self.arch.regs.arch_sp -= (self._shadow + si) * self._asize
+1 -2
View File
@@ -20,8 +20,7 @@ class QlArmBaseCC(QlCommonBaseCC):
return 1
def setReturnAddress(self, addr: int) -> None:
# TODO: do we need to update LR?
self.arch.stack_push(addr)
self.arch.regs.lr = addr
def unwind(self, nslots: int) -> int:
# TODO: cleanup?
+61 -61
View File
@@ -3,104 +3,104 @@
# Cross Platform and Multi Architecture Advanced Binary Emulation Framework
from unicorn.x86_const import (
UC_X86_REG_EAX, UC_X86_REG_RAX, UC_X86_REG_RCX, UC_X86_REG_RDI,
UC_X86_REG_RDX, UC_X86_REG_RSI, UC_X86_REG_R8, UC_X86_REG_R9,
UC_X86_REG_R10
UC_X86_REG_EAX, UC_X86_REG_RAX, UC_X86_REG_RCX, UC_X86_REG_RDI,
UC_X86_REG_RDX, UC_X86_REG_RSI, UC_X86_REG_R8, UC_X86_REG_R9,
UC_X86_REG_R10
)
from qiling.cc import QlCommonBaseCC
class QlIntelBaseCC(QlCommonBaseCC):
"""Calling convention base class for Intel-based systems.
Supports arguments passing over registers and stack.
"""
"""Calling convention base class for Intel-based systems.
Supports arguments passing over registers and stack.
"""
def setReturnAddress(self, addr: int) -> None:
self.arch.stack_push(addr)
def setReturnAddress(self, addr: int) -> None:
self.arch.stack_push(addr)
def unwind(self, nslots: int) -> int:
# no cleanup; just pop out the return address
return self.arch.stack_pop()
def unwind(self, nslots: int) -> int:
# no cleanup; just pop out the return address
return self.arch.stack_pop()
class QlIntel64(QlIntelBaseCC):
"""Calling convention base class for Intel-based 64-bit systems.
"""
"""Calling convention base class for Intel-based 64-bit systems.
"""
_retreg = UC_X86_REG_RAX
_retreg = UC_X86_REG_RAX
@staticmethod
def getNumSlots(argbits: int) -> int:
return max(argbits, 64) // 64
@staticmethod
def getNumSlots(argbits: int) -> int:
return max(argbits, 64) // 64
class QlIntel32(QlIntelBaseCC):
"""Calling convention base class for Intel-based 32-bit systems.
"""
"""Calling convention base class for Intel-based 32-bit systems.
"""
_retreg = UC_X86_REG_EAX
_retreg = UC_X86_REG_EAX
@staticmethod
def getNumSlots(argbits: int) -> int:
return max(argbits, 32) // 32
@staticmethod
def getNumSlots(argbits: int) -> int:
return max(argbits, 32) // 32
def getRawParam(self, slot: int, nbits: int = 0) -> int:
__super_getparam = super().getRawParam
def getRawParam(self, slot: int, nbits: int = 0) -> int:
__super_getparam = super().getRawParam
if nbits == 64:
lo = __super_getparam(slot)
hi = __super_getparam(slot + 1)
if nbits == 64:
lo = __super_getparam(slot)
hi = __super_getparam(slot + 1)
val = (hi << 32) | lo
else:
val = __super_getparam(slot, nbits)
val = (hi << 32) | lo
else:
val = __super_getparam(slot, nbits)
return val
return val
class amd64(QlIntel64):
"""Default calling convention for POSIX (x86-64).
First 6 arguments are passed in regs, the rest are passed on the stack.
"""
"""Default calling convention for POSIX (x86-64).
First 6 arguments are passed in regs, the rest are passed on the stack.
"""
_argregs = (UC_X86_REG_RDI, UC_X86_REG_RSI, UC_X86_REG_RDX, UC_X86_REG_R10, UC_X86_REG_R8, UC_X86_REG_R9) + (None, ) * 10
_argregs = (UC_X86_REG_RDI, UC_X86_REG_RSI, UC_X86_REG_RDX, UC_X86_REG_R10, UC_X86_REG_R8, UC_X86_REG_R9) + (None, ) * 10
class ms64(QlIntel64):
"""Default calling convention for Windows and UEFI (x86-64).
First 4 arguments are passed in regs, the rest are passed on the stack.
"""Default calling convention for Windows and UEFI (x86-64).
First 4 arguments are passed in regs, the rest are passed on the stack.
Each stack frame starts with a shadow space in size of 4 items, corresponding
to the first arguments passed in regs.
"""
Each stack frame starts with a shadow space in size of 4 items, corresponding
to the first arguments passed in regs.
"""
_argregs = (UC_X86_REG_RCX, UC_X86_REG_RDX, UC_X86_REG_R8, UC_X86_REG_R9) + (None, ) * 12
_shadow = 4
_argregs = (UC_X86_REG_RCX, UC_X86_REG_RDX, UC_X86_REG_R8, UC_X86_REG_R9) + (None, ) * 12
_shadow = 4
class macosx64(QlIntel64):
"""Default calling convention for Mac OS (x86-64).
First 6 arguments are passed in regs, the rest are passed on the stack.
"""
"""Default calling convention for Mac OS (x86-64).
First 6 arguments are passed in regs, the rest are passed on the stack.
"""
_argregs = (UC_X86_REG_RDI, UC_X86_REG_RSI, UC_X86_REG_RDX, UC_X86_REG_RCX, UC_X86_REG_R8, UC_X86_REG_R9) + (None, ) * 10
_argregs = (UC_X86_REG_RDI, UC_X86_REG_RSI, UC_X86_REG_RDX, UC_X86_REG_RCX, UC_X86_REG_R8, UC_X86_REG_R9) + (None, ) * 10
class cdecl(QlIntel32):
"""Calling convention used by all operating systems (x86).
All arguments are passed on the stack.
"""Calling convention used by all operating systems (x86).
All arguments are passed on the stack.
The caller is resopnsible to unwind the stack.
"""
The caller is resopnsible to unwind the stack.
"""
_argregs = (None, ) * 16
_argregs = (None, ) * 16
class stdcall(QlIntel32):
"""Calling convention used by all operating systems (x86).
All arguments are passed on the stack.
"""Calling convention used by all operating systems (x86).
All arguments are passed on the stack.
The callee is resopnsible to unwind the stack.
"""
The callee is resopnsible to unwind the stack.
"""
_argregs = (None, ) * 16
_argregs = (None, ) * 16
def unwind(self, nslots: int) -> int:
retaddr = super().unwind(nslots)
def unwind(self, nslots: int) -> int:
retaddr = super().unwind(nslots)
self.arch.regs.arch_sp += (nslots * self._asize)
self.arch.regs.arch_sp += (nslots * self._asize)
return retaddr
return retaddr
+13 -10
View File
@@ -7,15 +7,18 @@ from unicorn.mips_const import UC_MIPS_REG_V0, UC_MIPS_REG_A0, UC_MIPS_REG_A1, U
from qiling.cc import QlCommonBaseCC
class mipso32(QlCommonBaseCC):
_retreg = UC_MIPS_REG_V0
_argregs = (UC_MIPS_REG_A0, UC_MIPS_REG_A1, UC_MIPS_REG_A2, UC_MIPS_REG_A3) + (None, ) * 12
_shadow = 4
_retaddr_on_stack = False
_retreg = UC_MIPS_REG_V0
_argregs = (UC_MIPS_REG_A0, UC_MIPS_REG_A1, UC_MIPS_REG_A2, UC_MIPS_REG_A3) + (None, ) * 12
_shadow = 4
_retaddr_on_stack = False
@staticmethod
def getNumSlots(argbits: int):
return 1
def setReturnAddress(self, addr: int):
self.arch.regs.ra = addr
def unwind(self, nslots: int) -> int:
# TODO: stack frame unwiding?
return self.arch.regs.ra
@staticmethod
def getNumSlots(argbits: int):
return 1
def unwind(self, nslots: int) -> int:
# TODO: stack frame unwiding?
return self.arch.regs.ra
+3
View File
@@ -21,3 +21,6 @@ class ppc(QlCommonBaseCC):
@staticmethod
def getNumSlots(argbits: int):
return 1
def setReturnAddress(self, addr: int):
self.arch.regs.lr = addr
+4 -1
View File
@@ -19,4 +19,7 @@ class riscv(QlCommonBaseCC):
@staticmethod
def getNumSlots(argbits: int):
return 1
return 1
def setReturnAddress(self, addr: int):
self.arch.regs.ra = addr
+7 -1
View File
@@ -66,6 +66,12 @@ class QL_STOP(Flag):
EXIT_TRAP = (1 << 1)
class QL_STATE(Enum):
NOT_SET = 0
STARTED = 1
STOPPED = 2
QL_ARCH_INTERPRETER: Final = (QL_ARCH.EVM,)
QL_OS_POSIX: Final = (QL_OS.LINUX, QL_OS.FREEBSD, QL_OS.MACOS, QL_OS.QNX)
@@ -82,7 +88,7 @@ def __casefold_enum(e: Type[T]) -> Mapping[str, T]:
'''Create a casefolded mapping of an enum to allow case-insensitive lookup.
'''
return dict((k.casefold(), v) for k, v in e._member_map_.items())
return dict((k.casefold(), v) for k, v in e.__members__.items())
debugger_map = __casefold_enum(QL_DEBUGGER)
+45 -27
View File
@@ -20,7 +20,7 @@ if TYPE_CHECKING:
from .hw.hw import QlHwManager
from .loader.loader import QlLoader
from .const import QL_ARCH, QL_ENDIAN, QL_OS, QL_STOP, QL_VERBOSE, QL_ARCH_INTERPRETER, QL_OS_BAREMETAL
from .const import QL_ARCH, QL_ENDIAN, QL_OS, QL_STATE, QL_STOP, QL_VERBOSE, QL_ARCH_INTERPRETER, QL_OS_BAREMETAL
from .exception import QlErrorFileNotFound, QlErrorArch, QlErrorOsType
from .host import QlHost
from .log import *
@@ -32,20 +32,20 @@ from .core_hooks import QlCoreHooks
class Qiling(QlCoreHooks, QlCoreStructs):
def __init__(
self,
argv: Sequence[str] = None,
argv: Sequence[str] = [],
rootfs: str = r'.',
env: MutableMapping[AnyStr, AnyStr] = {},
code: bytes = None,
ostype: Union[str, QL_OS] = None,
archtype: Union[str, QL_ARCH] = None,
code: Optional[bytes] = None,
ostype: Optional[QL_OS] = None,
archtype: Optional[QL_ARCH] = None,
verbose: QL_VERBOSE = QL_VERBOSE.DEFAULT,
profile: str = None,
profile: Optional[Union[str, Mapping]] = None,
console: bool = True,
log_file=None,
log_override=None,
log_file: Optional[str] = None,
log_override: Optional['Logger'] = None,
log_plain: bool = False,
multithread: bool = False,
filter = None,
filter: Optional[str] = None,
stop: QL_STOP = QL_STOP.NONE,
*,
endian: Optional[QL_ENDIAN] = None,
@@ -90,18 +90,26 @@ class Qiling(QlCoreHooks, QlCoreStructs):
##############
# argv setup #
##############
if argv is None:
argv = ['qilingcode']
if argv:
if code:
raise AttributeError('argv and code are mutually execlusive')
elif not os.path.exists(argv[0]):
raise QlErrorFileNotFound(f'Target binary not found: "{argv[0]}"')
target = argv[0]
if not os.path.isfile(target):
raise QlErrorFileNotFound(f'Target binary not found: "{target}"')
else:
# an empty argv list means we are going to execute a shellcode. to keep
# the 'path' api compatible, we insert a dummy placeholder
argv = ['']
self._argv = argv
################
# rootfs setup #
################
if not os.path.exists(rootfs):
if not os.path.isdir(rootfs):
raise QlErrorFileNotFound(f'Target rootfs not found: "{rootfs}"')
self._rootfs = rootfs
@@ -109,13 +117,8 @@ class Qiling(QlCoreHooks, QlCoreStructs):
#################
# arch os setup #
#################
if type(archtype) is str:
archtype = arch_convert(archtype)
if type(ostype) is str:
ostype = os_convert(ostype)
# if provided arch was invalid or not provided, guess arch and os
# if arch was not provided, guess arch and os
if archtype is None:
guessed_archtype, guessed_ostype, guessed_archendian = ql_guess_emu_env(self.path)
@@ -132,12 +135,12 @@ class Qiling(QlCoreHooks, QlCoreStructs):
ostype = arch_os_convert(archtype)
# arch should have been determined by now; fail if not
if type(archtype) is not QL_ARCH:
raise QlErrorArch(f'Unknown or unsupported architecture: "{archtype}"')
if archtype is None:
raise QlErrorArch(f'Unknown or unsupported architecture')
# os should have been determined by now; fail if not
if type(ostype) is not QL_OS:
raise QlErrorOsType(f'Unknown or unsupported operating system: "{ostype}"')
if ostype is None:
raise QlErrorOsType(f'Unknown or unsupported operating system')
# if endianess is still undetermined, set it to little-endian.
# this setting is ignored for architectures with predefined endianess
@@ -151,6 +154,9 @@ class Qiling(QlCoreHooks, QlCoreStructs):
QlCoreStructs.__init__(self, self.arch.endian, self.arch.bits)
QlCoreHooks.__init__(self, self.uc)
# emulation has not been started yet
self._state = QL_STATE.NOT_SET
##########
# Logger #
##########
@@ -494,6 +500,13 @@ class Qiling(QlCoreHooks, QlCoreStructs):
"""
return self._stop_options
@property
def emu_state(self) -> QL_STATE:
"""Query emulation state.
"""
return self._state
def do_bin_patch(self):
ba = self.loader.load_address
@@ -687,11 +700,11 @@ class Qiling(QlCoreHooks, QlCoreStructs):
# Map "ql_path" to any objects which implements QlFsMappedObject.
def add_fs_mapper(self, ql_path: Union["PathLike", str], real_dest):
self.os.fs_mapper.add_fs_mapping(ql_path, real_dest)
self.os.fs_mapper.add_mapping(ql_path, real_dest)
# Remove "ql_path" mapping.
def remove_fs_mapper(self, ql_path: Union["PathLike", str]):
self.os.fs_mapper.remove_fs_mapping(ql_path)
self.os.fs_mapper.remove_mapping(ql_path)
# push to stack bottom, and update stack register
def stack_push(self, data):
@@ -714,6 +727,7 @@ class Qiling(QlCoreHooks, QlCoreStructs):
# stop emulation
def emu_stop(self):
self.uc.emu_stop()
self._state = QL_STATE.STOPPED
# stop emulation
def stop(self):
@@ -724,7 +738,7 @@ class Qiling(QlCoreHooks, QlCoreStructs):
self.os.stop()
else:
self.uc.emu_stop()
self.emu_stop()
# start emulation
def emu_start(self, begin: int, end: int, timeout: int = 0, count: int = 0):
@@ -749,9 +763,13 @@ class Qiling(QlCoreHooks, QlCoreStructs):
# reset exception status before emulation starts
self._internal_exception = None
self._state = QL_STATE.STARTED
# effectively start the emulation. this returns only after uc.emu_stop is called
self.uc.emu_start(begin, end, timeout, count)
self._state = QL_STATE.STOPPED
# if an exception was raised during emulation, propagate it up
if self.internal_exception is not None:
raise self.internal_exception
+46 -38
View File
@@ -1,5 +1,5 @@
#!/usr/bin/env python3
#
#
# Cross Platform and Multi Architecture Advanced Binary Emulation Framework
#
@@ -8,22 +8,53 @@
# handling hooks #
##############################################
import functools
from __future__ import annotations
from functools import wraps
from typing import Any, Callable, MutableMapping, MutableSequence, Protocol
from typing import TYPE_CHECKING
from unicorn import Uc
from unicorn.unicorn_const import *
from unicorn.unicorn_const import (
UC_HOOK_INTR,
UC_HOOK_INSN,
UC_HOOK_CODE,
UC_HOOK_BLOCK,
UC_HOOK_MEM_READ_UNMAPPED, # attempt to read from an unmapped memory location
UC_HOOK_MEM_WRITE_UNMAPPED, # attempt to write to an unmapped memory location
UC_HOOK_MEM_FETCH_UNMAPPED, # attempt to fetch from an unmapped memory location
UC_HOOK_MEM_UNMAPPED, # any of the 3 above
UC_HOOK_MEM_READ_PROT, # attempt to read from a non-readable memory location
UC_HOOK_MEM_WRITE_PROT, # attempt to write to a write-protected memory location
UC_HOOK_MEM_FETCH_PROT, # attempt to fetch from a non-executable memory location
UC_HOOK_MEM_PROT, # any of the 3 above
UC_HOOK_MEM_READ_INVALID, # UC_HOOK_MEM_READ_UNMAPPED | UC_HOOK_MEM_READ_PROT
UC_HOOK_MEM_WRITE_INVALID, # UC_HOOK_MEM_WRITE_UNMAPPED | UC_HOOK_MEM_WRITE_INVALID
UC_HOOK_MEM_FETCH_INVALID, # UC_HOOK_MEM_FETCH_UNMAPPED | UC_HOOK_MEM_FETCH_INVALID
UC_HOOK_MEM_INVALID, # any of the 3 above
UC_HOOK_MEM_READ, # valid memory read
UC_HOOK_MEM_WRITE, # valid memory write
UC_HOOK_MEM_FETCH, # valid instruction fetch
UC_HOOK_MEM_VALID, # any of the 3 above
UC_HOOK_MEM_READ_AFTER,
UC_HOOK_INSN_INVALID
)
from .core_hooks_types import Hook, HookAddr, HookIntr, HookRet
from .const import QL_HOOK_BLOCK
from .exception import QlErrorCoreHook
if TYPE_CHECKING:
from unicorn import Uc
from qiling import Qiling
class MemHookCallback(Protocol):
def __call__(self, __ql: 'Qiling', __access: int, __address: int, __size: int, __value: int, *__context: Any) -> Any:
def __call__(self, __ql: Qiling, __access: int, __address: int, __size: int, __value: int, *__context: Any) -> Any:
"""Memory access hook callback.
Args:
@@ -40,8 +71,9 @@ class MemHookCallback(Protocol):
"""
pass
class TraceHookCalback(Protocol):
def __call__(self, __ql: 'Qiling', __address: int, __size: int, *__context: Any) -> Any:
def __call__(self, __ql: Qiling, __address: int, __size: int, *__context: Any) -> Any:
"""Execution hook callback.
Args:
@@ -56,8 +88,9 @@ class TraceHookCalback(Protocol):
"""
pass
class AddressHookCallback(Protocol):
def __call__(self, __ql: 'Qiling', *__context: Any) -> Any:
def __call__(self, __ql: Qiling, *__context: Any) -> Any:
"""Address hook callback.
Args:
@@ -70,8 +103,9 @@ class AddressHookCallback(Protocol):
"""
pass
class InterruptHookCallback(Protocol):
def __call__(self, __ql: 'Qiling', intno: int, *__context: Any) -> Any:
def __call__(self, __ql: Qiling, intno: int, *__context: Any) -> Any:
"""Interrupt hook callback.
Args:
@@ -86,9 +120,8 @@ class InterruptHookCallback(Protocol):
pass
def hookcallback(ql: 'Qiling', callback: Callable):
functools.wraps(callback)
def hookcallback(ql: Qiling, callback: Callable):
@wraps(callback)
def wrapper(*args, **kwargs):
try:
return callback(*args, **kwargs)
@@ -113,10 +146,10 @@ class QlCoreHooks:
self._addr_hook: MutableMapping[int, MutableSequence[HookAddr]] = {}
self._addr_hook_fuc: MutableMapping[int, int] = {}
########################
# Callback definitions #
########################
def _hook_intr_cb(self, uc: Uc, intno: int, pack_data) -> None:
"""Interrupt hooks dispatcher.
"""
@@ -142,7 +175,6 @@ class QlCoreHooks:
if not handled:
raise QlErrorCoreHook("_hook_intr_cb : not handled")
def _hook_insn_cb(self, uc: Uc, *args):
"""Instruction hooks dispatcher.
"""
@@ -166,7 +198,6 @@ class QlCoreHooks:
# use the last return value received
return retval
def _hook_trace_cb(self, uc: Uc, addr: int, size: int, pack_data) -> None:
"""Code and block hooks dispatcher.
"""
@@ -183,7 +214,6 @@ class QlCoreHooks:
if type(ret) is int and ret & QL_HOOK_BLOCK:
break
def _hook_mem_cb(self, uc: Uc, access: int, addr: int, size: int, value: int, pack_data):
"""Memory access hooks dispatcher.
"""
@@ -207,7 +237,6 @@ class QlCoreHooks:
return True
def _hook_insn_invalid_cb(self, uc: Uc, pack_data) -> None:
"""Invalid instruction hooks dispatcher.
"""
@@ -228,7 +257,6 @@ class QlCoreHooks:
if not handled:
raise QlErrorCoreHook("_hook_insn_invalid_cb : not handled")
def _hook_addr_cb(self, uc: Uc, addr: int, size: int, pack_data):
"""Address hooks dispatcher.
"""
@@ -247,18 +275,17 @@ class QlCoreHooks:
###############
# Class Hooks #
###############
def _ql_hook_internal(self, hook_type: int, callback: Callable, context: Any, *args) -> int:
_callback = hookcallback(self, callback)
return self._h_uc.hook_add(hook_type, _callback, (self, context), 1, 0, *args)
def _ql_hook_addr_internal(self, callback: Callable, address: int) -> int:
_callback = hookcallback(self, callback)
return self._h_uc.hook_add(UC_HOOK_CODE, _callback, self, address, address)
def _ql_hook(self, hook_type: int, h: Hook, *args) -> None:
def __handle_intr(t: int) -> None:
@@ -330,7 +357,6 @@ class QlCoreHooks:
if hook_type & t:
handler(t)
def ql_hook(self, hook_type: int, callback: Callable, user_data: Any = None, begin: int = 1, end: int = 0, *args) -> HookRet:
"""Intercept certain emulation events within a specified range.
@@ -355,7 +381,6 @@ class QlCoreHooks:
return HookRet(self, hook_type, hook)
def hook_code(self, callback: TraceHookCalback, user_data: Any = None, begin: int = 1, end: int = 0) -> HookRet:
"""Intercept assembly instructions before they get executed.
@@ -374,12 +399,10 @@ class QlCoreHooks:
return self.ql_hook(UC_HOOK_CODE, callback, user_data, begin, end)
# TODO: remove; this is a special case of hook_intno(-1)
def hook_intr(self, callback, user_data=None, begin=1, end=0):
return self.ql_hook(UC_HOOK_INTR, callback, user_data, begin, end)
def hook_block(self, callback: TraceHookCalback, user_data: Any = None, begin: int = 1, end: int = 0) -> HookRet:
"""Intercept landings in new basic blocks in a specified range.
@@ -398,7 +421,6 @@ class QlCoreHooks:
return self.ql_hook(UC_HOOK_BLOCK, callback, user_data, begin, end)
def hook_mem_unmapped(self, callback: MemHookCallback, user_data: Any = None, begin: int = 1, end: int = 0) -> HookRet:
"""Intercept illegal accesses to unmapped memory in a specified range.
@@ -417,7 +439,6 @@ class QlCoreHooks:
return self.ql_hook(UC_HOOK_MEM_UNMAPPED, callback, user_data, begin, end)
def hook_mem_read_invalid(self, callback: MemHookCallback, user_data: Any = None, begin: int = 1, end: int = 0) -> HookRet:
"""Intercept illegal reading attempts from a specified range.
@@ -436,7 +457,6 @@ class QlCoreHooks:
return self.ql_hook(UC_HOOK_MEM_READ_INVALID, callback, user_data, begin, end)
def hook_mem_write_invalid(self, callback: MemHookCallback, user_data: Any = None, begin: int = 1, end: int = 0) -> HookRet:
"""Intercept illegal writing attempts to a specified range.
@@ -455,7 +475,6 @@ class QlCoreHooks:
return self.ql_hook(UC_HOOK_MEM_WRITE_INVALID, callback, user_data, begin, end)
def hook_mem_fetch_invalid(self, callback: MemHookCallback, user_data: Any = None, begin: int = 1, end: int = 0) -> HookRet:
"""Intercept illegal code fetching attempts from a specified range.
@@ -474,7 +493,6 @@ class QlCoreHooks:
return self.ql_hook(UC_HOOK_MEM_FETCH_INVALID, callback, user_data, begin, end)
def hook_mem_valid(self, callback: MemHookCallback, user_data: Any = None, begin: int = 1, end: int = 0) -> HookRet:
"""Intercept benign memory accesses within a specified range.
This is equivalent to hooking memory reads, writes and fetches.
@@ -494,7 +512,6 @@ class QlCoreHooks:
return self.ql_hook(UC_HOOK_MEM_VALID, callback, user_data, begin, end)
def hook_mem_invalid(self, callback: MemHookCallback, user_data: Any = None, begin: int = 1, end: int = 0) -> HookRet:
"""Intercept invalid memory accesses within a specified range.
This is equivalent to hooking invalid memory reads, writes and fetches.
@@ -514,7 +531,6 @@ class QlCoreHooks:
return self.ql_hook(UC_HOOK_MEM_INVALID, callback, user_data, begin, end)
def hook_address(self, callback: AddressHookCallback, address: int, user_data: Any = None) -> HookRet:
"""Intercept execution from a certain memory address.
@@ -540,7 +556,6 @@ class QlCoreHooks:
# note: assuming 0 is not a valid hook type
return HookRet(self, 0, hook)
def hook_intno(self, callback: InterruptHookCallback, intno: int, user_data: Any = None) -> HookRet:
"""Intercept interrupts.
@@ -558,7 +573,6 @@ class QlCoreHooks:
return HookRet(self, UC_HOOK_INTR, hook)
def hook_mem_read(self, callback: MemHookCallback, user_data: Any = None, begin: int = 1, end: int = 0) -> HookRet:
"""Intercept benign memory reads from a specified range.
@@ -577,7 +591,6 @@ class QlCoreHooks:
return self.ql_hook(UC_HOOK_MEM_READ, callback, user_data, begin, end)
def hook_mem_write(self, callback: MemHookCallback, user_data: Any = None, begin: int = 1, end: int = 0) -> HookRet:
"""Intercept benign memory writes to a specified range.
@@ -596,7 +609,6 @@ class QlCoreHooks:
return self.ql_hook(UC_HOOK_MEM_WRITE, callback, user_data, begin, end)
def hook_mem_fetch(self, callback: MemHookCallback, user_data: Any = None, begin: int = 1, end: int = 0) -> HookRet:
"""Intercept benign code fetches from a specified range.
@@ -615,7 +627,6 @@ class QlCoreHooks:
return self.ql_hook(UC_HOOK_MEM_FETCH, callback, user_data, begin, end)
def hook_insn(self, callback, insn_type: int, user_data: Any = None, begin: int = 1, end: int = 0) -> HookRet:
"""Intercept execution of a certain instruction type within a specified range.
@@ -637,7 +648,6 @@ class QlCoreHooks:
return self.ql_hook(UC_HOOK_INSN, callback, user_data, begin, end, insn_type)
def hook_del(self, hret: HookRet) -> None:
"""Unregister an existing hook and release its resources.
@@ -692,7 +702,6 @@ class QlCoreHooks:
if hook_type & t:
handler(t)
def clear_hooks(self):
for ptr in self._hook_fuc.values():
self._h_uc.hook_del(ptr)
@@ -705,7 +714,6 @@ class QlCoreHooks:
self.clear_ql_hooks()
def clear_ql_hooks(self):
self._hook = {}
self._hook_fuc = {}
+57 -57
View File
@@ -19,81 +19,81 @@ ReadableBuffer = Union[bytes, bytearray, memoryview]
# Don't assume self is Qiling.
class QlCoreStructs:
def __init__(self, endian: QL_ENDIAN, bit: int):
modifier = {
QL_ENDIAN.EL: '<',
QL_ENDIAN.EB: '>'
}[endian]
def __init__(self, endian: QL_ENDIAN, bit: int):
modifier = {
QL_ENDIAN.EL: '<',
QL_ENDIAN.EB: '>'
}[endian]
self._fmt8 = f'{modifier}B'
self._fmt8s = f'{modifier}b'
self._fmt16 = f'{modifier}H'
self._fmt16s = f'{modifier}h'
self._fmt32 = f'{modifier}I'
self._fmt32s = f'{modifier}i'
self._fmt64 = f'{modifier}Q'
self._fmt64s = f'{modifier}q'
self._fmt8 = f'{modifier}B'
self._fmt8s = f'{modifier}b'
self._fmt16 = f'{modifier}H'
self._fmt16s = f'{modifier}h'
self._fmt32 = f'{modifier}I'
self._fmt32s = f'{modifier}i'
self._fmt64 = f'{modifier}Q'
self._fmt64s = f'{modifier}q'
handlers = {
64 : (self.pack64, self.pack64s, self.unpack64, self.unpack64s),
32 : (self.pack32, self.pack32s, self.unpack32, self.unpack32s),
16 : (self.pack16, self.pack16s, self.unpack16, self.unpack16s),
}
handlers = {
64 : (self.pack64, self.pack64s, self.unpack64, self.unpack64s),
32 : (self.pack32, self.pack32s, self.unpack32, self.unpack32s),
16 : (self.pack16, self.pack16s, self.unpack16, self.unpack16s),
}
if bit not in handlers:
raise QlErrorStructConversion("Unsupported Qiling struct conversion")
if bit not in handlers:
raise QlErrorStructConversion("Unsupported Qiling struct conversion")
p, ps, up, ups = handlers[bit]
p, ps, up, ups = handlers[bit]
self.pack = p
self.packs = ps
self.unpack = up
self.unpacks = ups
self.pack = p
self.packs = ps
self.unpack = up
self.unpacks = ups
def pack64(self, x: int, /) -> bytes:
return struct.pack(self._fmt64, x)
def pack64(self, x: int, /) -> bytes:
return struct.pack(self._fmt64, x)
def pack64s(self, x: int, /) -> bytes:
return struct.pack(self._fmt64s, x)
def pack64s(self, x: int, /) -> bytes:
return struct.pack(self._fmt64s, x)
def unpack64(self, x: ReadableBuffer, /) -> int:
return struct.unpack(self._fmt64, x)[0]
def unpack64(self, x: ReadableBuffer, /) -> int:
return struct.unpack(self._fmt64, x)[0]
def unpack64s(self, x: ReadableBuffer, /) -> int:
return struct.unpack(self._fmt64s, x)[0]
def unpack64s(self, x: ReadableBuffer, /) -> int:
return struct.unpack(self._fmt64s, x)[0]
def pack32(self, x: int, /) -> bytes:
return struct.pack(self._fmt32, x)
def pack32(self, x: int, /) -> bytes:
return struct.pack(self._fmt32, x)
def pack32s(self, x: int, /) -> bytes:
return struct.pack(self._fmt32s, x)
def pack32s(self, x: int, /) -> bytes:
return struct.pack(self._fmt32s, x)
def unpack32(self, x: ReadableBuffer, /) -> int:
return struct.unpack(self._fmt32, x)[0]
def unpack32(self, x: ReadableBuffer, /) -> int:
return struct.unpack(self._fmt32, x)[0]
def unpack32s(self, x: ReadableBuffer, /) -> int:
return struct.unpack(self._fmt32s, x)[0]
def unpack32s(self, x: ReadableBuffer, /) -> int:
return struct.unpack(self._fmt32s, x)[0]
def pack16(self, x: int, /) -> bytes:
return struct.pack(self._fmt16, x)
def pack16(self, x: int, /) -> bytes:
return struct.pack(self._fmt16, x)
def pack16s(self, x: int, /) -> bytes:
return struct.pack(self._fmt16s, x)
def pack16s(self, x: int, /) -> bytes:
return struct.pack(self._fmt16s, x)
def unpack16(self, x: ReadableBuffer, /) -> int:
return struct.unpack(self._fmt16, x)[0]
def unpack16(self, x: ReadableBuffer, /) -> int:
return struct.unpack(self._fmt16, x)[0]
def unpack16s(self, x: ReadableBuffer, /) -> int:
return struct.unpack(self._fmt16s, x)[0]
def unpack16s(self, x: ReadableBuffer, /) -> int:
return struct.unpack(self._fmt16s, x)[0]
def pack8(self, x: int, /) -> bytes:
return struct.pack(self._fmt8, x)
def pack8(self, x: int, /) -> bytes:
return struct.pack(self._fmt8, x)
def pack8s(self, x: int, /) -> bytes:
return struct.pack(self._fmt8s, x)
def pack8s(self, x: int, /) -> bytes:
return struct.pack(self._fmt8s, x)
def unpack8(self, x: ReadableBuffer, /) -> int:
return struct.unpack(self._fmt8, x)[0]
def unpack8(self, x: ReadableBuffer, /) -> int:
return struct.unpack(self._fmt8, x)[0]
def unpack8s(self, x: ReadableBuffer, /) -> int:
return struct.unpack(self._fmt8s, x)[0]
def unpack8s(self, x: ReadableBuffer, /) -> int:
return struct.unpack(self._fmt8s, x)[0]
+46 -35
View File
@@ -30,7 +30,7 @@ from unicorn.unicorn_const import (
)
from qiling import Qiling
from qiling.const import QL_ARCH, QL_ENDIAN, QL_OS
from qiling.const import QL_ARCH, QL_ENDIAN, QL_OS, QL_STATE
from qiling.debugger import QlDebugger
from qiling.debugger.gdb.xmlregs import QlGdbFeatures
from qiling.debugger.gdb.utils import QlGdbUtils
@@ -78,36 +78,42 @@ class QlGdb(QlDebugger):
self.ip = ip
self.port = port
if ql.baremetal:
load_address = ql.loader.load_address
exit_point = load_address + os.path.getsize(ql.path)
elif ql.code:
load_address = ql.os.entry_point
exit_point = load_address + len(ql.code)
else:
load_address = ql.loader.load_address
exit_point = load_address + os.path.getsize(ql.path)
def __get_attach_addr() -> int:
if ql.baremetal:
entry_point = ql.loader.entry_point
if ql.baremetal:
entry_point = ql.loader.entry_point
elif ql.os.type in (QL_OS.LINUX, QL_OS.FREEBSD) and not ql.code:
entry_point = ql.os.elf_entry
else:
entry_point = ql.os.entry_point
elif ql.os.type in (QL_OS.LINUX, QL_OS.FREEBSD) and not ql.code:
entry_point = ql.os.elf_entry
# though linkers set the entry point LSB to indicate arm thumb mode, the
# effective entry point address is aligned. make sure we have it aligned
if hasattr(ql.arch, 'is_thumb'):
entry_point &= ~0b1
else:
entry_point = ql.os.entry_point
# Only part of the binary file will be debugged.
if ql.entry_point is not None:
entry_point = ql.entry_point
# though linkers set the entry point LSB to indicate arm thumb mode, the
# effective entry point address is aligned. make sure we have it aligned
if hasattr(ql.arch, 'is_thumb'):
entry_point &= ~0b1
if ql.exit_point is not None:
exit_point = ql.exit_point
return entry_point
self.gdb = QlGdbUtils(ql, entry_point, exit_point)
def __get_detach_addr() -> int:
if ql.baremetal:
base = ql.loader.load_address
size = os.path.getsize(ql.path)
elif ql.code:
base = ql.os.entry_point
size = len(ql.code)
else:
base = ql.loader.load_address
size = os.path.getsize(ql.path)
return base + size
attach_addr = __get_attach_addr() if ql.entry_point is None else ql.entry_point
detach_addr = __get_detach_addr() if ql.exit_point is None else ql.exit_point
self.gdb = QlGdbUtils(ql, attach_addr, detach_addr)
self.features = QlGdbFeatures(self.ql.arch.type, self.ql.os.type)
self.regsmap = self.features.regsmap
@@ -293,11 +299,11 @@ class QlGdb(QlDebugger):
addr, size = (int(p, 16) for p in subcmd.split(','))
try:
data = self.ql.mem.read(addr, size).hex()
except UcError:
return 'E14'
data = self.ql.mem.read(addr, size)
except UcError as ex:
return f'E{ex.errno:02d}'
else:
return data
return data.hex()
def handle_M(subcmd: str) -> Reply:
"""Write target memory.
@@ -313,8 +319,8 @@ class QlGdb(QlDebugger):
try:
self.ql.mem.write(addr, data)
except UcError:
return 'E01'
except UcError as ex:
return f'E{ex.errno:02d}'
else:
return REPLY_OK
@@ -673,6 +679,11 @@ class QlGdb(QlDebugger):
self.gdb.resume_emu(steps=1)
# if emulation has been stopped, signal program termination
if self.ql.emu_state is QL_STATE.STOPPED:
return f'S{SIGTERM:02x}'
# otherwise, this is just single stepping
return f'S{SIGTRAP:02x}'
def handle_X(subcmd: str) -> Reply:
@@ -688,8 +699,8 @@ class QlGdb(QlDebugger):
try:
if data:
self.ql.mem.write(addr, data.encode(ENCODING))
except UcError:
return 'E01'
except UcError as ex:
return f'E{ex.errno:02d}'
else:
return REPLY_OK
@@ -832,7 +843,7 @@ class GdbSerialConn:
buffer += incoming
# discard incoming acks
if buffer[0:1] == REPLY_ACK:
if buffer.startswith(REPLY_ACK):
del buffer[0]
packet = pattern.match(buffer)
+4 -4
View File
@@ -10,7 +10,7 @@ import unicorn
from capstone import CsInsn
from .misc import read_int
from .misc import read_int, InvalidInsn
class Context:
"""
@@ -48,9 +48,9 @@ class Context:
md = self.ql.arch.disassembler
md.detail = detail
if (addr := self.read_insn(address)):
return next(md.disasm(addr, address), None)
return None
if (bytes_read := self.read_insn(address)):
return next(md.disasm(bytes_read, address), InvalidInsn(bytes_read, address))
return InvalidInsn(bytes_read, address)
def try_read(self, address: int, size: int) -> Optional[bytes]:
"""
+15
View File
@@ -5,6 +5,8 @@
from typing import AnyStr, Callable, Optional
from dataclasses import dataclass
import ast
def check_and_eval(line: str):
@@ -25,6 +27,19 @@ def check_and_eval(line: str):
return eval(line)
@dataclass
class InvalidInsn:
"""
class for displaying invalid instruction
"""
bytes: bytes
address: bytes
mnemonic: str = 'invalid'
op_str: str = ''
def __post_init__(self):
self.size = len(self.bytes)
class Breakpoint:
"""
+13 -8
View File
@@ -78,10 +78,13 @@ class QlQdb(cmd.Cmd, QlDebugger):
if self.ql.os.type == QL_OS.BLOB:
self.ql.loader.entry_point = self.ql.loader.load_address
elif init_hook and self.ql.loader.entry_point != init_hook:
elif init_hook and self.ql.loader.entry_point != int(init_hook, 0):
self.do_breakpoint(init_hook)
self.cur_addr = self.ql.loader.entry_point
if self.ql.entry_point:
self.cur_addr = self.ql.entry_point
else:
self.cur_addr = self.ql.loader.entry_point
self.init_state = self.ql.save()
@@ -116,7 +119,7 @@ class QlQdb(cmd.Cmd, QlDebugger):
address = self.cur_addr
if getattr(self.ql.arch, 'is_thumb', False):
address |= 1
address |= 0b1
# assume we're running PE if on Windows
if self.ql.os.type == QL_OS.WINDOWS:
@@ -157,6 +160,7 @@ class QlQdb(cmd.Cmd, QlDebugger):
qdb_print(QDB_MSG.ERROR, "The program is not being run.")
else:
func(self, *args, **kwargs)
return inner
def parseline(self, line: str) -> Tuple[Optional[str], Optional[str], str]:
@@ -213,17 +217,19 @@ class QlQdb(cmd.Cmd, QlDebugger):
@SnapshotManager.snapshot
@save_reg_dump
@check_ql_alive
def do_step_in(self, *args) -> Optional[bool]:
def do_step_in(self, step: str = '', *args) -> Optional[bool]:
"""
execute one instruction at a time, will enter subroutine
"""
prophecy = self.predictor.predict()
if prophecy.where is True:
return True
qdb_print(QDB_MSG.INFO, 'program exited due to code end hitted')
self.do_context()
return False
step = 1 if step == '' else int(step)
step = 1
# make sure follow branching
if prophecy.going is True and self.ql.arch.type == QL_ARCH.MIPS:
step += 1
@@ -574,7 +580,6 @@ class QlQdb(cmd.Cmd, QlDebugger):
if input(f"{color.RED}[!] Are you sure about saying good bye ~ ? [Y/n]{color.END} ").strip() == "Y":
self.do_quit()
do_r = do_run
do_s = do_step_in
do_n = do_step_over
+2 -4
View File
@@ -157,6 +157,7 @@ class Render:
"""
opcode = "".join(f"{b:02x}" for b in insn.bytes)
trace_line = f"0x{insn.address:08x} │ {opcode:15s} {insn.mnemonic:10} {insn.op_str:35s}"
cursor = "►" if self.cur_addr == insn.address else " "
@@ -211,12 +212,9 @@ class ContextRender(Context, Render):
to_addr = self.cur_addr + self.disasm_num
cur_addr = from_addr
while cur_addr != to_addr:
while cur_addr <= to_addr:
insn = self.disasm(cur_addr)
# cur_addr += self.arch_insn_size
cur_addr += insn.size
if not insn:
continue
past_list.append(insn)
bk_list = []
+5 -4
View File
@@ -28,9 +28,6 @@ def ql_afl_fuzz(ql: Qiling,
:raises UcAflError: If something wrong happens with the fuzzer.
"""
ql.uc.ctl_exits_enabled(True)
ql.uc.ctl_set_exits(exits)
def _dummy_fuzz_callback(_ql: "Qiling"):
if isinstance(_ql.arch, QlArchARM):
pc = _ql.arch.effective_pc
@@ -43,17 +40,21 @@ def ql_afl_fuzz(ql: Qiling,
return UC_ERR_OK
return ql_afl_fuzz_custom(ql, input_file, place_input_callback, _dummy_fuzz_callback,
return ql_afl_fuzz_custom(ql, input_file, place_input_callback, _dummy_fuzz_callback, exits,
validate_crash_callback, always_validate, persistent_iters)
def ql_afl_fuzz_custom(ql: Qiling,
input_file: str,
place_input_callback: Callable[["Qiling", bytes, int], bool],
fuzzing_callback: Callable[["Qiling"], int],
exits: List[int] = [],
validate_crash_callback: Callable[["Qiling", bytes, int], bool] = None,
always_validate: bool = False,
persistent_iters: int = 1):
ql.uc.ctl_exits_enabled(True)
ql.uc.ctl_set_exits(exits)
def _ql_afl_place_input_wrapper(uc, input_bytes, iters, data):
(ql, cb, _, _) = data
@@ -0,0 +1,168 @@
from __future__ import annotations
from typing import List, Tuple, TYPE_CHECKING, Union, Optional, Any
if TYPE_CHECKING:
from qiling import Qiling
from qiling.core_hooks_types import HookRet
from capstone import Cs
import re
from capstone import CsInsn
class History:
history_hook_handle: HookRet
history: List[CsInsn] = []
ql: Qiling
md: Cs
arm_is_thumb: bool
def __init__(self, ql: Qiling) -> None:
self.ql = ql
self.md = self.ql.arch.disassembler
self.arm_is_thumb = getattr(ql.arch, 'is_thumb', False)
self.track_block_coverage()
def clear_history(self) -> None:
"""Clears the current state of the history
"""
self.history.clear()
def clear_hooks(self) -> None:
"""Clears the current history hook from the Qiling instance
Returns:
None
"""
self.ql.hook_del(self.history_hook_handle)
def __hook_block(self, ql: Qiling, address: int, size: int) -> Any:
'''
The unicorn block/instruction hook function for the track_block_coverage and track_instruction_coverage functions. This just give us a way to append capstone objects to the history list
'''
# get the current state of the thumb mode, only applys to arm
# originally we were going to access the ql.arch.disassembler directly for all architectures from in this callback, but in the
# implementation for arch.arm.disassembler, the capstone instance is recreated every time (to make sure THUMB mode is properly dealt with)
if self.arm_is_thumb is not getattr(ql.arch, "is_thumb", False):
# the thumb mode has changed, so we need to update the disassembler
self.arm_is_thumb = not self.arm_is_thumb
self.md = self.ql.arch.disassembler
# 0x10 is way more than enough bytes to grab a single instruction
ins_bytes = ql.mem.read(address, 0x10)
try:
self.history.append(next(self.md.disasm(ins_bytes, address)))
except StopIteration:
# if this ever happens, then the unicorn/qiling is going to crash because it tried to execute
# an instruction that it cant, so we are just not going to do anything
pass
def track_block_coverage(self) -> None:
"""Configures the history plugin to track all of the basic blocks that are executed. Removes any existing hooks
Returns:
None
"""
if getattr(self, 'history_hook_handle', None):
self.clear_hooks()
self.history_hook_handle = self.ql.hook_block(self.__hook_block)
def track_instruction_coverage(self) -> None:
"""Configures the history plugin to track all of the instructions that are executed. Removes any existing hooks
Returns:
None
"""
if getattr(self, 'history_hook_handle', None):
self.clear_hooks()
self.history_hook_handle = self.ql.hook_code(self.__hook_block)
def get_ins_only_lib(self, libs: List[str]) -> List[CsInsn]:
"""Returns a list of addresses that have been executed that are only in mmaps for objects that match the regex of items in the list
Args:
libs (List[str]): A list of regex strings to match against the library names in the memory maps
Returns:
List[capstone.CsInsn]: A list of CsInsn that have been executed and are only in the memory maps that match the regex
Examples:
>>> history.get_ins_only_lib([".*libc.so.*", ".*libpthread.so.*"])
"""
executable_maps = self.get_regex_matching_exec_maps(libs)
return [x for x in self.history if any(start <= x.address <= end for start, end, _, _, _ in executable_maps)]
def get_ins_exclude_lib(self, libs: List[str]) -> List[CsInsn]:
'''Returns a list of history instructions that are not in the libraries that match the regex in the libs list
Args:
libs (List[str]): A list of regex strings to match against the library names in the memory maps
Returns:
List[capstone.CsInsn]: A list of CsInsn that have been executed and are not in the memory maps that match the regex
Examples:
>>> history.get_ins_exclude_lib([".*libc.so.*", ".*libpthread.so.*"])
'''
executable_maps = self.get_regex_matching_exec_maps(libs)
return [h for h in self.history if not any(start <= h.address <= end for start, end, _, _, _ in executable_maps)]
def get_mem_map_from_addr(self, ins: Union[int, CsInsn]) -> Optional[Tuple]:
'''Returns the memory map that contains the instruction
Args:
ins (Union[int, CsInsn]): The instruction address to search for, can be either an int or a capstone.CsInsn
Returns:
Optional[Tuple]: A tuple that contains the memory map that contains the instruction
this tuple is in the format of (start_addr, end_addr, perms, name, path)
Examples:
>>> history.get_mem_map_from_addr(0x7ffff7dd1b97)
'''
if isinstance(ins, CsInsn):
ins = ins.address
assert isinstance(ins, int)
return next((x for x in self.ql.mem.get_mapinfo() if x[0] <= ins and x[1] >= ins), None)
def get_regex_matching_exec_maps(self, libs: List[str]) -> List[Tuple]:
'''Returns a list of tuples for current mmaps whose names match the regex of libs in the list
This is a wrapper around ql.mem.get_mapinfo() and just filters the results by the regex of the library names
and also only returns maps that are executable
Args:
libs (Union[str, Collection[str]]): A list of regex strings to match against the library names in the memory maps
Returns:
List[Tuple]: A list of tuples that match the regex and are executable
Examples:
>>> history.get_regex_matching_exec_maps([".*libc.so.*", ".*libpthread.so.*"])
>>> history.get_regex_matching_exec_maps(".*libc.*")
'''
# if libs is a string, convert it to a list
if isinstance(libs, str):
libs = [libs]
# filter the history list by the library name, using a list of regex
regex = [re.compile(lib) for lib in libs]
# filter the list of tuples
# so that we return only the ones where the library name matches the regex
regex_matching_libs = [x for x in self.ql.mem.get_mapinfo() if any(r.match(x[3]) for r in regex)]
# filter viable_libs for items that have the executable bit set
return [x for x in regex_matching_libs if 'x' in x[2]]
+3 -1
View File
@@ -501,6 +501,7 @@ class QlEmuRegView(simplecustviewer_t):
line = ""
cols = 3
reglist = [reglist[i:i+cols] for i in range(0,len(reglist),cols)]
arch = ql.arch.type
for regs in reglist:
for reg in regs:
line += COLSTR(" %4s: " % str(reg), SCOLOR_REG)
@@ -898,7 +899,7 @@ class QlEmuQiling:
elffile = ELFFile(f)
elf_header = elffile.header
if elf_header['e_type'] == 'ET_EXEC':
self.baseaddr = self.ql.os.elf_mem_start
self.baseaddr = self.ql.loader.images[0].base
elif elf_header['e_type'] == 'ET_DYN':
if self.ql.arch.bits == 32:
self.baseaddr = int(self.ql.os.profile.get("OS32", "load_address"), 16)
@@ -2026,6 +2027,7 @@ class QlEmuPlugin(plugin_t, UI_Hooks):
module = importlib.import_module(scriptname)
if is_reload:
del self.userobj
importlib.reload(module)
cls = getattr(module, classname)
return cls()
+35 -6
View File
@@ -2,19 +2,20 @@
#
# Cross Platform and Multi Architecture Advanced Binary Emulation Framework
#
import io
import os
from typing import TextIO
from qiling.os.posix import stat
class SimpleStringBuffer(io.BytesIO):
"""Simple FIFO pipe.
"""
def __init__(self):
super().__init__()
# Compatible with old implementation
def seek(self, offset: int, origin: int = 0) -> int:
# Imitate os.lseek
@@ -30,22 +31,23 @@ class SimpleStringBuffer(io.BytesIO):
ret = super().write(buf)
super().seek(pos)
return ret
# Compatible with previous TextIO
@property
def name(self):
return None
class SimpleStreamBase:
def __init__(self, fd: int):
super().__init__()
self.__fd = fd
self.__closed = False
def close(self) -> None:
self.__closed = True
@property
def closed(self) -> bool:
return self.__closed
@@ -56,18 +58,21 @@ class SimpleStreamBase:
def fstat(self):
return stat.Fstat(self.fileno())
class SimpleInStream(SimpleStreamBase, SimpleStringBuffer):
"""Simple input stream. May be used to mock stdin.
"""
pass
class SimpleOutStream(SimpleStreamBase, SimpleStringBuffer):
"""Simple output stream. May be used to mock stdout or stderr.
"""
pass
class NullOutStream(SimpleStreamBase):
"""Null out-stream, may be used to disregard process output.
"""
@@ -81,9 +86,33 @@ class NullOutStream(SimpleStreamBase):
def writable(self) -> bool:
return True
class SimpleBufferedStream(io.BytesIO):
"""Simple buffered IO.
"""
def __init__(self):
super.__init__()
super().__init__()
class InteractiveInStream(io.BytesIO):
def read(self, size: int) -> bytes:
'''
Read from the BytesIO buffer. If theres no data left in the buffer, get additional user input
Args:
size (int): The amount of bytes to read from the buffer
Returns:
bytes: The data read from the buffer
'''
# get the amount of bytes left in the buffer
bytes_left = self.getbuffer().nbytes - self.tell()
# if theres no bytes left in the buffer, get user input
if bytes_left == 0:
user_data = input().encode() + b'\x0a'
self.write(user_data)
self.seek(-len(user_data), io.SEEK_CUR)
return super().read(size)
+147 -147
View File
@@ -15,216 +15,216 @@ TraceRecord = Tuple[CsInsn, Iterable[Tuple[int, int]]]
# <WORKAROUND>
def __uc2_workaround() -> Mapping[int, int]:
"""Starting from Unicorn2, Unicorn and Capstone Intel registers definitions are
no longer aligned and cannot be used interchangebly. This temporary workaround
maps capstone x86 registers definitions to unicorn x86 registers definitions.
"""Starting from Unicorn2, Unicorn and Capstone Intel registers definitions are
no longer aligned and cannot be used interchangebly. This temporary workaround
maps capstone x86 registers definitions to unicorn x86 registers definitions.
see: https://github.com/unicorn-engine/unicorn/issues/1492
"""
see: https://github.com/unicorn-engine/unicorn/issues/1492
"""
from capstone import x86_const as cs_x86_const
from unicorn import x86_const as uc_x86_const
from capstone import x86_const as cs_x86_const
from unicorn import x86_const as uc_x86_const
def __canonicalized_mapping(module, prefix: str) -> Mapping[str, int]:
return dict((k[len(prefix):], getattr(module, k)) for k in dir(module) if k.startswith(prefix))
def __canonicalized_mapping(module, prefix: str) -> Mapping[str, int]:
return dict((k[len(prefix):], getattr(module, k)) for k in dir(module) if k.startswith(prefix))
cs_x86_regs = __canonicalized_mapping(cs_x86_const, 'X86_REG')
uc_x86_regs = __canonicalized_mapping(uc_x86_const, 'UC_X86_REG')
cs_x86_regs = __canonicalized_mapping(cs_x86_const, 'X86_REG')
uc_x86_regs = __canonicalized_mapping(uc_x86_const, 'UC_X86_REG')
return dict((cs_x86_regs[k], uc_x86_regs[k]) for k in cs_x86_regs if k in uc_x86_regs)
return dict((cs_x86_regs[k], uc_x86_regs[k]) for k in cs_x86_regs if k in uc_x86_regs)
CS_UC_REGS = __uc2_workaround()
# </WORKAROUND>
def __get_trace_records(ql: Qiling, address: int, size: int, md: Cs) -> Iterator[TraceRecord]:
"""[private] Acquire trace info for the current instruction and yield as a trace record.
A trace record is a parsed instruction paired to a list of registers and their values.
"""[private] Acquire trace info for the current instruction and yield as a trace record.
A trace record is a parsed instruction paired to a list of registers and their values.
This method might yield more than one record for a single instruction.
"""
This method might yield more than one record for a single instruction.
"""
# unicorn denotes unsupported instructions by a magic size value. though these instructions
# are not emulated, capstone can still parse them.
if size == 0xf1f1f1f1:
# note that invalid instructions will generate a StopIteration exception here
yield next(__get_trace_records(ql, address, 16, md))
return
# unicorn denotes unsupported instructions by a magic size value. though these instructions
# are not emulated, capstone can still parse them.
if size == 0xf1f1f1f1:
# note that invalid instructions will generate a StopIteration exception here
yield next(__get_trace_records(ql, address, 16, md))
return
# a trace line is generated even for hook addresses that do not contain meaningful opcodes.
# in that case, make it look like a nop
if address in ql._addr_hook:
buf = b'\x90'
else:
buf = ql.mem.read(address, size)
# a trace line is generated even for hook addresses that do not contain meaningful opcodes.
# in that case, make it look like a nop
if address in ql._addr_hook:
buf = b'\x90'
else:
buf = ql.mem.read(address, size)
for insn in md.disasm(buf, address):
# BUG: insn.regs_read doesn't work well, so we use insn.regs_access()[0]
state = tuple((reg, ql.arch.regs.read(CS_UC_REGS[reg])) for reg in insn.regs_access()[0])
for insn in md.disasm(buf, address):
# BUG: insn.regs_read doesn't work well, so we use insn.regs_access()[0]
state = tuple((reg, ql.arch.regs.read(CS_UC_REGS[reg])) for reg in insn.regs_access()[0])
yield (insn, state)
yield (insn, state)
def __to_trace_line(record: TraceRecord, symsmap: Mapping[int, str] = {}) -> str:
"""[private] Transform trace info into a formatted trace line.
"""
"""[private] Transform trace info into a formatted trace line.
"""
insn, state = record
insn, state = record
# when the rip register is referenced from within an instruction it is expected to point
# to the next instruction boundary. since unicorn has not executed the instruction yet
# is uses the cpu state resulted from the previous instruction - and rip points to the
# current instruction instead of the next one.
#
# here we patch rip value recorded in state to point to the next instruction boundary
state = tuple((reg, val + insn.size if reg == X86_REG_RIP else val) for reg, val in state)
# when the rip register is referenced from within an instruction it is expected to point
# to the next instruction boundary. since unicorn has not executed the instruction yet
# is uses the cpu state resulted from the previous instruction - and rip points to the
# current instruction instead of the next one.
#
# here we patch rip value recorded in state to point to the next instruction boundary
state = tuple((reg, val + insn.size if reg == X86_REG_RIP else val) for reg, val in state)
def __read_reg(reg: int) -> int:
"""[internal] Read a register value from the recorded state. Only registers that were
referenced by the current instruction can be read.
"""
def __read_reg(reg: int) -> int:
"""[internal] Read a register value from the recorded state. Only registers that were
referenced by the current instruction can be read.
"""
return 0 if reg == X86_REG_INVALID else next(v for r, v in state if r == reg)
return 0 if reg == X86_REG_INVALID else next(v for r, v in state if r == reg)
def __resolve(address: int) -> str:
"""[internal] Find the symbol that matches to the specified address (if any).
"""
def __resolve(address: int) -> str:
"""[internal] Find the symbol that matches to the specified address (if any).
"""
return symsmap.get(address, '')
return symsmap.get(address, '')
def __parse_op(op: X86Op) -> str:
"""[internal] Parse an operand and return its string representation. Indirect memory
references will be substitued by the effective address they refer to. If the referenced
address is associated with a symbol, it will be substitued by that symbol.
"""
def __parse_op(op: X86Op) -> str:
"""[internal] Parse an operand and return its string representation. Indirect memory
references will be substitued by the effective address they refer to. If the referenced
address is associated with a symbol, it will be substitued by that symbol.
"""
if op.type == CS_OP_REG:
return insn.reg_name(op.value.reg) or '?'
if op.type == CS_OP_REG:
return insn.reg_name(op.value.reg) or '?'
elif op.type == CS_OP_IMM:
imm = op.value.imm
elif op.type == CS_OP_IMM:
imm = op.value.imm
return __resolve(imm) or f'{imm:#x}'
return __resolve(imm) or f'{imm:#x}'
elif op.type == CS_OP_MEM:
mem = op.value.mem
elif op.type == CS_OP_MEM:
mem = op.value.mem
base = __read_reg(mem.base)
index = __read_reg(mem.index)
scale = mem.scale
disp = mem.disp
base = __read_reg(mem.base)
index = __read_reg(mem.index)
scale = mem.scale
disp = mem.disp
ea = base + index * scale + disp
seg = f'{insn.reg_name(mem.segment)}:' if mem.segment else ''
ea = base + index * scale + disp
seg = f'{insn.reg_name(mem.segment)}:' if mem.segment else ''
# we construct the string representation for each operand; denote memory
# dereferenes with the appropriate 'ptr' prefix. the 'lea' instruction is
# an exception since it does not use that notation.
if insn.id == X86_INS_LEA:
qualifier = f''
else:
ptr = {
1: 'byte',
2: 'word',
4: 'dword',
8: 'qword',
10: 'fword',
16: 'xmmword'
}[op.size]
# we construct the string representation for each operand; denote memory
# dereferenes with the appropriate 'ptr' prefix. the 'lea' instruction is
# an exception since it does not use that notation.
if insn.id == X86_INS_LEA:
qualifier = f''
else:
ptr = {
1: 'byte',
2: 'word',
4: 'dword',
8: 'qword',
10: 'fword',
16: 'xmmword'
}[op.size]
qualifier = f'{ptr} ptr '
qualifier = f'{ptr} ptr '
return f'{qualifier}{seg}[{__resolve(ea) or f"{ea:#x}"}]'
return f'{qualifier}{seg}[{__resolve(ea) or f"{ea:#x}"}]'
# unexpected op type
raise RuntimeError
# unexpected op type
raise RuntimeError
operands = ', '.join(__parse_op(o) for o in insn.operands)
reads = ', '.join(f'{insn.reg_name(reg)} = {val:#x}' for reg, val in state)
operands = ', '.join(__parse_op(o) for o in insn.operands)
reads = ', '.join(f'{insn.reg_name(reg)} = {val:#x}' for reg, val in state)
return f'{insn.address:08x} | {insn.bytes.hex():24s} {insn.mnemonic:10} {operands:56s} | {reads}'
return f'{insn.address:08x} | {insn.bytes.hex():24s} {insn.mnemonic:10} {operands:56s} | {reads}'
def enable_full_trace(ql: Qiling):
"""Enable instruction-level tracing.
"""Enable instruction-level tracing.
Trace line will be emitted for each instruction before it gets executed. The info
includes static data along with the relevant registers state and symbols resolving.
Trace line will be emitted for each instruction before it gets executed. The info
includes static data along with the relevant registers state and symbols resolving.
Args:
ql: qiling instance
"""
Args:
ql: qiling instance
"""
# enable detailed disassembly info
md = ql.arch.disassembler
md.detail = True
# enable detailed disassembly info
md = ql.arch.disassembler
md.detail = True
assert md.arch == CS_ARCH_X86, 'currently available only for intel architecture'
assert md.arch == CS_ARCH_X86, 'currently available only for intel architecture'
# if available, use symbols map to resolve memory accesses
symsmap = getattr(ql.loader, 'symsmap', {})
# if available, use symbols map to resolve memory accesses
symsmap = getattr(ql.loader, 'symsmap', {})
# show trace lines in a darker color so they would be easily distinguished from
# ordinary log records
faded_color = "\033[2m"
reset_color = "\033[0m"
# show trace lines in a darker color so they would be easily distinguished from
# ordinary log records
faded_color = "\033[2m"
reset_color = "\033[0m"
def __trace_hook(ql: Qiling, address: int, size: int):
"""[internal] Trace hook callback.
"""
def __trace_hook(ql: Qiling, address: int, size: int):
"""[internal] Trace hook callback.
"""
for record in __get_trace_records(ql, address, size, md):
line = __to_trace_line(record, symsmap)
for record in __get_trace_records(ql, address, size, md):
line = __to_trace_line(record, symsmap)
ql.log.debug(f'{faded_color}{line}{reset_color}')
ql.log.debug(f'{faded_color}{line}{reset_color}')
ql.hook_code(__trace_hook)
ql.hook_code(__trace_hook)
def enable_history_trace(ql: Qiling, nrecords: int):
"""Enable instruction-level tracing in history mode.
"""Enable instruction-level tracing in history mode.
To allow faster execution, the trace info collected throughout program execution is not
emitted and undergo as minimal post-processing as possible. When program crahses, the
last `nrecords` trace lines are shown.
To allow faster execution, the trace info collected throughout program execution is not
emitted and undergo as minimal post-processing as possible. When program crahses, the
last `nrecords` trace lines are shown.
Args:
ql: qiling instance
nrecords: number of last records to show
"""
Args:
ql: qiling instance
nrecords: number of last records to show
"""
# enable detailed disassembly info
md = ql.arch.disassembler
md.detail = True
# enable detailed disassembly info
md = ql.arch.disassembler
md.detail = True
assert md.arch == CS_ARCH_X86, 'currently available only for intel architecture'
assert md.arch == CS_ARCH_X86, 'currently available only for intel architecture'
# if available, use symbols map to resolve memory accesses
symsmap = getattr(ql.loader, 'symsmap', {})
# if available, use symbols map to resolve memory accesses
symsmap = getattr(ql.loader, 'symsmap', {})
history: Deque[TraceRecord] = deque(maxlen=nrecords)
history: Deque[TraceRecord] = deque(maxlen=nrecords)
def __trace_hook(ql: Qiling, address: int, size: int):
"""[internal] Trace hook callback.
"""
def __trace_hook(ql: Qiling, address: int, size: int):
"""[internal] Trace hook callback.
"""
history.extend(__get_trace_records(ql, address, size, md))
history.extend(__get_trace_records(ql, address, size, md))
ql.hook_code(__trace_hook)
ql.hook_code(__trace_hook)
# replace the emulation error handler with our own so we can emit the trace
# records when program crashes. before we do that, we save the original one
# so we can call it.
# replace the emulation error handler with our own so we can emit the trace
# records when program crashes. before we do that, we save the original one
# so we can call it.
orig_emu_error = ql.os.emu_error
orig_emu_error = ql.os.emu_error
def __emu_error(*args):
# first run the original emulation error handler
orig_emu_error(*args)
def __emu_error(*args):
# first run the original emulation error handler
orig_emu_error(*args)
# then parse and emit the trace info we collected
ql.log.error(f'History:')
for record in history:
line = __to_trace_line(record, symsmap)
# then parse and emit the trace info we collected
ql.log.error(f'History:')
for record in history:
line = __to_trace_line(record, symsmap)
ql.log.error(line)
ql.log.error(line)
ql.log.error(f'')
ql.log.error(f'')
ql.os.emu_error = __emu_error
ql.os.emu_error = __emu_error
+90 -90
View File
@@ -25,132 +25,132 @@ FuncArgs = Sequence[Tuple[str, str]]
FuncDecl = Tuple[FuncType, FuncName, FuncArgs]
def parse_json(jfile: TextIO) -> Sequence[FuncDecl]:
JObj = Mapping[str, Any]
JObj = Mapping[str, Any]
def __parse_param(arg: JObj) -> Tuple[str, str]:
ptrlvl = 0
def __parse_param(arg: JObj) -> Tuple[str, str]:
ptrlvl = 0
while type(arg['type']) is dict and 'type' in arg['type']:
arg = arg['type']
ptrlvl += 1
while type(arg['type']) is dict and 'type' in arg['type']:
arg = arg['type']
ptrlvl += 1
aname = arg.get('name', '')
atype = arg['type']
aname = arg.get('name', '')
atype = arg['type']
if arg.get('data_type') == 'Ptr':
ptrlvl += 1
if arg.get('data_type') == 'Ptr':
ptrlvl += 1
if type(atype) is dict:
if atype['data_type'] == 'Struct':
atype = atype['name']
if type(atype) is dict:
if atype['data_type'] == 'Struct':
atype = atype['name']
elif atype['data_type'] == 'Enum':
# BUG: windows_sdk_data repo doesn't specify the name of the enum
atype = 'enum?'
elif atype['data_type'] == 'Enum':
# BUG: windows_sdk_data repo doesn't specify the name of the enum
atype = 'enum?'
else:
raise RuntimeError(f'unexpected data_type (atype = {atype})')
else:
raise RuntimeError(f'unexpected data_type (atype = {atype})')
return (aname, atype + '*' * ptrlvl)
return (aname, atype + '*' * ptrlvl)
def __parse_args(args: Sequence[JObj]):
upidx = 1
def __parse_args(args: Sequence[JObj]):
upidx = 1
for a in args:
aname, atype = __parse_param(a)
for a in args:
aname, atype = __parse_param(a)
if not aname:
if atype == 'void':
assert len(args) == 1
continue
if not aname:
if atype == 'void':
assert len(args) == 1
continue
aname = f'unnamedParam{upidx}'
upidx += 1
aname = f'unnamedParam{upidx}'
upidx += 1
yield (aname, atype)
yield (aname, atype)
decls = json.load(jfile)
decls = json.load(jfile)
def __parse_decls(decls: Sequence):
for decl in decls:
# pick up only function declarations
if decl.get('data_type') == 'FuncDecl':
ftype = decl['type']
fname = decl['name']
fargs = decl['arguments']
# loc = 'api_locations'
def __parse_decls(decls: Sequence):
for decl in decls:
# pick up only function declarations
if decl.get('data_type') == 'FuncDecl':
ftype = decl['type']
fname = decl['name']
fargs = decl['arguments']
# loc = 'api_locations'
func_type = __parse_param(ftype)
func_name = fname
func_args = tuple(__parse_args(fargs))
func_type = __parse_param(ftype)
func_name = fname
func_args = tuple(__parse_args(fargs))
assert func_type[0] == fname, 'function name is inconsistent with its return type declaration'
assert func_type[0] == fname, 'function name is inconsistent with its return type declaration'
yield (func_type[1], func_name, func_args)
yield (func_type[1], func_name, func_args)
if type(decls) is not list:
return tuple()
if type(decls) is not list:
return tuple()
return tuple(__parse_decls(decls))
return tuple(__parse_decls(decls))
def dump_py(decls: Sequence[FuncDecl], cc: str) -> Iterable[str]:
print(f'')
print(f'from qiling import Qiling')
print(f'from qiling.os.windows.api import *')
print(f'from qiling.os.windows.fncc import *')
print(f'')
print(f'')
print(f'from qiling import Qiling')
print(f'from qiling.os.windows.api import *')
print(f'from qiling.os.windows.fncc import *')
print(f'')
indent: Final[str] = ' ' * 4
indent: Final[str] = ' ' * 4
def __patch_name(aname: str) -> str:
# merely a placeholder: nothing here yet
return aname
def __patch_name(aname: str) -> str:
# merely a placeholder: nothing here yet
return aname
def __patch_type(atype: str) -> str:
return 'POINTER' if atype.endswith('*') else atype
def __patch_type(atype: str) -> str:
return 'POINTER' if atype.endswith('*') else atype
for ftype, fname, fargs in decls:
if fargs:
names = [__patch_name(a[0]) for a in fargs]
types = [__patch_type(a[1]) for a in fargs]
for ftype, fname, fargs in decls:
if fargs:
names = [__patch_name(a[0]) for a in fargs]
types = [__patch_type(a[1]) for a in fargs]
longest = max(len(n) for n in names)
longest = max(len(n) for n in names)
args = ',\n'.join(f"{indent}'{n}'{' ' * (longest - len(n))} : {t}" for n, t in zip(names, types))
args = f'\n{args}\n'
else:
args = ''
args = ',\n'.join(f"{indent}'{n}'{' ' * (longest - len(n))} : {t}" for n, t in zip(names, types))
args = f'\n{args}\n'
else:
args = ''
decor = f'@winsdkapi(cc={cc}, params={{{args}}})'
proto = f'def hook_{fname}(ql: Qiling, address: int, params):'
body = f'{indent}pass'
decor = f'@winsdkapi(cc={cc}, params={{{args}}})'
proto = f'def hook_{fname}(ql: Qiling, address: int, params):'
body = f'{indent}pass'
# TODO: specify return type (ftype) as a comment, or None for a 'void'
# TODO: specify return type (ftype) as a comment, or None for a 'void'
yield f'{decor}\n{proto}\n{body}\n'
yield f'{decor}\n{proto}\n{body}\n'
def dump_c(decls: Sequence[FuncDecl], cc: str) -> Iterable[str]:
# use a dimmed color for data types
def __dim(s: str) -> str:
return f'\x1b[90m{s}\x1b[39m'
# use a dimmed color for data types
def __dim(s: str) -> str:
return f'\x1b[90m{s}\x1b[39m'
for ftype, fname, fargs in decls:
yield f'{__dim(ftype)} {fname} ({", ".join(f"{__dim(a[1])} {a[0]}" for a in fargs)});'
for ftype, fname, fargs in decls:
yield f'{__dim(ftype)} {fname} ({", ".join(f"{__dim(a[1])} {a[0]}" for a in fargs)});'
if __name__ == '__main__':
parser = argparse.ArgumentParser()
parser.add_argument('format', choices=('c', 'py-cdecl', 'py-stdcall'), help='Declarations output format')
parser.add_argument('jfiles', metavar='jsonfile', nargs='+', help='JSON file(s) containing API prototypes')
args = parser.parse_args()
parser = argparse.ArgumentParser()
parser.add_argument('format', choices=('c', 'py-cdecl', 'py-stdcall'), help='Declarations output format')
parser.add_argument('jfiles', metavar='jsonfile', nargs='+', help='JSON file(s) containing API prototypes')
args = parser.parse_args()
fmt, _, cc = args.format.partition('-')
fmt, _, cc = args.format.partition('-')
handler: Callable = {
'c' : dump_c,
'py' : dump_py
}[fmt]
handler: Callable = {
'c' : dump_c,
'py' : dump_py
}[fmt]
for filename in args.jfiles:
with open(filename, 'r') as jfile:
for decl in handler(parse_json(jfile), cc):
print(decl)
for filename in args.jfiles:
with open(filename, 'r') as jfile:
for decl in handler(parse_json(jfile), cc):
print(decl)
+1 -1
View File
@@ -106,7 +106,7 @@ class SAM3xaUotghs(QlConnectivityPeripheral):
self.intn = intn
@QlPeripheral.monitor()
def read(self, offset: int, size: int) -> int:
def read(self, offset: int, size: int) -> int:
buf = ctypes.create_string_buffer(size)
ctypes.memmove(buf, ctypes.addressof(self.instance) + offset, size)
return int.from_bytes(buf.raw, byteorder='little')
+32 -32
View File
@@ -12,40 +12,40 @@ from qiling.hw.const.stm32f4xx_usart import USART_SR, USART_CR1
class STM32F4xxUsart(QlConnectivityPeripheral):
class Type(ctypes.Structure):
""" the structure available in :
stm32f413xx.h
stm32f407xx.h
stm32f469xx.h
stm32f446xx.h
stm32f427xx.h
stm32f401xc.h
stm32f415xx.h
stm32f412cx.h
stm32f410rx.h
stm32f410tx.h
stm32f439xx.h
stm32f412vx.h
stm32f417xx.h
stm32f479xx.h
stm32f429xx.h
stm32f412rx.h
stm32f423xx.h
stm32f437xx.h
stm32f412zx.h
stm32f401xe.h
stm32f410cx.h
stm32f405xx.h
stm32f411xe.h
"""
stm32f413xx.h
stm32f407xx.h
stm32f469xx.h
stm32f446xx.h
stm32f427xx.h
stm32f401xc.h
stm32f415xx.h
stm32f412cx.h
stm32f410rx.h
stm32f410tx.h
stm32f439xx.h
stm32f412vx.h
stm32f417xx.h
stm32f479xx.h
stm32f429xx.h
stm32f412rx.h
stm32f423xx.h
stm32f437xx.h
stm32f412zx.h
stm32f401xe.h
stm32f410cx.h
stm32f405xx.h
stm32f411xe.h
"""
_fields_ = [
('SR' , ctypes.c_uint32), # USART Status register, Address offset: 0x00
('DR' , ctypes.c_uint32), # USART Data register, Address offset: 0x04
('BRR' , ctypes.c_uint32), # USART Baud rate register, Address offset: 0x08
('CR1' , ctypes.c_uint32), # USART Control register 1, Address offset: 0x0C
('CR2' , ctypes.c_uint32), # USART Control register 2, Address offset: 0x10
('CR3' , ctypes.c_uint32), # USART Control register 3, Address offset: 0x14
('GTPR', ctypes.c_uint32), # USART Guard time and prescaler register, Address offset: 0x18
]
('SR' , ctypes.c_uint32), # USART Status register, Address offset: 0x00
('DR' , ctypes.c_uint32), # USART Data register, Address offset: 0x04
('BRR' , ctypes.c_uint32), # USART Baud rate register, Address offset: 0x08
('CR1' , ctypes.c_uint32), # USART Control register 1, Address offset: 0x0C
('CR2' , ctypes.c_uint32), # USART Control register 2, Address offset: 0x10
('CR3' , ctypes.c_uint32), # USART Control register 3, Address offset: 0x14
('GTPR', ctypes.c_uint32), # USART Guard time and prescaler register, Address offset: 0x18
]
def __init__(self, ql, label, intn=None):
+73 -73
View File
@@ -7,94 +7,94 @@ from enum import IntEnum
class ADC_SR(IntEnum):
AWD = 1 << 0
EOS = 1 << 1
JEOS = 1 << 2
JSTRT = 1 << 3
STRT = 1 << 4
AWD = 1 << 0
EOS = 1 << 1
JEOS = 1 << 2
JSTRT = 1 << 3
STRT = 1 << 4
class ADC_CR1(IntEnum):
AWDCH = 0x1f << 0
EOSIE = 1 << 5
AWDIE = 1 << 6
JEOSIE = 1 << 7
SCAN = 1 << 8
AWDSGL = 1 << 9
JAUTO = 1 << 10
DISCEN = 1 << 11
JDISCEN = 1 << 12
DISCNUM = 0x7 << 13
DALMOD = 0xf << 16
JAWDEN = 1 << 22
AWDEN = 1 << 23
AWDCH = 0x1f << 0
EOSIE = 1 << 5
AWDIE = 1 << 6
JEOSIE = 1 << 7
SCAN = 1 << 8
AWDSGL = 1 << 9
JAUTO = 1 << 10
DISCEN = 1 << 11
JDISCEN = 1 << 12
DISCNUM = 0x7 << 13
DALMOD = 0xf << 16
JAWDEN = 1 << 22
AWDEN = 1 << 23
class ADC_CR2(IntEnum):
ADON = 1 << 0
CONT = 1 << 1
CAL = 1 << 2
RSTCAL = 1 << 3
DMA = 1 << 8
ALIGN = 1 << 11
JEXTSEL = 0x7 << 12
JEXTTRIG = 1 << 15
EXTSEL = 0x7 << 17
EXTTRIG = 1 << 20
JSWSTART = 1 << 21
SWSTART = 1 << 22
TSVREFE = 1 << 23
ADON = 1 << 0
CONT = 1 << 1
CAL = 1 << 2
RSTCAL = 1 << 3
DMA = 1 << 8
ALIGN = 1 << 11
JEXTSEL = 0x7 << 12
JEXTTRIG = 1 << 15
EXTSEL = 0x7 << 17
EXTTRIG = 1 << 20
JSWSTART = 1 << 21
SWSTART = 1 << 22
TSVREFE = 1 << 23
class ADC_SMPR1(IntEnum):
SMP10 = 0x7 << 0
SMP11 = 0x7 << 3
SMP12 = 0x7 << 6
SMP13 = 0x7 << 9
SMP14 = 0x7 << 12
SMP15 = 0x7 << 15
SMP16 = 0x7 << 18
SMP17 = 0x7 << 21
SMP10 = 0x7 << 0
SMP11 = 0x7 << 3
SMP12 = 0x7 << 6
SMP13 = 0x7 << 9
SMP14 = 0x7 << 12
SMP15 = 0x7 << 15
SMP16 = 0x7 << 18
SMP17 = 0x7 << 21
class ADC_SMPR2(IntEnum):
SMP0 = 0x7 << 0
SMP1 = 0x7 << 3
SMP2 = 0x7 << 6
SMP3 = 0x7 << 9
SMP4 = 0x7 << 12
SMP5 = 0x7 << 15
SMP6 = 0x7 << 18
SMP7 = 0x7 << 21
SMP8 = 0x7 << 24
SMP9 = 0x7 << 27
SMP0 = 0x7 << 0
SMP1 = 0x7 << 3
SMP2 = 0x7 << 6
SMP3 = 0x7 << 9
SMP4 = 0x7 << 12
SMP5 = 0x7 << 15
SMP6 = 0x7 << 18
SMP7 = 0x7 << 21
SMP8 = 0x7 << 24
SMP9 = 0x7 << 27
class ADC_SQR1(IntEnum):
SQ13 = 0x1f << 0
SQ14 = 0x1f << 5
SQ15 = 0x1f << 10
SQ16 = 0x1f << 15
L = 0xf << 20
SQ13 = 0x1f << 0
SQ14 = 0x1f << 5
SQ15 = 0x1f << 10
SQ16 = 0x1f << 15
L = 0xf << 20
class ADC_SQR2(IntEnum):
SQ7 = 0x1f << 0
SQ8 = 0x1f << 5
SQ9 = 0x1f << 10
SQ10 = 0x1f << 15
SQ11 = 0x1f << 20
SQ12 = 0x1f << 25
SQ7 = 0x1f << 0
SQ8 = 0x1f << 5
SQ9 = 0x1f << 10
SQ10 = 0x1f << 15
SQ11 = 0x1f << 20
SQ12 = 0x1f << 25
class ADC_SQR3(IntEnum):
SQ1 = 0x1f << 0
SQ2 = 0x1f << 5
SQ3 = 0x1f << 10
SQ4 = 0x1f << 15
SQ5 = 0x1f << 20
SQ6 = 0x1f << 25
SQ1 = 0x1f << 0
SQ2 = 0x1f << 5
SQ3 = 0x1f << 10
SQ4 = 0x1f << 15
SQ5 = 0x1f << 20
SQ6 = 0x1f << 25
class ADC_JSQR(IntEnum):
JSQ1 = 0x1f << 0
JSQ2 = 0x1f << 5
JSQ3 = 0x1f << 10
JSQ4 = 0x1f << 15
JL = 0x3 << 20
JSQ1 = 0x1f << 0
JSQ2 = 0x1f << 5
JSQ3 = 0x1f << 10
JSQ4 = 0x1f << 15
JL = 0x3 << 20
class ADC_DR(IntEnum):
DATA = 0xffff << 0
ADC2DATA = 0xffff << 16
DATA = 0xffff << 0
ADC2DATA = 0xffff << 16
+64 -64
View File
@@ -7,64 +7,64 @@ from enum import IntEnum
class DMA_ISR(IntEnum):
GIF1 = 1 << 0
TCIF1 = 1 << 1
HTIF1 = 1 << 2
TEIF1 = 1 << 3
GIF2 = 1 << 4
TCIF2 = 1 << 5
HTIF2 = 1 << 6
TEIF2 = 1 << 7
GIF3 = 1 << 8
TCIF3 = 1 << 9
HTIF3 = 1 << 10
TEIF3 = 1 << 11
GIF4 = 1 << 12
TCIF4 = 1 << 13
HTIF4 = 1 << 14
TEIF4 = 1 << 15
GIF5 = 1 << 16
TCIF5 = 1 << 17
HTIF5 = 1 << 18
TEIF5 = 1 << 19
GIF6 = 1 << 20
TCIF6 = 1 << 21
HTIF6 = 1 << 22
TEIF6 = 1 << 23
GIF7 = 1 << 24
TCIF7 = 1 << 25
HTIF7 = 1 << 26
TEIF7 = 1 << 27
GIF1 = 1 << 0
TCIF1 = 1 << 1
HTIF1 = 1 << 2
TEIF1 = 1 << 3
GIF2 = 1 << 4
TCIF2 = 1 << 5
HTIF2 = 1 << 6
TEIF2 = 1 << 7
GIF3 = 1 << 8
TCIF3 = 1 << 9
HTIF3 = 1 << 10
TEIF3 = 1 << 11
GIF4 = 1 << 12
TCIF4 = 1 << 13
HTIF4 = 1 << 14
TEIF4 = 1 << 15
GIF5 = 1 << 16
TCIF5 = 1 << 17
HTIF5 = 1 << 18
TEIF5 = 1 << 19
GIF6 = 1 << 20
TCIF6 = 1 << 21
HTIF6 = 1 << 22
TEIF6 = 1 << 23
GIF7 = 1 << 24
TCIF7 = 1 << 25
HTIF7 = 1 << 26
TEIF7 = 1 << 27
class DMA_IFCR(IntEnum):
CGIF1 = 1 << 0
CTCIF1 = 1 << 1
CHTIF1 = 1 << 2
CTEIF1 = 1 << 3
CGIF2 = 1 << 4
CTCIF2 = 1 << 5
CHTIF2 = 1 << 6
CTEIF2 = 1 << 7
CGIF3 = 1 << 8
CTCIF3 = 1 << 9
CHTIF3 = 1 << 10
CTEIF3 = 1 << 11
CGIF4 = 1 << 12
CTCIF4 = 1 << 13
CHTIF4 = 1 << 14
CTEIF4 = 1 << 15
CGIF5 = 1 << 16
CTCIF5 = 1 << 17
CHTIF5 = 1 << 18
CTEIF5 = 1 << 19
CGIF6 = 1 << 20
CTCIF6 = 1 << 21
CHTIF6 = 1 << 22
CTEIF6 = 1 << 23
CGIF7 = 1 << 24
CTCIF7 = 1 << 25
CHTIF7 = 1 << 26
CTEIF7 = 1 << 27
CGIF1 = 1 << 0
CTCIF1 = 1 << 1
CHTIF1 = 1 << 2
CTEIF1 = 1 << 3
CGIF2 = 1 << 4
CTCIF2 = 1 << 5
CHTIF2 = 1 << 6
CTEIF2 = 1 << 7
CGIF3 = 1 << 8
CTCIF3 = 1 << 9
CHTIF3 = 1 << 10
CTEIF3 = 1 << 11
CGIF4 = 1 << 12
CTCIF4 = 1 << 13
CHTIF4 = 1 << 14
CTEIF4 = 1 << 15
CGIF5 = 1 << 16
CTCIF5 = 1 << 17
CHTIF5 = 1 << 18
CTEIF5 = 1 << 19
CGIF6 = 1 << 20
CTCIF6 = 1 << 21
CHTIF6 = 1 << 22
CTEIF6 = 1 << 23
CGIF7 = 1 << 24
CTCIF7 = 1 << 25
CHTIF7 = 1 << 26
CTEIF7 = 1 << 27
class DMA_CR(IntEnum):
EN = 1 << 0
@@ -85,13 +85,13 @@ class DMA_CR(IntEnum):
MEM2MEM = 1 << 14
class DMA(IntEnum):
PERIPH_TO_MEMORY = 0
MEMORY_TO_PERIPH = DMA_CR.DIR
PERIPH_TO_MEMORY = 0
MEMORY_TO_PERIPH = DMA_CR.DIR
PDATAALIGN_BYTE = 0
PDATAALIGN_HALFWORD = DMA_CR.PSIZE_0
PDATAALIGN_WORD = DMA_CR.PSIZE_1
PDATAALIGN_BYTE = 0
PDATAALIGN_HALFWORD = DMA_CR.PSIZE_0
PDATAALIGN_WORD = DMA_CR.PSIZE_1
MDATAALIGN_BYTE = 0
MDATAALIGN_HALFWORD = DMA_CR.MSIZE_0
MDATAALIGN_WORD = DMA_CR.MSIZE_1
MDATAALIGN_BYTE = 0
MDATAALIGN_HALFWORD = DMA_CR.MSIZE_0
MDATAALIGN_WORD = DMA_CR.MSIZE_1
+96 -96
View File
@@ -43,117 +43,117 @@ class DMA_SxCR(IntEnum):
EN = 1 << 0
class DMA_SxFCR(IntEnum):
FEIE = 1 << 7
FS = 0x7 << 3
DMDIS = 1 << 2
FTH = 0x3 << 0
FEIE = 1 << 7
FS = 0x7 << 3
DMDIS = 1 << 2
FTH = 0x3 << 0
class DMA_LISR(IntEnum):
TCIF3 = 1 << 27
HTIF3 = 1 << 26
TEIF3 = 1 << 25
DMEIF3 = 1 << 24
FEIF3 = 1 << 22
TCIF2 = 1 << 21
HTIF2 = 1 << 20
TEIF2 = 1 << 19
DMEIF2 = 1 << 18
FEIF2 = 1 << 16
TCIF1 = 1 << 11
HTIF1 = 1 << 10
TEIF1 = 1 << 9
DMEIF1 = 1 << 8
FEIF1 = 1 << 6
TCIF0 = 1 << 5
HTIF0 = 1 << 4
TEIF0 = 1 << 3
DMEIF0 = 1 << 2
FEIF0 = 1 << 0
TCIF3 = 1 << 27
HTIF3 = 1 << 26
TEIF3 = 1 << 25
DMEIF3 = 1 << 24
FEIF3 = 1 << 22
TCIF2 = 1 << 21
HTIF2 = 1 << 20
TEIF2 = 1 << 19
DMEIF2 = 1 << 18
FEIF2 = 1 << 16
TCIF1 = 1 << 11
HTIF1 = 1 << 10
TEIF1 = 1 << 9
DMEIF1 = 1 << 8
FEIF1 = 1 << 6
TCIF0 = 1 << 5
HTIF0 = 1 << 4
TEIF0 = 1 << 3
DMEIF0 = 1 << 2
FEIF0 = 1 << 0
class DMA_HISR(IntEnum):
TCIF7 = 1 << 27
HTIF7 = 1 << 26
TEIF7 = 1 << 25
DMEIF7 = 1 << 24
FEIF7 = 1 << 22
TCIF6 = 1 << 21
HTIF6 = 1 << 20
TEIF6 = 1 << 19
DMEIF6 = 1 << 18
FEIF6 = 1 << 16
TCIF5 = 1 << 11
HTIF5 = 1 << 10
TEIF5 = 1 << 9
DMEIF5 = 1 << 8
FEIF5 = 1 << 6
TCIF4 = 1 << 5
HTIF4 = 1 << 4
TEIF4 = 1 << 3
DMEIF4 = 1 << 2
FEIF4 = 1 << 0
TCIF7 = 1 << 27
HTIF7 = 1 << 26
TEIF7 = 1 << 25
DMEIF7 = 1 << 24
FEIF7 = 1 << 22
TCIF6 = 1 << 21
HTIF6 = 1 << 20
TEIF6 = 1 << 19
DMEIF6 = 1 << 18
FEIF6 = 1 << 16
TCIF5 = 1 << 11
HTIF5 = 1 << 10
TEIF5 = 1 << 9
DMEIF5 = 1 << 8
FEIF5 = 1 << 6
TCIF4 = 1 << 5
HTIF4 = 1 << 4
TEIF4 = 1 << 3
DMEIF4 = 1 << 2
FEIF4 = 1 << 0
class DMA_LIFCR(IntEnum):
CTCIF3 = 1 << 27
CHTIF3 = 1 << 26
CTEIF3 = 1 << 25
CDMEIF3 = 1 << 24
CFEIF3 = 1 << 22
CTCIF2 = 1 << 21
CHTIF2 = 1 << 20
CTEIF2 = 1 << 19
CDMEIF2 = 1 << 18
CFEIF2 = 1 << 16
CTCIF1 = 1 << 11
CHTIF1 = 1 << 10
CTEIF1 = 1 << 9
CDMEIF1 = 1 << 8
CFEIF1 = 1 << 6
CTCIF0 = 1 << 5
CHTIF0 = 1 << 4
CTEIF0 = 1 << 3
CDMEIF0 = 1 << 2
CFEIF0 = 1 << 0
CTCIF3 = 1 << 27
CHTIF3 = 1 << 26
CTEIF3 = 1 << 25
CDMEIF3 = 1 << 24
CFEIF3 = 1 << 22
CTCIF2 = 1 << 21
CHTIF2 = 1 << 20
CTEIF2 = 1 << 19
CDMEIF2 = 1 << 18
CFEIF2 = 1 << 16
CTCIF1 = 1 << 11
CHTIF1 = 1 << 10
CTEIF1 = 1 << 9
CDMEIF1 = 1 << 8
CFEIF1 = 1 << 6
CTCIF0 = 1 << 5
CHTIF0 = 1 << 4
CTEIF0 = 1 << 3
CDMEIF0 = 1 << 2
CFEIF0 = 1 << 0
class DMA_HIFCR(IntEnum):
CTCIF7 = 1 << 27
CHTIF7 = 1 << 26
CTEIF7 = 1 << 25
CDMEIF7 = 1 << 24
CFEIF7 = 1 << 22
CTCIF6 = 1 << 21
CHTIF6 = 1 << 20
CTEIF6 = 1 << 19
CDMEIF6 = 1 << 18
CFEIF6 = 1 << 16
CTCIF5 = 1 << 11
CHTIF5 = 1 << 10
CTEIF5 = 1 << 9
CDMEIF5 = 1 << 8
CFEIF5 = 1 << 6
CTCIF4 = 1 << 5
CHTIF4 = 1 << 4
CTEIF4 = 1 << 3
CDMEIF4 = 1 << 2
CFEIF4 = 1 << 0
CTCIF7 = 1 << 27
CHTIF7 = 1 << 26
CTEIF7 = 1 << 25
CDMEIF7 = 1 << 24
CFEIF7 = 1 << 22
CTCIF6 = 1 << 21
CHTIF6 = 1 << 20
CTEIF6 = 1 << 19
CDMEIF6 = 1 << 18
CFEIF6 = 1 << 16
CTCIF5 = 1 << 11
CHTIF5 = 1 << 10
CTEIF5 = 1 << 9
CDMEIF5 = 1 << 8
CFEIF5 = 1 << 6
CTCIF4 = 1 << 5
CHTIF4 = 1 << 4
CTEIF4 = 1 << 3
CDMEIF4 = 1 << 2
CFEIF4 = 1 << 0
class DMA_SxPAR(IntEnum):
PA = 0xffffffff << 0
PA = 0xffffffff << 0
class DMA_SxM0AR(IntEnum):
M0A = 0xffffffff << 0
M0A = 0xffffffff << 0
class DMA_SxM1AR(IntEnum):
M1A = 0xffffffff << 0
M1A = 0xffffffff << 0
class DMA(IntEnum):
PERIPH_TO_MEMORY = 0
MEMORY_TO_PERIPH = DMA_SxCR.DIR_0
MEMORY_TO_MEMORY = DMA_SxCR.DIR_1
PERIPH_TO_MEMORY = 0
MEMORY_TO_PERIPH = DMA_SxCR.DIR_0
MEMORY_TO_MEMORY = DMA_SxCR.DIR_1
PDATAALIGN_BYTE = 0
PDATAALIGN_HALFWORD = DMA_SxCR.PSIZE_0
PDATAALIGN_WORD = DMA_SxCR.PSIZE_1
PDATAALIGN_BYTE = 0
PDATAALIGN_HALFWORD = DMA_SxCR.PSIZE_0
PDATAALIGN_WORD = DMA_SxCR.PSIZE_1
MDATAALIGN_BYTE = 0
MDATAALIGN_HALFWORD = DMA_SxCR.MSIZE_0
MDATAALIGN_WORD = DMA_SxCR.MSIZE_1
MDATAALIGN_BYTE = 0
MDATAALIGN_HALFWORD = DMA_SxCR.MSIZE_0
MDATAALIGN_WORD = DMA_SxCR.MSIZE_1
+216 -216
View File
@@ -2,271 +2,271 @@ from enum import IntEnum
class ETH_MACCR(IntEnum):
WD = 1 << 23
JD = 1 << 22
IFG = 0x7 << 17
CSD = 1 << 16
FES = 1 << 14
ROD = 1 << 13
LM = 1 << 12
DM = 1 << 11
IPCO = 1 << 10
RD = 1 << 9
APCS = 1 << 7
BL = 0x3 << 5
DC = 1 << 4
TE = 1 << 3
RE = 1 << 2
WD = 1 << 23
JD = 1 << 22
IFG = 0x7 << 17
CSD = 1 << 16
FES = 1 << 14
ROD = 1 << 13
LM = 1 << 12
DM = 1 << 11
IPCO = 1 << 10
RD = 1 << 9
APCS = 1 << 7
BL = 0x3 << 5
DC = 1 << 4
TE = 1 << 3
RE = 1 << 2
class ETH_MACFFR(IntEnum):
RA = 1 << 31
HPF = 1 << 10
SAF = 1 << 9
SAIF = 1 << 8
PCF = 0x3 << 6
PCF_BlockAll = 1 << 6
PCF_ForwardAll = 1 << 7
PCF_ForwardPassedAddrFilter = 0x3 << 6
BFD = 1 << 5
PAM = 1 << 4
DAIF = 1 << 3
HM = 1 << 2
HU = 1 << 1
PM = 1 << 0
RA = 1 << 31
HPF = 1 << 10
SAF = 1 << 9
SAIF = 1 << 8
PCF = 0x3 << 6
PCF_BlockAll = 1 << 6
PCF_ForwardAll = 1 << 7
PCF_ForwardPassedAddrFilter = 0x3 << 6
BFD = 1 << 5
PAM = 1 << 4
DAIF = 1 << 3
HM = 1 << 2
HU = 1 << 1
PM = 1 << 0
class ETH_MACMIIAR(IntEnum):
PA = 0x1f << 11
MR = 0x1f << 6
CR = 0x7 << 2
CR_Div62 = 1 << 2
CR_Div16 = 1 << 3
CR_Div26 = 0x3 << 2
CR_Div102 = 1 << 4
MW = 1 << 1
MB = 1 << 0
PA = 0x1f << 11
MR = 0x1f << 6
CR = 0x7 << 2
CR_Div62 = 1 << 2
CR_Div16 = 1 << 3
CR_Div26 = 0x3 << 2
CR_Div102 = 1 << 4
MW = 1 << 1
MB = 1 << 0
class ETH_MACFCR(IntEnum):
PT = 0xffff << 16
ZQPD = 1 << 7
PLT = 0x3 << 4
PLT_Minus28 = 1 << 4
PLT_Minus144 = 1 << 5
PLT_Minus256 = 0x3 << 4
UPFD = 1 << 3
RFCE = 1 << 2
TFCE = 1 << 1
FCBBPA = 1 << 0
PT = 0xffff << 16
ZQPD = 1 << 7
PLT = 0x3 << 4
PLT_Minus28 = 1 << 4
PLT_Minus144 = 1 << 5
PLT_Minus256 = 0x3 << 4
UPFD = 1 << 3
RFCE = 1 << 2
TFCE = 1 << 1
FCBBPA = 1 << 0
class ETH_MACVLANTR(IntEnum):
VLANTC = 1 << 16
VLANTI = 0xffff << 0
VLANTC = 1 << 16
VLANTI = 0xffff << 0
class ETH_MACPMTCSR(IntEnum):
WFFRPR = 1 << 31
GU = 1 << 9
WFR = 1 << 6
MPR = 1 << 5
WFE = 1 << 2
MPE = 1 << 1
PD = 1 << 0
WFFRPR = 1 << 31
GU = 1 << 9
WFR = 1 << 6
MPR = 1 << 5
WFE = 1 << 2
MPE = 1 << 1
PD = 1 << 0
class ETH_MACDBGR(IntEnum):
TFF = 1 << 25
TFNE = 1 << 24
TFWA = 1 << 22
TFRS = 0x3 << 20
TFRS_WRITING = 0x3 << 20
TFRS_WAITING = 1 << 21
TFRS_READ = 1 << 20
MTP = 1 << 19
MTFCS = 0x3 << 17
MTFCS_TRANSFERRING = 0x3 << 17
MTFCS_GENERATINGPCF = 1 << 18
MTFCS_WAITING = 1 << 17
MMTEA = 1 << 16
RFFL = 0x3 << 8
RFFL_FL = 0x3 << 8
RFFL_ABOVEFCT = 1 << 9
RFFL_BELOWFCT = 1 << 8
RFRCS = 0x3 << 5
RFRCS_FLUSHING = 0x3 << 5
RFRCS_STATUSREADING = 1 << 6
RFRCS_DATAREADING = 1 << 5
RFWRA = 1 << 4
MSFRWCS = 0x3 << 1
MMRPEA = 1 << 0
TFF = 1 << 25
TFNE = 1 << 24
TFWA = 1 << 22
TFRS = 0x3 << 20
TFRS_WRITING = 0x3 << 20
TFRS_WAITING = 1 << 21
TFRS_READ = 1 << 20
MTP = 1 << 19
MTFCS = 0x3 << 17
MTFCS_TRANSFERRING = 0x3 << 17
MTFCS_GENERATINGPCF = 1 << 18
MTFCS_WAITING = 1 << 17
MMTEA = 1 << 16
RFFL = 0x3 << 8
RFFL_FL = 0x3 << 8
RFFL_ABOVEFCT = 1 << 9
RFFL_BELOWFCT = 1 << 8
RFRCS = 0x3 << 5
RFRCS_FLUSHING = 0x3 << 5
RFRCS_STATUSREADING = 1 << 6
RFRCS_DATAREADING = 1 << 5
RFWRA = 1 << 4
MSFRWCS = 0x3 << 1
MMRPEA = 1 << 0
class ETH_MACSR(IntEnum):
TSTS = 1 << 9
MMCTS = 1 << 6
MMMCRS = 1 << 5
MMCS = 1 << 4
PMTS = 1 << 3
TSTS = 1 << 9
MMCTS = 1 << 6
MMMCRS = 1 << 5
MMCS = 1 << 4
PMTS = 1 << 3
class ETH_MACIMR(IntEnum):
TSTIM = 1 << 9
PMTIM = 1 << 3
TSTIM = 1 << 9
PMTIM = 1 << 3
class ETH_MACA1HR(IntEnum):
AE = 1 << 31
SA = 1 << 30
MBC = 0x3f << 24
MACA1H = 0xffff << 0
AE = 1 << 31
SA = 1 << 30
MBC = 0x3f << 24
MACA1H = 0xffff << 0
class ETH_MACA2HR(IntEnum):
AE = 1 << 31
SA = 1 << 30
MBC = 0x3f << 24
MACA2H = 0xffff << 0
AE = 1 << 31
SA = 1 << 30
MBC = 0x3f << 24
MACA2H = 0xffff << 0
class ETH_MACA3HR(IntEnum):
AE = 1 << 31
SA = 1 << 30
MBC = 0x3f << 24
MACA3H = 0xffff << 0
AE = 1 << 31
SA = 1 << 30
MBC = 0x3f << 24
MACA3H = 0xffff << 0
class ETH_MMCCR(IntEnum):
MCFHP = 1 << 5
MCP = 1 << 4
MCF = 1 << 3
ROR = 1 << 2
CSR = 1 << 1
CR = 1 << 0
MCFHP = 1 << 5
MCP = 1 << 4
MCF = 1 << 3
ROR = 1 << 2
CSR = 1 << 1
CR = 1 << 0
class ETH_MMCRIR(IntEnum):
RGUFS = 1 << 17
RFAES = 1 << 6
RFCES = 1 << 5
RGUFS = 1 << 17
RFAES = 1 << 6
RFCES = 1 << 5
class ETH_MMCTIR(IntEnum):
TGFS = 1 << 21
TGFMSCS = 1 << 15
TGFSCS = 1 << 14
TGFS = 1 << 21
TGFMSCS = 1 << 15
TGFSCS = 1 << 14
class ETH_MMCRIMR(IntEnum):
RGUFM = 1 << 17
RFAEM = 1 << 6
RFCEM = 1 << 5
RGUFM = 1 << 17
RFAEM = 1 << 6
RFCEM = 1 << 5
class ETH_MMCTIMR(IntEnum):
TGFM = 1 << 21
TGFMSCM = 1 << 15
TGFSCM = 1 << 14
TGFM = 1 << 21
TGFMSCM = 1 << 15
TGFSCM = 1 << 14
class ETH_PTPTSCR(IntEnum):
TSCNT = 0x3 << 16
TSARU = 1 << 5
TSITE = 1 << 4
TSSTU = 1 << 3
TSSTI = 1 << 2
TSFCU = 1 << 1
TSE = 1 << 0
TSCNT = 0x3 << 16
TSARU = 1 << 5
TSITE = 1 << 4
TSSTU = 1 << 3
TSSTI = 1 << 2
TSFCU = 1 << 1
TSE = 1 << 0
class ETH_PTPTSSR(IntEnum):
TSSMRME = 1 << 15
TSSEME = 1 << 14
TSSIPV4FE = 1 << 13
TSSIPV6FE = 1 << 12
TSSPTPOEFE = 1 << 11
TSPTPPSV2E = 1 << 10
TSSSR = 1 << 9
TSSARFE = 1 << 8
TSTTR = 1 << 5
TSSO = 1 << 4
TSSMRME = 1 << 15
TSSEME = 1 << 14
TSSIPV4FE = 1 << 13
TSSIPV6FE = 1 << 12
TSSPTPOEFE = 1 << 11
TSPTPPSV2E = 1 << 10
TSSSR = 1 << 9
TSSARFE = 1 << 8
TSTTR = 1 << 5
TSSO = 1 << 4
class ETH_PTPSSIR(IntEnum):
STSSI = 0xff << 0
STSSI = 0xff << 0
class ETH_PTPTSLR(IntEnum):
STPNS = 1 << 31
STSS = 0x7fffffff << 0
STPNS = 1 << 31
STSS = 0x7fffffff << 0
class ETH_PTPTSLUR(IntEnum):
TSUPNS = 1 << 31
TSUSS = 0x7fffffff << 0
TSUPNS = 1 << 31
TSUSS = 0x7fffffff << 0
class ETH_DMABMR(IntEnum):
AAB = 1 << 25
FPM = 1 << 24
USP = 1 << 23
RDP = 0x3f << 17
FB = 1 << 16
RTPR = 0x3 << 14
PBL = 0x3f << 8
EDE = 1 << 7
DSL = 0x1f << 2
DA = 1 << 1
SR = 1 << 0
AAB = 1 << 25
FPM = 1 << 24
USP = 1 << 23
RDP = 0x3f << 17
FB = 1 << 16
RTPR = 0x3 << 14
PBL = 0x3f << 8
EDE = 1 << 7
DSL = 0x1f << 2
DA = 1 << 1
SR = 1 << 0
class ETH_DMASR(IntEnum):
TSTS = 1 << 29
PMTS = 1 << 28
MMCS = 1 << 27
EBS = 0x7 << 23
EBS_DescAccess = 1 << 25
EBS_ReadTransf = 1 << 24
EBS_DataTransfTx = 1 << 23
TPS = 0x7 << 20
TPS_Fetching = 1 << 20
TPS_Waiting = 1 << 21
TPS_Reading = 0x3 << 20
TPS_Suspended = 0x3 << 21
TPS_Closing = 0x7 << 20
RPS = 0x7 << 17
RPS_Fetching = 1 << 17
RPS_Waiting = 0x3 << 17
RPS_Suspended = 1 << 19
RPS_Closing = 0x5 << 17
RPS_Queuing = 0x7 << 17
NIS = 1 << 16
AIS = 1 << 15
ERS = 1 << 14
FBES = 1 << 13
ETS = 1 << 10
RWTS = 1 << 9
RPSS = 1 << 8
RBUS = 1 << 7
RS = 1 << 6
TUS = 1 << 5
ROS = 1 << 4
TJTS = 1 << 3
TBUS = 1 << 2
TPSS = 1 << 1
TS = 1 << 0
TSTS = 1 << 29
PMTS = 1 << 28
MMCS = 1 << 27
EBS = 0x7 << 23
EBS_DescAccess = 1 << 25
EBS_ReadTransf = 1 << 24
EBS_DataTransfTx = 1 << 23
TPS = 0x7 << 20
TPS_Fetching = 1 << 20
TPS_Waiting = 1 << 21
TPS_Reading = 0x3 << 20
TPS_Suspended = 0x3 << 21
TPS_Closing = 0x7 << 20
RPS = 0x7 << 17
RPS_Fetching = 1 << 17
RPS_Waiting = 0x3 << 17
RPS_Suspended = 1 << 19
RPS_Closing = 0x5 << 17
RPS_Queuing = 0x7 << 17
NIS = 1 << 16
AIS = 1 << 15
ERS = 1 << 14
FBES = 1 << 13
ETS = 1 << 10
RWTS = 1 << 9
RPSS = 1 << 8
RBUS = 1 << 7
RS = 1 << 6
TUS = 1 << 5
ROS = 1 << 4
TJTS = 1 << 3
TBUS = 1 << 2
TPSS = 1 << 1
TS = 1 << 0
class ETH_DMAOMR(IntEnum):
DTCEFD = 1 << 26
RSF = 1 << 25
DFRF = 1 << 24
TSF = 1 << 21
FTF = 1 << 20
TTC = 0x7 << 14
ST = 1 << 13
FEF = 1 << 7
FGF = 1 << 6
RTC = 0x3 << 3
OSF = 1 << 2
SR = 1 << 1
DTCEFD = 1 << 26
RSF = 1 << 25
DFRF = 1 << 24
TSF = 1 << 21
FTF = 1 << 20
TTC = 0x7 << 14
ST = 1 << 13
FEF = 1 << 7
FGF = 1 << 6
RTC = 0x3 << 3
OSF = 1 << 2
SR = 1 << 1
class ETH_DMAIER(IntEnum):
NISE = 1 << 16
AISE = 1 << 15
ERIE = 1 << 14
FBEIE = 1 << 13
ETIE = 1 << 10
RWTIE = 1 << 9
RPSIE = 1 << 8
RBUIE = 1 << 7
RIE = 1 << 6
TUIE = 1 << 5
ROIE = 1 << 4
TJTIE = 1 << 3
TBUIE = 1 << 2
TPSIE = 1 << 1
TIE = 1 << 0
NISE = 1 << 16
AISE = 1 << 15
ERIE = 1 << 14
FBEIE = 1 << 13
ETIE = 1 << 10
RWTIE = 1 << 9
RPSIE = 1 << 8
RBUIE = 1 << 7
RIE = 1 << 6
TUIE = 1 << 5
ROIE = 1 << 4
TJTIE = 1 << 3
TBUIE = 1 << 2
TPSIE = 1 << 1
TIE = 1 << 0
class ETH_DMAMFBOCR(IntEnum):
OFOC = 1 << 28
MFA = 0x7ff << 17
OMFC = 1 << 16
MFC = 0xffff << 0
OFOC = 1 << 28
MFA = 0x7ff << 17
OMFC = 1 << 16
MFC = 0xffff << 0
+65 -65
View File
@@ -7,88 +7,88 @@ from enum import IntEnum
class I2C_CR1(IntEnum):
PE = 1 << 0
SMBUS = 1 << 1
SMBTYPE = 1 << 3
ENARP = 1 << 4
ENPEC = 1 << 5
ENGC = 1 << 6
NOSTRETCH = 1 << 7
START = 1 << 8
STOP = 1 << 9
ACK = 1 << 10
POS = 1 << 11
PEC = 1 << 12
ALERT = 1 << 13
SWRST = 1 << 15
PE = 1 << 0
SMBUS = 1 << 1
SMBTYPE = 1 << 3
ENARP = 1 << 4
ENPEC = 1 << 5
ENGC = 1 << 6
NOSTRETCH = 1 << 7
START = 1 << 8
STOP = 1 << 9
ACK = 1 << 10
POS = 1 << 11
PEC = 1 << 12
ALERT = 1 << 13
SWRST = 1 << 15
RW_MASK = PE|SMBUS|SMBTYPE|ENARP|ENPEC|ENGC|NOSTRETCH|START|STOP|ACK|POS|ALERT|SWRST
RW_MASK = PE|SMBUS|SMBTYPE|ENARP|ENPEC|ENGC|NOSTRETCH|START|STOP|ACK|POS|ALERT|SWRST
class I2C_CR2(IntEnum):
FREQ = 0x3f << 0
ITERREN = 1 << 8
ITEVTEN = 1 << 9
ITBUFEN = 1 << 10
DMAEN = 1 << 11
LAST = 1 << 12
FREQ = 0x3f << 0
ITERREN = 1 << 8
ITEVTEN = 1 << 9
ITBUFEN = 1 << 10
DMAEN = 1 << 11
LAST = 1 << 12
class I2C_OAR1(IntEnum):
ADD0 = 1 << 0
ADD1 = 1 << 1
ADD2 = 1 << 2
ADD3 = 1 << 3
ADD4 = 1 << 4
ADD5 = 1 << 5
ADD6 = 1 << 6
ADD7 = 1 << 7
ADD8 = 1 << 8
ADD9 = 1 << 9
ADDMODE = 1 << 15
ADD0 = 1 << 0
ADD1 = 1 << 1
ADD2 = 1 << 2
ADD3 = 1 << 3
ADD4 = 1 << 4
ADD5 = 1 << 5
ADD6 = 1 << 6
ADD7 = 1 << 7
ADD8 = 1 << 8
ADD9 = 1 << 9
ADDMODE = 1 << 15
ADDR1_7B = 0x7f << 1
ADDR1_10B = 0x3ff
ADDR1_7B = 0x7f << 1
ADDR1_10B = 0x3ff
class I2C_OAR2(IntEnum):
ENDUAL = 1 << 0
ADDR2 = 0x7f << 1
ENDUAL = 1 << 0
ADDR2 = 0x7f << 1
class I2C_DR(IntEnum):
DR = 0xff << 0
DR = 0xff << 0
class I2C_SR1(IntEnum):
SB = 1 << 0
ADDR = 1 << 1
BTF = 1 << 2
ADD10 = 1 << 3
STOPF = 1 << 4
RXNE = 1 << 6
TXE = 1 << 7
BERR = 1 << 8
ARLO = 1 << 9
AF = 1 << 10
OVR = 1 << 11
PECERR = 1 << 12
TIMEOUT = 1 << 14
SMBALERT = 1 << 15
SB = 1 << 0
ADDR = 1 << 1
BTF = 1 << 2
ADD10 = 1 << 3
STOPF = 1 << 4
RXNE = 1 << 6
TXE = 1 << 7
BERR = 1 << 8
ARLO = 1 << 9
AF = 1 << 10
OVR = 1 << 11
PECERR = 1 << 12
TIMEOUT = 1 << 14
SMBALERT = 1 << 15
class I2C_SR2(IntEnum):
MSL = 1 << 0
BSY = 1 << 1
TRA = 1 << 2
GENCALL = 1 << 4
SMBDEFAULT = 1 << 5
SMBHOST = 1 << 6
DALF = 1 << 7
PEC = 0xff << 8
MSL = 1 << 0
BSY = 1 << 1
TRA = 1 << 2
GENCALL = 1 << 4
SMBDEFAULT = 1 << 5
SMBHOST = 1 << 6
DALF = 1 << 7
PEC = 0xff << 8
class I2C_CCR(IntEnum):
CCR = 0xfff << 0
DTY = 1 << 14
FS = 1 << 15
CCR = 0xfff << 0
DTY = 1 << 14
FS = 1 << 15
class I2C_TRISE(IntEnum):
TRISE = 0x3f << 0
TRISE = 0x3f << 0
class I2C_FLTR(IntEnum):
DNF = 0xf << 0
ANOFF = 1 << 4
DNF = 0xf << 0
ANOFF = 1 << 4
+25 -25
View File
@@ -7,30 +7,30 @@ from enum import IntEnum
class PWR_CR(IntEnum):
LPDS = 1 << 0
PDDS = 1 << 1
CWUF = 1 << 2
CSBF = 1 << 3
PVDE = 1 << 4
PLS = 0x7 << 5
DBP = 1 << 8
FPDS = 1 << 9
LPLVDS = 1 << 10
MRLVDS = 1 << 11
ADCDC1 = 1 << 13
VOS = 0x3 << 14
ODEN = 1 << 16
ODSWEN = 1 << 17
UDEN = 0x3 << 18
LPDS = 1 << 0
PDDS = 1 << 1
CWUF = 1 << 2
CSBF = 1 << 3
PVDE = 1 << 4
PLS = 0x7 << 5
DBP = 1 << 8
FPDS = 1 << 9
LPLVDS = 1 << 10
MRLVDS = 1 << 11
ADCDC1 = 1 << 13
VOS = 0x3 << 14
ODEN = 1 << 16
ODSWEN = 1 << 17
UDEN = 0x3 << 18
class PWR_CSR(IntEnum):
WUF = 1 << 0
SBF = 1 << 1
PVDO = 1 << 2
BRR = 1 << 3
EWUP = 1 << 8
BRE = 1 << 9
VOSRDY = 1 << 14
ODRDY = 1 << 16
ODSWRDY = 1 << 17
UDRDY = 0x3 << 18
WUF = 1 << 0
SBF = 1 << 1
PVDO = 1 << 2
BRR = 1 << 3
EWUP = 1 << 8
BRE = 1 << 9
VOSRDY = 1 << 14
ODRDY = 1 << 16
ODSWRDY = 1 << 17
UDRDY = 0x3 << 18
+122 -122
View File
@@ -8,161 +8,161 @@ from enum import IntEnum
class RTC_TR(IntEnum):
PM = 1 << 22
HT = 0x3 << 20
HU = 0xf << 16
MNT = 0x7 << 12
MNU = 0xf << 8
ST = 0x7 << 4
SU = 0xf << 0
PM = 1 << 22
HT = 0x3 << 20
HU = 0xf << 16
MNT = 0x7 << 12
MNU = 0xf << 8
ST = 0x7 << 4
SU = 0xf << 0
class RTC_DR(IntEnum):
YT = 0xf << 20
YU = 0xf << 16
WDU = 0x7 << 13
MT = 1 << 12
MU = 0xf << 8
DT = 0x3 << 4
D = 0xf << 0
YT = 0xf << 20
YU = 0xf << 16
WDU = 0x7 << 13
MT = 1 << 12
MU = 0xf << 8
DT = 0x3 << 4
D = 0xf << 0
class RTC_CR(IntEnum):
COE = 1 << 23
OSEL = 0x3 << 21
POL = 1 << 20
COSEL = 1 << 19
BKP = 1 << 18
SUB1H = 1 << 17
ADD1H = 1 << 16
TSIE = 1 << 15
WUTIE = 1 << 14
ALRBIE = 1 << 13
ALRAIE = 1 << 12
TSE = 1 << 11
WUTE = 1 << 10
ALRBE = 1 << 9
ALRAE = 1 << 8
DCE = 1 << 7
FMT = 1 << 6
BYPSHAD = 1 << 5
REFCKON = 1 << 4
TSEDGE = 1 << 3
WUCKSEL = 0x7 << 0
COE = 1 << 23
OSEL = 0x3 << 21
POL = 1 << 20
COSEL = 1 << 19
BKP = 1 << 18
SUB1H = 1 << 17
ADD1H = 1 << 16
TSIE = 1 << 15
WUTIE = 1 << 14
ALRBIE = 1 << 13
ALRAIE = 1 << 12
TSE = 1 << 11
WUTE = 1 << 10
ALRBE = 1 << 9
ALRAE = 1 << 8
DCE = 1 << 7
FMT = 1 << 6
BYPSHAD = 1 << 5
REFCKON = 1 << 4
TSEDGE = 1 << 3
WUCKSEL = 0x7 << 0
class RTC_ISR(IntEnum):
RECALPF = 1 << 16
TAMP1F = 1 << 13
TAMP2F = 1 << 14
TSOVF = 1 << 12
TSF = 1 << 11
WUTF = 1 << 10
ALRBF = 1 << 9
ALRAF = 1 << 8
INIT = 1 << 7
INITF = 1 << 6
RSF = 1 << 5
INITS = 1 << 4
SHPF = 1 << 3
WUTWF = 1 << 2
ALRBWF = 1 << 1
ALRAWF = 1 << 0
RECALPF = 1 << 16
TAMP1F = 1 << 13
TAMP2F = 1 << 14
TSOVF = 1 << 12
TSF = 1 << 11
WUTF = 1 << 10
ALRBF = 1 << 9
ALRAF = 1 << 8
INIT = 1 << 7
INITF = 1 << 6
RSF = 1 << 5
INITS = 1 << 4
SHPF = 1 << 3
WUTWF = 1 << 2
ALRBWF = 1 << 1
ALRAWF = 1 << 0
class RTC_PRER(IntEnum):
PREDIV_A = 0x7f << 16
PREDIV_S = 0x7fff << 0
PREDIV_A = 0x7f << 16
PREDIV_S = 0x7fff << 0
class RTC_WUTR(IntEnum):
WUT = 0xffff << 0
WUT = 0xffff << 0
class RTC_CALIBR(IntEnum):
DCS = 1 << 7
DC = 0x1f << 0
DCS = 1 << 7
DC = 0x1f << 0
class RTC_ALRMAR(IntEnum):
MSK4 = 1 << 31
WDSEL = 1 << 30
DT = 0x3 << 28
D = 0xf << 24
MSK3 = 1 << 23
PM = 1 << 22
HT = 0x3 << 20
HU = 0xf << 16
MSK2 = 1 << 15
MNT = 0x7 << 12
MNU = 0xf << 8
MSK1 = 1 << 7
ST = 0x7 << 4
SU = 0xf << 0
MSK4 = 1 << 31
WDSEL = 1 << 30
DT = 0x3 << 28
D = 0xf << 24
MSK3 = 1 << 23
PM = 1 << 22
HT = 0x3 << 20
HU = 0xf << 16
MSK2 = 1 << 15
MNT = 0x7 << 12
MNU = 0xf << 8
MSK1 = 1 << 7
ST = 0x7 << 4
SU = 0xf << 0
class RTC_ALRMBR(IntEnum):
MSK4 = 1 << 31
WDSEL = 1 << 30
DT = 0x3 << 28
D = 0xf << 24
MSK3 = 1 << 23
PM = 1 << 22
HT = 0x3 << 20
HU = 0xf << 16
MSK2 = 1 << 15
MNT = 0x7 << 12
MNU = 0xf << 8
MSK1 = 1 << 7
ST = 0x7 << 4
SU = 0xf << 0
MSK4 = 1 << 31
WDSEL = 1 << 30
DT = 0x3 << 28
D = 0xf << 24
MSK3 = 1 << 23
PM = 1 << 22
HT = 0x3 << 20
HU = 0xf << 16
MSK2 = 1 << 15
MNT = 0x7 << 12
MNU = 0xf << 8
MSK1 = 1 << 7
ST = 0x7 << 4
SU = 0xf << 0
class RTC_WPR(IntEnum):
KEY = 0xff << 0
KEY = 0xff << 0
class RTC_SSR(IntEnum):
SS = 0xffff << 0
SS = 0xffff << 0
class RTC_SHIFTR(IntEnum):
SUBFS = 0x7fff << 0
ADD1S = 1 << 31
SUBFS = 0x7fff << 0
ADD1S = 1 << 31
class RTC_TSTR(IntEnum):
PM = 1 << 22
HT = 0x3 << 20
HU = 0xf << 16
MNT = 0x7 << 12
MNU = 0xf << 8
ST = 0x7 << 4
SU = 0xf << 0
PM = 1 << 22
HT = 0x3 << 20
HU = 0xf << 16
MNT = 0x7 << 12
MNU = 0xf << 8
ST = 0x7 << 4
SU = 0xf << 0
class RTC_TSDR(IntEnum):
WDU = 0x7 << 13
MT = 1 << 12
MU = 0xf << 8
DT = 0x3 << 4
D = 0xf << 0
WDU = 0x7 << 13
MT = 1 << 12
MU = 0xf << 8
DT = 0x3 << 4
D = 0xf << 0
class RTC_TSSSR(IntEnum):
SS = 0xffff << 0
SS = 0xffff << 0
class RTC_CALR(IntEnum):
CALP = 1 << 15
CALW8 = 1 << 14
CALW16 = 1 << 13
CALM = 0x1ff << 0
CALP = 1 << 15
CALW8 = 1 << 14
CALW16 = 1 << 13
CALM = 0x1ff << 0
class RTC_TAFCR(IntEnum):
ALARMOUTTYPE = 1 << 18
TSINSEL = 1 << 17
TAMP1INSEL = 1 << 16
TAMPPUDIS = 1 << 15
TAMPPRCH = 0x3 << 13
TAMPFLT = 0x3 << 11
TAMPFREQ = 0x7 << 8
TAMPTS = 1 << 7
TAMP2TRG = 1 << 4
TAMP2E = 1 << 3
TAMPIE = 1 << 2
TAMP1TRG = 1 << 1
TAMP1E = 1 << 0
ALARMOUTTYPE = 1 << 18
TSINSEL = 1 << 17
TAMP1INSEL = 1 << 16
TAMPPUDIS = 1 << 15
TAMPPRCH = 0x3 << 13
TAMPFLT = 0x3 << 11
TAMPFREQ = 0x7 << 8
TAMPTS = 1 << 7
TAMP2TRG = 1 << 4
TAMP2E = 1 << 3
TAMPIE = 1 << 2
TAMP1TRG = 1 << 1
TAMP1E = 1 << 0
class RTC_ALRMASSR(IntEnum):
MASKSS = 0xf << 24
SS = 0x7fff << 0
MASKSS = 0xf << 24
SS = 0x7fff << 0
class RTC_ALRMBSSR(IntEnum):
MASKSS = 0xf << 24
SS = 0x7fff << 0
MASKSS = 0xf << 24
SS = 0x7fff << 0
+86 -86
View File
@@ -7,99 +7,99 @@ from enum import IntEnum
class SDIO_CLKCR(IntEnum):
CLKDIV = 0xff << 0
CLKEN = 1 << 8
PWRSAV = 1 << 9
BYPASS = 1 << 10
WIDBUS = 0x3 << 11
NEGEDGE = 1 << 13
HWFC_EN = 1 << 14
CLKDIV = 0xff << 0
CLKEN = 1 << 8
PWRSAV = 1 << 9
BYPASS = 1 << 10
WIDBUS = 0x3 << 11
NEGEDGE = 1 << 13
HWFC_EN = 1 << 14
class SDIO_CMD(IntEnum):
CMDINDEX = 0x3f << 0
WAITRESP = 0x3 << 6
WAITINT = 1 << 8
WAITPEND = 1 << 9
CPSMEN = 1 << 10
SDIOSUSPEND = 1 << 11
ENCMDCOMPL = 1 << 12
NIEN = 1 << 13
CEATACMD = 1 << 14
CMDINDEX = 0x3f << 0
WAITRESP = 0x3 << 6
WAITINT = 1 << 8
WAITPEND = 1 << 9
CPSMEN = 1 << 10
SDIOSUSPEND = 1 << 11
ENCMDCOMPL = 1 << 12
NIEN = 1 << 13
CEATACMD = 1 << 14
class SDIO_DCTRL(IntEnum):
DTEN = 1 << 0
DTDIR = 1 << 1
DTMODE = 1 << 2
DMAEN = 1 << 3
DBLOCKSIZE = 0xf << 4
RWSTART = 1 << 8
RWSTOP = 1 << 9
RWMOD = 1 << 10
SDIOEN = 1 << 11
DTEN = 1 << 0
DTDIR = 1 << 1
DTMODE = 1 << 2
DMAEN = 1 << 3
DBLOCKSIZE = 0xf << 4
RWSTART = 1 << 8
RWSTOP = 1 << 9
RWMOD = 1 << 10
SDIOEN = 1 << 11
class SDIO_STA(IntEnum):
CCRCFAIL = 1 << 0
DCRCFAIL = 1 << 1
CTIMEOUT = 1 << 2
DTIMEOUT = 1 << 3
TXUNDERR = 1 << 4
RXOVERR = 1 << 5
CMDREND = 1 << 6
CMDSENT = 1 << 7
DATAEND = 1 << 8
STBITERR = 1 << 9
DBCKEND = 1 << 10
CMDACT = 1 << 11
TXACT = 1 << 12
RXACT = 1 << 13
TXFIFOHE = 1 << 14
RXFIFOHF = 1 << 15
TXFIFOF = 1 << 16
RXFIFOF = 1 << 17
TXFIFOE = 1 << 18
RXFIFOE = 1 << 19
TXDAVL = 1 << 20
RXDAVL = 1 << 21
SDIOIT = 1 << 22
CEATAEND = 1 << 23
CCRCFAIL = 1 << 0
DCRCFAIL = 1 << 1
CTIMEOUT = 1 << 2
DTIMEOUT = 1 << 3
TXUNDERR = 1 << 4
RXOVERR = 1 << 5
CMDREND = 1 << 6
CMDSENT = 1 << 7
DATAEND = 1 << 8
STBITERR = 1 << 9
DBCKEND = 1 << 10
CMDACT = 1 << 11
TXACT = 1 << 12
RXACT = 1 << 13
TXFIFOHE = 1 << 14
RXFIFOHF = 1 << 15
TXFIFOF = 1 << 16
RXFIFOF = 1 << 17
TXFIFOE = 1 << 18
RXFIFOE = 1 << 19
TXDAVL = 1 << 20
RXDAVL = 1 << 21
SDIOIT = 1 << 22
CEATAEND = 1 << 23
class SDIO_ICR(IntEnum):
CCRCFAILC = 1 << 0
DCRCFAILC = 1 << 1
CTIMEOUTC = 1 << 2
DTIMEOUTC = 1 << 3
TXUNDERRC = 1 << 4
RXOVERRC = 1 << 5
CMDRENDC = 1 << 6
CMDSENTC = 1 << 7
DATAENDC = 1 << 8
STBITERRC = 1 << 9
DBCKENDC = 1 << 10
SDIOITC = 1 << 22
CEATAENDC = 1 << 23
CCRCFAILC = 1 << 0
DCRCFAILC = 1 << 1
CTIMEOUTC = 1 << 2
DTIMEOUTC = 1 << 3
TXUNDERRC = 1 << 4
RXOVERRC = 1 << 5
CMDRENDC = 1 << 6
CMDSENTC = 1 << 7
DATAENDC = 1 << 8
STBITERRC = 1 << 9
DBCKENDC = 1 << 10
SDIOITC = 1 << 22
CEATAENDC = 1 << 23
class SDIO_MASK(IntEnum):
CCRCFAILIE = 1 << 0
DCRCFAILIE = 1 << 1
CTIMEOUTIE = 1 << 2
DTIMEOUTIE = 1 << 3
TXUNDERRIE = 1 << 4
RXOVERRIE = 1 << 5
CMDRENDIE = 1 << 6
CMDSENTIE = 1 << 7
DATAENDIE = 1 << 8
STBITERRIE = 1 << 9
DBCKENDIE = 1 << 10
CMDACTIE = 1 << 11
TXACTIE = 1 << 12
RXACTIE = 1 << 13
TXFIFOHEIE = 1 << 14
RXFIFOHFIE = 1 << 15
TXFIFOFIE = 1 << 16
RXFIFOFIE = 1 << 17
TXFIFOEIE = 1 << 18
RXFIFOEIE = 1 << 19
TXDAVLIE = 1 << 20
RXDAVLIE = 1 << 21
SDIOITIE = 1 << 22
CEATAENDIE = 1 << 23
CCRCFAILIE = 1 << 0
DCRCFAILIE = 1 << 1
CTIMEOUTIE = 1 << 2
DTIMEOUTIE = 1 << 3
TXUNDERRIE = 1 << 4
RXOVERRIE = 1 << 5
CMDRENDIE = 1 << 6
CMDSENTIE = 1 << 7
DATAENDIE = 1 << 8
STBITERRIE = 1 << 9
DBCKENDIE = 1 << 10
CMDACTIE = 1 << 11
TXACTIE = 1 << 12
RXACTIE = 1 << 13
TXFIFOHEIE = 1 << 14
RXFIFOHFIE = 1 << 15
TXFIFOFIE = 1 << 16
RXFIFOFIE = 1 << 17
TXFIFOEIE = 1 << 18
RXFIFOEIE = 1 << 19
TXDAVLIE = 1 << 20
RXDAVLIE = 1 << 21
SDIOITIE = 1 << 22
CEATAENDIE = 1 << 23
+46 -46
View File
@@ -7,63 +7,63 @@ from enum import IntEnum
class SPI_CR1(IntEnum):
CPHA = 1 << 0
CPOL = 1 << 1
MSTR = 1 << 2
BR = 0x7 << 3
SPE = 1 << 6
LSBFIRST = 1 << 7
SSI = 1 << 8
SSM = 1 << 9
RXONLY = 1 << 10
DFF = 1 << 11
CRCNEXT = 1 << 12
CRCEN = 1 << 13
BIDIOE = 1 << 14
BIDIMODE = 1 << 15
CPHA = 1 << 0
CPOL = 1 << 1
MSTR = 1 << 2
BR = 0x7 << 3
SPE = 1 << 6
LSBFIRST = 1 << 7
SSI = 1 << 8
SSM = 1 << 9
RXONLY = 1 << 10
DFF = 1 << 11
CRCNEXT = 1 << 12
CRCEN = 1 << 13
BIDIOE = 1 << 14
BIDIMODE = 1 << 15
RW_MASK = 0xffff
RW_MASK = 0xffff
class SPI_CR2(IntEnum):
RXDMAEN = 1 << 0
TXDMAEN = 1 << 1
SSOE = 1 << 2
FRF = 1 << 4
ERRIE = 1 << 5
RXNEIE = 1 << 6
TXEIE = 1 << 7
RXDMAEN = 1 << 0
TXDMAEN = 1 << 1
SSOE = 1 << 2
FRF = 1 << 4
ERRIE = 1 << 5
RXNEIE = 1 << 6
TXEIE = 1 << 7
RW_MASK = RXDMAEN|TXDMAEN|SSOE|FRF|ERRIE|RXNEIE|TXEIE
RW_MASK = RXDMAEN|TXDMAEN|SSOE|FRF|ERRIE|RXNEIE|TXEIE
class SPI_SR(IntEnum):
RXNE = 1 << 0
TXE = 1 << 1
CHSIDE = 1 << 2
UDR = 1 << 3
CRCERR = 1 << 4
MODF = 1 << 5
OVR = 1 << 6
BSY = 1 << 7
FRE = 1 << 8
RXNE = 1 << 0
TXE = 1 << 1
CHSIDE = 1 << 2
UDR = 1 << 3
CRCERR = 1 << 4
MODF = 1 << 5
OVR = 1 << 6
BSY = 1 << 7
FRE = 1 << 8
class SPI_CRCPR(IntEnum):
CRCPOLY = 0xffff
CRCPOLY = 0xffff
class SPI_I2SCFGR(IntEnum):
CHLEN = 1 << 0
DATLEN = 0x3 << 1
CKPOL = 1 << 3
I2SSTD = 0x3 << 4
PCMSYNC = 1 << 7
I2SCFG = 0x3 << 8
I2SE = 1 << 10
I2SMOD = 1 << 11
CHLEN = 1 << 0
DATLEN = 0x3 << 1
CKPOL = 1 << 3
I2SSTD = 0x3 << 4
PCMSYNC = 1 << 7
I2SCFG = 0x3 << 8
I2SE = 1 << 10
I2SMOD = 1 << 11
RW_MASK = CHLEN|DATLEN|CKPOL|I2SSTD|PCMSYNC|I2SCFG|I2SE|I2SMOD
RW_MASK = CHLEN|DATLEN|CKPOL|I2SSTD|PCMSYNC|I2SCFG|I2SE|I2SMOD
class SPI_I2SPR(IntEnum):
I2SDIV = 0xff << 0
ODD = 1 << 8
MCKOE = 1 << 9
I2SDIV = 0xff << 0
ODD = 1 << 8
MCKOE = 1 << 9
RW_MASK = I2SDIV|ODD|MCKOE
RW_MASK = I2SDIV|ODD|MCKOE
+127 -127
View File
@@ -7,170 +7,170 @@ from enum import IntEnum
class TIM_CR1(IntEnum):
CEN = 1 << 0
UDIS = 1 << 1
URS = 1 << 2
OPM = 1 << 3
DIR = 1 << 4
CMS = 0x3 << 5
ARPE = 1 << 7
CKD = 0x3 << 8
CEN = 1 << 0
UDIS = 1 << 1
URS = 1 << 2
OPM = 1 << 3
DIR = 1 << 4
CMS = 0x3 << 5
ARPE = 1 << 7
CKD = 0x3 << 8
class TIM_CR2(IntEnum):
CCPC = 1 << 0
CCS = 1 << 2
CCDS = 1 << 3
MMS = 0x7 << 4
TI1S = 1 << 7
OIS1 = 1 << 8
OIS1N = 1 << 9
OIS2 = 1 << 10
OIS2N = 1 << 11
OIS3 = 1 << 12
OIS3N = 1 << 13
OIS4 = 1 << 14
CCPC = 1 << 0
CCS = 1 << 2
CCDS = 1 << 3
MMS = 0x7 << 4
TI1S = 1 << 7
OIS1 = 1 << 8
OIS1N = 1 << 9
OIS2 = 1 << 10
OIS2N = 1 << 11
OIS3 = 1 << 12
OIS3N = 1 << 13
OIS4 = 1 << 14
class TIM_SMCR(IntEnum):
SMS = 0x7 << 0
TS = 0x7 << 4
MSM = 1 << 7
ETF = 0xf << 8
ETPS = 0x3 << 12
ECE = 1 << 14
ETP = 1 << 15
SMS = 0x7 << 0
TS = 0x7 << 4
MSM = 1 << 7
ETF = 0xf << 8
ETPS = 0x3 << 12
ECE = 1 << 14
ETP = 1 << 15
class TIM_DIER(IntEnum):
UIE = 1 << 0
CC1IE = 1 << 1
CC2IE = 1 << 2
CC3IE = 1 << 3
CC4IE = 1 << 4
COMIE = 1 << 5
TIE = 1 << 6
BIE = 1 << 7
UDE = 1 << 8
CC1DE = 1 << 9
CC2DE = 1 << 10
CC3DE = 1 << 11
CC4DE = 1 << 12
COMDE = 1 << 13
TDE = 1 << 14
UIE = 1 << 0
CC1IE = 1 << 1
CC2IE = 1 << 2
CC3IE = 1 << 3
CC4IE = 1 << 4
COMIE = 1 << 5
TIE = 1 << 6
BIE = 1 << 7
UDE = 1 << 8
CC1DE = 1 << 9
CC2DE = 1 << 10
CC3DE = 1 << 11
CC4DE = 1 << 12
COMDE = 1 << 13
TDE = 1 << 14
class TIM_SR(IntEnum):
UIF = 1 << 0
CC1IF = 1 << 1
CC2IF = 1 << 2
CC3IF = 1 << 3
CC4IF = 1 << 4
COMIF = 1 << 5
TIF = 1 << 6
BIF = 1 << 7
CC1OF = 1 << 9
CC2OF = 1 << 10
CC3OF = 1 << 11
CC4OF = 1 << 12
UIF = 1 << 0
CC1IF = 1 << 1
CC2IF = 1 << 2
CC3IF = 1 << 3
CC4IF = 1 << 4
COMIF = 1 << 5
TIF = 1 << 6
BIF = 1 << 7
CC1OF = 1 << 9
CC2OF = 1 << 10
CC3OF = 1 << 11
CC4OF = 1 << 12
class TIM_EGR(IntEnum):
UG = 1 << 0
CC1G = 1 << 1
CC2G = 1 << 2
CC3G = 1 << 3
CC4G = 1 << 4
COMG = 1 << 5
TG = 1 << 6
BG = 1 << 7
UG = 1 << 0
CC1G = 1 << 1
CC2G = 1 << 2
CC3G = 1 << 3
CC4G = 1 << 4
COMG = 1 << 5
TG = 1 << 6
BG = 1 << 7
class TIM_CCMR1(IntEnum):
CC1S = 0x3 << 0
OC1FE = 1 << 2
OC1PE = 1 << 3
OC1M = 0x7 << 4
OC1CE = 1 << 7
CC2S = 0x3 << 8
OC2FE = 1 << 10
OC2PE = 1 << 11
OC2M = 0x7 << 12
OC2CE = 1 << 15
IC1PSC = 0x3 << 2
IC1F = 0xf << 4
IC2PSC = 0x3 << 10
IC2F = 0xf << 12
CC1S = 0x3 << 0
OC1FE = 1 << 2
OC1PE = 1 << 3
OC1M = 0x7 << 4
OC1CE = 1 << 7
CC2S = 0x3 << 8
OC2FE = 1 << 10
OC2PE = 1 << 11
OC2M = 0x7 << 12
OC2CE = 1 << 15
IC1PSC = 0x3 << 2
IC1F = 0xf << 4
IC2PSC = 0x3 << 10
IC2F = 0xf << 12
class TIM_CCMR2(IntEnum):
CC3S = 0x3 << 0
OC3FE = 1 << 2
OC3PE = 1 << 3
OC3M = 0x7 << 4
OC3CE = 1 << 7
CC4S = 0x3 << 8
OC4FE = 1 << 10
OC4PE = 1 << 11
OC4M = 0x7 << 12
OC4CE = 1 << 15
IC3PSC = 0x3 << 2
IC3F = 0xf << 4
IC4PSC = 0x3 << 10
IC4F = 0xf << 12
CC3S = 0x3 << 0
OC3FE = 1 << 2
OC3PE = 1 << 3
OC3M = 0x7 << 4
OC3CE = 1 << 7
CC4S = 0x3 << 8
OC4FE = 1 << 10
OC4PE = 1 << 11
OC4M = 0x7 << 12
OC4CE = 1 << 15
IC3PSC = 0x3 << 2
IC3F = 0xf << 4
IC4PSC = 0x3 << 10
IC4F = 0xf << 12
class TIM_CCER(IntEnum):
CC1E = 1 << 0
CC1P = 1 << 1
CC1NE = 1 << 2
CC1NP = 1 << 3
CC2E = 1 << 4
CC2P = 1 << 5
CC2NE = 1 << 6
CC2NP = 1 << 7
CC3E = 1 << 8
CC3P = 1 << 9
CC3NE = 1 << 10
CC3NP = 1 << 11
CC4E = 1 << 12
CC4P = 1 << 13
CC4NP = 1 << 15
CC1E = 1 << 0
CC1P = 1 << 1
CC1NE = 1 << 2
CC1NP = 1 << 3
CC2E = 1 << 4
CC2P = 1 << 5
CC2NE = 1 << 6
CC2NP = 1 << 7
CC3E = 1 << 8
CC3P = 1 << 9
CC3NE = 1 << 10
CC3NP = 1 << 11
CC4E = 1 << 12
CC4P = 1 << 13
CC4NP = 1 << 15
class TIM_CNT(IntEnum):
CNT = 0xffffffff << 0
CNT = 0xffffffff << 0
class TIM_PSC(IntEnum):
PSC = 0xffff << 0
PSC = 0xffff << 0
class TIM_ARR(IntEnum):
ARR = 0xffffffff << 0
ARR = 0xffffffff << 0
class TIM_RCR(IntEnum):
REP = 0xff << 0
REP = 0xff << 0
class TIM_CCR1(IntEnum):
CCR1 = 0xffff << 0
CCR1 = 0xffff << 0
class TIM_CCR2(IntEnum):
CCR2 = 0xffff << 0
CCR2 = 0xffff << 0
class TIM_CCR3(IntEnum):
CCR3 = 0xffff << 0
CCR3 = 0xffff << 0
class TIM_CCR4(IntEnum):
CCR4 = 0xffff << 0
CCR4 = 0xffff << 0
class TIM_BDTR(IntEnum):
DTG = 0xff << 0
LOCK = 0x3 << 8
OSSI = 1 << 10
OSSR = 1 << 11
BKE = 1 << 12
BKP = 1 << 13
AOE = 1 << 14
MOE = 1 << 15
DTG = 0xff << 0
LOCK = 0x3 << 8
OSSI = 1 << 10
OSSR = 1 << 11
BKE = 1 << 12
BKP = 1 << 13
AOE = 1 << 14
MOE = 1 << 15
class TIM_DCR(IntEnum):
DBA = 0x1f << 0
DBL = 0x1f << 8
DBA = 0x1f << 0
DBL = 0x1f << 8
class TIM_DMAR(IntEnum):
DMAB = 0xffff << 0
DMAB = 0xffff << 0
class TIM_OR(IntEnum):
TI1_RMP = 0x3 << 0
TI4_RMP = 0x3 << 6
ITR1_RMP = 0x3 << 10
TI1_RMP = 0x3 << 0
TI4_RMP = 0x3 << 6
ITR1_RMP = 0x3 << 10
+26 -26
View File
@@ -20,11 +20,11 @@ class USART_SR(IntEnum):
RESET = TXE | TC
class USART_DR(IntEnum):
DR = 0x1ff << 0
DR = 0x1ff << 0
class USART_BRR(IntEnum):
DIV_Fraction = 0xf << 0
DIV_Mantissa = 0xfff << 4
DIV_Fraction = 0xf << 0
DIV_Mantissa = 0xfff << 4
class USART_CR1(IntEnum):
OVER8 = 1 << 15
@@ -44,30 +44,30 @@ class USART_CR1(IntEnum):
SBK = 1 << 0
class USART_CR2(IntEnum):
ADD = 0xf << 0
LBDL = 1 << 5
LBDIE = 1 << 6
LBCL = 1 << 8
CPHA = 1 << 9
CPOL = 1 << 10
CLKEN = 1 << 11
STOP = 0x3 << 12
LINEN = 1 << 14
ADD = 0xf << 0
LBDL = 1 << 5
LBDIE = 1 << 6
LBCL = 1 << 8
CPHA = 1 << 9
CPOL = 1 << 10
CLKEN = 1 << 11
STOP = 0x3 << 12
LINEN = 1 << 14
class USART_CR3(IntEnum):
EIE = 1 << 0
IREN = 1 << 1
IRLP = 1 << 2
HDSEL = 1 << 3
NACK = 1 << 4
SCEN = 1 << 5
DMAR = 1 << 6
DMAT = 1 << 7
RTSE = 1 << 8
CTSE = 1 << 9
CTSIE = 1 << 10
ONEBIT = 1 << 11
EIE = 1 << 0
IREN = 1 << 1
IRLP = 1 << 2
HDSEL = 1 << 3
NACK = 1 << 4
SCEN = 1 << 5
DMAR = 1 << 6
DMAT = 1 << 7
RTSE = 1 << 8
CTSE = 1 << 9
CTSIE = 1 << 10
ONEBIT = 1 << 11
class USART_GTPR(IntEnum):
PSC = 0xff << 0
GT = 0xff << 8
PSC = 0xff << 0
GT = 0xff << 8
+155 -155
View File
@@ -27,12 +27,12 @@ class RCC_CR(IntEnum):
class RCC_PLLCFGR(IntEnum):
PLLM = 0x3f << 0
PLLN = 0x1ff << 6
PLLP = 0x3 << 16
PLLSRC = 1 << 22
PLLSRC_HSE = 1 << 22
PLLQ = 0xf << 24
PLLM = 0x3f << 0
PLLN = 0x1ff << 6
PLLP = 0x3 << 16
PLLSRC = 1 << 22
PLLSRC_HSE = 1 << 22
PLLQ = 0xf << 24
class RCC_CFGR(IntEnum):
@@ -56,186 +56,186 @@ class RCC_CFGR(IntEnum):
RW_MASK = SW | HPRE | PPRE1 | PPRE2 | MCO1 | I2SSCR | MCO1PRE | MCO2PRE | MCO2
class RCC_CIR(IntEnum):
LSIRDYF = 1 << 0
LSERDYF = 1 << 1
HSIRDYF = 1 << 2
HSERDYF = 1 << 3
PLLRDYF = 1 << 4
PLLI2SRDYF = 1 << 5
CSSF = 1 << 7
LSIRDYIE = 1 << 8
LSERDYIE = 1 << 9
HSIRDYIE = 1 << 10
HSERDYIE = 1 << 11
PLLRDYIE = 1 << 12
PLLI2SRDYIE = 1 << 13
LSIRDYC = 1 << 16
LSERDYC = 1 << 17
HSIRDYC = 1 << 18
HSERDYC = 1 << 19
PLLRDYC = 1 << 20
PLLI2SRDYC = 1 << 21
CSSC = 1 << 23
LSIRDYF = 1 << 0
LSERDYF = 1 << 1
HSIRDYF = 1 << 2
HSERDYF = 1 << 3
PLLRDYF = 1 << 4
PLLI2SRDYF = 1 << 5
CSSF = 1 << 7
LSIRDYIE = 1 << 8
LSERDYIE = 1 << 9
HSIRDYIE = 1 << 10
HSERDYIE = 1 << 11
PLLRDYIE = 1 << 12
PLLI2SRDYIE = 1 << 13
LSIRDYC = 1 << 16
LSERDYC = 1 << 17
HSIRDYC = 1 << 18
HSERDYC = 1 << 19
PLLRDYC = 1 << 20
PLLI2SRDYC = 1 << 21
CSSC = 1 << 23
class RCC_AHB1RSTR(IntEnum):
GPIOARST = 1 << 0
GPIOBRST = 1 << 1
GPIOCRST = 1 << 2
GPIODRST = 1 << 3
GPIOERST = 1 << 4
GPIOHRST = 1 << 7
CRCRST = 1 << 12
DMA1RST = 1 << 21
DMA2RST = 1 << 22
GPIOARST = 1 << 0
GPIOBRST = 1 << 1
GPIOCRST = 1 << 2
GPIODRST = 1 << 3
GPIOERST = 1 << 4
GPIOHRST = 1 << 7
CRCRST = 1 << 12
DMA1RST = 1 << 21
DMA2RST = 1 << 22
class RCC_AHB2RSTR(IntEnum):
OTGFSRST = 1 << 7
OTGFSRST = 1 << 7
class RCC_APB1RSTR(IntEnum):
TIM2RST = 1 << 0
TIM3RST = 1 << 1
TIM4RST = 1 << 2
TIM5RST = 1 << 3
WWDGRST = 1 << 11
SPI2RST = 1 << 14
SPI3RST = 1 << 15
USART2RST = 1 << 17
I2C1RST = 1 << 21
I2C2RST = 1 << 22
I2C3RST = 1 << 23
PWRRST = 1 << 28
TIM2RST = 1 << 0
TIM3RST = 1 << 1
TIM4RST = 1 << 2
TIM5RST = 1 << 3
WWDGRST = 1 << 11
SPI2RST = 1 << 14
SPI3RST = 1 << 15
USART2RST = 1 << 17
I2C1RST = 1 << 21
I2C2RST = 1 << 22
I2C3RST = 1 << 23
PWRRST = 1 << 28
class RCC_APB2RSTR(IntEnum):
TIM1RST = 1 << 0
USART1RST = 1 << 4
USART6RST = 1 << 5
ADCRST = 1 << 8
SDIORST = 1 << 11
SPI1RST = 1 << 12
SPI4RST = 1 << 13
SYSCFGRST = 1 << 14
TIM9RST = 1 << 16
TIM10RST = 1 << 17
TIM11RST = 1 << 18
SPI5RST = 1 << 20
TIM1RST = 1 << 0
USART1RST = 1 << 4
USART6RST = 1 << 5
ADCRST = 1 << 8
SDIORST = 1 << 11
SPI1RST = 1 << 12
SPI4RST = 1 << 13
SYSCFGRST = 1 << 14
TIM9RST = 1 << 16
TIM10RST = 1 << 17
TIM11RST = 1 << 18
SPI5RST = 1 << 20
class RCC_AHB1ENR(IntEnum):
GPIOAEN = 1 << 0
GPIOBEN = 1 << 1
GPIOCEN = 1 << 2
GPIODEN = 1 << 3
GPIOEEN = 1 << 4
GPIOHEN = 1 << 7
CRCEN = 1 << 12
DMA1EN = 1 << 21
DMA2EN = 1 << 22
GPIOAEN = 1 << 0
GPIOBEN = 1 << 1
GPIOCEN = 1 << 2
GPIODEN = 1 << 3
GPIOEEN = 1 << 4
GPIOHEN = 1 << 7
CRCEN = 1 << 12
DMA1EN = 1 << 21
DMA2EN = 1 << 22
class RCC_AHB2ENR(IntEnum):
OTGFSEN = 1 << 7
OTGFSEN = 1 << 7
class RCC_APB1ENR(IntEnum):
TIM2EN = 1 << 0
TIM3EN = 1 << 1
TIM4EN = 1 << 2
TIM5EN = 1 << 3
WWDGEN = 1 << 11
SPI2EN = 1 << 14
SPI3EN = 1 << 15
USART2EN = 1 << 17
I2C1EN = 1 << 21
I2C2EN = 1 << 22
I2C3EN = 1 << 23
PWREN = 1 << 28
TIM2EN = 1 << 0
TIM3EN = 1 << 1
TIM4EN = 1 << 2
TIM5EN = 1 << 3
WWDGEN = 1 << 11
SPI2EN = 1 << 14
SPI3EN = 1 << 15
USART2EN = 1 << 17
I2C1EN = 1 << 21
I2C2EN = 1 << 22
I2C3EN = 1 << 23
PWREN = 1 << 28
class RCC_APB2ENR(IntEnum):
TIM1EN = 1 << 0
USART1EN = 1 << 4
USART6EN = 1 << 5
ADC1EN = 1 << 8
SDIOEN = 1 << 11
SPI1EN = 1 << 12
SPI4EN = 1 << 13
SYSCFGEN = 1 << 14
TIM9EN = 1 << 16
TIM10EN = 1 << 17
TIM11EN = 1 << 18
SPI5EN = 1 << 20
TIM1EN = 1 << 0
USART1EN = 1 << 4
USART6EN = 1 << 5
ADC1EN = 1 << 8
SDIOEN = 1 << 11
SPI1EN = 1 << 12
SPI4EN = 1 << 13
SYSCFGEN = 1 << 14
TIM9EN = 1 << 16
TIM10EN = 1 << 17
TIM11EN = 1 << 18
SPI5EN = 1 << 20
class RCC_AHB1LPENR(IntEnum):
GPIOALPEN = 1 << 0
GPIOBLPEN = 1 << 1
GPIOCLPEN = 1 << 2
GPIODLPEN = 1 << 3
GPIOELPEN = 1 << 4
GPIOHLPEN = 1 << 7
CRCLPEN = 1 << 12
FLITFLPEN = 1 << 15
SRAM1LPEN = 1 << 16
DMA1LPEN = 1 << 21
DMA2LPEN = 1 << 22
GPIOALPEN = 1 << 0
GPIOBLPEN = 1 << 1
GPIOCLPEN = 1 << 2
GPIODLPEN = 1 << 3
GPIOELPEN = 1 << 4
GPIOHLPEN = 1 << 7
CRCLPEN = 1 << 12
FLITFLPEN = 1 << 15
SRAM1LPEN = 1 << 16
DMA1LPEN = 1 << 21
DMA2LPEN = 1 << 22
class RCC_AHB2LPENR(IntEnum):
OTGFSLPEN = 1 << 7
OTGFSLPEN = 1 << 7
class RCC_APB1LPENR(IntEnum):
TIM2LPEN = 1 << 0
TIM3LPEN = 1 << 1
TIM4LPEN = 1 << 2
TIM5LPEN = 1 << 3
WWDGLPEN = 1 << 11
SPI2LPEN = 1 << 14
SPI3LPEN = 1 << 15
USART2LPEN = 1 << 17
I2C1LPEN = 1 << 21
I2C2LPEN = 1 << 22
I2C3LPEN = 1 << 23
PWRLPEN = 1 << 28
TIM2LPEN = 1 << 0
TIM3LPEN = 1 << 1
TIM4LPEN = 1 << 2
TIM5LPEN = 1 << 3
WWDGLPEN = 1 << 11
SPI2LPEN = 1 << 14
SPI3LPEN = 1 << 15
USART2LPEN = 1 << 17
I2C1LPEN = 1 << 21
I2C2LPEN = 1 << 22
I2C3LPEN = 1 << 23
PWRLPEN = 1 << 28
class RCC_APB2LPENR(IntEnum):
TIM1LPEN = 1 << 0
USART1LPEN = 1 << 4
USART6LPEN = 1 << 5
ADC1LPEN = 1 << 8
SDIOLPEN = 1 << 11
SPI1LPEN = 1 << 12
SPI4LPEN = 1 << 13
SYSCFGLPEN = 1 << 14
TIM9LPEN = 1 << 16
TIM10LPEN = 1 << 17
TIM11LPEN = 1 << 18
SPI5LPEN = 1 << 20
TIM1LPEN = 1 << 0
USART1LPEN = 1 << 4
USART6LPEN = 1 << 5
ADC1LPEN = 1 << 8
SDIOLPEN = 1 << 11
SPI1LPEN = 1 << 12
SPI4LPEN = 1 << 13
SYSCFGLPEN = 1 << 14
TIM9LPEN = 1 << 16
TIM10LPEN = 1 << 17
TIM11LPEN = 1 << 18
SPI5LPEN = 1 << 20
class RCC_BDCR(IntEnum):
LSEON = 1 << 0
LSERDY = 1 << 1
LSEBYP = 1 << 2
LSEMOD = 1 << 3
RTCSEL = 0x3 << 8
RTCEN = 1 << 15
BDRST = 1 << 16
LSEON = 1 << 0
LSERDY = 1 << 1
LSEBYP = 1 << 2
LSEMOD = 1 << 3
RTCSEL = 0x3 << 8
RTCEN = 1 << 15
BDRST = 1 << 16
class RCC_CSR(IntEnum):
LSION = 1 << 0
LSIRDY = 1 << 1
RMVF = 1 << 24
BORRSTF = 1 << 25
PINRSTF = 1 << 26
PORRSTF = 1 << 27
SFTRSTF = 1 << 28
IWDGRSTF = 1 << 29
WWDGRSTF = 1 << 30
LPWRRSTF = 1 << 31
LSION = 1 << 0
LSIRDY = 1 << 1
RMVF = 1 << 24
BORRSTF = 1 << 25
PINRSTF = 1 << 26
PORRSTF = 1 << 27
SFTRSTF = 1 << 28
IWDGRSTF = 1 << 29
WWDGRSTF = 1 << 30
LPWRRSTF = 1 << 31
class RCC_SSCGR(IntEnum):
MODPER = 0x1fff << 0
INCSTEP = 0x7fff << 13
SPREADSEL = 1 << 30
SSCGEN = 1 << 31
MODPER = 0x1fff << 0
INCSTEP = 0x7fff << 13
SPREADSEL = 1 << 30
SSCGEN = 1 << 31
class RCC_PLLI2SCFGR(IntEnum):
PLLI2SM = 0x3f << 0
PLLI2SN = 0x1ff << 6
PLLI2SR = 0x7 << 28
PLLI2SM = 0x3f << 0
PLLI2SN = 0x1ff << 6
PLLI2SR = 0x7 << 28
class RCC_DCKCFGR(IntEnum):
TIMPRE = 1 << 24
TIMPRE = 1 << 24
+28 -28
View File
@@ -69,36 +69,36 @@ class Stream(ctypes.Structure):
class STM32F4xxDma(QlPeripheral):
class Type(ctypes.Structure):
""" the structure available in :
stm32f413xx.h
stm32f407xx.h
stm32f469xx.h
stm32f446xx.h
stm32f427xx.h
stm32f401xc.h
stm32f415xx.h
stm32f412cx.h
stm32f410rx.h
stm32f410tx.h
stm32f439xx.h
stm32f412vx.h
stm32f417xx.h
stm32f479xx.h
stm32f429xx.h
stm32f412rx.h
stm32f423xx.h
stm32f437xx.h
stm32f412zx.h
stm32f401xe.h
stm32f410cx.h
stm32f405xx.h
stm32f411xe.h
"""
stm32f413xx.h
stm32f407xx.h
stm32f469xx.h
stm32f446xx.h
stm32f427xx.h
stm32f401xc.h
stm32f415xx.h
stm32f412cx.h
stm32f410rx.h
stm32f410tx.h
stm32f439xx.h
stm32f412vx.h
stm32f417xx.h
stm32f479xx.h
stm32f429xx.h
stm32f412rx.h
stm32f423xx.h
stm32f437xx.h
stm32f412zx.h
stm32f401xe.h
stm32f410cx.h
stm32f405xx.h
stm32f411xe.h
"""
_fields_ = [
('LISR' , ctypes.c_uint32), # DMA low interrupt status register, Address offset: 0x00
('HISR' , ctypes.c_uint32), # DMA high interrupt status register, Address offset: 0x04
('LIFCR', ctypes.c_uint32), # DMA low interrupt flag clear register, Address offset: 0x08
('HIFCR', ctypes.c_uint32), # DMA high interrupt flag clear register, Address offset: 0x0C
('LISR' , ctypes.c_uint32), # DMA low interrupt status register, Address offset: 0x00
('HISR' , ctypes.c_uint32), # DMA high interrupt status register, Address offset: 0x04
('LIFCR', ctypes.c_uint32), # DMA low interrupt flag clear register, Address offset: 0x08
('HIFCR', ctypes.c_uint32), # DMA high interrupt flag clear register, Address offset: 0x0C
('stream', Stream * 8),
]
+1 -1
View File
@@ -43,7 +43,7 @@ class STM32F1xxFlash(QlPeripheral):
self.instance = self.struct()
@QlPeripheral.monitor()
def read(self, offset: int, size: int) -> int:
def read(self, offset: int, size: int) -> int:
buf = ctypes.create_string_buffer(size)
ctypes.memmove(buf, ctypes.addressof(self.instance) + offset, size)
return int.from_bytes(buf.raw, byteorder='little')
+1 -1
View File
@@ -55,7 +55,7 @@ class STM32F4xxFlash(QlPeripheral):
self.instance = self.struct()
@QlPeripheral.monitor()
def read(self, offset: int, size: int) -> int:
def read(self, offset: int, size: int) -> int:
buf = ctypes.create_string_buffer(size)
ctypes.memmove(buf, ctypes.addressof(self.instance) + offset, size)
return int.from_bytes(buf.raw, byteorder='little')
+1 -1
View File
@@ -39,7 +39,7 @@ class GD32VF1xxGpio(QlPeripheral, GpioHooks):
)
@QlPeripheral.monitor()
def read(self, offset: int, size: int) -> int:
def read(self, offset: int, size: int) -> int:
buf = ctypes.create_string_buffer(size)
ctypes.memmove(buf, ctypes.addressof(self.instance) + offset, size)
return int.from_bytes(buf.raw, byteorder='little')
+1 -1
View File
@@ -38,7 +38,7 @@ class STM32F1xxAfio(QlPeripheral):
self.instance = self.struct()
@QlPeripheral.monitor()
def read(self, offset: int, size: int) -> int:
def read(self, offset: int, size: int) -> int:
buf = ctypes.create_string_buffer(size)
ctypes.memmove(buf, ctypes.addressof(self.instance) + offset, size)
return int.from_bytes(buf.raw, byteorder='little')
+1 -1
View File
@@ -36,7 +36,7 @@ class STM32F4xxGpio(STM32F1xxGpio):
stm32f410cx.h
stm32f405xx.h
stm32f411xe.h
"""
"""
_fields_ = [
('MODER' , ctypes.c_uint32), # GPIO port mode register, Address offset: 0x00
+187 -187
View File
@@ -13,226 +13,226 @@ from qiling.hw.utils.access import Access, AccessSequence, Action
class STM32F4xxI2c(QlConnectivityPeripheral):
class Type(ctypes.Structure):
""" the structure is available in :
stm32f423xx.h
stm32f469xx.h
stm32f427xx.h
stm32f479xx.h
stm32f413xx.h
stm32f429xx.h
stm32f439xx.h
stm32f412cx.h
stm32f412rx.h
stm32f410tx.h
stm32f410cx.h
stm32f412zx.h
stm32f446xx.h
stm32f401xc.h
stm32f437xx.h
stm32f401xe.h
stm32f412vx.h
stm32f410rx.h
stm32f411xe.h
"""
class Type(ctypes.Structure):
""" the structure is available in :
stm32f423xx.h
stm32f469xx.h
stm32f427xx.h
stm32f479xx.h
stm32f413xx.h
stm32f429xx.h
stm32f439xx.h
stm32f412cx.h
stm32f412rx.h
stm32f410tx.h
stm32f410cx.h
stm32f412zx.h
stm32f446xx.h
stm32f401xc.h
stm32f437xx.h
stm32f401xe.h
stm32f412vx.h
stm32f410rx.h
stm32f411xe.h
"""
_fields_ = [
('CR1' , ctypes.c_uint32), # I2C Control register 1, Address offset: 0x00
('CR2' , ctypes.c_uint32), # I2C Control register 2, Address offset: 0x04
('OAR1' , ctypes.c_uint32), # I2C Own address register 1, Address offset: 0x08
('OAR2' , ctypes.c_uint32), # I2C Own address register 2, Address offset: 0x0C
('DR' , ctypes.c_uint32), # I2C Data register, Address offset: 0x10
('SR1' , ctypes.c_uint32), # I2C Status register 1, Address offset: 0x14
('SR2' , ctypes.c_uint32), # I2C Status register 2, Address offset: 0x18
('CCR' , ctypes.c_uint32), # I2C Clock control register, Address offset: 0x1C
('TRISE', ctypes.c_uint32), # I2C TRISE register, Address offset: 0x20
('FLTR' , ctypes.c_uint32), # I2C FLTR register, Address offset: 0x24
]
_fields_ = [
('CR1' , ctypes.c_uint32), # I2C Control register 1, Address offset: 0x00
('CR2' , ctypes.c_uint32), # I2C Control register 2, Address offset: 0x04
('OAR1' , ctypes.c_uint32), # I2C Own address register 1, Address offset: 0x08
('OAR2' , ctypes.c_uint32), # I2C Own address register 2, Address offset: 0x0C
('DR' , ctypes.c_uint32), # I2C Data register, Address offset: 0x10
('SR1' , ctypes.c_uint32), # I2C Status register 1, Address offset: 0x14
('SR2' , ctypes.c_uint32), # I2C Status register 2, Address offset: 0x18
('CCR' , ctypes.c_uint32), # I2C Clock control register, Address offset: 0x1C
('TRISE', ctypes.c_uint32), # I2C TRISE register, Address offset: 0x20
('FLTR' , ctypes.c_uint32), # I2C FLTR register, Address offset: 0x24
]
def __init__(self, ql, label, ev_intn=None, er_intn=None):
super().__init__(ql, label, 2)
def __init__(self, ql, label, ev_intn=None, er_intn=None):
super().__init__(ql, label, 2)
self.history = AccessSequence()
self.history = AccessSequence()
self.ev_intn = ev_intn # event interrupt
self.er_intn = er_intn # error interrupt
self.reset()
self.ev_intn = ev_intn # event interrupt
self.er_intn = er_intn # error interrupt
self.reset()
def reset(self):
self.instance = self.struct(
TRISE = 0x0002
)
def reset(self):
self.instance = self.struct(
TRISE = 0x0002
)
@QlPeripheral.recorder()
@QlPeripheral.monitor()
def read(self, offset: int, size: int) -> int:
buf = ctypes.create_string_buffer(size)
ctypes.memmove(buf, ctypes.addressof(self.instance) + offset, size)
@QlPeripheral.recorder()
@QlPeripheral.monitor()
def read(self, offset: int, size: int) -> int:
buf = ctypes.create_string_buffer(size)
ctypes.memmove(buf, ctypes.addressof(self.instance) + offset, size)
if self.history.match([
Access(Action.READ, self.struct.SR1.offset),
Access(Action.READ, self.struct.SR2.offset)
]):
self.instance.SR1 &= ~I2C_SR1.ADDR
if self.history.match([
Access(Action.READ, self.struct.SR1.offset),
Access(Action.READ, self.struct.SR2.offset)
]):
self.instance.SR1 &= ~I2C_SR1.ADDR
return int.from_bytes(buf.raw, byteorder='little')
return int.from_bytes(buf.raw, byteorder='little')
@QlPeripheral.recorder()
@QlPeripheral.monitor()
def write(self, offset: int, size: int, value: int):
if offset in [self.struct.SR1.offset, self.struct.SR2.offset]:
return
@QlPeripheral.recorder()
@QlPeripheral.monitor()
def write(self, offset: int, size: int, value: int):
if offset in [self.struct.SR1.offset, self.struct.SR2.offset]:
return
if offset == self.struct.CR1.offset:
self.instance.CR1 = value & I2C_CR1.RW_MASK
if offset == self.struct.CR1.offset:
self.instance.CR1 = value & I2C_CR1.RW_MASK
if value & I2C_CR1.START:
self.generate_start()
if value & I2C_CR1.START:
self.generate_start()
if value & I2C_CR1.STOP:
self.generate_stop()
if value & I2C_CR1.STOP:
self.generate_stop()
return
return
if offset == self.struct.DR.offset:
self.instance.DR = value & I2C_DR.DR
self.instance.SR1 &= ~I2C_SR1.TXE
if offset == self.struct.DR.offset:
self.instance.DR = value & I2C_DR.DR
self.instance.SR1 &= ~I2C_SR1.TXE
if self.is_master_mode():
if self.is_7bit_mode():
if self.instance.SR2 & I2C_SR2.TRA:
self.send_data()
if self.is_master_mode():
if self.is_7bit_mode():
if self.instance.SR2 & I2C_SR2.TRA:
self.send_data()
else:
self.send_address()
else:
self.send_address()
# TODO 10-bit mode
# TODO 10-bit mode
return
return
data = (value).to_bytes(size, 'little')
ctypes.memmove(ctypes.addressof(self.instance) + offset, data, size)
data = (value).to_bytes(size, 'little')
ctypes.memmove(ctypes.addressof(self.instance) + offset, data, size)
## I2C Control register 2 (I2C_CR2)
def send_event_interrupt(self):
"""
ITBUFEN: Buffer interrupt enable
0: TxE = 1 or RxNE = 1 does not generate any interrupt.
1: TxE = 1 or RxNE = 1 generates Event Interrupt (whatever the state of DMAEN)
## I2C Control register 2 (I2C_CR2)
def send_event_interrupt(self):
"""
ITBUFEN: Buffer interrupt enable
0: TxE = 1 or RxNE = 1 does not generate any interrupt.
1: TxE = 1 or RxNE = 1 generates Event Interrupt (whatever the state of DMAEN)
ITEVTEN: Event interrupt enable
0: Event interrupt disabled
1: Event interrupt enabled
This interrupt is generated when:
- SB = 1 (Master)
- ADDR = 1 (Master/Slave)
- ADD10= 1 (Master)
- STOPF = 1 (Slave)
- BTF = 1 with no TxE or RxNE event
- TxE event to 1 if ITBUFEN = 1
- RxNE event to 1if ITBUFEN = 1
"""
if self.ev_intn is None:
return
if not self.instance.CR2 & I2C_CR2.ITEVTEN:
return
ITEVTEN: Event interrupt enable
0: Event interrupt disabled
1: Event interrupt enabled
This interrupt is generated when:
- SB = 1 (Master)
- ADDR = 1 (Master/Slave)
- ADD10= 1 (Master)
- STOPF = 1 (Slave)
- BTF = 1 with no TxE or RxNE event
- TxE event to 1 if ITBUFEN = 1
- RxNE event to 1if ITBUFEN = 1
"""
if self.ev_intn is None:
return
if not self.instance.CR2 & I2C_CR2.ITEVTEN:
return
BUF_IT = I2C_SR1.TXE|I2C_SR1.RXNE
SLAVE_IT = I2C_SR1.STOPF|I2C_SR1.ADDR|I2C_SR1.BTF
MASTER_IT = I2C_SR1.SB|I2C_SR1.ADDR|I2C_SR1.ADD10|I2C_SR1.BTF
BUF_IT = I2C_SR1.TXE|I2C_SR1.RXNE
SLAVE_IT = I2C_SR1.STOPF|I2C_SR1.ADDR|I2C_SR1.BTF
MASTER_IT = I2C_SR1.SB|I2C_SR1.ADDR|I2C_SR1.ADD10|I2C_SR1.BTF
if (self.instance.CR2 & I2C_CR2.ITBUFEN and self.instance.SR1 & BUF_IT) or \
(self.is_slave_mode() and self.instance.SR1 & SLAVE_IT) or \
(self.is_master_mode() and self.instance.SR1 & MASTER_IT):
self.ql.hw.nvic.set_pending(self.ev_intn)
if (self.instance.CR2 & I2C_CR2.ITBUFEN and self.instance.SR1 & BUF_IT) or \
(self.is_slave_mode() and self.instance.SR1 & SLAVE_IT) or \
(self.is_master_mode() and self.instance.SR1 & MASTER_IT):
self.ql.hw.nvic.set_pending(self.ev_intn)
## I2C Status register 1 (I2C_SR1)
def generate_start(self):
"""
SB: Start bit (Master mode)
0: No Start condition
1: Start condition generated.
- Set when a Start condition generated.
- Cleared by software by reading the SR1 register followed by writing the DR register, or by hardware when PE=0
"""
## I2C Status register 1 (I2C_SR1)
def generate_start(self):
"""
SB: Start bit (Master mode)
0: No Start condition
1: Start condition generated.
- Set when a Start condition generated.
- Cleared by software by reading the SR1 register followed by writing the DR register, or by hardware when PE=0
"""
# TODO: generate a start condition
self.fetch_device_address()
self.instance.SR1 |= I2C_SR1.SB
self.instance.CR1 &= ~I2C_CR1.START
# TODO: generate a start condition
self.fetch_device_address()
self.instance.SR1 |= I2C_SR1.SB
self.instance.CR1 &= ~I2C_CR1.START
self.set_master_mode()
self.set_master_mode()
def generate_stop(self):
# TODO: generate a stop condition
self.instance.CR1 &= ~I2C_CR1.STOP
self.instance.SR1 |= I2C_SR1.STOPF
self.instance.SR1 &= ~I2C_SR1.ADDR
self.set_slave_mode()
self.instance.SR2 &= ~I2C_SR2.TRA
def send_address(self):
if self.instance.DR == self.instance.OAR1 >> 1:
# TODO: send ACK
self.instance.SR1 &= ~I2C_SR1.SB
self.instance.SR1 |= I2C_SR1.ADDR | I2C_SR1.TXE | I2C_SR1.AF
self.instance.SR2 |= I2C_SR2.TRA
def generate_stop(self):
# TODO: generate a stop condition
self.instance.CR1 &= ~I2C_CR1.STOP
self.instance.SR1 |= I2C_SR1.STOPF
self.instance.SR1 &= ~I2C_SR1.ADDR
self.set_slave_mode()
self.instance.SR2 &= ~I2C_SR2.TRA
def send_address(self):
if self.instance.DR == self.instance.OAR1 >> 1:
# TODO: send ACK
self.instance.SR1 &= ~I2C_SR1.SB
self.instance.SR1 |= I2C_SR1.ADDR | I2C_SR1.TXE | I2C_SR1.AF
self.instance.SR2 |= I2C_SR2.TRA
def send_data(self):
self.instance.SR1 |= I2C_SR1.BTF | I2C_SR1.TXE
def send_data(self):
self.instance.SR1 |= I2C_SR1.BTF | I2C_SR1.TXE
self.send_to_user(self.instance.DR)
self.send_to_user(self.instance.DR)
## I2C Status register 2 (I2C_SR2)
def is_master_mode(self):
"""
I2C Status register 2 (I2C_SR2) MSL bit
0: Slave Mode
1: Master Mode
"""
return self.instance.SR2 & I2C_SR2.MSL
## I2C Status register 2 (I2C_SR2)
def is_master_mode(self):
"""
I2C Status register 2 (I2C_SR2) MSL bit
0: Slave Mode
1: Master Mode
"""
return self.instance.SR2 & I2C_SR2.MSL
def is_slave_mode(self):
return not self.is_master_mode()
def is_slave_mode(self):
return not self.is_master_mode()
def set_master_mode(self):
"""
I2C Status register 2 (I2C_SR2) MSL bit
- Set by hardware as soon as the interface is in Master mode (SB=1)
"""
self.instance.SR2 |= I2C_SR2.MSL
def set_slave_mode(self):
"""
I2C Status register 2 (I2C_SR2) MSL bit
- Cleared by hardware after detecting a Stop condition on the bus
or a loss of arbitration (ARLO=1), or by hardware when PE=0.
"""
self.instance.SR2 &= ~I2C_SR2.MSL
def set_master_mode(self):
"""
I2C Status register 2 (I2C_SR2) MSL bit
- Set by hardware as soon as the interface is in Master mode (SB=1)
"""
self.instance.SR2 |= I2C_SR2.MSL
def set_slave_mode(self):
"""
I2C Status register 2 (I2C_SR2) MSL bit
- Cleared by hardware after detecting a Stop condition on the bus
or a loss of arbitration (ARLO=1), or by hardware when PE=0.
"""
self.instance.SR2 &= ~I2C_SR2.MSL
## I2C Own address register 1 (I2C_OAR1)
def is_7bit_mode(self):
return self.instance.OAR2 & I2C_OAR2.ENDUAL or not self.instance.OAR1 & I2C_OAR1.ADDMODE
## I2C Own address register 1 (I2C_OAR1)
def is_7bit_mode(self):
return self.instance.OAR2 & I2C_OAR2.ENDUAL or not self.instance.OAR1 & I2C_OAR1.ADDMODE
def fetch_device_address(self):
# dual addressing mode
if self.instance.OAR2 & I2C_OAR2.ENDUAL:
self.instance.OAR1 = self.device_list[0].address << 1
self.instance.OAR2 = I2C_OAR2.ENDUAL | (self.device_list[1].address << 1)
def fetch_device_address(self):
# dual addressing mode
if self.instance.OAR2 & I2C_OAR2.ENDUAL:
self.instance.OAR1 = self.device_list[0].address << 1
self.instance.OAR2 = I2C_OAR2.ENDUAL | (self.device_list[1].address << 1)
# single device, 10-bit slave address
elif self.instance.OAR1 & I2C_OAR1.ADDMODE:
self.instance.OAR1 = I2C_OAR1.ADDMODE | self.device_list[0].address
# single device, 7-bit slave address
else:
self.instance.OAR1 = self.device_list[0].address << 1
# single device, 10-bit slave address
elif self.instance.OAR1 & I2C_OAR1.ADDMODE:
self.instance.OAR1 = I2C_OAR1.ADDMODE | self.device_list[0].address
# single device, 7-bit slave address
else:
self.instance.OAR1 = self.device_list[0].address << 1
@QlConnectivityPeripheral.device_handler
def step(self):
self.send_event_interrupt()
@QlConnectivityPeripheral.device_handler
def step(self):
self.send_event_interrupt()
+1 -1
View File
@@ -725,7 +725,7 @@ class GD32VF1xxEclic(QlPeripheral):
)
@QlPeripheral.monitor()
def read(self, offset: int, size: int) -> int:
def read(self, offset: int, size: int) -> int:
buf = ctypes.create_string_buffer(size)
ctypes.memmove(buf, ctypes.addressof(self.instance) + offset, size)
return int.from_bytes(buf.raw, byteorder='little')
+1 -1
View File
@@ -53,7 +53,7 @@ class STM32F1xxExti(QlPeripheral):
]
@QlPeripheral.monitor()
def read(self, offset: int, size: int) -> int:
def read(self, offset: int, size: int) -> int:
buf = ctypes.create_string_buffer(size)
ctypes.memmove(buf, ctypes.addressof(self.instance) + offset, size)
return int.from_bytes(buf.raw, byteorder='little')
+30 -30
View File
@@ -10,36 +10,36 @@ from qiling.hw.peripheral import QlPeripheral
class STM32F4xxExti(QlPeripheral):
class Type(ctypes.Structure):
""" the structure available in :
stm32f413xx.h
stm32f407xx.h
stm32f469xx.h
stm32f446xx.h
stm32f427xx.h
stm32f401xc.h
stm32f415xx.h
stm32f412cx.h
stm32f410rx.h
stm32f410tx.h
stm32f439xx.h
stm32f412vx.h
stm32f417xx.h
stm32f479xx.h
stm32f429xx.h
stm32f412rx.h
stm32f423xx.h
stm32f437xx.h
stm32f412zx.h
stm32f401xe.h
stm32f410cx.h
stm32f405xx.h
stm32f411xe.h
"""
stm32f413xx.h
stm32f407xx.h
stm32f469xx.h
stm32f446xx.h
stm32f427xx.h
stm32f401xc.h
stm32f415xx.h
stm32f412cx.h
stm32f410rx.h
stm32f410tx.h
stm32f439xx.h
stm32f412vx.h
stm32f417xx.h
stm32f479xx.h
stm32f429xx.h
stm32f412rx.h
stm32f423xx.h
stm32f437xx.h
stm32f412zx.h
stm32f401xe.h
stm32f410cx.h
stm32f405xx.h
stm32f411xe.h
"""
_fields_ = [
('IMR' , ctypes.c_uint32), # EXTI Interrupt mask register, Address offset: 0x00
('EMR' , ctypes.c_uint32), # EXTI Event mask register, Address offset: 0x04
('RTSR' , ctypes.c_uint32), # EXTI Rising trigger selection register, Address offset: 0x08
('FTSR' , ctypes.c_uint32), # EXTI Falling trigger selection register, Address offset: 0x0C
('SWIER', ctypes.c_uint32), # EXTI Software interrupt event register, Address offset: 0x10
('PR' , ctypes.c_uint32), # EXTI Pending register, Address offset: 0x14
('IMR' , ctypes.c_uint32), # EXTI Interrupt mask register, Address offset: 0x00
('EMR' , ctypes.c_uint32), # EXTI Event mask register, Address offset: 0x04
('RTSR' , ctypes.c_uint32), # EXTI Rising trigger selection register, Address offset: 0x08
('FTSR' , ctypes.c_uint32), # EXTI Falling trigger selection register, Address offset: 0x0C
('SWIER', ctypes.c_uint32), # EXTI Software interrupt event register, Address offset: 0x10
('PR' , ctypes.c_uint32), # EXTI Pending register, Address offset: 0x14
]
+57 -57
View File
@@ -8,68 +8,68 @@ from qiling.hw.peripheral import QlPeripheral
class STM32F4xxCrc(QlPeripheral):
class Type(ctypes.Structure):
""" the structure available in :
stm32f413xx.h
stm32f407xx.h
stm32f469xx.h
stm32f446xx.h
stm32f427xx.h
stm32f401xc.h
stm32f415xx.h
stm32f412cx.h
stm32f410rx.h
stm32f410tx.h
stm32f439xx.h
stm32f412vx.h
stm32f417xx.h
stm32f479xx.h
stm32f429xx.h
stm32f412rx.h
stm32f423xx.h
stm32f437xx.h
stm32f412zx.h
stm32f401xe.h
stm32f410cx.h
stm32f405xx.h
stm32f411xe.h
"""
class Type(ctypes.Structure):
""" the structure available in :
stm32f413xx.h
stm32f407xx.h
stm32f469xx.h
stm32f446xx.h
stm32f427xx.h
stm32f401xc.h
stm32f415xx.h
stm32f412cx.h
stm32f410rx.h
stm32f410tx.h
stm32f439xx.h
stm32f412vx.h
stm32f417xx.h
stm32f479xx.h
stm32f429xx.h
stm32f412rx.h
stm32f423xx.h
stm32f437xx.h
stm32f412zx.h
stm32f401xe.h
stm32f410cx.h
stm32f405xx.h
stm32f411xe.h
"""
_fields_ = [
('DR' , ctypes.c_uint32), # CRC Data register, Address offset: 0x00
('IDR' , ctypes.c_uint8), # CRC Independent data register, Address offset: 0x04
('RESERVED0', ctypes.c_uint8), # Reserved, 0x05
('RESERVED1', ctypes.c_uint8), # Reserved, 0x06
('CR' , ctypes.c_uint32), # CRC Control register, Address offset: 0x08
]
_fields_ = [
('DR' , ctypes.c_uint32), # CRC Data register, Address offset: 0x00
('IDR' , ctypes.c_uint8), # CRC Independent data register, Address offset: 0x04
('RESERVED0', ctypes.c_uint8), # Reserved, 0x05
('RESERVED1', ctypes.c_uint8), # Reserved, 0x06
('CR' , ctypes.c_uint32), # CRC Control register, Address offset: 0x08
]
def __init__(self, ql, label):
super().__init__(ql, label)
def __init__(self, ql, label):
super().__init__(ql, label)
self.instance = self.struct(
self.instance = self.struct(
DR = 0xffffffff,
)
@QlPeripheral.monitor()
def read(self, offset: int, size: int) -> int:
buf = ctypes.create_string_buffer(size)
ctypes.memmove(buf, ctypes.addressof(self.instance) + offset, size)
return int.from_bytes(buf.raw, byteorder='little')
@QlPeripheral.monitor()
def read(self, offset: int, size: int) -> int:
buf = ctypes.create_string_buffer(size)
ctypes.memmove(buf, ctypes.addressof(self.instance) + offset, size)
return int.from_bytes(buf.raw, byteorder='little')
@QlPeripheral.monitor()
def write(self, offset: int, size: int, value: int):
if offset == self.struct.CR.offset:
if value & 1: # RESET bit
self.instance.DR = 0xffffffff
return
elif offset == self.struct.DR.offset:
for i in range(31, -1, -1):
if self.instance.DR & 0x80000000:
self.instance.DR <<= 1
self.instance.DR ^= 0x04c11db7
else:
self.instance.DR <<= 1
@QlPeripheral.monitor()
def write(self, offset: int, size: int, value: int):
if offset == self.struct.CR.offset:
if value & 1: # RESET bit
self.instance.DR = 0xffffffff
return
elif offset == self.struct.DR.offset:
for i in range(31, -1, -1):
if self.instance.DR & 0x80000000:
self.instance.DR <<= 1
self.instance.DR ^= 0x04c11db7
else:
self.instance.DR <<= 1
if value & (1 << i):
self.instance.DR ^= 0x04c11db7
if value & (1 << i):
self.instance.DR ^= 0x04c11db7
+1 -1
View File
@@ -52,7 +52,7 @@ class GD32VF1xxRcu(QlPeripheral):
self.intn = intn
@QlPeripheral.monitor()
def read(self, offset: int, size: int) -> int:
def read(self, offset: int, size: int) -> int:
buf = ctypes.create_string_buffer(size)
ctypes.memmove(buf, ctypes.addressof(self.instance) + offset, size)
return int.from_bytes(buf.raw, byteorder='little')
+15 -15
View File
@@ -43,25 +43,25 @@ class STM32F1xxRcc(QlPeripheral):
)
self.rdyon = {
'CR': [
(RCC_CR.HSIRDY , RCC_CR.HSION ),
(RCC_CR.HSERDY , RCC_CR.HSEON ),
(RCC_CR.PLLRDY , RCC_CR.PLLON ),
(RCC_CR.PLLI2SRDY, RCC_CR.PLLI2SON),
],
'CFGR': [
(RCC_CFGR.SWS_0, RCC_CFGR.SW_0),
(RCC_CFGR.SWS_1, RCC_CFGR.SW_1),
],
'CSR': [
(RCC_CSR.LSIRDY, RCC_CSR.LSION)
]
}
'CR': [
(RCC_CR.HSIRDY , RCC_CR.HSION ),
(RCC_CR.HSERDY , RCC_CR.HSEON ),
(RCC_CR.PLLRDY , RCC_CR.PLLON ),
(RCC_CR.PLLI2SRDY, RCC_CR.PLLI2SON),
],
'CFGR': [
(RCC_CFGR.SWS_0, RCC_CFGR.SW_0),
(RCC_CFGR.SWS_1, RCC_CFGR.SW_1),
],
'CSR': [
(RCC_CSR.LSIRDY, RCC_CSR.LSION)
]
}
self.intn = intn
@QlPeripheral.monitor()
def read(self, offset: int, size: int) -> int:
def read(self, offset: int, size: int) -> int:
buf = ctypes.create_string_buffer(size)
ctypes.memmove(buf, ctypes.addressof(self.instance) + offset, size)
return int.from_bytes(buf.raw, byteorder='little')
+1 -1
View File
@@ -52,7 +52,7 @@ class STM32F4xxDbgmcu(QlPeripheral):
)
@QlPeripheral.monitor()
def read(self, offset: int, size: int) -> int:
def read(self, offset: int, size: int) -> int:
buf = ctypes.create_string_buffer(size)
ctypes.memmove(buf, ctypes.addressof(self.instance) + offset, size)
return int.from_bytes(buf.raw, byteorder='little')
+90 -90
View File
@@ -9,102 +9,102 @@ from qiling.hw.const.stm32fxxx_rcc import RCC_CR, RCC_CFGR, RCC_CSR
class STM32F4xxRcc(QlPeripheral):
class Type(ctypes.Structure):
""" the structure available in :
stm32f401xc.h
stm32f401xe.h
stm32f411xe.h
"""
class Type(ctypes.Structure):
""" the structure available in :
stm32f401xc.h
stm32f401xe.h
stm32f411xe.h
"""
_fields_ = [
('CR' , ctypes.c_uint32), # RCC clock control register, Address offset: 0x00
('PLLCFGR' , ctypes.c_uint32), # RCC PLL configuration register, Address offset: 0x04
('CFGR' , ctypes.c_uint32), # RCC clock configuration register, Address offset: 0x08
('CIR' , ctypes.c_uint32), # RCC clock interrupt register, Address offset: 0x0C
('AHB1RSTR' , ctypes.c_uint32), # RCC AHB1 peripheral reset register, Address offset: 0x10
('AHB2RSTR' , ctypes.c_uint32), # RCC AHB2 peripheral reset register, Address offset: 0x14
('AHB3RSTR' , ctypes.c_uint32), # RCC AHB3 peripheral reset register, Address offset: 0x18
('RESERVED0' , ctypes.c_uint32), # Reserved, 0x1C
('APB1RSTR' , ctypes.c_uint32), # RCC APB1 peripheral reset register, Address offset: 0x20
('APB2RSTR' , ctypes.c_uint32), # RCC APB2 peripheral reset register, Address offset: 0x24
('RESERVED1' , ctypes.c_uint32 * 2), # Reserved, 0x28-0x2C
('AHB1ENR' , ctypes.c_uint32), # RCC AHB1 peripheral clock register, Address offset: 0x30
('AHB2ENR' , ctypes.c_uint32), # RCC AHB2 peripheral clock register, Address offset: 0x34
('AHB3ENR' , ctypes.c_uint32), # RCC AHB3 peripheral clock register, Address offset: 0x38
('RESERVED2' , ctypes.c_uint32), # Reserved, 0x3C
('APB1ENR' , ctypes.c_uint32), # RCC APB1 peripheral clock enable register, Address offset: 0x40
('APB2ENR' , ctypes.c_uint32), # RCC APB2 peripheral clock enable register, Address offset: 0x44
('RESERVED3' , ctypes.c_uint32 * 2), # Reserved, 0x48-0x4C
('AHB1LPENR' , ctypes.c_uint32), # RCC AHB1 peripheral clock enable in low power mode register, Address offset: 0x50
('AHB2LPENR' , ctypes.c_uint32), # RCC AHB2 peripheral clock enable in low power mode register, Address offset: 0x54
('AHB3LPENR' , ctypes.c_uint32), # RCC AHB3 peripheral clock enable in low power mode register, Address offset: 0x58
('RESERVED4' , ctypes.c_uint32), # Reserved, 0x5C
('APB1LPENR' , ctypes.c_uint32), # RCC APB1 peripheral clock enable in low power mode register, Address offset: 0x60
('APB2LPENR' , ctypes.c_uint32), # RCC APB2 peripheral clock enable in low power mode register, Address offset: 0x64
('RESERVED5' , ctypes.c_uint32 * 2), # Reserved, 0x68-0x6C
('BDCR' , ctypes.c_uint32), # RCC Backup domain control register, Address offset: 0x70
('CSR' , ctypes.c_uint32), # RCC clock control & status register, Address offset: 0x74
('RESERVED6' , ctypes.c_uint32 * 2), # Reserved, 0x78-0x7C
('SSCGR' , ctypes.c_uint32), # RCC spread spectrum clock generation register, Address offset: 0x80
('PLLI2SCFGR', ctypes.c_uint32), # RCC PLLI2S configuration register, Address offset: 0x84
('RESERVED7' , ctypes.c_uint32), # Reserved, 0x88
('DCKCFGR' , ctypes.c_uint32), # RCC Dedicated Clocks configuration register, Address offset: 0x8C
]
_fields_ = [
('CR' , ctypes.c_uint32), # RCC clock control register, Address offset: 0x00
('PLLCFGR' , ctypes.c_uint32), # RCC PLL configuration register, Address offset: 0x04
('CFGR' , ctypes.c_uint32), # RCC clock configuration register, Address offset: 0x08
('CIR' , ctypes.c_uint32), # RCC clock interrupt register, Address offset: 0x0C
('AHB1RSTR' , ctypes.c_uint32), # RCC AHB1 peripheral reset register, Address offset: 0x10
('AHB2RSTR' , ctypes.c_uint32), # RCC AHB2 peripheral reset register, Address offset: 0x14
('AHB3RSTR' , ctypes.c_uint32), # RCC AHB3 peripheral reset register, Address offset: 0x18
('RESERVED0' , ctypes.c_uint32), # Reserved, 0x1C
('APB1RSTR' , ctypes.c_uint32), # RCC APB1 peripheral reset register, Address offset: 0x20
('APB2RSTR' , ctypes.c_uint32), # RCC APB2 peripheral reset register, Address offset: 0x24
('RESERVED1' , ctypes.c_uint32 * 2), # Reserved, 0x28-0x2C
('AHB1ENR' , ctypes.c_uint32), # RCC AHB1 peripheral clock register, Address offset: 0x30
('AHB2ENR' , ctypes.c_uint32), # RCC AHB2 peripheral clock register, Address offset: 0x34
('AHB3ENR' , ctypes.c_uint32), # RCC AHB3 peripheral clock register, Address offset: 0x38
('RESERVED2' , ctypes.c_uint32), # Reserved, 0x3C
('APB1ENR' , ctypes.c_uint32), # RCC APB1 peripheral clock enable register, Address offset: 0x40
('APB2ENR' , ctypes.c_uint32), # RCC APB2 peripheral clock enable register, Address offset: 0x44
('RESERVED3' , ctypes.c_uint32 * 2), # Reserved, 0x48-0x4C
('AHB1LPENR' , ctypes.c_uint32), # RCC AHB1 peripheral clock enable in low power mode register, Address offset: 0x50
('AHB2LPENR' , ctypes.c_uint32), # RCC AHB2 peripheral clock enable in low power mode register, Address offset: 0x54
('AHB3LPENR' , ctypes.c_uint32), # RCC AHB3 peripheral clock enable in low power mode register, Address offset: 0x58
('RESERVED4' , ctypes.c_uint32), # Reserved, 0x5C
('APB1LPENR' , ctypes.c_uint32), # RCC APB1 peripheral clock enable in low power mode register, Address offset: 0x60
('APB2LPENR' , ctypes.c_uint32), # RCC APB2 peripheral clock enable in low power mode register, Address offset: 0x64
('RESERVED5' , ctypes.c_uint32 * 2), # Reserved, 0x68-0x6C
('BDCR' , ctypes.c_uint32), # RCC Backup domain control register, Address offset: 0x70
('CSR' , ctypes.c_uint32), # RCC clock control & status register, Address offset: 0x74
('RESERVED6' , ctypes.c_uint32 * 2), # Reserved, 0x78-0x7C
('SSCGR' , ctypes.c_uint32), # RCC spread spectrum clock generation register, Address offset: 0x80
('PLLI2SCFGR', ctypes.c_uint32), # RCC PLLI2S configuration register, Address offset: 0x84
('RESERVED7' , ctypes.c_uint32), # Reserved, 0x88
('DCKCFGR' , ctypes.c_uint32), # RCC Dedicated Clocks configuration register, Address offset: 0x8C
]
def __init__(self, ql, label, intn=None):
super().__init__(ql, label)
def __init__(self, ql, label, intn=None):
super().__init__(ql, label)
self.instance = self.struct(
CR = 0x00000083,
PLLCFGR = 0x24003010,
AHB1LPENR = 0x0061900F,
AHB2LPENR = 0x00000080,
APB1LPENR = 0x10E2C80F,
APB2LPENR = 0x00077930,
CSR = 0x0E000000,
PLLI2SCFGR = 0x24003000,
)
self.instance = self.struct(
CR = 0x00000083,
PLLCFGR = 0x24003010,
AHB1LPENR = 0x0061900F,
AHB2LPENR = 0x00000080,
APB1LPENR = 0x10E2C80F,
APB2LPENR = 0x00077930,
CSR = 0x0E000000,
PLLI2SCFGR = 0x24003000,
)
self.rdyon = {
'CR': [
(RCC_CR.HSIRDY , RCC_CR.HSION ),
(RCC_CR.HSERDY , RCC_CR.HSEON ),
(RCC_CR.PLLRDY , RCC_CR.PLLON ),
(RCC_CR.PLLI2SRDY, RCC_CR.PLLI2SON),
],
'CFGR': [
(RCC_CFGR.SWS_0, RCC_CFGR.SW_0),
(RCC_CFGR.SWS_1, RCC_CFGR.SW_1),
],
'CSR': [
(RCC_CSR.LSIRDY, RCC_CSR.LSION)
]
}
self.rdyon = {
'CR': [
(RCC_CR.HSIRDY , RCC_CR.HSION ),
(RCC_CR.HSERDY , RCC_CR.HSEON ),
(RCC_CR.PLLRDY , RCC_CR.PLLON ),
(RCC_CR.PLLI2SRDY, RCC_CR.PLLI2SON),
],
'CFGR': [
(RCC_CFGR.SWS_0, RCC_CFGR.SW_0),
(RCC_CFGR.SWS_1, RCC_CFGR.SW_1),
],
'CSR': [
(RCC_CSR.LSIRDY, RCC_CSR.LSION)
]
}
self.intn = intn
self.intn = intn
@QlPeripheral.monitor()
def read(self, offset: int, size: int) -> int:
buf = ctypes.create_string_buffer(size)
ctypes.memmove(buf, ctypes.addressof(self.instance) + offset, size)
return int.from_bytes(buf.raw, byteorder='little')
@QlPeripheral.monitor()
def read(self, offset: int, size: int) -> int:
buf = ctypes.create_string_buffer(size)
ctypes.memmove(buf, ctypes.addressof(self.instance) + offset, size)
return int.from_bytes(buf.raw, byteorder='little')
@QlPeripheral.monitor()
def write(self, offset: int, size: int, value: int):
if offset == self.struct.CR.offset:
value = (self.instance.CR & RCC_CR.RO_MASK) | (value & RCC_CR.RW_MASK)
elif offset == self.struct.CFGR.offset:
value = (self.instance.CFGR & RCC_CFGR.RO_MASK) | (value & RCC_CFGR.RW_MASK)
@QlPeripheral.monitor()
def write(self, offset: int, size: int, value: int):
if offset == self.struct.CR.offset:
value = (self.instance.CR & RCC_CR.RO_MASK) | (value & RCC_CR.RW_MASK)
elif offset == self.struct.CFGR.offset:
value = (self.instance.CFGR & RCC_CFGR.RO_MASK) | (value & RCC_CFGR.RW_MASK)
data = (value).to_bytes(size, 'little')
ctypes.memmove(ctypes.addressof(self.instance) + offset, data, size)
data = (value).to_bytes(size, 'little')
ctypes.memmove(ctypes.addressof(self.instance) + offset, data, size)
def step(self):
for reg, rdyon in self.rdyon.items():
value = getattr(self.instance, reg)
for rdy, on in rdyon:
if value & on:
value |= rdy
else:
value &= ~rdy
setattr(self.instance, reg, value)
def step(self):
for reg, rdyon in self.rdyon.items():
value = getattr(self.instance, reg)
for rdy, on in rdyon:
if value & on:
value |= rdy
else:
value &= ~rdy
setattr(self.instance, reg, value)
+228 -228
View File
@@ -10,262 +10,262 @@ from .stm32f4xx_rcc import STM32F4xxRcc
class STM32F4xxRccV1(STM32F4xxRcc):
class Type(ctypes.Structure):
""" the structure available in :
stm32f413xx.h
stm32f412vx.h
stm32f412rx.h
stm32f423xx.h
stm32f412zx.h
"""
stm32f413xx.h
stm32f412vx.h
stm32f412rx.h
stm32f423xx.h
stm32f412zx.h
"""
_fields_ = [
('CR' , ctypes.c_uint32), # RCC clock control register, Address offset: 0x00
('PLLCFGR' , ctypes.c_uint32), # RCC PLL configuration register, Address offset: 0x04
('CFGR' , ctypes.c_uint32), # RCC clock configuration register, Address offset: 0x08
('CIR' , ctypes.c_uint32), # RCC clock interrupt register, Address offset: 0x0C
('AHB1RSTR' , ctypes.c_uint32), # RCC AHB1 peripheral reset register, Address offset: 0x10
('AHB2RSTR' , ctypes.c_uint32), # RCC AHB2 peripheral reset register, Address offset: 0x14
('AHB3RSTR' , ctypes.c_uint32), # RCC AHB3 peripheral reset register, Address offset: 0x18
('RESERVED0' , ctypes.c_uint32), # Reserved, 0x1C
('APB1RSTR' , ctypes.c_uint32), # RCC APB1 peripheral reset register, Address offset: 0x20
('APB2RSTR' , ctypes.c_uint32), # RCC APB2 peripheral reset register, Address offset: 0x24
('RESERVED1' , ctypes.c_uint32 * 2), # Reserved, 0x28-0x2C
('AHB1ENR' , ctypes.c_uint32), # RCC AHB1 peripheral clock register, Address offset: 0x30
('AHB2ENR' , ctypes.c_uint32), # RCC AHB2 peripheral clock register, Address offset: 0x34
('AHB3ENR' , ctypes.c_uint32), # RCC AHB3 peripheral clock register, Address offset: 0x38
('RESERVED2' , ctypes.c_uint32), # Reserved, 0x3C
('APB1ENR' , ctypes.c_uint32), # RCC APB1 peripheral clock enable register, Address offset: 0x40
('APB2ENR' , ctypes.c_uint32), # RCC APB2 peripheral clock enable register, Address offset: 0x44
('RESERVED3' , ctypes.c_uint32 * 2), # Reserved, 0x48-0x4C
('AHB1LPENR' , ctypes.c_uint32), # RCC AHB1 peripheral clock enable in low power mode register, Address offset: 0x50
('AHB2LPENR' , ctypes.c_uint32), # RCC AHB2 peripheral clock enable in low power mode register, Address offset: 0x54
('AHB3LPENR' , ctypes.c_uint32), # RCC AHB3 peripheral clock enable in low power mode register, Address offset: 0x58
('RESERVED4' , ctypes.c_uint32), # Reserved, 0x5C
('APB1LPENR' , ctypes.c_uint32), # RCC APB1 peripheral clock enable in low power mode register, Address offset: 0x60
('APB2LPENR' , ctypes.c_uint32), # RCC APB2 peripheral clock enable in low power mode register, Address offset: 0x64
('RESERVED5' , ctypes.c_uint32 * 2), # Reserved, 0x68-0x6C
('BDCR' , ctypes.c_uint32), # RCC Backup domain control register, Address offset: 0x70
('CSR' , ctypes.c_uint32), # RCC clock control & status register, Address offset: 0x74
('RESERVED6' , ctypes.c_uint32 * 2), # Reserved, 0x78-0x7C
('SSCGR' , ctypes.c_uint32), # RCC spread spectrum clock generation register, Address offset: 0x80
('PLLI2SCFGR', ctypes.c_uint32), # RCC PLLI2S configuration register, Address offset: 0x84
('RESERVED7' , ctypes.c_uint32), # Reserved, 0x84
('DCKCFGR' , ctypes.c_uint32), # RCC Dedicated Clocks configuration register, Address offset: 0x8C
('CKGATENR' , ctypes.c_uint32), # RCC Clocks Gated ENable Register, Address offset: 0x90
('DCKCFGR2' , ctypes.c_uint32), # RCC Dedicated Clocks configuration register 2, Address offset: 0x94
]
('CR' , ctypes.c_uint32), # RCC clock control register, Address offset: 0x00
('PLLCFGR' , ctypes.c_uint32), # RCC PLL configuration register, Address offset: 0x04
('CFGR' , ctypes.c_uint32), # RCC clock configuration register, Address offset: 0x08
('CIR' , ctypes.c_uint32), # RCC clock interrupt register, Address offset: 0x0C
('AHB1RSTR' , ctypes.c_uint32), # RCC AHB1 peripheral reset register, Address offset: 0x10
('AHB2RSTR' , ctypes.c_uint32), # RCC AHB2 peripheral reset register, Address offset: 0x14
('AHB3RSTR' , ctypes.c_uint32), # RCC AHB3 peripheral reset register, Address offset: 0x18
('RESERVED0' , ctypes.c_uint32), # Reserved, 0x1C
('APB1RSTR' , ctypes.c_uint32), # RCC APB1 peripheral reset register, Address offset: 0x20
('APB2RSTR' , ctypes.c_uint32), # RCC APB2 peripheral reset register, Address offset: 0x24
('RESERVED1' , ctypes.c_uint32 * 2), # Reserved, 0x28-0x2C
('AHB1ENR' , ctypes.c_uint32), # RCC AHB1 peripheral clock register, Address offset: 0x30
('AHB2ENR' , ctypes.c_uint32), # RCC AHB2 peripheral clock register, Address offset: 0x34
('AHB3ENR' , ctypes.c_uint32), # RCC AHB3 peripheral clock register, Address offset: 0x38
('RESERVED2' , ctypes.c_uint32), # Reserved, 0x3C
('APB1ENR' , ctypes.c_uint32), # RCC APB1 peripheral clock enable register, Address offset: 0x40
('APB2ENR' , ctypes.c_uint32), # RCC APB2 peripheral clock enable register, Address offset: 0x44
('RESERVED3' , ctypes.c_uint32 * 2), # Reserved, 0x48-0x4C
('AHB1LPENR' , ctypes.c_uint32), # RCC AHB1 peripheral clock enable in low power mode register, Address offset: 0x50
('AHB2LPENR' , ctypes.c_uint32), # RCC AHB2 peripheral clock enable in low power mode register, Address offset: 0x54
('AHB3LPENR' , ctypes.c_uint32), # RCC AHB3 peripheral clock enable in low power mode register, Address offset: 0x58
('RESERVED4' , ctypes.c_uint32), # Reserved, 0x5C
('APB1LPENR' , ctypes.c_uint32), # RCC APB1 peripheral clock enable in low power mode register, Address offset: 0x60
('APB2LPENR' , ctypes.c_uint32), # RCC APB2 peripheral clock enable in low power mode register, Address offset: 0x64
('RESERVED5' , ctypes.c_uint32 * 2), # Reserved, 0x68-0x6C
('BDCR' , ctypes.c_uint32), # RCC Backup domain control register, Address offset: 0x70
('CSR' , ctypes.c_uint32), # RCC clock control & status register, Address offset: 0x74
('RESERVED6' , ctypes.c_uint32 * 2), # Reserved, 0x78-0x7C
('SSCGR' , ctypes.c_uint32), # RCC spread spectrum clock generation register, Address offset: 0x80
('PLLI2SCFGR', ctypes.c_uint32), # RCC PLLI2S configuration register, Address offset: 0x84
('RESERVED7' , ctypes.c_uint32), # Reserved, 0x84
('DCKCFGR' , ctypes.c_uint32), # RCC Dedicated Clocks configuration register, Address offset: 0x8C
('CKGATENR' , ctypes.c_uint32), # RCC Clocks Gated ENable Register, Address offset: 0x90
('DCKCFGR2' , ctypes.c_uint32), # RCC Dedicated Clocks configuration register 2, Address offset: 0x94
]
class STM32F4xxRccV2(STM32F4xxRcc):
class Type(ctypes.Structure):
""" the structure available in :
stm32f407xx.h
stm32f415xx.h
stm32f417xx.h
stm32f405xx.h
"""
stm32f407xx.h
stm32f415xx.h
stm32f417xx.h
stm32f405xx.h
"""
_fields_ = [
('CR' , ctypes.c_uint32), # RCC clock control register, Address offset: 0x00
('PLLCFGR' , ctypes.c_uint32), # RCC PLL configuration register, Address offset: 0x04
('CFGR' , ctypes.c_uint32), # RCC clock configuration register, Address offset: 0x08
('CIR' , ctypes.c_uint32), # RCC clock interrupt register, Address offset: 0x0C
('AHB1RSTR' , ctypes.c_uint32), # RCC AHB1 peripheral reset register, Address offset: 0x10
('AHB2RSTR' , ctypes.c_uint32), # RCC AHB2 peripheral reset register, Address offset: 0x14
('AHB3RSTR' , ctypes.c_uint32), # RCC AHB3 peripheral reset register, Address offset: 0x18
('RESERVED0' , ctypes.c_uint32), # Reserved, 0x1C
('APB1RSTR' , ctypes.c_uint32), # RCC APB1 peripheral reset register, Address offset: 0x20
('APB2RSTR' , ctypes.c_uint32), # RCC APB2 peripheral reset register, Address offset: 0x24
('RESERVED1' , ctypes.c_uint32 * 2), # Reserved, 0x28-0x2C
('AHB1ENR' , ctypes.c_uint32), # RCC AHB1 peripheral clock register, Address offset: 0x30
('AHB2ENR' , ctypes.c_uint32), # RCC AHB2 peripheral clock register, Address offset: 0x34
('AHB3ENR' , ctypes.c_uint32), # RCC AHB3 peripheral clock register, Address offset: 0x38
('RESERVED2' , ctypes.c_uint32), # Reserved, 0x3C
('APB1ENR' , ctypes.c_uint32), # RCC APB1 peripheral clock enable register, Address offset: 0x40
('APB2ENR' , ctypes.c_uint32), # RCC APB2 peripheral clock enable register, Address offset: 0x44
('RESERVED3' , ctypes.c_uint32 * 2), # Reserved, 0x48-0x4C
('AHB1LPENR' , ctypes.c_uint32), # RCC AHB1 peripheral clock enable in low power mode register, Address offset: 0x50
('AHB2LPENR' , ctypes.c_uint32), # RCC AHB2 peripheral clock enable in low power mode register, Address offset: 0x54
('AHB3LPENR' , ctypes.c_uint32), # RCC AHB3 peripheral clock enable in low power mode register, Address offset: 0x58
('RESERVED4' , ctypes.c_uint32), # Reserved, 0x5C
('APB1LPENR' , ctypes.c_uint32), # RCC APB1 peripheral clock enable in low power mode register, Address offset: 0x60
('APB2LPENR' , ctypes.c_uint32), # RCC APB2 peripheral clock enable in low power mode register, Address offset: 0x64
('RESERVED5' , ctypes.c_uint32 * 2), # Reserved, 0x68-0x6C
('BDCR' , ctypes.c_uint32), # RCC Backup domain control register, Address offset: 0x70
('CSR' , ctypes.c_uint32), # RCC clock control & status register, Address offset: 0x74
('RESERVED6' , ctypes.c_uint32 * 2), # Reserved, 0x78-0x7C
('SSCGR' , ctypes.c_uint32), # RCC spread spectrum clock generation register, Address offset: 0x80
('PLLI2SCFGR', ctypes.c_uint32), # RCC PLLI2S configuration register, Address offset: 0x84
]
('CR' , ctypes.c_uint32), # RCC clock control register, Address offset: 0x00
('PLLCFGR' , ctypes.c_uint32), # RCC PLL configuration register, Address offset: 0x04
('CFGR' , ctypes.c_uint32), # RCC clock configuration register, Address offset: 0x08
('CIR' , ctypes.c_uint32), # RCC clock interrupt register, Address offset: 0x0C
('AHB1RSTR' , ctypes.c_uint32), # RCC AHB1 peripheral reset register, Address offset: 0x10
('AHB2RSTR' , ctypes.c_uint32), # RCC AHB2 peripheral reset register, Address offset: 0x14
('AHB3RSTR' , ctypes.c_uint32), # RCC AHB3 peripheral reset register, Address offset: 0x18
('RESERVED0' , ctypes.c_uint32), # Reserved, 0x1C
('APB1RSTR' , ctypes.c_uint32), # RCC APB1 peripheral reset register, Address offset: 0x20
('APB2RSTR' , ctypes.c_uint32), # RCC APB2 peripheral reset register, Address offset: 0x24
('RESERVED1' , ctypes.c_uint32 * 2), # Reserved, 0x28-0x2C
('AHB1ENR' , ctypes.c_uint32), # RCC AHB1 peripheral clock register, Address offset: 0x30
('AHB2ENR' , ctypes.c_uint32), # RCC AHB2 peripheral clock register, Address offset: 0x34
('AHB3ENR' , ctypes.c_uint32), # RCC AHB3 peripheral clock register, Address offset: 0x38
('RESERVED2' , ctypes.c_uint32), # Reserved, 0x3C
('APB1ENR' , ctypes.c_uint32), # RCC APB1 peripheral clock enable register, Address offset: 0x40
('APB2ENR' , ctypes.c_uint32), # RCC APB2 peripheral clock enable register, Address offset: 0x44
('RESERVED3' , ctypes.c_uint32 * 2), # Reserved, 0x48-0x4C
('AHB1LPENR' , ctypes.c_uint32), # RCC AHB1 peripheral clock enable in low power mode register, Address offset: 0x50
('AHB2LPENR' , ctypes.c_uint32), # RCC AHB2 peripheral clock enable in low power mode register, Address offset: 0x54
('AHB3LPENR' , ctypes.c_uint32), # RCC AHB3 peripheral clock enable in low power mode register, Address offset: 0x58
('RESERVED4' , ctypes.c_uint32), # Reserved, 0x5C
('APB1LPENR' , ctypes.c_uint32), # RCC APB1 peripheral clock enable in low power mode register, Address offset: 0x60
('APB2LPENR' , ctypes.c_uint32), # RCC APB2 peripheral clock enable in low power mode register, Address offset: 0x64
('RESERVED5' , ctypes.c_uint32 * 2), # Reserved, 0x68-0x6C
('BDCR' , ctypes.c_uint32), # RCC Backup domain control register, Address offset: 0x70
('CSR' , ctypes.c_uint32), # RCC clock control & status register, Address offset: 0x74
('RESERVED6' , ctypes.c_uint32 * 2), # Reserved, 0x78-0x7C
('SSCGR' , ctypes.c_uint32), # RCC spread spectrum clock generation register, Address offset: 0x80
('PLLI2SCFGR', ctypes.c_uint32), # RCC PLLI2S configuration register, Address offset: 0x84
]
class STM32F4xxRccV3(STM32F4xxRcc):
class Type(ctypes.Structure):
""" the structure available in :
stm32f469xx.h
stm32f427xx.h
stm32f439xx.h
stm32f479xx.h
stm32f429xx.h
stm32f437xx.h
"""
stm32f469xx.h
stm32f427xx.h
stm32f439xx.h
stm32f479xx.h
stm32f429xx.h
stm32f437xx.h
"""
_fields_ = [
('CR' , ctypes.c_uint32), # RCC clock control register, Address offset: 0x00
('PLLCFGR' , ctypes.c_uint32), # RCC PLL configuration register, Address offset: 0x04
('CFGR' , ctypes.c_uint32), # RCC clock configuration register, Address offset: 0x08
('CIR' , ctypes.c_uint32), # RCC clock interrupt register, Address offset: 0x0C
('AHB1RSTR' , ctypes.c_uint32), # RCC AHB1 peripheral reset register, Address offset: 0x10
('AHB2RSTR' , ctypes.c_uint32), # RCC AHB2 peripheral reset register, Address offset: 0x14
('AHB3RSTR' , ctypes.c_uint32), # RCC AHB3 peripheral reset register, Address offset: 0x18
('RESERVED0' , ctypes.c_uint32), # Reserved, 0x1C
('APB1RSTR' , ctypes.c_uint32), # RCC APB1 peripheral reset register, Address offset: 0x20
('APB2RSTR' , ctypes.c_uint32), # RCC APB2 peripheral reset register, Address offset: 0x24
('RESERVED1' , ctypes.c_uint32 * 2), # Reserved, 0x28-0x2C
('AHB1ENR' , ctypes.c_uint32), # RCC AHB1 peripheral clock register, Address offset: 0x30
('AHB2ENR' , ctypes.c_uint32), # RCC AHB2 peripheral clock register, Address offset: 0x34
('AHB3ENR' , ctypes.c_uint32), # RCC AHB3 peripheral clock register, Address offset: 0x38
('RESERVED2' , ctypes.c_uint32), # Reserved, 0x3C
('APB1ENR' , ctypes.c_uint32), # RCC APB1 peripheral clock enable register, Address offset: 0x40
('APB2ENR' , ctypes.c_uint32), # RCC APB2 peripheral clock enable register, Address offset: 0x44
('RESERVED3' , ctypes.c_uint32 * 2), # Reserved, 0x48-0x4C
('AHB1LPENR' , ctypes.c_uint32), # RCC AHB1 peripheral clock enable in low power mode register, Address offset: 0x50
('AHB2LPENR' , ctypes.c_uint32), # RCC AHB2 peripheral clock enable in low power mode register, Address offset: 0x54
('AHB3LPENR' , ctypes.c_uint32), # RCC AHB3 peripheral clock enable in low power mode register, Address offset: 0x58
('RESERVED4' , ctypes.c_uint32), # Reserved, 0x5C
('APB1LPENR' , ctypes.c_uint32), # RCC APB1 peripheral clock enable in low power mode register, Address offset: 0x60
('APB2LPENR' , ctypes.c_uint32), # RCC APB2 peripheral clock enable in low power mode register, Address offset: 0x64
('RESERVED5' , ctypes.c_uint32 * 2), # Reserved, 0x68-0x6C
('BDCR' , ctypes.c_uint32), # RCC Backup domain control register, Address offset: 0x70
('CSR' , ctypes.c_uint32), # RCC clock control & status register, Address offset: 0x74
('RESERVED6' , ctypes.c_uint32 * 2), # Reserved, 0x78-0x7C
('SSCGR' , ctypes.c_uint32), # RCC spread spectrum clock generation register, Address offset: 0x80
('PLLI2SCFGR', ctypes.c_uint32), # RCC PLLI2S configuration register, Address offset: 0x84
('PLLSAICFGR', ctypes.c_uint32), # RCC PLLSAI configuration register, Address offset: 0x88
('DCKCFGR' , ctypes.c_uint32), # RCC Dedicated Clocks configuration register, Address offset: 0x8C
]
('CR' , ctypes.c_uint32), # RCC clock control register, Address offset: 0x00
('PLLCFGR' , ctypes.c_uint32), # RCC PLL configuration register, Address offset: 0x04
('CFGR' , ctypes.c_uint32), # RCC clock configuration register, Address offset: 0x08
('CIR' , ctypes.c_uint32), # RCC clock interrupt register, Address offset: 0x0C
('AHB1RSTR' , ctypes.c_uint32), # RCC AHB1 peripheral reset register, Address offset: 0x10
('AHB2RSTR' , ctypes.c_uint32), # RCC AHB2 peripheral reset register, Address offset: 0x14
('AHB3RSTR' , ctypes.c_uint32), # RCC AHB3 peripheral reset register, Address offset: 0x18
('RESERVED0' , ctypes.c_uint32), # Reserved, 0x1C
('APB1RSTR' , ctypes.c_uint32), # RCC APB1 peripheral reset register, Address offset: 0x20
('APB2RSTR' , ctypes.c_uint32), # RCC APB2 peripheral reset register, Address offset: 0x24
('RESERVED1' , ctypes.c_uint32 * 2), # Reserved, 0x28-0x2C
('AHB1ENR' , ctypes.c_uint32), # RCC AHB1 peripheral clock register, Address offset: 0x30
('AHB2ENR' , ctypes.c_uint32), # RCC AHB2 peripheral clock register, Address offset: 0x34
('AHB3ENR' , ctypes.c_uint32), # RCC AHB3 peripheral clock register, Address offset: 0x38
('RESERVED2' , ctypes.c_uint32), # Reserved, 0x3C
('APB1ENR' , ctypes.c_uint32), # RCC APB1 peripheral clock enable register, Address offset: 0x40
('APB2ENR' , ctypes.c_uint32), # RCC APB2 peripheral clock enable register, Address offset: 0x44
('RESERVED3' , ctypes.c_uint32 * 2), # Reserved, 0x48-0x4C
('AHB1LPENR' , ctypes.c_uint32), # RCC AHB1 peripheral clock enable in low power mode register, Address offset: 0x50
('AHB2LPENR' , ctypes.c_uint32), # RCC AHB2 peripheral clock enable in low power mode register, Address offset: 0x54
('AHB3LPENR' , ctypes.c_uint32), # RCC AHB3 peripheral clock enable in low power mode register, Address offset: 0x58
('RESERVED4' , ctypes.c_uint32), # Reserved, 0x5C
('APB1LPENR' , ctypes.c_uint32), # RCC APB1 peripheral clock enable in low power mode register, Address offset: 0x60
('APB2LPENR' , ctypes.c_uint32), # RCC APB2 peripheral clock enable in low power mode register, Address offset: 0x64
('RESERVED5' , ctypes.c_uint32 * 2), # Reserved, 0x68-0x6C
('BDCR' , ctypes.c_uint32), # RCC Backup domain control register, Address offset: 0x70
('CSR' , ctypes.c_uint32), # RCC clock control & status register, Address offset: 0x74
('RESERVED6' , ctypes.c_uint32 * 2), # Reserved, 0x78-0x7C
('SSCGR' , ctypes.c_uint32), # RCC spread spectrum clock generation register, Address offset: 0x80
('PLLI2SCFGR', ctypes.c_uint32), # RCC PLLI2S configuration register, Address offset: 0x84
('PLLSAICFGR', ctypes.c_uint32), # RCC PLLSAI configuration register, Address offset: 0x88
('DCKCFGR' , ctypes.c_uint32), # RCC Dedicated Clocks configuration register, Address offset: 0x8C
]
class STM32F446Rcc(STM32F4xxRcc):
class Type(ctypes.Structure):
""" the structure available in :
stm32f446xx.h
"""
stm32f446xx.h
"""
_fields_ = [
('CR' , ctypes.c_uint32), # RCC clock control register, Address offset: 0x00
('PLLCFGR' , ctypes.c_uint32), # RCC PLL configuration register, Address offset: 0x04
('CFGR' , ctypes.c_uint32), # RCC clock configuration register, Address offset: 0x08
('CIR' , ctypes.c_uint32), # RCC clock interrupt register, Address offset: 0x0C
('AHB1RSTR' , ctypes.c_uint32), # RCC AHB1 peripheral reset register, Address offset: 0x10
('AHB2RSTR' , ctypes.c_uint32), # RCC AHB2 peripheral reset register, Address offset: 0x14
('AHB3RSTR' , ctypes.c_uint32), # RCC AHB3 peripheral reset register, Address offset: 0x18
('RESERVED0' , ctypes.c_uint32), # Reserved, 0x1C
('APB1RSTR' , ctypes.c_uint32), # RCC APB1 peripheral reset register, Address offset: 0x20
('APB2RSTR' , ctypes.c_uint32), # RCC APB2 peripheral reset register, Address offset: 0x24
('RESERVED1' , ctypes.c_uint32 * 2), # Reserved, 0x28-0x2C
('AHB1ENR' , ctypes.c_uint32), # RCC AHB1 peripheral clock register, Address offset: 0x30
('AHB2ENR' , ctypes.c_uint32), # RCC AHB2 peripheral clock register, Address offset: 0x34
('AHB3ENR' , ctypes.c_uint32), # RCC AHB3 peripheral clock register, Address offset: 0x38
('RESERVED2' , ctypes.c_uint32), # Reserved, 0x3C
('APB1ENR' , ctypes.c_uint32), # RCC APB1 peripheral clock enable register, Address offset: 0x40
('APB2ENR' , ctypes.c_uint32), # RCC APB2 peripheral clock enable register, Address offset: 0x44
('RESERVED3' , ctypes.c_uint32 * 2), # Reserved, 0x48-0x4C
('AHB1LPENR' , ctypes.c_uint32), # RCC AHB1 peripheral clock enable in low power mode register, Address offset: 0x50
('AHB2LPENR' , ctypes.c_uint32), # RCC AHB2 peripheral clock enable in low power mode register, Address offset: 0x54
('AHB3LPENR' , ctypes.c_uint32), # RCC AHB3 peripheral clock enable in low power mode register, Address offset: 0x58
('RESERVED4' , ctypes.c_uint32), # Reserved, 0x5C
('APB1LPENR' , ctypes.c_uint32), # RCC APB1 peripheral clock enable in low power mode register, Address offset: 0x60
('APB2LPENR' , ctypes.c_uint32), # RCC APB2 peripheral clock enable in low power mode register, Address offset: 0x64
('RESERVED5' , ctypes.c_uint32 * 2), # Reserved, 0x68-0x6C
('BDCR' , ctypes.c_uint32), # RCC Backup domain control register, Address offset: 0x70
('CSR' , ctypes.c_uint32), # RCC clock control & status register, Address offset: 0x74
('RESERVED6' , ctypes.c_uint32 * 2), # Reserved, 0x78-0x7C
('SSCGR' , ctypes.c_uint32), # RCC spread spectrum clock generation register, Address offset: 0x80
('PLLI2SCFGR', ctypes.c_uint32), # RCC PLLI2S configuration register, Address offset: 0x84
('PLLSAICFGR', ctypes.c_uint32), # RCC PLLSAI configuration register, Address offset: 0x88
('DCKCFGR' , ctypes.c_uint32), # RCC Dedicated Clocks configuration register, Address offset: 0x8C
('CKGATENR' , ctypes.c_uint32), # RCC Clocks Gated ENable Register, Address offset: 0x90
('DCKCFGR2' , ctypes.c_uint32), # RCC Dedicated Clocks configuration register 2, Address offset: 0x94
]
('CR' , ctypes.c_uint32), # RCC clock control register, Address offset: 0x00
('PLLCFGR' , ctypes.c_uint32), # RCC PLL configuration register, Address offset: 0x04
('CFGR' , ctypes.c_uint32), # RCC clock configuration register, Address offset: 0x08
('CIR' , ctypes.c_uint32), # RCC clock interrupt register, Address offset: 0x0C
('AHB1RSTR' , ctypes.c_uint32), # RCC AHB1 peripheral reset register, Address offset: 0x10
('AHB2RSTR' , ctypes.c_uint32), # RCC AHB2 peripheral reset register, Address offset: 0x14
('AHB3RSTR' , ctypes.c_uint32), # RCC AHB3 peripheral reset register, Address offset: 0x18
('RESERVED0' , ctypes.c_uint32), # Reserved, 0x1C
('APB1RSTR' , ctypes.c_uint32), # RCC APB1 peripheral reset register, Address offset: 0x20
('APB2RSTR' , ctypes.c_uint32), # RCC APB2 peripheral reset register, Address offset: 0x24
('RESERVED1' , ctypes.c_uint32 * 2), # Reserved, 0x28-0x2C
('AHB1ENR' , ctypes.c_uint32), # RCC AHB1 peripheral clock register, Address offset: 0x30
('AHB2ENR' , ctypes.c_uint32), # RCC AHB2 peripheral clock register, Address offset: 0x34
('AHB3ENR' , ctypes.c_uint32), # RCC AHB3 peripheral clock register, Address offset: 0x38
('RESERVED2' , ctypes.c_uint32), # Reserved, 0x3C
('APB1ENR' , ctypes.c_uint32), # RCC APB1 peripheral clock enable register, Address offset: 0x40
('APB2ENR' , ctypes.c_uint32), # RCC APB2 peripheral clock enable register, Address offset: 0x44
('RESERVED3' , ctypes.c_uint32 * 2), # Reserved, 0x48-0x4C
('AHB1LPENR' , ctypes.c_uint32), # RCC AHB1 peripheral clock enable in low power mode register, Address offset: 0x50
('AHB2LPENR' , ctypes.c_uint32), # RCC AHB2 peripheral clock enable in low power mode register, Address offset: 0x54
('AHB3LPENR' , ctypes.c_uint32), # RCC AHB3 peripheral clock enable in low power mode register, Address offset: 0x58
('RESERVED4' , ctypes.c_uint32), # Reserved, 0x5C
('APB1LPENR' , ctypes.c_uint32), # RCC APB1 peripheral clock enable in low power mode register, Address offset: 0x60
('APB2LPENR' , ctypes.c_uint32), # RCC APB2 peripheral clock enable in low power mode register, Address offset: 0x64
('RESERVED5' , ctypes.c_uint32 * 2), # Reserved, 0x68-0x6C
('BDCR' , ctypes.c_uint32), # RCC Backup domain control register, Address offset: 0x70
('CSR' , ctypes.c_uint32), # RCC clock control & status register, Address offset: 0x74
('RESERVED6' , ctypes.c_uint32 * 2), # Reserved, 0x78-0x7C
('SSCGR' , ctypes.c_uint32), # RCC spread spectrum clock generation register, Address offset: 0x80
('PLLI2SCFGR', ctypes.c_uint32), # RCC PLLI2S configuration register, Address offset: 0x84
('PLLSAICFGR', ctypes.c_uint32), # RCC PLLSAI configuration register, Address offset: 0x88
('DCKCFGR' , ctypes.c_uint32), # RCC Dedicated Clocks configuration register, Address offset: 0x8C
('CKGATENR' , ctypes.c_uint32), # RCC Clocks Gated ENable Register, Address offset: 0x90
('DCKCFGR2' , ctypes.c_uint32), # RCC Dedicated Clocks configuration register 2, Address offset: 0x94
]
class Type(ctypes.Structure):
""" the structure available in :
stm32f469xx.h
stm32f427xx.h
stm32f439xx.h
stm32f479xx.h
stm32f429xx.h
stm32f437xx.h
"""
stm32f469xx.h
stm32f427xx.h
stm32f439xx.h
stm32f479xx.h
stm32f429xx.h
stm32f437xx.h
"""
_fields_ = [
('CR' , ctypes.c_uint32), # RCC clock control register, Address offset: 0x00
('PLLCFGR' , ctypes.c_uint32), # RCC PLL configuration register, Address offset: 0x04
('CFGR' , ctypes.c_uint32), # RCC clock configuration register, Address offset: 0x08
('CIR' , ctypes.c_uint32), # RCC clock interrupt register, Address offset: 0x0C
('AHB1RSTR' , ctypes.c_uint32), # RCC AHB1 peripheral reset register, Address offset: 0x10
('AHB2RSTR' , ctypes.c_uint32), # RCC AHB2 peripheral reset register, Address offset: 0x14
('AHB3RSTR' , ctypes.c_uint32), # RCC AHB3 peripheral reset register, Address offset: 0x18
('RESERVED0' , ctypes.c_uint32), # Reserved, 0x1C
('APB1RSTR' , ctypes.c_uint32), # RCC APB1 peripheral reset register, Address offset: 0x20
('APB2RSTR' , ctypes.c_uint32), # RCC APB2 peripheral reset register, Address offset: 0x24
('RESERVED1' , ctypes.c_uint32 * 2), # Reserved, 0x28-0x2C
('AHB1ENR' , ctypes.c_uint32), # RCC AHB1 peripheral clock register, Address offset: 0x30
('AHB2ENR' , ctypes.c_uint32), # RCC AHB2 peripheral clock register, Address offset: 0x34
('AHB3ENR' , ctypes.c_uint32), # RCC AHB3 peripheral clock register, Address offset: 0x38
('RESERVED2' , ctypes.c_uint32), # Reserved, 0x3C
('APB1ENR' , ctypes.c_uint32), # RCC APB1 peripheral clock enable register, Address offset: 0x40
('APB2ENR' , ctypes.c_uint32), # RCC APB2 peripheral clock enable register, Address offset: 0x44
('RESERVED3' , ctypes.c_uint32 * 2), # Reserved, 0x48-0x4C
('AHB1LPENR' , ctypes.c_uint32), # RCC AHB1 peripheral clock enable in low power mode register, Address offset: 0x50
('AHB2LPENR' , ctypes.c_uint32), # RCC AHB2 peripheral clock enable in low power mode register, Address offset: 0x54
('AHB3LPENR' , ctypes.c_uint32), # RCC AHB3 peripheral clock enable in low power mode register, Address offset: 0x58
('RESERVED4' , ctypes.c_uint32), # Reserved, 0x5C
('APB1LPENR' , ctypes.c_uint32), # RCC APB1 peripheral clock enable in low power mode register, Address offset: 0x60
('APB2LPENR' , ctypes.c_uint32), # RCC APB2 peripheral clock enable in low power mode register, Address offset: 0x64
('RESERVED5' , ctypes.c_uint32 * 2), # Reserved, 0x68-0x6C
('BDCR' , ctypes.c_uint32), # RCC Backup domain control register, Address offset: 0x70
('CSR' , ctypes.c_uint32), # RCC clock control & status register, Address offset: 0x74
('RESERVED6' , ctypes.c_uint32 * 2), # Reserved, 0x78-0x7C
('SSCGR' , ctypes.c_uint32), # RCC spread spectrum clock generation register, Address offset: 0x80
('PLLI2SCFGR', ctypes.c_uint32), # RCC PLLI2S configuration register, Address offset: 0x84
('PLLSAICFGR', ctypes.c_uint32), # RCC PLLSAI configuration register, Address offset: 0x88
('DCKCFGR' , ctypes.c_uint32), # RCC Dedicated Clocks configuration register, Address offset: 0x8C
]
('CR' , ctypes.c_uint32), # RCC clock control register, Address offset: 0x00
('PLLCFGR' , ctypes.c_uint32), # RCC PLL configuration register, Address offset: 0x04
('CFGR' , ctypes.c_uint32), # RCC clock configuration register, Address offset: 0x08
('CIR' , ctypes.c_uint32), # RCC clock interrupt register, Address offset: 0x0C
('AHB1RSTR' , ctypes.c_uint32), # RCC AHB1 peripheral reset register, Address offset: 0x10
('AHB2RSTR' , ctypes.c_uint32), # RCC AHB2 peripheral reset register, Address offset: 0x14
('AHB3RSTR' , ctypes.c_uint32), # RCC AHB3 peripheral reset register, Address offset: 0x18
('RESERVED0' , ctypes.c_uint32), # Reserved, 0x1C
('APB1RSTR' , ctypes.c_uint32), # RCC APB1 peripheral reset register, Address offset: 0x20
('APB2RSTR' , ctypes.c_uint32), # RCC APB2 peripheral reset register, Address offset: 0x24
('RESERVED1' , ctypes.c_uint32 * 2), # Reserved, 0x28-0x2C
('AHB1ENR' , ctypes.c_uint32), # RCC AHB1 peripheral clock register, Address offset: 0x30
('AHB2ENR' , ctypes.c_uint32), # RCC AHB2 peripheral clock register, Address offset: 0x34
('AHB3ENR' , ctypes.c_uint32), # RCC AHB3 peripheral clock register, Address offset: 0x38
('RESERVED2' , ctypes.c_uint32), # Reserved, 0x3C
('APB1ENR' , ctypes.c_uint32), # RCC APB1 peripheral clock enable register, Address offset: 0x40
('APB2ENR' , ctypes.c_uint32), # RCC APB2 peripheral clock enable register, Address offset: 0x44
('RESERVED3' , ctypes.c_uint32 * 2), # Reserved, 0x48-0x4C
('AHB1LPENR' , ctypes.c_uint32), # RCC AHB1 peripheral clock enable in low power mode register, Address offset: 0x50
('AHB2LPENR' , ctypes.c_uint32), # RCC AHB2 peripheral clock enable in low power mode register, Address offset: 0x54
('AHB3LPENR' , ctypes.c_uint32), # RCC AHB3 peripheral clock enable in low power mode register, Address offset: 0x58
('RESERVED4' , ctypes.c_uint32), # Reserved, 0x5C
('APB1LPENR' , ctypes.c_uint32), # RCC APB1 peripheral clock enable in low power mode register, Address offset: 0x60
('APB2LPENR' , ctypes.c_uint32), # RCC APB2 peripheral clock enable in low power mode register, Address offset: 0x64
('RESERVED5' , ctypes.c_uint32 * 2), # Reserved, 0x68-0x6C
('BDCR' , ctypes.c_uint32), # RCC Backup domain control register, Address offset: 0x70
('CSR' , ctypes.c_uint32), # RCC clock control & status register, Address offset: 0x74
('RESERVED6' , ctypes.c_uint32 * 2), # Reserved, 0x78-0x7C
('SSCGR' , ctypes.c_uint32), # RCC spread spectrum clock generation register, Address offset: 0x80
('PLLI2SCFGR', ctypes.c_uint32), # RCC PLLI2S configuration register, Address offset: 0x84
('PLLSAICFGR', ctypes.c_uint32), # RCC PLLSAI configuration register, Address offset: 0x88
('DCKCFGR' , ctypes.c_uint32), # RCC Dedicated Clocks configuration register, Address offset: 0x8C
]
class STM32F412Rcc(STM32F4xxRcc):
class Type(ctypes.Structure):
""" the structure available in :
stm32f412cx.h
"""
stm32f412cx.h
"""
_fields_ = [
('CR' , ctypes.c_uint32), # RCC clock control register, Address offset: 0x00
('PLLCFGR' , ctypes.c_uint32), # RCC PLL configuration register, Address offset: 0x04
('CFGR' , ctypes.c_uint32), # RCC clock configuration register, Address offset: 0x08
('CIR' , ctypes.c_uint32), # RCC clock interrupt register, Address offset: 0x0C
('AHB1RSTR' , ctypes.c_uint32), # RCC AHB1 peripheral reset register, Address offset: 0x10
('AHB2RSTR' , ctypes.c_uint32), # RCC AHB2 peripheral reset register, Address offset: 0x14
('RESERVED0' , ctypes.c_uint32 * 2), # Reserved, 0x18-0x1C
('APB1RSTR' , ctypes.c_uint32), # RCC APB1 peripheral reset register, Address offset: 0x20
('APB2RSTR' , ctypes.c_uint32), # RCC APB2 peripheral reset register, Address offset: 0x24
('RESERVED1' , ctypes.c_uint32 * 2), # Reserved, 0x28-0x2C
('AHB1ENR' , ctypes.c_uint32), # RCC AHB1 peripheral clock register, Address offset: 0x30
('AHB2ENR' , ctypes.c_uint32), # RCC AHB2 peripheral clock register, Address offset: 0x34
('RESERVED2' , ctypes.c_uint32 * 2), # Reserved, 0x38-0x3C
('APB1ENR' , ctypes.c_uint32), # RCC APB1 peripheral clock enable register, Address offset: 0x40
('APB2ENR' , ctypes.c_uint32), # RCC APB2 peripheral clock enable register, Address offset: 0x44
('RESERVED3' , ctypes.c_uint32 * 2), # Reserved, 0x48-0x4C
('AHB1LPENR' , ctypes.c_uint32), # RCC AHB1 peripheral clock enable in low power mode register, Address offset: 0x50
('AHB2LPENR' , ctypes.c_uint32), # RCC AHB2 peripheral clock enable in low power mode register, Address offset: 0x54
('RESERVED4' , ctypes.c_uint32 * 2), # Reserved, 0x58-0x5C
('APB1LPENR' , ctypes.c_uint32), # RCC APB1 peripheral clock enable in low power mode register, Address offset: 0x60
('APB2LPENR' , ctypes.c_uint32), # RCC APB2 peripheral clock enable in low power mode register, Address offset: 0x64
('RESERVED5' , ctypes.c_uint32 * 2), # Reserved, 0x68-0x6C
('BDCR' , ctypes.c_uint32), # RCC Backup domain control register, Address offset: 0x70
('CSR' , ctypes.c_uint32), # RCC clock control & status register, Address offset: 0x74
('RESERVED6' , ctypes.c_uint32 * 2), # Reserved, 0x78-0x7C
('SSCGR' , ctypes.c_uint32), # RCC spread spectrum clock generation register, Address offset: 0x80
('PLLI2SCFGR', ctypes.c_uint32), # RCC PLLI2S configuration register, Address offset: 0x84
('RESERVED7' , ctypes.c_uint32), # Reserved, 0x88
('DCKCFGR' , ctypes.c_uint32), # RCC Dedicated Clocks configuration register, Address offset: 0x8C
('CKGATENR' , ctypes.c_uint32), # RCC Clocks Gated ENable Register, Address offset: 0x90
('DCKCFGR2' , ctypes.c_uint32), # RCC Dedicated Clocks configuration register 2, Address offset: 0x94
]
('CR' , ctypes.c_uint32), # RCC clock control register, Address offset: 0x00
('PLLCFGR' , ctypes.c_uint32), # RCC PLL configuration register, Address offset: 0x04
('CFGR' , ctypes.c_uint32), # RCC clock configuration register, Address offset: 0x08
('CIR' , ctypes.c_uint32), # RCC clock interrupt register, Address offset: 0x0C
('AHB1RSTR' , ctypes.c_uint32), # RCC AHB1 peripheral reset register, Address offset: 0x10
('AHB2RSTR' , ctypes.c_uint32), # RCC AHB2 peripheral reset register, Address offset: 0x14
('RESERVED0' , ctypes.c_uint32 * 2), # Reserved, 0x18-0x1C
('APB1RSTR' , ctypes.c_uint32), # RCC APB1 peripheral reset register, Address offset: 0x20
('APB2RSTR' , ctypes.c_uint32), # RCC APB2 peripheral reset register, Address offset: 0x24
('RESERVED1' , ctypes.c_uint32 * 2), # Reserved, 0x28-0x2C
('AHB1ENR' , ctypes.c_uint32), # RCC AHB1 peripheral clock register, Address offset: 0x30
('AHB2ENR' , ctypes.c_uint32), # RCC AHB2 peripheral clock register, Address offset: 0x34
('RESERVED2' , ctypes.c_uint32 * 2), # Reserved, 0x38-0x3C
('APB1ENR' , ctypes.c_uint32), # RCC APB1 peripheral clock enable register, Address offset: 0x40
('APB2ENR' , ctypes.c_uint32), # RCC APB2 peripheral clock enable register, Address offset: 0x44
('RESERVED3' , ctypes.c_uint32 * 2), # Reserved, 0x48-0x4C
('AHB1LPENR' , ctypes.c_uint32), # RCC AHB1 peripheral clock enable in low power mode register, Address offset: 0x50
('AHB2LPENR' , ctypes.c_uint32), # RCC AHB2 peripheral clock enable in low power mode register, Address offset: 0x54
('RESERVED4' , ctypes.c_uint32 * 2), # Reserved, 0x58-0x5C
('APB1LPENR' , ctypes.c_uint32), # RCC APB1 peripheral clock enable in low power mode register, Address offset: 0x60
('APB2LPENR' , ctypes.c_uint32), # RCC APB2 peripheral clock enable in low power mode register, Address offset: 0x64
('RESERVED5' , ctypes.c_uint32 * 2), # Reserved, 0x68-0x6C
('BDCR' , ctypes.c_uint32), # RCC Backup domain control register, Address offset: 0x70
('CSR' , ctypes.c_uint32), # RCC clock control & status register, Address offset: 0x74
('RESERVED6' , ctypes.c_uint32 * 2), # Reserved, 0x78-0x7C
('SSCGR' , ctypes.c_uint32), # RCC spread spectrum clock generation register, Address offset: 0x80
('PLLI2SCFGR', ctypes.c_uint32), # RCC PLLI2S configuration register, Address offset: 0x84
('RESERVED7' , ctypes.c_uint32), # Reserved, 0x88
('DCKCFGR' , ctypes.c_uint32), # RCC Dedicated Clocks configuration register, Address offset: 0x8C
('CKGATENR' , ctypes.c_uint32), # RCC Clocks Gated ENable Register, Address offset: 0x90
('DCKCFGR2' , ctypes.c_uint32), # RCC Dedicated Clocks configuration register 2, Address offset: 0x94
]
+20 -20
View File
@@ -10,25 +10,25 @@ from qiling.hw.peripheral import QlPeripheral
class STM32F4xxSyscfg(QlPeripheral):
class Type(ctypes.Structure):
""" the structure available in :
stm32f407xx.h
stm32f469xx.h
stm32f427xx.h
stm32f401xc.h
stm32f415xx.h
stm32f439xx.h
stm32f417xx.h
stm32f479xx.h
stm32f429xx.h
stm32f437xx.h
stm32f401xe.h
stm32f405xx.h
stm32f411xe.h
"""
stm32f407xx.h
stm32f469xx.h
stm32f427xx.h
stm32f401xc.h
stm32f415xx.h
stm32f439xx.h
stm32f417xx.h
stm32f479xx.h
stm32f429xx.h
stm32f437xx.h
stm32f401xe.h
stm32f405xx.h
stm32f411xe.h
"""
_fields_ = [
('MEMRMP' , ctypes.c_uint32), # SYSCFG memory remap register, Address offset: 0x00
('PMC' , ctypes.c_uint32), # SYSCFG peripheral mode configuration register, Address offset: 0x04
('EXTICR' , ctypes.c_uint32 * 4), # SYSCFG external interrupt configuration registers, Address offset: 0x08-0x14
('RESERVED', ctypes.c_uint32 * 2), # Reserved, 0x18-0x1C
('CMPCR' , ctypes.c_uint32), # SYSCFG Compensation cell control register, Address offset: 0x20
]
('MEMRMP' , ctypes.c_uint32), # SYSCFG memory remap register, Address offset: 0x00
('PMC' , ctypes.c_uint32), # SYSCFG peripheral mode configuration register, Address offset: 0x04
('EXTICR' , ctypes.c_uint32 * 4), # SYSCFG external interrupt configuration registers, Address offset: 0x08-0x14
('RESERVED', ctypes.c_uint32 * 2), # Reserved, 0x18-0x1C
('CMPCR' , ctypes.c_uint32), # SYSCFG Compensation cell control register, Address offset: 0x20
]
+1 -1
View File
@@ -66,7 +66,7 @@ class SAM3xaPmc(QlPeripheral):
self.intn = intn
@QlPeripheral.monitor()
def read(self, offset: int, size: int) -> int:
def read(self, offset: int, size: int) -> int:
buf = ctypes.create_string_buffer(size)
ctypes.memmove(buf, ctypes.addressof(self.instance) + offset, size)
return int.from_bytes(buf.raw, byteorder='little')
+41 -41
View File
@@ -10,49 +10,49 @@ from qiling.hw.const.stm32f4xx_pwr import PWR_CR, PWR_CSR
class STM32F4xxPwr(QlPeripheral):
class Type(ctypes.Structure):
""" the structure available in :
stm32f413xx.h
stm32f407xx.h
stm32f469xx.h
stm32f446xx.h
stm32f427xx.h
stm32f401xc.h
stm32f415xx.h
stm32f412cx.h
stm32f410rx.h
stm32f410tx.h
stm32f439xx.h
stm32f412vx.h
stm32f417xx.h
stm32f479xx.h
stm32f429xx.h
stm32f412rx.h
stm32f423xx.h
stm32f437xx.h
stm32f412zx.h
stm32f401xe.h
stm32f410cx.h
stm32f405xx.h
stm32f411xe.h
"""
class Type(ctypes.Structure):
""" the structure available in :
stm32f413xx.h
stm32f407xx.h
stm32f469xx.h
stm32f446xx.h
stm32f427xx.h
stm32f401xc.h
stm32f415xx.h
stm32f412cx.h
stm32f410rx.h
stm32f410tx.h
stm32f439xx.h
stm32f412vx.h
stm32f417xx.h
stm32f479xx.h
stm32f429xx.h
stm32f412rx.h
stm32f423xx.h
stm32f437xx.h
stm32f412zx.h
stm32f401xe.h
stm32f410cx.h
stm32f405xx.h
stm32f411xe.h
"""
_fields_ = [
('CR' , ctypes.c_uint32), # PWR power control register, Address offset: 0x00
('CSR', ctypes.c_uint32), # PWR power control/status register, Address offset: 0x04
]
_fields_ = [
('CR' , ctypes.c_uint32), # PWR power control register, Address offset: 0x00
('CSR', ctypes.c_uint32), # PWR power control/status register, Address offset: 0x04
]
def __init__(self, ql: Qiling, label: str):
super().__init__(ql, label)
def __init__(self, ql: Qiling, label: str):
super().__init__(ql, label)
self.instance = self.struct()
self.instance = self.struct()
@QlPeripheral.monitor()
def write(self, offset: int, size: int, value: int):
if offset == self.struct.CR.offset:
if value & PWR_CR.ODEN:
self.instance.CSR |= PWR_CSR.ODRDY
if value & PWR_CR.ODSWEN:
self.instance.CSR |= PWR_CSR.ODSWRDY
@QlPeripheral.monitor()
def write(self, offset: int, size: int, value: int):
if offset == self.struct.CR.offset:
if value & PWR_CR.ODEN:
self.instance.CSR |= PWR_CSR.ODRDY
if value & PWR_CR.ODSWEN:
self.instance.CSR |= PWR_CSR.ODSWRDY
self.raw_write(offset, size, value)
self.raw_write(offset, size, value)
+1 -1
View File
@@ -90,7 +90,7 @@ class STM32F4xxSpi(QlConnectivityPeripheral):
value &= SPI_CR2.RW_MASK
elif offset == self.struct.CRCPR.offset:
value &= SPI_CRCPR.CRCPOLY
value &= SPI_CRCPR.CRCPOLY
elif offset == self.struct.I2SCFGR.offset:
value &= SPI_I2SCFGR.RW_MASK
+24 -24
View File
@@ -13,30 +13,30 @@ from qiling.hw.const.stm32f4xx_rtc import RTC_TR, RTC_ISR
class STM32F4xxRtc(QlPeripheral):
class Type(ctypes.Structure):
""" the structure is available in :
stm32f423xx.h
stm32f469xx.h
stm32f427xx.h
stm32f479xx.h
stm32f413xx.h
stm32f429xx.h
stm32f439xx.h
stm32f415xx.h
stm32f412cx.h
stm32f412rx.h
stm32f410tx.h
stm32f410cx.h
stm32f412zx.h
stm32f405xx.h
stm32f407xx.h
stm32f417xx.h
stm32f446xx.h
stm32f401xc.h
stm32f437xx.h
stm32f401xe.h
stm32f412vx.h
stm32f410rx.h
stm32f411xe.h
"""
stm32f423xx.h
stm32f469xx.h
stm32f427xx.h
stm32f479xx.h
stm32f413xx.h
stm32f429xx.h
stm32f439xx.h
stm32f415xx.h
stm32f412cx.h
stm32f412rx.h
stm32f410tx.h
stm32f410cx.h
stm32f412zx.h
stm32f405xx.h
stm32f407xx.h
stm32f417xx.h
stm32f446xx.h
stm32f401xc.h
stm32f437xx.h
stm32f401xe.h
stm32f412vx.h
stm32f410rx.h
stm32f411xe.h
"""
_fields_ = [
('TR' , ctypes.c_uint32), # RTC time register, Address offset: 0x00
+1 -1
View File
@@ -84,7 +84,7 @@ class QlLoaderDOS(QlLoader):
# https://en.wikipedia.org/wiki/Master_boot_record#BIOS_to_MBR_interface
if not self.ql.os.fs_mapper.has_mapping(0x80):
self.ql.os.fs_mapper.add_fs_mapping(0x80, QlDisk(path, 0x80))
self.ql.os.fs_mapper.add_mapping(0x80, QlDisk(path, 0x80))
# 0x80 -> first drive
self.ql.arch.regs.dx = 0x80
+21 -13
View File
@@ -197,12 +197,16 @@ class QlLoaderELF(QlLoader):
# map the memory regions
for lbound, ubound, perms in load_regions:
try:
self.ql.mem.map(lbound, ubound - lbound, perms, os.path.basename(info))
except QlMemoryMappedError:
self.ql.log.exception(f'Failed to map {lbound:#x}-{ubound:#x}')
else:
self.ql.log.debug(f'Mapped {lbound:#x}-{ubound:#x}')
size = ubound - lbound
# there might be a region with zero size. in this case, do not mmap it
if size:
try:
self.ql.mem.map(lbound, size, perms, os.path.basename(info))
except QlMemoryMappedError:
self.ql.log.exception(f'Failed to map {lbound:#x}-{ubound:#x}')
else:
self.ql.log.debug(f'Mapped {lbound:#x}-{ubound:#x}')
# load loadable segments contents to memory
for seg in load_segments:
@@ -230,10 +234,15 @@ class QlLoaderELF(QlLoader):
# load the interpreter, if there is one
if interp_path:
interp_local_path = os.path.normpath(self.ql.rootfs + interp_path)
self.ql.log.debug(f'Interpreter path: {interp_local_path}')
interp_vpath = self.ql.os.path.virtual_abspath(interp_path)
interp_hpath = self.ql.os.path.virtual_to_host_path(interp_path)
with open(interp_local_path, 'rb') as infile:
self.ql.log.debug(f'Interpreter path: {interp_vpath}')
if not self.ql.os.path.is_safe_host_path(interp_hpath):
raise PermissionError(f'unsafe path: {interp_hpath}')
with open(interp_hpath, 'rb') as infile:
interp = ELFFile(infile)
min_vaddr = min(seg['p_vaddr'] for seg in interp.iter_segments(type='PT_LOAD'))
@@ -244,10 +253,10 @@ class QlLoaderELF(QlLoader):
self.ql.log.debug(f'Interpreter addr: {interp_address:#x}')
# load interpreter segments data to memory
interp_start, interp_end = load_elf_segments(interp, interp_address, interp_local_path)
interp_start, interp_end = load_elf_segments(interp, interp_address, interp_vpath)
# add interpreter to the loaded images list
self.images.append(Image(interp_start, interp_end, os.path.abspath(interp_local_path)))
self.images.append(Image(interp_start, interp_end, interp_hpath))
# determine entry point
entry_point = interp_address + interp['e_entry']
@@ -268,7 +277,7 @@ class QlLoaderELF(QlLoader):
Top of stack remains aligned to pointer size
"""
data = s.encode('utf-8') + b'\x00'
data = s.encode('latin') + b'\x00'
top = self.ql.mem.align(top - len(data), self.ql.arch.pointersize)
self.ql.mem.write(top, data)
@@ -353,7 +362,6 @@ class QlLoaderELF(QlLoader):
self.init_sp = self.ql.arch.regs.arch_sp
self.ql.os.entry_point = self.entry_point = entry_point
self.ql.os.elf_mem_start = mem_start
self.ql.os.elf_entry = self.elf_entry
self.ql.os.function_hook = FunctionHook(self.ql, elf_phdr, elf_phnum, elf_phent, load_address, mem_end)
+8 -3
View File
@@ -1,18 +1,23 @@
#!/usr/bin/env python3
#
#
# Cross Platform and Multi Architecture Advanced Binary Emulation Framework
#
from __future__ import annotations
import os
from typing import Any, Mapping, MutableSequence, NamedTuple, Optional
from typing import TYPE_CHECKING, Any, Mapping, MutableSequence, NamedTuple, Optional
if TYPE_CHECKING:
from qiling import Qiling
from qiling import Qiling
class Image(NamedTuple):
base: int
end: int
path: str
class QlLoader:
def __init__(self, ql: Qiling):
self.ql = ql
+120 -31
View File
@@ -3,15 +3,20 @@
# Cross Platform and Multi Architecture Advanced Binary Emulation Framework
#
import os, pefile, pickle, secrets, ntpath
from typing import Any, Dict, MutableMapping, NamedTuple, Optional, Mapping, Sequence, Tuple, Union
from __future__ import annotations
import os
import pefile
import pickle
import secrets
import ntpath
from typing import TYPE_CHECKING, Any, Dict, MutableMapping, NamedTuple, Optional, Mapping, Sequence, Tuple, Union
from unicorn import UcError
from unicorn.x86_const import UC_X86_REG_CR4, UC_X86_REG_CR8
from qiling import Qiling
from qiling.arch.x86_const import FS_SEGMENT_ADDR, GS_SEGMENT_ADDR
from qiling.const import QL_ARCH
from qiling.const import QL_ARCH, QL_STATE
from qiling.exception import QlErrorArch
from qiling.os.const import POINTER
from qiling.os.windows.api import HINSTANCE, DWORD, LPVOID
@@ -20,6 +25,11 @@ from qiling.os.windows.utils import has_lib_ext
from qiling.os.windows.structs import *
from .loader import QlLoader, Image
if TYPE_CHECKING:
from logging import Logger
from qiling import Qiling
class QlPeCacheEntry(NamedTuple):
ba: int
data: bytearray
@@ -182,7 +192,7 @@ class Process:
relocate = True
if relocate:
with ShowProgress(0.1337):
with ShowProgress(self.ql.log, 0.1337):
dll.relocate_image(image_base)
data = bytearray(dll.get_memory_mapped_image())
@@ -247,13 +257,8 @@ class Process:
#
# in case of a dll loaded from a hooked API call, failures would not be
# recoverable and we have to give up its DllMain.
if not self.ql.os.PE_RUN:
# temporarily set PE_RUN to allow proper fcall unwinding during
# execution of DllMain
self.ql.os.PE_RUN = True
if self.ql.emu_state is not QL_STATE.STARTED:
self.call_dll_entrypoint(dll, dll_base, dll_len, dll_name)
self.ql.os.PE_RUN = False
self.ql.log.info(f'Done loading {dll_name}')
@@ -553,6 +558,10 @@ class Process:
# Do a full load if IMAGE_DIRECTORY_ENTRY_EXPORT is present so we can load the exports
pe.full_load()
# address corner case for malformed export tables where IMAGE_DIRECTORY_ENTRY_EXPORT exists, but DIRECTORY_ENTRY_EXPORT does not
if not hasattr(pe, 'DIRECTORY_ENTRY_EXPORT'):
return
iat = {}
@@ -864,45 +873,125 @@ class QlLoaderPE(QlLoader, Process):
self.ql.os.entry_point = self.entry_point
self.init_sp = self.ql.arch.regs.arch_sp
class ShowProgress:
"""Display a progress animation while performing a time
consuming task.
"""Display a progress animation while performing a time consuming task.
Example:
>>> with ShowProgress(0.1):
>>> with ShowProgress(logger, 0.15):
... do_some_time_consuming_task()
"""
def __init__(self, interval: float) -> None:
import sys
from threading import Thread, Event
# animation frames: a sequence of chars or strings to display. any sequence of string elements
# may be used as long as they are of the same length.
#
# for example: ['> ', '>> ', ' >> ', ' >>', ' >', ' ']
_frames_ = r'/-\|'
# animation frames; any sequence of chars or strings may be used, as long
# as they are of the same length. e.g. ['> ', '>> ', ' >> ', ' >>', ' >', ' ']
frames = r'/-\|'
stream = sys.stderr
# animation marker: this is used to tell animation log records from the rest.
_marker_ = r'$__ql_anim__'
def __init__(self, logger: Logger, interval: float) -> None:
from typing import List, Callable
from threading import Thread, Event
def show_animation():
i = 0
while not self.stopped.wait(interval):
# TODO: find a proper way to use the logger for that
print(f'[{frames[i % len(frames)]}]', end='\r', flush=True, file=stream)
frame = self._frames_[i % len(self._frames_)]
logger.info(f'{self._marker_}{frame}')
i += 1
def show_nothing():
pass
# avoid flooding log files with animation frames
action = show_animation if stream.isatty() else show_nothing
self.stopped = Event()
self.thread = Thread(target=action)
self.thread = Thread(target=show_animation)
self.logger = logger
self.handlers_restorers: List[Callable[[], None]] = []
def __setup_handlers(self):
from logging import Filter, Formatter, LogRecord, StreamHandler
# while progress animation is useful on tty streams, it is not very useful on log files
# and most probably just flood the log files with animation frames.
#
# to avoid such flooding an animation filter is added to the non-tty stream handlers to
# filter out the animation records. in addition, tty stream handlers are assigned with
# an animation formatter to display the animation frames nicely.
#
# when the animation context exits, all the changes made to the handlers are reverted.
def has_anim_marker(rec: LogRecord) -> bool:
"""Tell whether a log record is an animation record or not.
"""
return rec.getMessage().startswith(ShowProgress._marker_)
def strip_anim_marker(rec: LogRecord) -> None:
"""Remove animation marker from log record.
"""
rec.message = rec.message[len(ShowProgress._marker_):]
class AnimFormatter(Formatter):
"""A log record formatter that removes animation markers.
"""
def formatMessage(self, record: LogRecord) -> str:
if has_anim_marker(record):
strip_anim_marker(record)
return super().formatMessage(record)
class AnimFilter(Filter):
"""A log record filter that thwarts animation records.
"""
def filter(self, record: LogRecord) -> bool:
return not has_anim_marker(record)
# the animation frames will be displayed within brackets
anim_formatter = AnimFormatter('[%(message)s]')
anim_filter = AnimFilter()
for h in self.logger.handlers:
# if this is a tty stream handler, modify some of its attributes to
# let the animation display correctly
if isinstance(h, StreamHandler) and h.stream.isatty():
orig_terminator = h.terminator
orig_formatter = h.formatter
h.terminator = '\r'
h.setFormatter(anim_formatter)
def __restore_modified() -> None:
h.terminator = orig_terminator
h.setFormatter(orig_formatter)
restorer = __restore_modified
# otherwise, apply a filter that will ignore animation records
else:
h.addFilter(anim_filter)
def __restore_silenced() -> None:
h.removeFilter(anim_filter)
restorer = __restore_silenced
self.handlers_restorers.append(restorer)
def __restore_handlers(self) -> None:
for restorer in self.handlers_restorers:
restorer()
def __enter__(self):
self.__setup_handlers()
self.thread.start()
return self
def __exit__(self, *args) -> None:
def __exit__(self, extype, value, traceback):
self.stopped.set()
self.__restore_handlers()
+43 -19
View File
@@ -3,32 +3,39 @@
# Cross Platform and Multi Architecture Advanced Binary Emulation Framework
#
from __future__ import annotations
import copy
import logging
import os
import re
import weakref
from typing import Optional, TextIO
from typing import TYPE_CHECKING, Optional, TextIO
from logging import Filter, Formatter, LogRecord, Logger, NullHandler, StreamHandler, FileHandler
from qiling.const import QL_VERBOSE
if TYPE_CHECKING:
from qiling import Qiling
QL_INSTANCE_ID = 114514
FMT_STR = '%(levelname)s\t%(message)s'
class COLOR:
WHITE = '\033[37m'
CRIMSON = '\033[31m'
RED = '\033[91m'
GREEN = '\033[92m'
YELLOW = '\033[93m'
BLUE = '\033[94m'
MAGENTA = '\033[95m'
CYAN = '\033[96m'
ENDC = '\033[0m'
DEFAULT = '\033[39m'
class QlBaseFormatter(logging.Formatter):
class QlBaseFormatter(Formatter):
__level_tag = {
'WARNING' : '[!]',
'INFO' : '[=]',
@@ -37,9 +44,10 @@ class QlBaseFormatter(logging.Formatter):
'ERROR' : '[x]'
}
def __init__(self, ql, *args, **kwargs):
def __init__(self, ql: Qiling, *args, **kwargs):
super().__init__(*args, **kwargs)
self.ql = weakref.proxy(ql)
self.ql: Qiling = weakref.proxy(ql)
def get_level_tag(self, level: str) -> str:
return self.__level_tag[level]
@@ -47,7 +55,7 @@ class QlBaseFormatter(logging.Formatter):
def get_thread_tag(self, thread: str) -> str:
return thread
def format(self, record: logging.LogRecord):
def format(self, record: LogRecord):
# In case we have multiple formatters, we have to keep a copy of the record.
record = copy.copy(record)
@@ -64,6 +72,7 @@ class QlBaseFormatter(logging.Formatter):
return super().format(record)
class QlColoredFormatter(QlBaseFormatter):
__level_color = {
'WARNING' : COLOR.YELLOW,
@@ -76,22 +85,24 @@ class QlColoredFormatter(QlBaseFormatter):
def get_level_tag(self, level: str) -> str:
s = super().get_level_tag(level)
return f'{self.__level_color[level]}{s}{COLOR.ENDC}'
return f'{self.__level_color[level]}{s}{COLOR.DEFAULT}'
def get_thread_tag(self, tid: str) -> str:
s = super().get_thread_tag(tid)
return f'{COLOR.GREEN}{s}{COLOR.ENDC}'
return f'{COLOR.GREEN}{s}{COLOR.DEFAULT}'
class RegexFilter(logging.Filter):
class RegexFilter(Filter):
def update_filter(self, regexp: str):
self._filter = re.compile(regexp)
def filter(self, record: logging.LogRecord):
def filter(self, record: LogRecord):
msg = record.getMessage()
return self._filter.match(msg) is not None
def resolve_logger_level(verbose: QL_VERBOSE) -> int:
return {
QL_VERBOSE.DISABLED : logging.CRITICAL,
@@ -102,6 +113,7 @@ def resolve_logger_level(verbose: QL_VERBOSE) -> int:
QL_VERBOSE.DUMP : logging.DEBUG
}[verbose]
def __is_color_terminal(stream: TextIO) -> bool:
"""Determine whether standard output is attached to a color terminal.
@@ -142,7 +154,8 @@ def __is_color_terminal(stream: TextIO) -> bool:
return handler(stream.fileno())
def setup_logger(ql, log_file: Optional[str], console: bool, log_override: Optional[logging.Logger], log_plain: bool):
def setup_logger(ql: Qiling, log_file: Optional[str], console: bool, log_override: Optional[Logger], log_plain: bool):
global QL_INSTANCE_ID
# If there is an override for our logger, then use it.
@@ -155,15 +168,19 @@ def setup_logger(ql, log_file: Optional[str], console: bool, log_override: Optio
# Disable propagation to avoid duplicate output.
log.propagate = False
# Clear all handlers and filters.
log.handlers = []
log.filters = []
log.handlers.clear()
log.filters.clear()
# Do we have console output?
if console:
handler = logging.StreamHandler()
handler = StreamHandler()
if log_plain or not __is_color_terminal(handler.stream):
# adhere to the NO_COLOR convention (see: https://no-color.org/)
no_color = os.getenv('NO_COLOR', False)
if no_color or log_plain or not __is_color_terminal(handler.stream):
formatter = QlBaseFormatter(ql, FMT_STR)
else:
formatter = QlColoredFormatter(ql, FMT_STR)
@@ -171,18 +188,25 @@ def setup_logger(ql, log_file: Optional[str], console: bool, log_override: Optio
handler.setFormatter(formatter)
log.addHandler(handler)
else:
handler = logging.NullHandler()
handler = NullHandler()
log.addHandler(handler)
# Do we have to write log to a file?
if log_file is not None:
handler = logging.FileHandler(log_file)
handler = FileHandler(log_file)
formatter = QlBaseFormatter(ql, FMT_STR)
handler.setFormatter(formatter)
log.addHandler(handler)
log.setLevel(logging.INFO)
# optimize logging speed by avoiding the collection of unnecesary logging properties
logging._srcfile = None
logging.logThreads = False
logging.logProcesses = False
logging.logMultiprocessing = False
return log
__all__ = ['RegexFilter', 'setup_logger', 'resolve_logger_level']
+8 -8
View File
@@ -22,14 +22,14 @@ IntHandler = Callable[[Qiling], None]
# http://www2.ift.ulaval.ca/~marchand/ift17583/dosints.pdf
handlers: Mapping[int, IntHandler] = {
0x10: int10.handler,
0x13: int13.handler,
0x15: int15.handler,
0x16: int16.handler,
0x19: int19.handler,
0x1a: int1a.handler,
0x20: int20.handler,
0x21: int21.handler
0x10: int10.handler,
0x13: int13.handler,
0x15: int15.handler,
0x16: int16.handler,
0x19: int19.handler,
0x1a: int1a.handler,
0x20: int20.handler,
0x21: int21.handler
}
__all__ = ['handlers']
+182 -182
View File
@@ -10,236 +10,236 @@ from typing import Mapping
from qiling import Qiling
COLORS_MAPPING = {
0: curses.COLOR_BLACK,
1: curses.COLOR_BLUE,
2: curses.COLOR_GREEN,
3: curses.COLOR_CYAN,
4: curses.COLOR_RED,
5: curses.COLOR_MAGENTA,
6: 9,
7: 7,
8: 8,
9: 6,
10: 10,
11: 14,
12: 9,
13: 13,
14: curses.COLOR_YELLOW,
15: curses.COLOR_WHITE
0: curses.COLOR_BLACK,
1: curses.COLOR_BLUE,
2: curses.COLOR_GREEN,
3: curses.COLOR_CYAN,
4: curses.COLOR_RED,
5: curses.COLOR_MAGENTA,
6: 9,
7: 7,
8: 8,
9: 6,
10: 10,
11: 14,
12: 9,
13: 13,
14: curses.COLOR_YELLOW,
15: curses.COLOR_WHITE
}
REVERSE_COLORS_MAPPING = {v : k for k, v in COLORS_MAPPING.items()}
def get_attr(color_pairs: Mapping[int, Mapping[int, int]], char: int) -> int:
fg = (char & 0x0f)
bg = (char & 0xf0) >> 4
fg = (char & 0x0f)
bg = (char & 0xf0) >> 4
# For blinking
attr = color_pairs[fg][bg & 0b0111]
# For blinking
attr = color_pairs[fg][bg & 0b0111]
if (bg & 0b1000) != 0:
attr |= curses.A_BLINK
if (bg & 0b1000) != 0:
attr |= curses.A_BLINK
return attr
return attr
def get_ch_non_blocking(scr) -> int:
scr.timeout(0)
key = scr.getch()
scr.timeout(-1)
scr.timeout(0)
key = scr.getch()
scr.timeout(-1)
return key
return key
def __leaf_00(ql: Qiling):
# time to set up curses
# copied from curses.wrapper
# time to set up curses
# copied from curses.wrapper
stdscr = curses.initscr()
curses.noecho()
curses.cbreak()
stdscr.keypad(True)
stdscr = curses.initscr()
curses.noecho()
curses.cbreak()
stdscr.keypad(True)
try:
curses.start_color()
except:
pass
try:
curses.start_color()
except:
pass
al = ql.arch.regs.al
al = ql.arch.regs.al
resolution = {
0x00 : (25, 40),
0x01 : (25, 40),
0x02 : (25, 80),
0x03 : (25, 80),
0x04 : (200, 320),
0x05 : (200, 320),
0x06 : (200, 640),
0x08 : (200, 160),
0x09 : (200, 320),
0x0a : (200, 640),
0x0d : (200, 320),
0x0e : (200, 640),
0x0f : (350, 640),
0x10 : (350, 640),
0x11 : (480, 640),
0x12 : (480, 640),
0x13 : (200, 320)
}.get(al)
resolution = {
0x00 : (25, 40),
0x01 : (25, 40),
0x02 : (25, 80),
0x03 : (25, 80),
0x04 : (200, 320),
0x05 : (200, 320),
0x06 : (200, 640),
0x08 : (200, 160),
0x09 : (200, 320),
0x0a : (200, 640),
0x0d : (200, 320),
0x0e : (200, 640),
0x0f : (350, 640),
0x10 : (350, 640),
0x11 : (480, 640),
0x12 : (480, 640),
0x13 : (200, 320)
}.get(al)
if resolution is None:
ql.log.exception(f'resolution not implemented (al: {al:#02x})')
raise NotImplementedError()
if resolution is None:
ql.log.exception(f'resolution not implemented (al: {al:#02x})')
raise NotImplementedError()
curses.resizeterm(*resolution)
curses.resizeterm(*resolution)
# Quoted from https://linux.die.net/man/3/resizeterm
#
# If ncurses is configured to supply its own SIGWINCH handler,
# the resizeterm function ungetch's a KEY_RESIZE which will be
# read on the next call to getch.
ch = get_ch_non_blocking(stdscr)
# Quoted from https://linux.die.net/man/3/resizeterm
#
# If ncurses is configured to supply its own SIGWINCH handler,
# the resizeterm function ungetch's a KEY_RESIZE which will be
# read on the next call to getch.
ch = get_ch_non_blocking(stdscr)
if ch == curses.KEY_RESIZE:
ql.log.info(f'terminal has been resized')
elif ch != -1:
curses.ungetch(ch)
if ch == curses.KEY_RESIZE:
ql.log.info(f'terminal has been resized')
elif ch != -1:
curses.ungetch(ch)
stdscr.scrollok(True)
stdscr.scrollok(True)
if not curses.has_colors():
ql.log.warning(f'your terminal does not support colors, content might not be displayed correctly')
if not curses.has_colors():
ql.log.warning(f'your terminal does not support colors, content might not be displayed correctly')
# https://en.wikipedia.org/wiki/BIOS_color_attributes
# blink support?
if curses.has_colors():
for fg in range(16):
for bg in range(16):
color_pair_index = 16 * fg + bg + 1
# https://en.wikipedia.org/wiki/BIOS_color_attributes
# blink support?
if curses.has_colors():
for fg in range(16):
for bg in range(16):
color_pair_index = 16 * fg + bg + 1
if fg not in ql.os.color_pairs:
ql.os.color_pairs[fg] = {}
if fg not in ql.os.color_pairs:
ql.os.color_pairs[fg] = {}
curses.init_pair(color_pair_index, COLORS_MAPPING[fg], COLORS_MAPPING[bg])
color_pair = curses.color_pair(color_pair_index)
curses.init_pair(color_pair_index, COLORS_MAPPING[fg], COLORS_MAPPING[bg])
color_pair = curses.color_pair(color_pair_index)
ql.os.color_pairs[fg][bg] = color_pair
ql.os.revese_color_pairs[color_pair] = (fg, bg)
ql.os.color_pairs[fg][bg] = color_pair
ql.os.revese_color_pairs[color_pair] = (fg, bg)
ql.os.stdscr = stdscr
ql.os.stdscr = stdscr
def __leaf_01(ql: Qiling):
# limited support
ch = ql.arch.regs.ch
# limited support
ch = ql.arch.regs.ch
if (ch & 0x20):
curses.curs_set(0)
if (ch & 0x20):
curses.curs_set(0)
def __leaf_02(ql: Qiling):
# page number ignored
dh = ql.arch.regs.dh # row
dl = ql.arch.regs.dl # column
# page number ignored
dh = ql.arch.regs.dh # row
dl = ql.arch.regs.dl # column
ql.os.stdscr.move(dh, dl)
ql.os.stdscr.move(dh, dl)
def __leaf_05(ql: Qiling):
# No idea how to implement, do nothing here.
ql.arch.regs.al = 0
# No idea how to implement, do nothing here.
ql.arch.regs.al = 0
def __leaf_06(ql: Qiling):
stdscr = ql.os.stdscr
stdscr = ql.os.stdscr
al = ql.arch.regs.al # lines to scroll
ch = ql.arch.regs.ch # row of upper-left cornner
cl = ql.arch.regs.cl # column of upper-left corner
dh = ql.arch.regs.dh # row of lower right corner
dl = ql.arch.regs.dl # column of lower righ corner
bh = ql.arch.regs.bh # color
al = ql.arch.regs.al # lines to scroll
ch = ql.arch.regs.ch # row of upper-left cornner
cl = ql.arch.regs.cl # column of upper-left corner
dh = ql.arch.regs.dh # row of lower right corner
dl = ql.arch.regs.dl # column of lower righ corner
bh = ql.arch.regs.bh # color
y, x = stdscr.getmaxyx()
cy, cx = stdscr.getyx()
attr = get_attr(ql.os.color_pairs, bh)
y, x = stdscr.getmaxyx()
cy, cx = stdscr.getyx()
attr = get_attr(ql.os.color_pairs, bh)
if ch != 0 or cl != 0 or dh != y - 1 or dl != x - 1:
ql.log.warning(f'Partial scroll is unsupported. Will scroll the whole page.')
ql.log.warning(f'Resolution: {y}x{x} but asked to scroll [({ch},{cl}), ({dh}, {dl})]')
if ch != 0 or cl != 0 or dh != y - 1 or dl != x - 1:
ql.log.warning(f'Partial scroll is unsupported. Will scroll the whole page.')
ql.log.warning(f'Resolution: {y}x{x} but asked to scroll [({ch},{cl}), ({dh}, {dl})]')
if al == 0:
stdscr.clear()
if al == 0:
stdscr.clear()
# Alternate way?
#for ln in range(y):
# stdscr.addstr(ln, 0, " " * x, attr)
# Alternate way?
#for ln in range(y):
# stdscr.addstr(ln, 0, " " * x, attr)
stdscr.bkgd(" ", attr)
stdscr.move(0, 0)
stdscr.bkgd(" ", attr)
stdscr.move(0, 0)
else:
stdscr.scroll(al)
ny = 0
else:
stdscr.scroll(al)
ny = 0
if cy - al < 0:
ny = 0
else:
ny = cy - al + 1
if cy - al < 0:
ny = 0
else:
ny = cy - al + 1
if al > y:
al = y
if al > y:
al = y
for ln in range(al):
stdscr.addstr(ny + ln, 0, " " * x, attr)
for ln in range(al):
stdscr.addstr(ny + ln, 0, " " * x, attr)
stdscr.move(cy, cx)
stdscr.move(cy, cx)
def __leaf_08(ql: Qiling):
stdscr = ql.os.stdscr
stdscr = ql.os.stdscr
if stdscr is None:
ql.arch.regs.ax = 0x0720
else:
cy, cx = stdscr.getyx()
inch = stdscr.inch(cy, cx)
attr = inch & curses.A_COLOR
ch = inch & 0xFF
ql.arch.regs.al = ch
pair_number = curses.pair_number(attr)
if stdscr is None:
ql.arch.regs.ax = 0x0720
else:
cy, cx = stdscr.getyx()
inch = stdscr.inch(cy, cx)
attr = inch & curses.A_COLOR
ch = inch & 0xFF
ql.arch.regs.al = ch
pair_number = curses.pair_number(attr)
fg, bg = curses.pair_content(pair_number)
orig_fg = REVERSE_COLORS_MAPPING[fg]
orig_bg = REVERSE_COLORS_MAPPING[bg]
fg, bg = curses.pair_content(pair_number)
orig_fg = REVERSE_COLORS_MAPPING[fg]
orig_bg = REVERSE_COLORS_MAPPING[bg]
if attr & curses.A_BLINK:
orig_bg |= 0b1000
if attr & curses.A_BLINK:
orig_bg |= 0b1000
ql.arch.regs.ah = ((orig_bg << 4) & orig_fg)
ql.arch.regs.ah = ((orig_bg << 4) & orig_fg)
def __leaf_0e(ql: Qiling):
al = ql.arch.regs.al
al = ql.arch.regs.al
ql.log.debug(f'echo: {al:02x} -> {curses.ascii.unctrl(al)}')
ql.log.debug(f'echo: {al:02x} -> {curses.ascii.unctrl(al)}')
stdscr = ql.os.stdscr
cy, cx = stdscr.getyx()
stdscr = ql.os.stdscr
cy, cx = stdscr.getyx()
# https://stackoverflow.com/questions/27674158/how-to-get-color-information-with-mvinch
# https://linux.die.net/man/3/inch
# https://github.com/mirror/ncurses/blob/master/include/curses.h.in#L1197
# wtf curses...
# https://stackoverflow.com/questions/27674158/how-to-get-color-information-with-mvinch
# https://linux.die.net/man/3/inch
# https://github.com/mirror/ncurses/blob/master/include/curses.h.in#L1197
# wtf curses...
if al == 0xa:
y, x = stdscr.getmaxyx()
if al == 0xa:
y, x = stdscr.getmaxyx()
# \n will erase current line with echochar, so we have to handle it carefully.
ql.log.info(f"Resolution: {x}x{y}, Cursor position: {cx},{cy}, Going to get a new line.")
# \n will erase current line with echochar, so we have to handle it carefully.
ql.log.info(f"Resolution: {x}x{y}, Cursor position: {cx},{cy}, Going to get a new line.")
if (y - 1) == cy:
# scroll doesn't affect our cursor
stdscr.scroll(1)
stdscr.move(cy, 0)
else:
stdscr.move(cy + 1, 0)
else:
attr = stdscr.inch(cy, cx) & curses.A_COLOR
if (y - 1) == cy:
# scroll doesn't affect our cursor
stdscr.scroll(1)
stdscr.move(cy, 0)
else:
stdscr.move(cy + 1, 0)
else:
attr = stdscr.inch(cy, cx) & curses.A_COLOR
stdscr.echochar(al, attr)
stdscr.echochar(al, attr)
# BIOS video support
@@ -247,23 +247,23 @@ def __leaf_0e(ql: Qiling):
# https://stanislavs.org/helppc/idx_interrupt.html
# implemented by curses
def handler(ql: Qiling):
ah = ql.arch.regs.ah
ah = ql.arch.regs.ah
leaffunc = {
0x00 : __leaf_00,
0x01 : __leaf_01,
0x02 : __leaf_02,
0x05 : __leaf_05,
0x06 : __leaf_06,
0x08 : __leaf_08,
0x0e : __leaf_0e
}.get(ah)
leaffunc = {
0x00 : __leaf_00,
0x01 : __leaf_01,
0x02 : __leaf_02,
0x05 : __leaf_05,
0x06 : __leaf_06,
0x08 : __leaf_08,
0x0e : __leaf_0e
}.get(ah)
if leaffunc is None:
ql.log.exception(f'leaf {ah:02x}h of INT 10h is not implemented')
raise NotImplementedError()
if leaffunc is None:
ql.log.exception(f'leaf {ah:02x}h of INT 10h is not implemented')
raise NotImplementedError()
leaffunc(ql)
leaffunc(ql)
if ql.os.stdscr is not None:
ql.os.stdscr.refresh()
if ql.os.stdscr is not None:
ql.os.stdscr.refresh()
+109 -109
View File
@@ -11,152 +11,152 @@ from qiling import Qiling
from .. import utils
class DiskError(IntEnum):
NoError = 0
BadCommand = 1
AddressNotFound = 2
DiskWriteProtectError = 3
SectorNotFound = 4
FixedDiskResetFailed = 5
DiskChangedOrRemoved = 6
BadFixedDiskParameterTable = 7
DMAOverrun = 8
DMAAcessAcrossBoundary = 9
BadFixedDiskSectorFlag = 10
BadFixedDiskCylinder = 11
UnsupportedTrack = 12
InvalidNumberofSectors = 13
NoError = 0
BadCommand = 1
AddressNotFound = 2
DiskWriteProtectError = 3
SectorNotFound = 4
FixedDiskResetFailed = 5
DiskChangedOrRemoved = 6
BadFixedDiskParameterTable = 7
DMAOverrun = 8
DMAAcessAcrossBoundary = 9
BadFixedDiskSectorFlag = 10
BadFixedDiskCylinder = 11
UnsupportedTrack = 12
InvalidNumberofSectors = 13
FixedDiskControlledDataAdressDetected = 14
FixedDiskDMAArbitrationLevelOutofRange = 15
ECCErrorOnRead = 16
RecoverableFixedDiskDataError = 17
ControllerError = 32
SeekFailure = 64
Timeout = 128
FixedDiskDriveNotReady = 170
FixedDiskUndefinedError = 187
FixedDiskWriteFault = 204
FixedDiskStatusError = 224
SenseOperationFailed = 255
ECCErrorOnRead = 16
RecoverableFixedDiskDataError = 17
ControllerError = 32
SeekFailure = 64
Timeout = 128
FixedDiskDriveNotReady = 170
FixedDiskUndefinedError = 187
FixedDiskWriteFault = 204
FixedDiskStatusError = 224
SenseOperationFailed = 255
def parse_dap(dapbs):
return struct.unpack("<BBHHHQ", dapbs)
return struct.unpack("<BBHHHQ", dapbs)
def __leaf_00(ql: Qiling):
ql.os.clear_cf()
ql.os.clear_cf()
def __leaf_02(ql: Qiling):
idx = ql.arch.regs.dl
idx = ql.arch.regs.dl
if not ql.os.fs_mapper.has_mapping(idx):
ql.log.warning(f'Warning: No such disk: {idx:#x}')
ql.arch.regs.ah = DiskError.BadCommand.value
ql.os.set_cf()
return
if not ql.os.fs_mapper.has_mapping(idx):
ql.log.warning(f'Warning: No such disk: {idx:#x}')
ql.arch.regs.ah = DiskError.BadCommand.value
ql.os.set_cf()
return
cylinder = ((ql.arch.regs.cx & 0xff00) >> 8) | ((ql.arch.regs.cx & 0xC0) << 2)
head = ql.arch.regs.dh
sector = ql.arch.regs.cx & 63
cnt = ql.arch.regs.al
cylinder = ((ql.arch.regs.cx & 0xff00) >> 8) | ((ql.arch.regs.cx & 0xC0) << 2)
head = ql.arch.regs.dh
sector = ql.arch.regs.cx & 63
cnt = ql.arch.regs.al
disk = ql.os.fs_mapper.open(idx, None)
content = disk.read_chs(cylinder, head, sector, cnt)
disk = ql.os.fs_mapper.open(idx, None)
content = disk.read_chs(cylinder, head, sector, cnt)
ql.mem.write(utils.linaddr(ql.arch.regs.es, ql.arch.regs.bx), content)
ql.os.clear_cf()
ql.arch.regs.ah = 0
ql.arch.regs.al = sector
ql.mem.write(utils.linaddr(ql.arch.regs.es, ql.arch.regs.bx), content)
ql.os.clear_cf()
ql.arch.regs.ah = 0
ql.arch.regs.al = sector
# @see: https://stanislavs.org/helppc/int_13-8.html
def __leaf_08(ql: Qiling):
idx = ql.arch.regs.dl
idx = ql.arch.regs.dl
if not ql.os.fs_mapper.has_mapping(idx):
ql.log.warning(f'Warning: No such disk: {idx:#x}')
ql.arch.regs.ah = DiskError.BadCommand.value
ql.os.set_cf()
return
if not ql.os.fs_mapper.has_mapping(idx):
ql.log.warning(f'Warning: No such disk: {idx:#x}')
ql.arch.regs.ah = DiskError.BadCommand.value
ql.os.set_cf()
return
disk = ql.os.fs_mapper.open(idx, None)
ql.arch.regs.dl = ql.os.fs_mapper.mapping_count()
ql.arch.regs.dh = disk.n_heads - 1
ql.arch.regs.bl = 0x4
ql.arch.regs.di = 0
ql.arch.regs.ds = 0
disk = ql.os.fs_mapper.open(idx, None)
ql.arch.regs.dl = ql.os.fs_mapper.mapping_count()
ql.arch.regs.dh = disk.n_heads - 1
ql.arch.regs.bl = 0x4
ql.arch.regs.di = 0
ql.arch.regs.ds = 0
n_sectors = min(disk.n_sectors, 63)
n_cylinders = min(disk.n_cylinders, 1023)
n_sectors = min(disk.n_sectors, 63)
n_cylinders = min(disk.n_cylinders, 1023)
cx = (n_sectors & 0b111111)
cx |= ((n_cylinders & 0b11) << 6)
cx |= (((n_cylinders & 0b1111111100) >> 2) << 8)
cx = (n_sectors & 0b111111)
cx |= ((n_cylinders & 0b11) << 6)
cx |= (((n_cylinders & 0b1111111100) >> 2) << 8)
ql.arch.regs.cx = cx
ql.arch.regs.ah = 0
ql.os.clear_cf()
ql.arch.regs.cx = cx
ql.arch.regs.ah = 0
ql.os.clear_cf()
def __leaf_41(ql: Qiling):
ql.arch.regs.ah = 0
# 1 -> Device Access using the packet structure.
# 2 -> Drive locking and ejecting.
# 4 -> Enhanced Disk Drive Support.
ql.arch.regs.bx = 0xaa55
ql.arch.regs.cx = 7
ql.arch.regs.ah = 0
# 1 -> Device Access using the packet structure.
# 2 -> Drive locking and ejecting.
# 4 -> Enhanced Disk Drive Support.
ql.arch.regs.bx = 0xaa55
ql.arch.regs.cx = 7
def __leaf_42(ql: Qiling):
idx = ql.arch.regs.dl
idx = ql.arch.regs.dl
if not ql.os.fs_mapper.has_mapping(idx):
ql.log.warning(f'Warning: No such disk: {idx:#x}')
ql.arch.regs.ah = DiskError.BadCommand.value
ql.os.set_cf()
return
if not ql.os.fs_mapper.has_mapping(idx):
ql.log.warning(f'Warning: No such disk: {idx:#x}')
ql.arch.regs.ah = DiskError.BadCommand.value
ql.os.set_cf()
return
dapbs = ql.mem.read(utils.linaddr(ql.arch.regs.ds, ql.arch.regs.si), 16)
_, _, cnt, offset, segment, lba = parse_dap(dapbs)
ql.log.info(f'Reading {cnt} sectors from disk {idx:#x} with LBA {lba}')
dapbs = ql.mem.read(utils.linaddr(ql.arch.regs.ds, ql.arch.regs.si), 16)
_, _, cnt, offset, segment, lba = parse_dap(dapbs)
ql.log.info(f'Reading {cnt} sectors from disk {idx:#x} with LBA {lba}')
disk = ql.os.fs_mapper.open(idx, None)
content = disk.read_sectors(lba, cnt)
ql.mem.write(utils.linaddr(segment, offset), content)
disk = ql.os.fs_mapper.open(idx, None)
content = disk.read_sectors(lba, cnt)
ql.mem.write(utils.linaddr(segment, offset), content)
ql.os.clear_cf()
ql.arch.regs.ah = 0
ql.os.clear_cf()
ql.arch.regs.ah = 0
def __leaf_43(ql: Qiling):
idx = ql.arch.regs.dl
idx = ql.arch.regs.dl
if not ql.os.fs_mapper.has_mapping(idx):
ql.log.info(f"Warning: No such disk: {hex(idx)}")
ql.arch.regs.ah = DiskError.BadCommand.value
ql.os.set_cf()
return
if not ql.os.fs_mapper.has_mapping(idx):
ql.log.info(f"Warning: No such disk: {hex(idx)}")
ql.arch.regs.ah = DiskError.BadCommand.value
ql.os.set_cf()
return
dapbs = ql.mem.read(utils.linaddr(ql.arch.regs.ds, ql.arch.regs.si), 16)
_, _, cnt, offset, segment, lba = parse_dap(dapbs)
ql.log.info(f'Writing {cnt} sectors to disk {idx:#x} with LBA {lba}')
dapbs = ql.mem.read(utils.linaddr(ql.arch.regs.ds, ql.arch.regs.si), 16)
_, _, cnt, offset, segment, lba = parse_dap(dapbs)
ql.log.info(f'Writing {cnt} sectors to disk {idx:#x} with LBA {lba}')
disk = ql.os.fs_mapper.open(idx, None)
buffer = ql.mem.read(utils.linaddr(segment, offset), cnt * disk.sector_size)
disk.write_sectors(lba, cnt, buffer)
disk = ql.os.fs_mapper.open(idx, None)
buffer = ql.mem.read(utils.linaddr(segment, offset), cnt * disk.sector_size)
disk.write_sectors(lba, cnt, buffer)
ql.os.clear_cf()
ql.arch.regs.ah = 0
ql.os.clear_cf()
ql.arch.regs.ah = 0
# @see: https://en.wikipedia.org/wiki/INT_13H
def handler(ql: Qiling):
ah = ql.arch.regs.ah
ah = ql.arch.regs.ah
leaffunc = {
0x00 : __leaf_00,
0x02 : __leaf_02,
0x08 : __leaf_08,
0x41 : __leaf_41,
0x42 : __leaf_42,
0x43 : __leaf_43
}.get(ah)
leaffunc = {
0x00 : __leaf_00,
0x02 : __leaf_02,
0x08 : __leaf_08,
0x41 : __leaf_41,
0x42 : __leaf_42,
0x43 : __leaf_43
}.get(ah)
if leaffunc is None:
ql.log.exception(f'leaf {ah:02x}h of INT 13h is not implemented')
raise NotImplementedError()
if leaffunc is None:
ql.log.exception(f'leaf {ah:02x}h of INT 13h is not implemented')
raise NotImplementedError()
leaffunc(ql)
leaffunc(ql)

Some files were not shown because too many files have changed in this diff Show More