Showing posts with label CorePy. Show all posts
Showing posts with label CorePy. Show all posts

4/11/2025

PciScan.py (II)

 Introduction

This python script is published here on 4/2/2016. That just an sample code for demoing the capability of python language to read/write IO port via CorePy.

It is changed to PciScanSample1.py and another two PciScan sample scripts are also published.

The another two samples demo how to read/write IO port by EfiPy2 new X86Processor class in EfiPy2.Lib.X86Processor.

Formal PciScan script

And for EfiPy2, the formal PciScan script is here.

This script can dump PCI device ID and Device ID, its device name and class name will be dumped as well.

The device name and class name data base is got from pci.ids which is also used popular Unix-like lspci in pciutils package.

The new github repository pciid.py is duty on parsing pci.ids to python dictionary in here and here.

This is the result after launch PciScan.py in Qemu.




And this is what is saw in ubuntu


3/23/2025

CPU informations and configurations

After CPUID, MSR draft is also complete. The samples in QEMU are put in

python X86MsrInfo -d -a --verbose

X86MsrInfo.txt

This sample can dump MSR registers in each CPU core with parameter "-a".

Or with "-c n" parameter to dump MSR registers in specified CPU core, the n is core index in EFI_MP_SERVICES_PROTOCOL.



3/15/2025

X86CpuInfo.py

Introduction

This script makes me possible to check processor information.

Command line:

python X86CpuInfo.py > X86CpuInfo.txt

This is the result on QEMU



3/09/2025

EfiPy2.Lib.X86Processor and X86ProcessorSample.py (EFI_MP_SERVICES_PROTOCOL)

EfiPy2.Lib.X86Processor

This is a EFI_MP_SERVICES_PROTOCOL related libary making Python invoke CPUID, MSR and MMIO related function running on different CPU core.

These processor functions are made from CorePy. It also provides the capabilities

1. Geting which CPU core python application runs on (X86Processors.WhoAmI).

2. Local APIC MMIO Address (X86Processors.LocalApicAddress)

3. Each APIC IDs from EFI_MP_SERVICES_PROTOCOL

X86ProcessorSample.py

This is a sample code of getting APIC ID on each core via EfiPy2.Lib.X86Processor.

Sample output from EfiPy2 on QEMU.







3/03/2025

About CorePy

 About

CorePy is used to assembly machine code in python script. EfiPy project uses it for some function wich is not available by UEFI protcol easily, for example to read/write I/O, CPUID and MSR.

CorePy is developmented in Linux system. the prologue and epilogue in current status have to be improved for fitting current UEFI calling convention .

Note:

Calling convetion code is patched at

https://github.com/EfiPy/EfiPy2/commit/217fdd233568449d71b2b4082b6220d7fb8

171da


7/10/2024

MsrBasic.py

Quick update

This is the same as CpuIdBasic.py. It  calls corepy library to achieve reading MSR data.

Here is new version of CpuIdBasic.py.

Instruction rdmsr in corepy is missed for months and it is patched in Efi/StdLib/lib/python36.8/corepy/arch/x86_64/isa/x86_64_isa.py

Both CpuId and Msr register query program run in BSP (Boot Strap Processor, not Board Support Package), only.

10/22/2023

CpuIdBasic.py

Introduction

We had the CPUID in EfiPy introduction in it. there are new implemented CpuId library in EfiPy2.

Recently EDK2 added each CPUID data structure in it. CpuIdBasic.py uses these data structure to get detail data more easily.

CpuId Library

EfiPy2 adds EfiPy2.Lib.CpuId module, it contain...

  1. Assembly code ready class CpuIdClass() to get CPUID and,
  2. Generic data structure CPUID_GENERIC_REGISTERs, sink of cpuid return value.
CpuIdClass recommend to use GetId2() method for reading cpuid.

  #
  # UINT32 GetId (UINT32 eax, UINT32 ecx, struct CpuIdReg &CpuIdReg);
  #
  def GetId2 (self, eax, ecx, CpuIdReg):
eax and ecx is cpuid instruction input parameter and CpuIdReg is GetId2() return value which includes EAX/EBX/ECX/EDX packed in it.

