Newer
Older
AMI-Aptio-BIOS-Reversed / UefiCpuPkg / CpuIoPei / CpuIoPei.c
@Ajax Dong Ajax Dong 2 days ago 13 KB Full restructure
/** @file
 * CpuIoPei - CPU I/O PEI Module
 *
 * Source: UefiCpuPkg/CpuIoPei/CpuIoPei.c
 * This PEIM provides CPU I/O, MMIO, and port I/O access services
 * via the EFI_PEI_CPU_IO_PPI interface during the PEI phase.
 *
 * Decompiled from: HR650X BIOS, CpuIoPei.efi (PE32+ x86)
 * MD5:  f486e28500aeebac3792779ab72777cb
 * SHA256: 8bad4b7e3743a5a8074efd6de47d732e32e4bd1ccff56bb36cdc90aea7ae91bd
 * Image base: 0xffc18f74
 * Image size: 0x14a0
 * Image arch: 32-bit (Ia32)
 */

#include "CpuIoPei.h"

//
// Library helper: memset via compiler intrinsic
//
void * SetMem(void *buf, unsigned int count, char value)
{
  memset(buf, value, count);
  return buf;
}

//
// Library helper: memset32 via compiler intrinsic
//
void * SetMem32(void *buf, unsigned int count, int value)
{
  memset32(buf, value, count);
  return buf;
}

//
// Library helper: memset32 for 2-dword fill pattern
//
int  SetMem32Fill(int Buf, int Count, int Fill0, int Fill1)
{
  do
  {
    *(_DWORD *)(Buf + 8 * Count - 8) = Fill0;
    *(_DWORD *)(Buf + 8 * Count-- - 4) = Fill1;
  }
  while ( Count );
  return Buf;
}

//
// Library helper: memcpy with overlap handling
//
char * CopyMem(char *dst, char *src, unsigned int count)
{
  unsigned int count_1;
  char *dst_1;
  char *src_1;

  count_1 = count;
  if ( src < dst && &src[count - 1] >= dst )
  {
    // Overlapping: copy backwards
    src_1 = &src[count - 1];
    dst_1 = &dst[count - 1];
  }
  else
  {
    // No overlap: copy dword-aligned first, then remainder
    count_1 = count & 3;
    qmemcpy(dst, src, 4 * (count >> 2));
    src_1 = &src[4 * (count >> 2)];
    dst_1 = &dst[4 * (count >> 2)];
  }
  qmemcpy(dst_1, src_1, count_1);
  return dst;
}

//
// I/O Port Read - Byte string
//
__int64  IoReadBufferFx(unsigned __int16 Port, unsigned int Count, unsigned __int8 *Buffer)
{
  __int64 result;
  WORD2(result) = Port;
  __inbytestring(Port, Buffer, Count);
  return result;
}

//
// I/O Port Read - Word string
//
__int64  IoReadPortWordString(unsigned __int16 Port, unsigned int Count, unsigned __int16 *Buffer)
{
  __int64 result;
  WORD2(result) = Port;
  __inwordstring(Port, Buffer, Count);
  return result;
}

//
// I/O Port Read - Dword string
//
__int64  IoReadPortDwordString(unsigned __int16 Port, unsigned int Count, unsigned int *Buffer)
{
  __int64 result;
  WORD2(result) = Port;
  __indwordstring(Port, Buffer, Count);
  return result;
}

//
// I/O Port Write - Byte string
//
__int64  IoWriteBufferByte(unsigned __int16 Port, unsigned int Count, unsigned __int8 *Buffer)
{
  __int64 result;
  WORD2(result) = Port;
  __outbytestring(Port, Buffer, Count);
  return result;
}

//
// I/O Port Write - Word string
//
__int64  IoWritePortWordString(unsigned __int16 Port, unsigned int Count, unsigned __int16 *Buffer)
{
  __int64 result;
  WORD2(result) = Port;
  __outwordstring(Port, Buffer, Count);
  return result;
}

//
// I/O Port Write - Dword string
//
__int64  IoWritePortDwordString(unsigned __int16 Port, unsigned int Count, unsigned int *Buffer)
{
  __int64 result;
  WORD2(result) = Port;
  __outdwordstring(Port, Buffer, Count);
  return result;
}

//
// I/O Port Read - Word (single, aligned)
//
int  IoReadPortWord(unsigned __int16 Port)
{
  int DebugInstance;
  int result;

  if ( (Port & 1) != 0 )
  {
    DebugInstance = GetDebugInstance();
    if ( DebugInstance )
      (*(void ( **)(const char *, int, const char *))(DebugInstance + 4))(
        "e:\\hs\\MdePkg\\Library\\BaseIoLibIntrinsic\\IoLibMsc.c",
        133,
        "(Port & 1) == 0");
  }
  LOWORD(result) = __inword(Port);
  return (unsigned __int16)result;
}

