44#
55
66import ctypes
7+ from typing import List , Tuple
78
89from qiling .core import Qiling
910
1011
1112class QlPeripheral :
1213 class Type (ctypes .Structure ):
14+ """ Define the reigister fields of peripheral.
15+
16+ Example:
17+ fields_ = [
18+ ('SR' , ctypes.c_uint32),
19+ ('DR' , ctypes.c_uint32),
20+ ('BRR' , ctypes.c_uint32),
21+ ('CR1' , ctypes.c_uint32),
22+ ('CR2' , ctypes.c_uint32),
23+ ('CR3' , ctypes.c_uint32),
24+ ('GTPR', ctypes.c_uint32),
25+ ]
26+ """
1327 _fields_ = []
1428
1529 def __init__ (self , ql : Qiling , label : str ):
@@ -18,6 +32,9 @@ def __init__(self, ql: Qiling, label: str):
1832 self .struct = type (self ).Type
1933
2034 def step (self ):
35+ """ Update the state of the peripheral,
36+ called after each instruction is executed
37+ """
2138 pass
2239
2340 def read (self , offset : int , size : int ) -> int :
@@ -27,25 +44,54 @@ def read(self, offset: int, size: int) -> int:
2744 def write (self , offset : int , size : int , value : int ):
2845 self .ql .log .debug (f'[{ self .label .upper ()} ] [W] { self .find_field (offset , size ):10s} = { hex (value )} ' )
2946
30- def in_field (self , field , offset , size ) :
47+ def in_field (self , field , offset : int , size : int ) -> bool :
3148 return field .offset <= offset and offset + size <= field .offset + field .size
3249
33- def find_field (self , offset , size ) -> str :
50+ def find_field (self , offset : int , size : int ) -> str :
51+ """ Return field names in interval [offset: offset + size],
52+ the function is designed for logging and debugging.
53+
54+ Returns:
55+ str: Field name
56+ """
57+
58+ field_list = []
3459 for name , _ in self .struct ._fields_ :
3560 field = getattr (self .struct , name )
36- if (offset , size ) == (field .offset , field .size ):
37- return name
38- if self .in_field (field , offset , size ):
39- return f'{ name } [{ offset - field .offset } :{ offset - field .offset + size } ]'
61+
62+ lbound = max (0 , offset - field .offset )
63+ ubound = min (offset + size - field .offset , field .size )
64+ if lbound < ubound :
65+ if lbound == 0 and ubound == field .size :
66+ field_list .append (name )
67+ else :
68+ field_list .append (f'{ name } [{ lbound } :{ ubound } ]' )
69+
70+ return ',' .join (field_list )
4071
4172 @property
42- def region (self ):
73+ def region (self ) -> List [Tuple ]:
74+ """Get the memory intervals occupyied by peripheral (base address = 0x0).
75+
76+ Returns:
77+ List[Tuple]: Memory intervals occupyied by peripheral
78+ """
4379 return [(0 , ctypes .sizeof (self .struct ))]
4480
4581 @property
46- def size (self ):
82+ def size (self ) -> int :
83+ """Calculate the memory size occupyied by peripheral.
84+
85+ Returns:
86+ int: Size
87+ """
4788 return sum (rbound - lbound for lbound , rbound in self .region )
4889
4990 @property
50- def base (self ):
91+ def base (self ) -> int :
92+ """Get the base address from QlHwManager.
93+
94+ Returns:
95+ int: Peripheral's base address
96+ """
5197 return self .ql .hw .region [self .label ][0 ][0 ]
0 commit comments