If there is no suitable EAX/EBX/ECX/EDX definition exiting in EfiPy2 package (EfiPy2.MdePkg.Register.Intel.Cpuid for example), user application can have self-defined structure like CPUID_GENERIC_REGISTERs

class CPUID_GENERIC_REGISTERs (EfiPy.Structure):
  _pack_   = 1
  _fields_ = [
    ('EAX',  EfiPy.UINT32),
    ('EBX',  EfiPy.UINT32),
    ('ECX',  EfiPy.UINT32),
    ('EDX',  EfiPy.UINT32)
  ]

Example 1 - Using CPUID_GENERIC_REGISTERs

import basic library

import EfiPy2 as EfiPy
import EfiPy2.MdePkg.Register.Intel.Cpuid as CpuidRegs
from EfiPy2.Lib import CpuId

Create object from CpuIdClass

CpuIdObj  = CpuId.CpuIdClass()

pick CPUID_GENERIC_REGISTERs as cpuid return value

CpuIdReg  = CpuId.CPUID_GENERIC_REGISTERs()

Execution

rax = CpuIdObj.GetId2 (0, 0, CpuIdReg)

Dump execution result and pre-defined value

#
# CpuIdReg.??? are return value.
#
print (f'''
CPU signature From cpuid instruction
============================================
  EAX = 0x{CpuIdReg.EAX:08X}
  EBX = 0x{CpuIdReg.EBX:08X}
  ECX = 0x{CpuIdReg.ECX:08X}
  EDX = 0x{CpuIdReg.EDX:08X}
''')

#
CpuidRegs.CPUID_SIGNATURE_GENUINE_INTEL_E?are pre-defined value
in EfiPy2.MdePkg.Register.Intel.Cpuid
#
print (f'''
CPU signature from pre-defined constant
============================================
  EBX = 0x{CpuidRegs.CPUID_SIGNATURE_GENUINE_INTEL_EBX:08X}
  ECX = 0x{CpuidRegs.CPUID_SIGNATURE_GENUINE_INTEL_ECX:08X}
  EDX = 0x{CpuidRegs.CPUID_SIGNATURE_GENUINE_INTEL_EDX:08X}
''')

Example 2 - Get CPUID EXA=0x01

EAX=0x01 is know as CPUID_VERSION_INFO.

Efipy2.MdePkg.Intel.CpuId also define version information detailed item.
This example packed these structure into single structure
CPUID_VERSION_INFO_EAX
CPUID_VERSION_INFO_EBX
CPUID_VERSION_INFO_ECX
CPUID_VERSION_INFO_EDX

class CpuIdRegisters (EfiPy.Structure):
  _pack_   = 1
  _fields_ = [
    ('EAX',  CpuidRegs.CPUID_VERSION_INFO_EAX),
    ('EBX',  CpuidRegs.CPUID_VERSION_INFO_EBX),
    ('ECX',  CpuidRegs.CPUID_VERSION_INFO_ECX),
    ('EDX',  CpuidRegs.CPUID_VERSION_INFO_EDX)
  ]
CpuIdReg  = CpuIdRegisters()

By these pre-defined bit field data, each needed data can be extract from python code.
For example...

print (f'''
CPU version information in bit field format
============================================
  CpuIdReg.EAX.Bits.SteppingId:    {CpuIdReg.EAX.Bits.SteppingId}
  CpuIdReg.EAX.Bits.Model:         {CpuIdReg.EAX.Bits.Model}
  CpuIdReg.EAX.Bits.FamilyId:      {CpuIdReg.EAX.Bits.FamilyId}
....
''')

Conclusion

This example can run in both UEFI and Linux.












































And the assmeblt code by corepy is
or

AT&T syntax format or Intel syntax format as wish.




10/09/2023

CorePy

CorePy

 It is taken back to EfiPy.

There is little of information about corepy. We still can find the fist paper about corepy in PDF.

High-Performance Code Generation Using CorePy

With some modification,  most instructins list in x86_64_isa.py can be used in Linux and EfiPy2, again, with python 3.X. Modified code is here,

PciScan.py, CpuId.py levelage corepy making EfiPy doing low  level operation easier.

Here is snapshot how CpuId.py using cpuid instruction based on corepy library.