//
// I/O Port Write - Word (single, aligned)
//
unsigned __int16  IoWritePortWord(unsigned __int16 Port, unsigned __int16 Value)
{
  int DebugInstance;

  if ( (Port & 1) != 0 )
  {
    DebugInstance = GetDebugInstance();
    if ( DebugInstance )
      (*(void ( **)(const char *, int, const char *))(DebugInstance + 4))(
        "e:\\hs\\MdePkg\\Library\\BaseIoLibIntrinsic\\IoLibMsc.c",
        163,
        "(Port & 1) == 0");
  }
  __outword(Port, Value);
  return Value;
}

//
// I/O Port Read - Dword (single, aligned)
//
unsigned __int32  IoReadPortDword(unsigned __int16 Port)
{
  int DebugInstance;

  if ( (Port & 3) != 0 )
  {
    DebugInstance = GetDebugInstance();
    if ( DebugInstance )
      (*(void ( **)(const char *, int, const char *))(DebugInstance + 4))(
        "e:\\hs\\MdePkg\\Library\\BaseIoLibIntrinsic\\IoLibMsc.c",
        193,
        "(Port & 3) == 0");
  }
  return __indword(Port);
}

//
// I/O Port Write - Dword (single, aligned)
//
unsigned int  IoWritePortDword(unsigned __int16 Port, unsigned int Value)
{
  int DebugInstance;

  if ( (Port & 3) != 0 )
  {
    DebugInstance = GetDebugInstance();
    if ( DebugInstance )
      (*(void ( **)(const char *, int, const char *))(DebugInstance + 4))(
        "e:\\hs\\MdePkg\\Library\\BaseIoLibIntrinsic\\IoLibMsc.c",
        223,
        "(Port & 3) == 0");
  }
  __outdword(Port, Value);
  return Value;
}

//
// MMIO Read - Word (aligned)
//
int  IoReadMmioWord(unsigned __int16 *Address)
{
  int DebugInstance;

  if ( ((unsigned __int8)Address & 1) != 0 )
  {
    DebugInstance = GetDebugInstance();
    if ( DebugInstance )
      (*(void ( **)(const char *, int, const char *))(DebugInstance + 4))(
        "e:\\hs\\MdePkg\\Library\\BaseIoLibIntrinsic\\IoLib.c",
        151,
        "(Address & 1) == 0");
  }
  return *Address;
}

//
// MMIO Write - Word (aligned)
//
__int16  IoWriteMmioWord(_WORD *Address, __int16 Value)
{
  int DebugInstance;

  if ( ((unsigned __int8)Address & 1) != 0 )
  {
    DebugInstance = GetDebugInstance();
    if ( DebugInstance )
      (*(void ( **)(const char *, int, const char *))(DebugInstance + 4))(
        "e:\\hs\\MdePkg\\Library\\BaseIoLibIntrinsic\\IoLib.c",
        183,
        "(Address & 1) == 0");
  }
  *Address = Value;
  return Value;
}

//
// MMIO Read - Qword (aligned)
//
__int64  IoReadMmioQword(void *Address)
{
  int DebugInstance;

  if ( ((unsigned __int8)Address & 7) != 0 )
  {
    DebugInstance = GetDebugInstance();
    if ( DebugInstance )
      (*(void ( **)(const char *, int, const char *))(DebugInstance + 4))(
        "e:\\hs\\MdePkg\\Library\\BaseIoLibIntrinsic\\IoLib.c",
        284,
        "(Address & 7) == 0");
  }
  return *(_QWORD *)Address;
}

//
// MMIO Write - Qword (aligned)
//
int  IoWriteMmioQword(void *Address, int Lo32, int Hi32)
{
  int DebugInstance;

  if ( ((unsigned __int8)Address & 7) != 0 )
  {
    DebugInstance = GetDebugInstance();
    if ( DebugInstance )
      (*(void ( **)(const char *, int, const char *))(DebugInstance + 4))(
        "e:\\hs\\MdePkg\\Library\\BaseIoLibIntrinsic\\IoLib.c",
        314,
        "(Address & 7) == 0");
  }
  *(_DWORD *)Address = Lo32;
  *((_DWORD *)Address + 1) = Hi32;
  return Lo32;
}

