Saturday, October 21, 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.




No comments:

Post a Comment