4/22/2016

x86 instruction CPUID in CorePy/EfiPy

Sample code
https://github.com/EfiPy/EfiPy2/blob/main/Efi/Apps/EfiPy2Sample/CpuIdBasic.py

Description

In this demo, the sample script shows how to uses x86 instruction CPUID with CorePy/EfiPy2.
We have put CpuId module in EfiPy2.Lib in EfiPy2, that is the re-usable CpuId module need to be import as
from EfiPy2.Lib import CpuId

In CpuId module, it has class named "CpuIdClass". and create object as
CpuIdObj  = CpuId.CpuIdClass()

CpuId module also provide generic register suit for CPUID instruction operation by CorePy.
CpuIdReg  = CpuId.CPUID_GENERIC_REGISTERs()

CpuIdClass has two member functions... GetId () and GetId2 (). Both functions take three parameters. The first two parameters are EAX and ECX by instruction CPUID. But the third parameter is memory address by GetId (),  CPUID_GENERIC_REGISTERs object for GetId2 ().

Also, user can create its own register with pack structure type for CPUID, for example...

import EfiPy2.MdePkg.Register.Intel.Cpuid as CpuidRegs

class CpuIdRegisters (EfiPy.Structure):
  _pack_   = 1
  _fields_ = [
    ('EAX',  CpuidRegs.CPUID_VERSION_INFO_EAX),
    ('EBX',  CpuidRegs.CPUID_VERSION_INFO_EBX),
    ('ECX',  CpuidRegs.CPUID_VERSION_INFO_ECX),
    ('EDX',  CpuidRegs.CPUID_VERSION_INFO_EDX)
  ]
CpuIdReg  = CpuIdRegisters()

This registers can be used to get CPU version infor by...

rax = CpuIdObj.GetId2 (CpuidRegs.CPUID_VERSION_INFO, 0, CpuIdReg)

Due to CpuidRegs.CPUID_VERSION_INFO_EAXCpuidRegs.CPUID_VERSION_INFO_EBXCpuidRegs.CPUID_VERSION_INFO_ECX and CpuidRegs.CPUID_VERSION_INFO_EDX are union type including each bit field, Python script can also dump version information detail.



4/02/2016

PCI Scan

Sample Code Name
https://github.com/EfiPy/EfiPy2/blob/main/Efi/Apps/EfiPy2Sample/PciScan.py

Description

PCI Scanning program is the sample of how data returned by CorePy then transfer to EfiPy2.

It uses below functions, constants and structure in  EfiPy2
EfiPy2.MdePkg.IndustryStandard.Pci
Structure PCI_TYPE_GENERIC
Structure PCI_CONFIG_ACCESS_CF8
PCI_MAX_BUS
PCI_MAX_DEVICE
PCI_MAX_FUNC
IS_PCI_MULTI_FUNC

CorePy code in PCI scanning script, it uses I/O port 0x0cf8, 0x0cfc for scanning PCI generic register.
It also needs input parameter for assigning PCI bus, Device, function and registers.

EfiPy2 full package is from https://github.com/EfiPy/EfiPy2

Pseudo Sample Code

class PciScan:

  #
  # Prebuild assembly code
  #
  def __init__ (self):
    self.code.add(x86.mov(reg.rax, mem.MemRef(reg.rbp, 16)))
    self.code.add(x86.mov(reg.dx, 0x0cf8))
    self.code.add(x86.out(reg.dx, reg.eax))

    self.code.add(x86.mov(reg.dx, 0x0cfc))
    self.code.add(x86.in_(reg.eax, reg.dx))


  #
  # Get PCI register entry, return UINT32 value
  #
  def scan (self, Bus = 0, Dev = 0, Func = 0, Reg = 0):
    reg = pci.PCI_CONFIG_ACCESS_CF8((Reg & 0xFC, Func, Dev, Bus, 0, 1))

    self.params.p1 = reg.Uint32
    ret = self.proc.execute(self.code,
                            params = self.params,
                            mode = 'int')

    return ret


if __name__ == '__main__':

  PciDev  = PciScan()
  ret = PciDev.scan(Bus, Dev, Func, Reg)

Result