//
// Unaligned Read - 16-bit
//
__int16 __thiscall ReadUnaligned16(void *Buffer)
{
  int DebugInstance;

  if ( !Buffer )
  {
    DebugInstance = GetDebugInstance();
    if ( DebugInstance )
      (*(void ( **)(const char *, int, const char *))(DebugInstance + 4))(
        "e:\\hs\\MdePkg\\Library\\BaseLib\\Unaligned.c",
        38,
        "Buffer != ((void *) 0)");
  }
  return *(_WORD *)Buffer;
}

//
// Unaligned Write - 16-bit
//
__int16  WriteUnaligned16(_WORD *Buffer, __int16 Value)
{
  int DebugInstance;

  if ( !Buffer )
  {
    DebugInstance = GetDebugInstance();
    if ( DebugInstance )
      (*(void ( **)(const char *, int, const char *))(DebugInstance + 4))(
        "e:\\hs\\MdePkg\\Library\\BaseLib\\Unaligned.c",
        65,
        "Buffer != ((void *) 0)");
  }
  *Buffer = Value;
  return Value;
}

//
// Unaligned Read - 32-bit
//
int __thiscall ReadUnaligned32(void *Buffer)
{
  int DebugInstance;

  if ( !Buffer )
  {
    DebugInstance = GetDebugInstance();
    if ( DebugInstance )
      (*(void ( **)(const char *, int, const char *))(DebugInstance + 4))(
        "e:\\hs\\MdePkg\\Library\\BaseLib\\Unaligned.c",
        141,
        "Buffer != ((void *) 0)");
  }
  return *(_DWORD *)Buffer;
}

//
// Unaligned Write - 32-bit
//
int  WriteUnaligned32(_DWORD *Buffer, int Value)
{
  int DebugInstance;

  if ( !Buffer )
  {
    DebugInstance = GetDebugInstance();
    if ( DebugInstance )
      (*(void ( **)(const char *, int, const char *))(DebugInstance + 4))(
        "e:\\hs\\MdePkg\\Library\\BaseLib\\Unaligned.c",
        168,
        "Buffer != ((void *) 0)");
  }
  *Buffer = Value;
  return Value;
}

//
// Unaligned Read - 64-bit
//
__int64 __thiscall ReadUnaligned64(void *Buffer)
{
  int DebugInstance;

  if ( !Buffer )
  {
    DebugInstance = GetDebugInstance();
    if ( DebugInstance )
      (*(void ( **)(const char *, int, const char *))(DebugInstance + 4))(
        "e:\\hs\\MdePkg\\Library\\BaseLib\\Unaligned.c",
        192,
        "Buffer != ((void *) 0)");
  }
  return *(_QWORD *)Buffer;
}

//
// Unaligned Write - 64-bit
//
int  WriteUnaligned64(_DWORD *Buffer, int Lo32, int Hi32)
{
  int DebugInstance;

  if ( !Buffer )
  {
    DebugInstance = GetDebugInstance();
    if ( DebugInstance )
      (*(void ( **)(const char *, int, const char *))(DebugInstance + 4))(
        "e:\\hs\\MdePkg\\Library\\BaseLib\\Unaligned.c",
        219,
        "Buffer != ((void *) 0)");
  }
  *Buffer = Lo32;
  *(Buffer + 1) = Hi32;
  return Lo32;
}

//
// 64-bit Left Shift
//
__int64  LShiftU64(__int64 Value)
{
  unsigned int Count;
  int DebugInstance;
  __int64 Result;

  if ( Count >= 0x40 )
  {
    DebugInstance = GetDebugInstance();
    if ( DebugInstance )
      (*(void ( **)(const char *, int, const char *))(DebugInstance + 4))(
        "e:\\hs\\MdePkg\\Library\\BaseLib\\LShiftU64.c",
        39,
        "Count < 64");
  }
  LODWORD(Result) = 0;
  HIDWORD(Result) = Value;
  if ( (Count & 0x20) == 0 )
    Result = Value;
  return Result << (Count & 0x1F);
}

//
// 64-bit Right Shift
//
unsigned __int64  RShiftU64(unsigned __int64 Value)
{
  unsigned int Count;
  int DebugInstance;
  unsigned __int64 Result;

  if ( Count >= 0x40 )
  {
    DebugInstance = GetDebugInstance();
    if ( DebugInstance )
      (*(void ( **)(const char *, int, const char *))(DebugInstance + 4))(
        "e:\\hs\\MdePkg\\Library\\BaseLib\\RShiftU64.c",
        39,
        "Count < 64");
  }
  Result = HIDWORD(Value);
  if ( (Count & 0x20) == 0 )
    Result = Value;
  return Result >> (Count & 0x1F);
}

