LoLeOp module includes these data types:
Io8, Io16, Io32, Io64, Mem8, Mem16, Mem32, Mem64, CpuId, Msr
These data types are based on LoleOp basic class
BitOp::_MemArray, BitOp::_MemCell,
BitOp::_CellCascade, rUnionOp::rUnionOp
To create LoLeOp new data type, this is the basic procedure.
1. Define new class, which is inherit from _MemCell, input(MemSet) output(MemGet) function.
2. create new data type by _MemArray instance.
Using LoLeOp.Mem.Mem8 as sample
from BitOp import _MemCell, _MemArray
#1. New class which is inherit from _MemCell.
class _Mem8 (_MemCell):
# 1.1 Output function.
def MemSet (self, Address, Value):
a = EfiPy.UINT8.from_address (Address)
a.value = Value & 0xFF
# 1.2 Input function
def MemGet (self, Address):
a = EfiPy.UINT8.from_address (Address)
return a.value
2. New data type.
Mem8 = _MemArray ("Mem8", 8, CellClass = _Mem8)
Comments:
MemSet (self, Address, Value)
#
# INPUT:
# self _MemArray class instance
# Address Memory address in integer
# Value value to set
#
# OUTPUT: <<None>>
#
MemGet (self, Address)
#
# INPUT:
# self _MemArray class instance
# Address Memory address in integer
#
# OUTPUT:
# value to get
#
_MemArray::__init__ (self, Name, Width = 8, **args)
#
# INPUT:
# self _MemArray class instance
# Name String of new data type name
# Width new data type bit width
# **args: {
# CellExt: Reference from _MemCell
# DictKey: Direct item in _MemArray: default None
# CellClass: bit field operation class
# }
#
By MemSet and MemGet parameter, there can be another data type Io8, Io16, Io32, Io64.
# _IoBit is inherit from _MemCell, it is for override
# output string in _MemCell
class _IoBit8 (_IoBit):
#
# ; Intel assembly syntax
# MOV DX, port
# IN AL, DX ; return value
#
def MemGet (self, port):
IoParams.p1 = port
ret = IoProc.execute(IoCodeGet8, params = IoParams, mode = 'int')
return ret & 0xFF
#
# ; Intel assembly syntax
# MOV DX, port
# MOV AL, val
# OUT AL, DX
#
def MemSet (self, port, val):
IoParams.p1 = port
IoParams.p2 = val & 0xFF
IoProc.execute(IoCodeSet8, params = IoParams, mode = 'int')
# create Io8 data type.
Io8 = _MemArray ("Io8", 8, CellClass = _IoBit8)
Saturday, January 13, 2018
EfiPy_r0.1.8(24622) release
EfiPy_r0.1.8(24622) 2018/01/13:
1. Fix library pAnalyzer import error
2. Add library EfiPyLib
3. Add EfiPyHexDump library
4. Add EfiPyVariableDump library
5. Add DmpBoot and DmpStore utilities
6. Correct case sentence error
7. Restructure ProcessorBinding module and add for AArch64, Arm, Ia32, X64
(for AArch64, Arm, Ia32, it adds ProcessorBinding.py, advance.)
(EfiPy does not run on these ISA AArch64, Arm, Ia32, yet.)
8. Change simple function to lambda
9. Correct missed class EFI_HII_FORM_PACKAGE_HDR
10. Remove redundant code
11. Move EfiPyShellPkg to EfiPyLib and rename to EfiPyShell
12. LoLeOp: Change class name from _CellCOnj to _CellCascade
1. Fix library pAnalyzer import error
2. Add library EfiPyLib
3. Add EfiPyHexDump library
4. Add EfiPyVariableDump library
5. Add DmpBoot and DmpStore utilities
6. Correct case sentence error
7. Restructure ProcessorBinding module and add for AArch64, Arm, Ia32, X64
(for AArch64, Arm, Ia32, it adds ProcessorBinding.py, advance.)
(EfiPy does not run on these ISA AArch64, Arm, Ia32, yet.)
8. Change simple function to lambda
9. Correct missed class EFI_HII_FORM_PACKAGE_HDR
10. Remove redundant code
11. Move EfiPyShellPkg to EfiPyLib and rename to EfiPyShell
12. LoLeOp: Change class name from _CellCOnj to _CellCascade
Monday, January 8, 2018
LoLeOp Basic operation
As address 0xC0000000 and 0xD0000000 an example.
#
# +---- qMem1 = [0xC0000000]
# +---- qMem1 = Mem8[0xC0000000][:]
# +---- Mem8[0xC0000000]
# | bit bit
# | 0 1
# | +---+---------+
# | Address V V |
# \ +-----------+---+---+---+---+---+---+---+---+ |
# +-------> |0xC0000000 | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | |
# +-----------+---+---+---+---+---+---+---+---+ |
# ^ ^ ^ |
# | | | |
# pReg1 = Mem8[0xC0000000][1:2] --+ | | |
# pReg1[0] -----------------------+ | | |
# rReg1 = pReg1 ------------------+---+ | |
# Mem8[0xC0000000][1:2] ----------+---+ | |
# Mem8[0xC0000000][2:1] ----------+---+ | |
# | |
# Mem8[0xC0000000][-1] -----------------------------------+ |
# |
# +---- qMem2 = Mem8[0xD0000000][:] |
# +---- Mem8[0xD0000000] |
# +---- Mem8[0xD0000000][:] |
# | |
# | +-------------------------------------------------------+
# | |
# | +--- cReg1 = Mem8[Mem8[0xC0000000][5:6], Mem8[0xD0000000][3:5]]
# | +--- cReg1 = Mem8[pReg1, pReg2]
# | +--- cReg2 = cReg1
# | | bit bit
# | | 2 3
# | +--------------------------+---+
# | | |
# | Address V V
# \ +-----------+---+---+---+---+---+---+---+---+
# +-> |0xD0000000 | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 |
# +-----------+---+---+---+---+---+---+---+---+
# ^ ^ ^
# pReg2 = Mem8[0xD0000000][5:6] | | |
# Mem8[0xD0000000][5:6] -------------------+---+ |
# Mem8[0xD0000000][6:5] -------------------+---+ |
# |
# Mem8[0xD0000000][-1] ----------------------------+
#
from LoLeOp.Mem import Mem8, Mem16, Mem32, Mem64
qMem1 = Mem8[0xC0000000]
pReg1 = Mem8[0xC0000000][1:2]
qMem2 = Mem8[0xD0000000]
pReg2 = Mem8[0xD0000000][5:6]
cReg1 = Mem8[Mem8[0xC0000000][5:6], Mem8[0xD0000000][3:5]]
cReg2 = Mem8[pReg1, pReg2]
Mem8[0xC0000000] means an object pointer to address 0xC0000000.
qMem1 = Mem8[0xC0000000] means qMem1 is an variable pointer to address 0xC0000000.
If value at address 0xC0000000 is changed by hardware or by another process,
value of qMem1 and Mem8[0xC0000000] pointer to are changed at next statement for reading
qMem1 and Mem8[0xC0000000].
qMem2 and Mem8[0xD0000000] have the same behavior as qMem1.
pReg1 and Mem8[0xC0000000][1:2] means bit 1 and bit 2 value of address 0xC0000000.
pReg2 and Mem8[0xC0000000][5:6] have the same behavior as pReg1.
cReg1 and cReg2 are cascade bits status from Mem8[0xC0000000][5:6] and Mem8[0xD0000000][3:5].
1. Read value from memory address 0xC0000000
Python program with LoLeOp library:
from LoLeOp.Mem import Mem8, Mem16, Mem32, Mem64
#
# // C language
# printf ("0x%02X\n", *(volatile unsigned char *)0xC0000000);
#
print "0x%02X" % Mem8[0xC0000000]
#
# Create variable qMem1 pointer to 0xC0000000
#
# // C language, similar behavior not all the same as LoLeOp
# volatile unsigned char *qMem1 = (volatile unsigned char *)0xC0000000;
#
qMem1 = Mem8[0xC0000000]
But Python statement using LoLeOp library
qMem1[0] # This means the 0 bit of address 0xC0000000 with LoLeOp data type.
is not equal to C language statment
qMem1[0]; // This means: (volatile unsigned char *)0xC0000000[0];
#
# Create variable rMem1 with the same address of qMem1
#
# // C language
# volatile unsigned char *rMem1 = qMem1
#
rMem1 = qMem1
2. Get bits value from memory address 0xC0000000.
#
# Get bit 1 value in address 0xC0000000
#
# { // C language
# unsigned char mask = 1;
# (*(volatile unsigned char *)0xC0000000 >> 0x01 ) & mask;
# }
#
Mem8[0xC0000000][1]
Get last bit(bit 7) value in address 0xC0000000
Mem8[0xC0000000][-1]
Get bit 2 and set bit 1 value in address 0xC0000000
Mem8[0xC0000000][2:1]
Mem8[0xC0000000][1:2] # It is another statement.
Set pReg1 as object for bit 2 and bit 1 in address 0xC0000000
qMem1 = Mem8[0xC0000000]
pReg1 = Mem8[0xC0000000][2:1]
pReg1 = Mem8[0xC0000000][1:2] # It is another statement.
pReg1 = qMem1[1:2]
pReg1 = qMem1[2:1]
Following C language has similar result with above python code. But it is
hard to get the same result as LoLeOp.
unsigned char pReg1 (void)
{
volatile unsigned char *qMem1 = (volatile unsigned char *)0xC0000000;
return (*qMem1 >> 1) & 0x03;
}
Get bit 0 of pReg1, that is Mem8[0xC0000000][1], too.
pReg1[0]
Set rReg1 as pReg1, that is rReg1 is Mem8[0xC0000000][2:1], too.
rReg1 = pReg1
Get bit 0 of rReg1, that is Mem8[0xC0000000][1], too.
rReg1[0]
Get all bit in rReg1, that is Mem8[0xC0000000][2:1], too.
rReg1[:]
rReg1[0:-1]
rReg1[-1:0]
Set sReg1 as bit 0 of rReg1, that is sReg1 is Mem8[0xC0000000][1], too.
sReg1 = rReg1[0]
3. Set value in memory address 0xC0000000
Set value of address 0xC0000000 as 3. Python code with LoLeOp library:
from LoLeOp.Mem import Mem8, Mem16, Mem32, Mem64
qMem1 = Mem8[0xC0000000]
rMem1 = qMem1
#
# *(volatile unsigned char *)0xC0000000 = (unsigned char)3;
# following Python statement are the same.
#
Mem8[0xC0000000] = 3
qMem1[:] = 3
rMem1[:] = 3
Note: qMem1 = 3, qMem1's data type will be int, not LoLeOp Mem8.
4. Set bits value in memory address 0xC0000000.
#
# Get bit 1 value in address 0xC0000000
#
# { // C language
# unsigned char mask = 1;
# (*(volatile unsigned char *)0xC0000000 >> 0x01 ) & mask;
# }
#
Mem8[0xC0000000][1]
Set last bit(bit 7) value in address 0xC0000000 as 1
Mem8[0xC0000000][-1] = 1
Set bit 2 and set bit 1 in address 0xC0000000 as 2
Mem8[0xC0000000][2:1] = 2
Mem8[0xC0000000][1:2] = 2 # It is another statement.
Set pReg1 as bit 2 and set bit 1 in address 0xC0000000
pReg1 = Mem8[0xC0000000][2:1]
And set bit 1 of pReg1 as 0.
pReg1 = Mem8[0xC0000000][2:1]
pReg1[1] = 0
Mem8[0xC0000000][2] = 0
5. LoLeOp attribute
LoLeOp are new created class (data type) from current Python programming.
It transfer to integer as following python code
qMem1 = Mem8[0xC0000000]
pReg1 = Mem8[0xC0000000][1:2]
int (Mem8[0xC0000000])
int (qMem1)
int (pReg1)
print "%02X" % qMem1[0xC0000000]
print "%02X" % qMem1
print "%02X" % pReg1
It output to string as following python code
qMem1 = Mem8[0xC0000000]
pReg1 = Mem8[0xC0000000][1:2]
str (Mem8[0xC0000000])
str (qMem1)
str (pReg1)
print "%02X", Mem8[0xC0000000]
print "%02X", qMem1
print "%02X", pReg1
Return bit numbers of LoLeOp object
len (Mem8[0xC0000000]) # return 8
len (pReg1) # return 2
len (qMem1) # return 8
6. Logic operation
LoLeOp support these logic operation and return boolean data type (True or False).
These are legal logic operation
qMem1 = Mem8[0xC0000000]
qMem2 = Mem8[0xD0000000]
pReg1 = Mem8[0xC0000000][1:2]
pReg2 = Mem8[0xD0000000][6:5]
Mem8[0xC0000000] < Mem8[0xD0000000]
Mem8[0xC0000000][2:5] < Mem8[0xD0000000][2:5]
qMem1 < qMem2
qMem1[2:5] < qMem2[2:5]
pReg1 < pReg2
pReg1[1] < pReg2[1]
Mem8[0xC0000000] <= Mem8[0xD0000000]
Mem8[0xC0000000][2:5] <= Mem8[0xD0000000][2:5]
qMem1 <= qMem2
qMem1[2:5] <= qMem2[2:5]
pReg1 <= pReg2
pReg1[1] <= pReg2[1]
Mem8[0xC0000000] == Mem8[0xD0000000]
Mem8[0xC0000000][2:5] == Mem8[0xD0000000][2:5]
qMem1 == qMem2
qMem1[2:5] == qMem2[2:5]
pReg1 == pReg2
pReg1[1] == pReg2[1]
Mem8[0xC0000000] != Mem8[0xD0000000]
Mem8[0xC0000000][2:5] != Mem8[0xD0000000][2:5]
qMem1 != qMem2
qMem1[2:5] != qMem2[2:5]
pReg1 != pReg2
pReg1[1] != pReg2[1]
Mem8[0xC0000000] > Mem8[0xD0000000]
Mem8[0xC0000000][2:5] > Mem8[0xD0000000][2:5]
qMem1 > qMem2
qMem1[2:5] > qMem2[2:5]
pReg1 > pReg2
pReg1[1] > pReg2[1]
Mem8[0xC0000000] >= Mem8[0xD0000000]
Mem8[0xC0000000][2:5] >= Mem8[0xD0000000][2:5]
qMem1 >= qMem2
qMem1[2:5] >= qMem2[2:5]
pReg1 >= pReg2
pReg1[1] >= pReg2[1]
not pReg1
7. Arithmetic operation and bit operation
All LoLeOp arithmetic operation and bit operation return integer data type. that is
qMem1 = Mem8[0xC0000000]
qMem2 = Mem8[0xD0000000]
pReg1 = Mem8[0xC0000000][1:2]
pReg2 = Mem8[0xD0000000][6:5]
TestValue1 = Mem8[0xC0000000] + Mem8[0xD0000000]
TestValue2 = qMem1 - qMem2
TestValue3 = pReg1 * pReg2
TestValue4 = qMem1 / qMem2
TestValue5 = qMem1
TestValue5 += qMem1
TestValue6 = qMem1 << 3
TestValue7 = qMem1 >> 1
TestValue8 = qMem1 & qMem2
TestValue9 = qMem1 | qMem2
TestValue10 = qMem1 ^ qMem2
TestValue[1...10] are ineteger data type, not LoLeOp type.
LoLeOp support any arithmetic operation and bit operation defined in Python.
Another note:
Mem8[0xC0000000] += 3 is equal to these statement
t = Mem8[0xC0000000] + 3 # t data type is integer
Mem8[0xC0000000] = 3 # write value t back to Mem8[0xD0000000]
8. cascade
cascade in LoLeOp is another data type present bits in different address
qMem1 = Mem8[0xC0000000]
qMem2 = Mem8[0xD0000000]
cReg1 = Mem8[Mem8[0xC0000000][5:6], Mem8[0xD0000000][3:5]]
cReg1 = Mem8[pReg1, pReg2]
cReg2 = cReg1
cReg1 and cReg2 are the same with following bit sequence present when it
convert to integer. Its length is 4 (4 bits width)
bit4 bit3 bit2 bit1 bit0
qMem2[5] qMem2[4] qMem2[3] qMem1[6] qMem1[5]
Any read/write operation affect corresponding bit position.
#
# +---- qMem1 = [0xC0000000]
# +---- qMem1 = Mem8[0xC0000000][:]
# +---- Mem8[0xC0000000]
# | bit bit
# | 0 1
# | +---+---------+
# | Address V V |
# \ +-----------+---+---+---+---+---+---+---+---+ |
# +-------> |0xC0000000 | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | |
# +-----------+---+---+---+---+---+---+---+---+ |
# ^ ^ ^ |
# | | | |
# pReg1 = Mem8[0xC0000000][1:2] --+ | | |
# pReg1[0] -----------------------+ | | |
# rReg1 = pReg1 ------------------+---+ | |
# Mem8[0xC0000000][1:2] ----------+---+ | |
# Mem8[0xC0000000][2:1] ----------+---+ | |
# | |
# Mem8[0xC0000000][-1] -----------------------------------+ |
# |
# +---- qMem2 = Mem8[0xD0000000][:] |
# +---- Mem8[0xD0000000] |
# +---- Mem8[0xD0000000][:] |
# | |
# | +-------------------------------------------------------+
# | |
# | +--- cReg1 = Mem8[Mem8[0xC0000000][5:6], Mem8[0xD0000000][3:5]]
# | +--- cReg1 = Mem8[pReg1, pReg2]
# | +--- cReg2 = cReg1
# | | bit bit
# | | 2 3
# | +--------------------------+---+
# | | |
# | Address V V
# \ +-----------+---+---+---+---+---+---+---+---+
# +-> |0xD0000000 | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 |
# +-----------+---+---+---+---+---+---+---+---+
# ^ ^ ^
# pReg2 = Mem8[0xD0000000][5:6] | | |
# Mem8[0xD0000000][5:6] -------------------+---+ |
# Mem8[0xD0000000][6:5] -------------------+---+ |
# |
# Mem8[0xD0000000][-1] ----------------------------+
#
from LoLeOp.Mem import Mem8, Mem16, Mem32, Mem64
qMem1 = Mem8[0xC0000000]
pReg1 = Mem8[0xC0000000][1:2]
qMem2 = Mem8[0xD0000000]
pReg2 = Mem8[0xD0000000][5:6]
cReg1 = Mem8[Mem8[0xC0000000][5:6], Mem8[0xD0000000][3:5]]
cReg2 = Mem8[pReg1, pReg2]
Mem8[0xC0000000] means an object pointer to address 0xC0000000.
qMem1 = Mem8[0xC0000000] means qMem1 is an variable pointer to address 0xC0000000.
If value at address 0xC0000000 is changed by hardware or by another process,
value of qMem1 and Mem8[0xC0000000] pointer to are changed at next statement for reading
qMem1 and Mem8[0xC0000000].
qMem2 and Mem8[0xD0000000] have the same behavior as qMem1.
pReg1 and Mem8[0xC0000000][1:2] means bit 1 and bit 2 value of address 0xC0000000.
pReg2 and Mem8[0xC0000000][5:6] have the same behavior as pReg1.
cReg1 and cReg2 are cascade bits status from Mem8[0xC0000000][5:6] and Mem8[0xD0000000][3:5].
1. Read value from memory address 0xC0000000
Python program with LoLeOp library:
from LoLeOp.Mem import Mem8, Mem16, Mem32, Mem64
#
# // C language
# printf ("0x%02X\n", *(volatile unsigned char *)0xC0000000);
#
print "0x%02X" % Mem8[0xC0000000]
#
# Create variable qMem1 pointer to 0xC0000000
#
# // C language, similar behavior not all the same as LoLeOp
# volatile unsigned char *qMem1 = (volatile unsigned char *)0xC0000000;
#
qMem1 = Mem8[0xC0000000]
But Python statement using LoLeOp library
qMem1[0] # This means the 0 bit of address 0xC0000000 with LoLeOp data type.
is not equal to C language statment
qMem1[0]; // This means: (volatile unsigned char *)0xC0000000[0];
#
# Create variable rMem1 with the same address of qMem1
#
# // C language
# volatile unsigned char *rMem1 = qMem1
#
rMem1 = qMem1
2. Get bits value from memory address 0xC0000000.
#
# Get bit 1 value in address 0xC0000000
#
# { // C language
# unsigned char mask = 1;
# (*(volatile unsigned char *)0xC0000000 >> 0x01 ) & mask;
# }
#
Mem8[0xC0000000][1]
Get last bit(bit 7) value in address 0xC0000000
Mem8[0xC0000000][-1]
Get bit 2 and set bit 1 value in address 0xC0000000
Mem8[0xC0000000][2:1]
Mem8[0xC0000000][1:2] # It is another statement.
Set pReg1 as object for bit 2 and bit 1 in address 0xC0000000
qMem1 = Mem8[0xC0000000]
pReg1 = Mem8[0xC0000000][2:1]
pReg1 = Mem8[0xC0000000][1:2] # It is another statement.
pReg1 = qMem1[1:2]
pReg1 = qMem1[2:1]
Following C language has similar result with above python code. But it is
hard to get the same result as LoLeOp.
unsigned char pReg1 (void)
{
volatile unsigned char *qMem1 = (volatile unsigned char *)0xC0000000;
return (*qMem1 >> 1) & 0x03;
}
Get bit 0 of pReg1, that is Mem8[0xC0000000][1], too.
pReg1[0]
Set rReg1 as pReg1, that is rReg1 is Mem8[0xC0000000][2:1], too.
rReg1 = pReg1
Get bit 0 of rReg1, that is Mem8[0xC0000000][1], too.
rReg1[0]
Get all bit in rReg1, that is Mem8[0xC0000000][2:1], too.
rReg1[:]
rReg1[0:-1]
rReg1[-1:0]
Set sReg1 as bit 0 of rReg1, that is sReg1 is Mem8[0xC0000000][1], too.
sReg1 = rReg1[0]
3. Set value in memory address 0xC0000000
Set value of address 0xC0000000 as 3. Python code with LoLeOp library:
from LoLeOp.Mem import Mem8, Mem16, Mem32, Mem64
qMem1 = Mem8[0xC0000000]
rMem1 = qMem1
#
# *(volatile unsigned char *)0xC0000000 = (unsigned char)3;
# following Python statement are the same.
#
Mem8[0xC0000000] = 3
qMem1[:] = 3
rMem1[:] = 3
Note: qMem1 = 3, qMem1's data type will be int, not LoLeOp Mem8.
4. Set bits value in memory address 0xC0000000.
#
# Get bit 1 value in address 0xC0000000
#
# { // C language
# unsigned char mask = 1;
# (*(volatile unsigned char *)0xC0000000 >> 0x01 ) & mask;
# }
#
Mem8[0xC0000000][1]
Set last bit(bit 7) value in address 0xC0000000 as 1
Mem8[0xC0000000][-1] = 1
Set bit 2 and set bit 1 in address 0xC0000000 as 2
Mem8[0xC0000000][2:1] = 2
Mem8[0xC0000000][1:2] = 2 # It is another statement.
Set pReg1 as bit 2 and set bit 1 in address 0xC0000000
pReg1 = Mem8[0xC0000000][2:1]
And set bit 1 of pReg1 as 0.
pReg1 = Mem8[0xC0000000][2:1]
pReg1[1] = 0
Mem8[0xC0000000][2] = 0
5. LoLeOp attribute
LoLeOp are new created class (data type) from current Python programming.
It transfer to integer as following python code
qMem1 = Mem8[0xC0000000]
pReg1 = Mem8[0xC0000000][1:2]
int (Mem8[0xC0000000])
int (qMem1)
int (pReg1)
print "%02X" % qMem1[0xC0000000]
print "%02X" % qMem1
print "%02X" % pReg1
It output to string as following python code
qMem1 = Mem8[0xC0000000]
pReg1 = Mem8[0xC0000000][1:2]
str (Mem8[0xC0000000])
str (qMem1)
str (pReg1)
print "%02X", Mem8[0xC0000000]
print "%02X", qMem1
print "%02X", pReg1
Return bit numbers of LoLeOp object
len (Mem8[0xC0000000]) # return 8
len (pReg1) # return 2
len (qMem1) # return 8
6. Logic operation
LoLeOp support these logic operation and return boolean data type (True or False).
These are legal logic operation
qMem1 = Mem8[0xC0000000]
qMem2 = Mem8[0xD0000000]
pReg1 = Mem8[0xC0000000][1:2]
pReg2 = Mem8[0xD0000000][6:5]
Mem8[0xC0000000] < Mem8[0xD0000000]
Mem8[0xC0000000][2:5] < Mem8[0xD0000000][2:5]
qMem1 < qMem2
qMem1[2:5] < qMem2[2:5]
pReg1 < pReg2
pReg1[1] < pReg2[1]
Mem8[0xC0000000] <= Mem8[0xD0000000]
Mem8[0xC0000000][2:5] <= Mem8[0xD0000000][2:5]
qMem1 <= qMem2
qMem1[2:5] <= qMem2[2:5]
pReg1 <= pReg2
pReg1[1] <= pReg2[1]
Mem8[0xC0000000] == Mem8[0xD0000000]
Mem8[0xC0000000][2:5] == Mem8[0xD0000000][2:5]
qMem1 == qMem2
qMem1[2:5] == qMem2[2:5]
pReg1 == pReg2
pReg1[1] == pReg2[1]
Mem8[0xC0000000] != Mem8[0xD0000000]
Mem8[0xC0000000][2:5] != Mem8[0xD0000000][2:5]
qMem1 != qMem2
qMem1[2:5] != qMem2[2:5]
pReg1 != pReg2
pReg1[1] != pReg2[1]
Mem8[0xC0000000] > Mem8[0xD0000000]
Mem8[0xC0000000][2:5] > Mem8[0xD0000000][2:5]
qMem1 > qMem2
qMem1[2:5] > qMem2[2:5]
pReg1 > pReg2
pReg1[1] > pReg2[1]
Mem8[0xC0000000] >= Mem8[0xD0000000]
Mem8[0xC0000000][2:5] >= Mem8[0xD0000000][2:5]
qMem1 >= qMem2
qMem1[2:5] >= qMem2[2:5]
pReg1 >= pReg2
pReg1[1] >= pReg2[1]
not pReg1
7. Arithmetic operation and bit operation
All LoLeOp arithmetic operation and bit operation return integer data type. that is
qMem1 = Mem8[0xC0000000]
qMem2 = Mem8[0xD0000000]
pReg1 = Mem8[0xC0000000][1:2]
pReg2 = Mem8[0xD0000000][6:5]
TestValue1 = Mem8[0xC0000000] + Mem8[0xD0000000]
TestValue2 = qMem1 - qMem2
TestValue3 = pReg1 * pReg2
TestValue4 = qMem1 / qMem2
TestValue5 = qMem1
TestValue5 += qMem1
TestValue6 = qMem1 << 3
TestValue7 = qMem1 >> 1
TestValue8 = qMem1 & qMem2
TestValue9 = qMem1 | qMem2
TestValue10 = qMem1 ^ qMem2
TestValue[1...10] are ineteger data type, not LoLeOp type.
LoLeOp support any arithmetic operation and bit operation defined in Python.
Another note:
Mem8[0xC0000000] += 3 is equal to these statement
t = Mem8[0xC0000000] + 3 # t data type is integer
Mem8[0xC0000000] = 3 # write value t back to Mem8[0xD0000000]
8. cascade
cascade in LoLeOp is another data type present bits in different address
qMem1 = Mem8[0xC0000000]
qMem2 = Mem8[0xD0000000]
cReg1 = Mem8[Mem8[0xC0000000][5:6], Mem8[0xD0000000][3:5]]
cReg1 = Mem8[pReg1, pReg2]
cReg2 = cReg1
cReg1 and cReg2 are the same with following bit sequence present when it
convert to integer. Its length is 4 (4 bits width)
bit4 bit3 bit2 bit1 bit0
qMem2[5] qMem2[4] qMem2[3] qMem1[6] qMem1[5]
Any read/write operation affect corresponding bit position.
Tuesday, January 2, 2018
LoLeOp Introduction
LoLeOp (Low Level Operation) can access (Read/Write) system memory/information in bit unit.
To get bit 2 at memory address 0xC0000000: Mem8[0xC0000000][2]
To get bit 3, 4, 5 at memory address 0xC0000000: Mem8[0xC0000000][3:5]
To set bit 2 at memory address 0xC0000000 as 1: Mem8[0xC0000000][2] = 1
To set bit 3, 4, 5 at memory address 0xC0000000 as 3: Mem8[0xC0000000][5:3] = 3
In hardware description, it often provides this kind of register tables.
(PCI BAR Address Map as example)
BAR0L: BAR0 Lower Address Map (offset 0x010)
Reset: 0000_0000h.
+-------+--------------+------+-------------------------------------------+
| Bits | Name | Attr | Description |
+-------+--------------+------+-------------------------------------------+
| 31:17 | BaseAddr | R/w | Indicates the Addr[31:17] of the base |
| | | | address. |
+-------+--------------+------+-------------------------------------------+
| 16:4 | Reserved | | |
+-------+--------------+------+-------------------------------------------+
| 3 | Prefetchable | R/w | Indicates BAR 0 is prefetchable. |
+-------+--------------+------+-------------------------------------------+
| 2:1 | Type | R/w | Indicates BAR 0 is in a 64-bit access |
| | | | space. |
+-------+--------------+------+-------------------------------------------+
| 0 | Space | R/w | Indicates BAR 0 is a memory space. |
+-------+--------------+------+-------------------------------------------+
BAR0H: BAR0 Upper Address Map (offset 0x014)
Reset: 0000_0000h.
+-------+--------------+------+-------------------------------------------+
| Bits | Name | Attr | Description |
+-------+--------------+------+-------------------------------------------+
| 31:0 | BaseAddr | R/w | Indicates the Addr[63:32] of the base |
| | | | address. |
+-------+--------------+------+-------------------------------------------+
If PCI bus 1, device 1, function 2 Configuration Space maps in MMIO address is 0xE010A000. Each field of registers BAR0 can be read from 0xE010A010 and 0xE010A014. ( *(UINT32 *)0xE010A010 and *(UINT32 *)0xE010A014 )
It is more programmable/Readable with LoLeOp library.
from LoLeOp.Mem import Mem8, Mem16, Mem32, Mem64
#
# Read each register fields of BAR0 (Bus 1, Device 1, Function 2)
#
BAR0L = 0xE010A010
BAR0H = 0xE010A014
print 'Register "Prefetchable": 0x%02X' % Mem32[BAR0L][0]
print 'Register "Type": 0x%02X' % Mem32[BAR0L][2:1]
print 'Register "Space": 0x%02X' % Mem32[BAR0L][3]
print 'Register "BaseAddr": 0x%016X' % (Mem32[Mem32[BAR0L][31:17], Mem32[BAR0H]] << 17)
#
# Setting BaseAddr of BAR0 as 0xD0000000 >> 17
#
Mem32[Mem32[BAR0L][31:17], Mem32[BAR0H]] = 0xD0000000 >> 17
In above Python code Mem32[BAR0L][2:1], It has the same effect of C language.
{
UINT32 BAR0L = 0xE010A010;
Printf (L"Register \"Type\": 0x%02X", (*((UINT32 *)0xE010A010) >> 1) & 0x03);
}
Mem32[BAR0L] means an instance at address 0xE010A010 with 32 bits width. Mem32[BAR0L][2:1] and Mem32[BAR0L][1:2] means an instance with bit 1 and bit 2 at address 0xE010A010. Mem32[Mem32[BAR0L][31:17], Mem32[BAR0H]] means an instance includes Mem32[BAR0H] and Mem32[BAR0L][31:17].
LoLeOp includes these application classes
Mem8, Mem16, Mem32, Mem64
Memory (including mmio) Read/Write in any memory area.
Io8, Io16, Io32, Io64
Io Read/Write
Cmos
cmos area data read/write
CpuId
x86 cpuid instruction input EAX and ECX (optional), output EAX, EBX, ECX, EDX.
Msr
x86 rdmsr/wrmsr instruction with input ECX, output EDX:EAX.
LeLoOp includes these basic classes
_MemArray, _MemCell, _CellConj, rUnionOp
Samples:
Host\AppPkg\LoLeOp\Samples
To get bit 2 at memory address 0xC0000000: Mem8[0xC0000000][2]
To get bit 3, 4, 5 at memory address 0xC0000000: Mem8[0xC0000000][3:5]
To set bit 2 at memory address 0xC0000000 as 1: Mem8[0xC0000000][2] = 1
To set bit 3, 4, 5 at memory address 0xC0000000 as 3: Mem8[0xC0000000][5:3] = 3
In hardware description, it often provides this kind of register tables.
(PCI BAR Address Map as example)
BAR0L: BAR0 Lower Address Map (offset 0x010)
Reset: 0000_0000h.
+-------+--------------+------+-------------------------------------------+
| Bits | Name | Attr | Description |
+-------+--------------+------+-------------------------------------------+
| 31:17 | BaseAddr | R/w | Indicates the Addr[31:17] of the base |
| | | | address. |
+-------+--------------+------+-------------------------------------------+
| 16:4 | Reserved | | |
+-------+--------------+------+-------------------------------------------+
| 3 | Prefetchable | R/w | Indicates BAR 0 is prefetchable. |
+-------+--------------+------+-------------------------------------------+
| 2:1 | Type | R/w | Indicates BAR 0 is in a 64-bit access |
| | | | space. |
+-------+--------------+------+-------------------------------------------+
| 0 | Space | R/w | Indicates BAR 0 is a memory space. |
+-------+--------------+------+-------------------------------------------+
BAR0H: BAR0 Upper Address Map (offset 0x014)
Reset: 0000_0000h.
+-------+--------------+------+-------------------------------------------+
| Bits | Name | Attr | Description |
+-------+--------------+------+-------------------------------------------+
| 31:0 | BaseAddr | R/w | Indicates the Addr[63:32] of the base |
| | | | address. |
+-------+--------------+------+-------------------------------------------+
If PCI bus 1, device 1, function 2 Configuration Space maps in MMIO address is 0xE010A000. Each field of registers BAR0 can be read from 0xE010A010 and 0xE010A014. ( *(UINT32 *)0xE010A010 and *(UINT32 *)0xE010A014 )
It is more programmable/Readable with LoLeOp library.
from LoLeOp.Mem import Mem8, Mem16, Mem32, Mem64
#
# Read each register fields of BAR0 (Bus 1, Device 1, Function 2)
#
BAR0L = 0xE010A010
BAR0H = 0xE010A014
print 'Register "Prefetchable": 0x%02X' % Mem32[BAR0L][0]
print 'Register "Type": 0x%02X' % Mem32[BAR0L][2:1]
print 'Register "Space": 0x%02X' % Mem32[BAR0L][3]
print 'Register "BaseAddr": 0x%016X' % (Mem32[Mem32[BAR0L][31:17], Mem32[BAR0H]] << 17)
#
# Setting BaseAddr of BAR0 as 0xD0000000 >> 17
#
Mem32[Mem32[BAR0L][31:17], Mem32[BAR0H]] = 0xD0000000 >> 17
In above Python code Mem32[BAR0L][2:1], It has the same effect of C language.
{
UINT32 BAR0L = 0xE010A010;
Printf (L"Register \"Type\": 0x%02X", (*((UINT32 *)0xE010A010) >> 1) & 0x03);
}
Mem32[BAR0L] means an instance at address 0xE010A010 with 32 bits width. Mem32[BAR0L][2:1] and Mem32[BAR0L][1:2] means an instance with bit 1 and bit 2 at address 0xE010A010. Mem32[Mem32[BAR0L][31:17], Mem32[BAR0H]] means an instance includes Mem32[BAR0H] and Mem32[BAR0L][31:17].
LoLeOp includes these application classes
Mem8, Mem16, Mem32, Mem64
Memory (including mmio) Read/Write in any memory area.
Io8, Io16, Io32, Io64
Io Read/Write
Cmos
cmos area data read/write
CpuId
x86 cpuid instruction input EAX and ECX (optional), output EAX, EBX, ECX, EDX.
Msr
x86 rdmsr/wrmsr instruction with input ECX, output EDX:EAX.
LeLoOp includes these basic classes
_MemArray, _MemCell, _CellConj, rUnionOp
Samples:
Host\AppPkg\LoLeOp\Samples
EfiPy_r0.1.7(24622) release
EfiPy_r0.1.7(24622) 2018/01/02:
1. Change folder Disk/ to Target/
2. Change folder Src/ to Host/
3. Move corepy, EfiPy, LoLeOp, pAnalyzer libraries to EFI\StdLib\lib\python.27\site-packages folder.
4. Move corepy, EfiPy, LoLeOp, pAnalyzer source code to Host\AppPkg folder.
5. Makes EfiPy and ctypes built in library and link them with PythonCore.inf
6. Update/Addd 00_ReadMe.txt, 01_History.txt and 02_Installation.txt in Document folder.
7. Fix corepy fail because restructure error
8. remove redundant output message in corepy
9. Fix EfiPy sample ConnectScan.py import pAnalyzer error
1. Change folder Disk/ to Target/
2. Change folder Src/ to Host/
3. Move corepy, EfiPy, LoLeOp, pAnalyzer libraries to EFI\StdLib\lib\python.27\site-packages folder.
4. Move corepy, EfiPy, LoLeOp, pAnalyzer source code to Host\AppPkg folder.
5. Makes EfiPy and ctypes built in library and link them with PythonCore.inf
6. Update/Addd 00_ReadMe.txt, 01_History.txt and 02_Installation.txt in Document folder.
7. Fix corepy fail because restructure error
8. remove redundant output message in corepy
9. Fix EfiPy sample ConnectScan.py import pAnalyzer error
Subscribe to:
Posts (Atom)