Friday, July 6, 2018

EfiPy_r0.1.13(24622) release

EfiPy_r0.1.13(24622) 2018/07/07:
  1. Fix Setting MSR fail via LoLeOp


Thank anonymous for his feedback and fixing this issue.

Friday, June 29, 2018

Load and run EDK2 DuetPkg from DOS

Made some modification from EDK2 DuetPkg.
Its purpose is as title and with this benefit:
    DuetPkg can be load/run without destroying boot storage.

The project name is LoadDuetPkg at https://github.com/EfiPy/LoadDuetPkg
For more detail, please reference GitHub.

Monday, February 19, 2018

EfiPy_r0.1.12(24622) release

EfiPy_r0.1.12(24622) 2018/02/19:
  1. EfiPyLib: Move ACPI library to EfiPyLib/Acpi
     EfiPyLib/EfiPyAcpiBase.py ==> EfiPyLib/Acpi/EfiPyAcpiBase.py
     EfiPyLib/EfiPyAcpiMcfg.py ==> EfiPyLib/Acpi/AcpiMcfg.py
  2. EfiPyLib: Complete these ACPI tables
     EfiPyLib/Acpi/AcpiRsdt.py
     EfiPyLib/Acpi/AcpiXsdt.py
     EfiPyLib/Acpi/AcpiFacp.py
     EfiPyLib/Acpi/AcpiMcfg.py
     EfiPyLib/Acpi/AcpiFacs.py
     EfiPyLib/Acpi/AcpiApic.py
  3. EfiPyLib: New ACPI utility functions in EfiPyAcpiLib.py
               AcpiDump(Signature), AcpiCheckSum(Signature)

Sunday, February 11, 2018

Build Python .py file to standalone application in UEFI

It is included after EfiPy_r0.1.9(24622). And its sample is at:
1. Source code: Host\AppPkg\py2efi\Samples
2. Target folder: fsx:\EFI\Tools\Samples\py2efi
It is called Py2Efi and is built on UEFI shell.

Sample in this document:
   fsx:\EFI\Tools\Samples\py2efi\CpuId\
   included files: CpuIds.py and Setup.py

Build CpuIds.py to CpuIds.efi file
  fsx:\EFI\Tools\Samples\py2efi\CpuId\>python Setup.py py2efi

Result:
  CpuIds.efi is produced at fsx:\EFI\Tools\Samples\py2efi\CpuId\dist\CpuIds.efi

Note:
  Py2Efi is from Py2EXE
https://pypi.python.org/pypi/py2exe/
http://www.py2exe.org/

Saturday, February 10, 2018

EfiPy_r0.1.11(24622) release

EfiPy_r0.1.11(24622) 2018/02/10:
  1. Py2Efi: Add _LoLeOp Module into Py2EfiX64.efi
EfiPy_r0.1.10(24622) 2018/02/09:
  1. EfiPy: code refine
  2. LoLeOp: Add _LoLeOp modules in python.efi
  3. LoLeOp: Change Mem, Io, cpuid and msr to CPython level access.
  4. LoLeOp: Remove unused py files in LoLeOp library
  5. CorePy: Move old LoLeOp basic library to CorePy/Samples as CorePy sample code in EfiPy
  6. CorePy: Add PciScan.py as CorePy sample program in EfiPy
  7. EfiPy: PCI, Change C MACRO to Python lambda function
  8. EfiPyLib: Add EfiPyAcpiBase module (ACPI RSDP, XSDT, RSDT)
  9. EfiPyLib: Add EfiPyAcpiMcfg module (ACPI MCFG)
  10. EfiPy: Correct EFI_PCI_ADDRESS function in PciRootBridgeIo.py
  11. LoLeOp: Change index calculation in MemSet, MemGet in BitOp.py
  12. EfiPyLib: Add Pci library(PciEmulate.py, PciStructure.py, PciIo.py) and its Sample(PciSample.py)
  13. EfiPyLib::EfiPyHexDump.py: Fix address error of hex dump
  14. LoLeOp::BitOp.py: Using deepcopy in _MemArray::__init__
  15. LoLeOp::CmosSample.py: DictKey update
  16. LoLeOp::BitOp.py, rUnionOp.py: Add CellBase in rUnionOp class

Note:
  1. LoLeOP: Its low level interface is moved to CPython. Original CorePy level interface is moved to as CoprePy sample. This purpose is to speed up program initial performance.
  2. As note 1, Python.efi and Py2EfiX64.efi have to be re-built. Pre-built efi files are included in this release.

Saturday, February 3, 2018

EfiPy_r0.1.9(24622) release

EfiPy_r0.1.9(24622) 2018/02/04:
  1. LoLeOp: Add recursive bit operation sample code
  2. LoLeOp: Remove cache in rUnionOp
  3. LoLeOp: Add EfiCpuId library and CpuIds.py utilitie
  4. EfiPy: Add sample program for analyze run time Python.efi PE32 structure.
  5. PeFile: Add pefile library into EfiPy environment
  6. Py2Efi: New module Py2Efi and its samples
  7. EfiPy: Correct MdePkg/IndustryStandard/PeImage.py
  8. Rebuild pyc for runtime performance

Saturday, January 13, 2018

Create new LoLeOp data type

  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)

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

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.

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

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