mirror of
https://github.com/qilingframework/qiling.git
synced 2026-10-12 02:21:40 +00:00
Merge pull request #1368 from qilingframework/dev
Getting ready for 1.4.6
This commit is contained in:
@@ -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,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
|
||||
|
||||
@@ -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()
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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()
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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')])
|
||||
|
||||
@@ -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);
|
||||
# }
|
||||
# }
|
||||
# }
|
||||
# }
|
||||
|
||||
@@ -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')
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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 []
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
@@ -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"
|
||||
|
||||
@@ -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:
|
||||
|
||||
@@ -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()
|
||||
|
||||
@@ -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'))
|
||||
|
||||
|
||||
@@ -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')
|
||||
|
||||
@@ -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,))
|
||||
|
||||
@@ -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')
|
||||
|
||||
@@ -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()
|
||||
|
||||
@@ -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()
|
||||
|
||||
@@ -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()
|
||||
|
||||
@@ -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):
|
||||
|
||||
@@ -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())
|
||||
|
||||
@@ -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')
|
||||
|
||||
@@ -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)
|
||||
@@ -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")
|
||||
@@ -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
|
||||
|
||||
@@ -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
@@ -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
@@ -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
@@ -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
|
||||
|
||||
|
||||
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
|
||||
|
||||
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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)
|
||||
|
||||
@@ -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]:
|
||||
"""
|
||||
|
||||
@@ -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:
|
||||
"""
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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 = []
|
||||
|
||||
@@ -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]]
|
||||
@@ -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()
|
||||
|
||||
@@ -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
@@ -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
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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')
|
||||
|
||||
@@ -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):
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
@@ -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
|
||||
|
||||
@@ -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
@@ -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
|
||||
|
||||
@@ -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),
|
||||
]
|
||||
|
||||
|
||||
@@ -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')
|
||||
|
||||
@@ -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')
|
||||
|
||||
@@ -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')
|
||||
|
||||
@@ -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')
|
||||
|
||||
@@ -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
@@ -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()
|
||||
|
||||
@@ -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')
|
||||
|
||||
@@ -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')
|
||||
|
||||
@@ -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
|
||||
]
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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')
|
||||
|
||||
@@ -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')
|
||||
|
||||
@@ -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')
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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
|
||||
]
|
||||
|
||||
@@ -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
|
||||
]
|
||||
@@ -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')
|
||||
|
||||
@@ -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)
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
@@ -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)
|
||||
|
||||
|
||||
@@ -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
@@ -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
@@ -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']
|
||||
|
||||
@@ -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
@@ -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
@@ -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
Reference in New Issue
Block a user