//
// CMOS Check Mode: determine debug printing capabilities
// Selects RTC register 0x4A to read the debug mode.
// Returns 0 (no debug), negative error codes, or status.
//
int CmosCheckMode()
{
  unsigned __int8 Save;
  char Mode;
  char Mode2;

  Save = __inbyte(0x70u);
  __outbyte(0x70u, Save & 0x80 | 0x4Au);
  Mode = __inbyte(0x71u);
  Mode2 = Mode;
  if ( (unsigned __int8)Mode <= 3u )
  {
LABEL_4:
    if ( !Mode2 )
      return 0;
    goto LABEL_5;
  }
  Mode2 = Mode;
  if ( !Mode )
  {
    Mode2 = MEMORY[0xFDAF0490] & 2 | 1;
    goto LABEL_4;
  }
LABEL_5:
  if ( Mode2 != -1 )
    return Mode2 != 1 ? -2147483578 : -2147483644;
  return 0;
}

//
// Get PEI Services Table Pointer
// Retrieves via IDT entry at offset -4 from IDT base.
//
int GetPeiServicesTable()
{
  int PeiServices;
  _BYTE Idtr[2];
  int IdtBase;

  ReadIdtr(Idtr);
  PeiServices = *(_DWORD *)(IdtBase - 4);
  if ( !PeiServices )
    DebugAssert(
      (int)"e:\\hs\\MdePkg\\Library\\PeiServicesTablePointerLibIdt\\PeiServicesTablePointer.c",
      48,
      (int)"PeiServices != ((void *) 0)");
  return PeiServices;
}

//
// Read IDTR (SIDT instruction)
//
void *__thiscall ReadIdtr(void *Idtr)
{
  if ( !Idtr )
    DebugAssert(
      (int)"e:\\hs\\MdePkg\\Library\\BaseLib\\X86ReadIdtr.c",
      37,
      (int)"Idtr != ((void *) 0)");
  __sidt(Idtr);
  return Idtr;
}

//
// Get Debug Instance from PEI Services
// Locates the gEfiPeiDebug2PpiGuid PPI.
//
int GetDebugInstance()
{
  int PeiServicesTable;
  _BYTE v2[4];
  int DebugInstance;

  PeiServicesTable = GetPeiServicesTable();
  if ( (*(int ( **)(int, void *, _DWORD, _BYTE *, int *))(*(_DWORD *)PeiServicesTable + 32))(
         PeiServicesTable,
         &gPeiDebug2PpiGuid,
         0,
         v2,
         &DebugInstance) >= 0 )
    return DebugInstance;
  else
    return 0;
}

//
// Debug Print (conditional on error level via CmosCheckMode)
//
int  DebugPrint(int ErrorLevel, const char *Format, ...)
{
  int result;
  int ( **DebugInstance)(int, const char *, char *);
  va_list va;

  va_start(va, Format);
  result = GetDebugInstance();
  DebugInstance = (int ( **)(int, const char *, char *))result;
  if ( result )
  {
    result = CmosCheckMode();
    if ( (result & ErrorLevel) != 0 )
      return (*DebugInstance)(ErrorLevel, Format, (char *)va);
  }
  return result;
}

//
// Debug Assert (via debug instance)
//
int  DebugAssert(
        const char *FileName,
        int LineNumber,
        const char *Assertion)
{
  int result;

  result = GetDebugInstance();
  if ( result )
    return (*(int ( **)(const char *, int, const char *))(result + 4))(
             FileName,
             LineNumber,
             Assertion);
  return result;
}

//
// CpuIoPei Entry Point
//
// Installs the CPU I/O PPI (EFI_PEI_CPU_IO_PPI) into the PEI database.
// On first invocation: installs via InstallPpi.
// On shadow (reload after memory): RegisterForShadow only.
//
EFI_STATUS
EFIAPI
CpuIoPeiEntryPoint(
  IN EFI_HANDLE        ImageHandle,
  IN EFI_SYSTEM_TABLE  *SystemTable
  )
{
  EFI_PEI_SERVICES    **PeiServices;
  EFI_STATUS          Status;

  PeiServices = GetPeiServicesTable();

  // RegisterForShadow detects if this is first-time or reinstall
  Status = (*PeiServices)->RegisterForShadow(ImageHandle);
  *(VOID **)((UINTN)SystemTable + 96) = &mCpuIoPpi;

  if (Status == EFI_ALREADY_STARTED) {
    DEBUG ((EFI_D_INFO,
      "CpuIO PPI has been loaded into memory.  Reinstalled PPI=0x%x\n",
      &mCpuIoPpi));
  } else {
    // First install: install the CPU I/O PPI descriptor
    PeiServices = GetPeiServicesTable();
    Status = (*PeiServices)->InstallPpi (&mCpuIoPpiDescriptor);
    ASSERT_EFI_ERROR (Status);
  }

  return EFI_SUCCESS;
}