Step to UEFI (202)IoRead 研究

IO Port 的访问是对硬件的最基本操作,在 UEFI Shell 下我们通过 IoLib 中的IoRead8 IoRead16 IoRead32 这样的来进行读取。本文介绍Shell 下的 IoRead8 的具体实现。

首先编写一个代码用于测试:

#include  <Uefi.h>
#include  <Library/UefiLib.h>
#include  <Library/ShellCEntryLib.h>
#include  <Library/IoLib.h>

extern  EFI_SYSTEM_TABLE    *gST;
extern  EFI_BOOT_SERVICES   *gBS;

/***
  Print a welcoming message.

  Establishes the main structure of the application.

  @retval  0         The application exited normally.
  @retval  Other     An error occurred.
***/
INTN
EFIAPI
ShellAppMain (
  IN UINTN Argc,
  IN CHAR16 **Argv
  )
{
        Print(L"Read 80Port=%x\n",IoRead8(0x80));

    return(0);
}

编译之后,在 \Build\AppPkg\DEBUG_VS2015x86\X64\AppPkg\Applications\IOStudy\IOStudy\Makefile 可以看到使用了下面的 Library:

$(BIN_DIR)\MdePkg\Library\BaseIoLibIntrinsic\BaseIoLibIntrinsic\OUTPUT\BaseIoLibIntrinsic.lib

进一步研究,在 \MdePkg\Library\BaseIoLibIntrinsic\IoLibMsc.c 可以看到如下的实现:

/**
  Reads an 8-bit I/O port.

  Reads the 8-bit I/O port specified by Port. The 8-bit read value is returned.
  This function must guarantee that all I/O read and write operations are
  serialized.

  If 8-bit I/O port operations are not supported, then ASSERT().

  @param  Port  The I/O port to read.

  @return The value read.

**/
UINT8
EFIAPI
IoRead8 (
  IN      UINTN                     Port
  )
{
  UINT8                             Value;

  _ReadWriteBarrier ();
  Value = (UINT8)_inp ((UINT16)Port);
  _ReadWriteBarrier ();
  return Value;
}

为了证明这里就是我们要找到的具体实现,可以在  \MdePkg\Library\BaseIoLibIntrinsic\BaseIoLibIntrinsic.inf 加入如下代码:

 [BuildOptions]
  MSFT:*_*_X64_CC_FLAGS  = /FAsc /Od

重新编译(同时还需要删除 \Build\AppPkg\DEBUG_VS2015x86\X64\MdePkg\Library 中的BaseIoLibIntrinsic),之后可以在\Build\AppPkg\DEBUG_VS2015x86\X64\AppPkg\Applications\IOStudy\IOStudy 看到多出来一个IoLibMsc.cod 文件。

IoRead8	PROC						; COMDAT

; 73   : {

$LN3:
  00000	48 89 4c 24 08	 mov	 QWORD PTR [rsp+8], rcx
  00005	48 83 ec 18	 sub	 rsp, 24

; 74   :   UINT8                             Value;
; 75   : 
; 76   :   _ReadWriteBarrier ();
; 77   :   Value = (UINT8)_inp ((UINT16)Port);

  00009	0f b7 54 24 20	 movzx	 edx, WORD PTR Port$[rsp]
  0000e	ec		 in	 al, dx
  0000f	88 04 24	 mov	 BYTE PTR Value$[rsp], al

; 78   :   _ReadWriteBarrier ();
; 79   :   return Value;

  00012	8a 04 24	 mov	 al, BYTE PTR Value$[rsp]

; 80   : }

  00015	48 83 c4 18	 add	 rsp, 24
  00019	c3		 ret	 0
IoRead8	ENDP

在这里可以证明确实是IoLibMsc.c 中实现的。

_inp() 的作用是“从某个端口输入一个字节 (_inp)、一个字 (_inpw) 或一个双字 (_inpd)。” 但是看起来目前已经过时【参考1】。

与这个函数类似,还可以使用__inword 来实现读取某一个 Port,__outword直接写入某一个Port【参考2】。

参考:

  1. https://docs.microsoft.com/zh-cn/cpp/c-runtime-library/inp-inpw-inpd?view=vs-2019这些函数已过时。 从 Visual Studio 2015 开始,CRT 中不再提供这些函数。
  2. https://docs.microsoft.com/zh-cn/cpp/intrinsics/inword?view=vs-2017

=============================================================

2024年2月22日 IoLib 提供了如下的函数:

#define IO_LIB_ADDRESS(Segment, Port) \
  ( ((Port) & 0xffff) | (((Segment) & 0xffff) << 16) )

UINT8
EFIAPI
IoRead8 (
  IN      UINTN  Port
  );

UINT8
EFIAPI
IoWrite8 (
  IN      UINTN  Port,
  IN      UINT8  Value
  );

VOID
EFIAPI
IoReadFifo8 (
  IN      UINTN  Port,
  IN      UINTN  Count,
  OUT     VOID   *Buffer
  );

VOID
EFIAPI
IoWriteFifo8 (
  IN      UINTN  Port,
  IN      UINTN  Count,
  IN      VOID   *Buffer
  );

UINT8
EFIAPI
IoOr8 (
  IN      UINTN  Port,
  IN      UINT8  OrData
  );

UINT8
EFIAPI
IoAnd8 (
  IN      UINTN  Port,
  IN      UINT8  AndData
  );

UINT8
EFIAPI
IoAndThenOr8 (
  IN      UINTN  Port,
  IN      UINT8  AndData,
  IN      UINT8  OrData
  );

UINT8
EFIAPI
IoBitFieldRead8 (
  IN      UINTN  Port,
  IN      UINTN  StartBit,
  IN      UINTN  EndBit
  );

UINT8
EFIAPI
IoBitFieldWrite8 (
  IN      UINTN  Port,
  IN      UINTN  StartBit,
  IN      UINTN  EndBit,
  IN      UINT8  Value
  );

UINT8
EFIAPI
IoBitFieldOr8 (
  IN      UINTN  Port,
  IN      UINTN  StartBit,
  IN      UINTN  EndBit,
  IN      UINT8  OrData
  );

UINT8
EFIAPI
IoBitFieldAnd8 (
  IN      UINTN  Port,
  IN      UINTN  StartBit,
  IN      UINTN  EndBit,
  IN      UINT8  AndData
  );

UINT8
EFIAPI
IoBitFieldAndThenOr8 (
  IN      UINTN  Port,
  IN      UINTN  StartBit,
  IN      UINTN  EndBit,
  IN      UINT8  AndData,
  IN      UINT8  OrData
  );

UINT16
EFIAPI
IoRead16 (
  IN      UINTN  Port
  );

UINT16
EFIAPI
IoWrite16 (
  IN      UINTN   Port,
  IN      UINT16  Value
  );

VOID
EFIAPI
IoReadFifo16 (
  IN      UINTN  Port,
  IN      UINTN  Count,
  OUT     VOID   *Buffer
  );

VOID
EFIAPI
IoWriteFifo16 (
  IN      UINTN  Port,
  IN      UINTN  Count,
  IN      VOID   *Buffer
  );

UINT16
EFIAPI
IoOr16 (
  IN      UINTN   Port,
  IN      UINT16  OrData
  );

UINT16
EFIAPI
IoAnd16 (
  IN      UINTN   Port,
  IN      UINT16  AndData
  );

UINT16
EFIAPI
IoAndThenOr16 (
  IN      UINTN   Port,
  IN      UINT16  AndData,
  IN      UINT16  OrData
  );

UINT16
EFIAPI
IoBitFieldRead16 (
  IN      UINTN  Port,
  IN      UINTN  StartBit,
  IN      UINTN  EndBit
  );

UINT16
EFIAPI
IoBitFieldWrite16 (
  IN      UINTN   Port,
  IN      UINTN   StartBit,
  IN      UINTN   EndBit,
  IN      UINT16  Value
  );

UINT16
EFIAPI
IoBitFieldOr16 (
  IN      UINTN   Port,
  IN      UINTN   StartBit,
  IN      UINTN   EndBit,
  IN      UINT16  OrData
  );

UINT16
EFIAPI
IoBitFieldAnd16 (
  IN      UINTN   Port,
  IN      UINTN   StartBit,
  IN      UINTN   EndBit,
  IN      UINT16  AndData
  );

UINT16
EFIAPI
IoBitFieldAndThenOr16 (
  IN      UINTN   Port,
  IN      UINTN   StartBit,
  IN      UINTN   EndBit,
  IN      UINT16  AndData,
  IN      UINT16  OrData
  );

UINT32
EFIAPI
IoRead32 (
  IN      UINTN  Port
  );

UINT32
EFIAPI
IoWrite32 (
  IN      UINTN   Port,
  IN      UINT32  Value
  );

VOID
EFIAPI
IoReadFifo32 (
  IN      UINTN  Port,
  IN      UINTN  Count,
  OUT     VOID   *Buffer
  );

VOID
EFIAPI
IoWriteFifo32 (
  IN      UINTN  Port,
  IN      UINTN  Count,
  IN      VOID   *Buffer
  );

UINT32
EFIAPI
IoOr32 (
  IN      UINTN   Port,
  IN      UINT32  OrData
  );

UINT32
EFIAPI
IoAnd32 (
  IN      UINTN   Port,
  IN      UINT32  AndData
  );

UINT32
EFIAPI
IoAndThenOr32 (
  IN      UINTN   Port,
  IN      UINT32  AndData,
  IN      UINT32  OrData
  );

UINT32
EFIAPI
IoBitFieldRead32 (
  IN      UINTN  Port,
  IN      UINTN  StartBit,
  IN      UINTN  EndBit
  );

UINT32
EFIAPI
IoBitFieldWrite32 (
  IN      UINTN   Port,
  IN      UINTN   StartBit,
  IN      UINTN   EndBit,
  IN      UINT32  Value
  );

UINT32
EFIAPI
IoBitFieldOr32 (
  IN      UINTN   Port,
  IN      UINTN   StartBit,
  IN      UINTN   EndBit,
  IN      UINT32  OrData
  );

UINT32
EFIAPI
IoBitFieldAnd32 (
  IN      UINTN   Port,
  IN      UINTN   StartBit,
  IN      UINTN   EndBit,
  IN      UINT32  AndData
  );

UINT32
EFIAPI
IoBitFieldAndThenOr32 (
  IN      UINTN   Port,
  IN      UINTN   StartBit,
  IN      UINTN   EndBit,
  IN      UINT32  AndData,
  IN      UINT32  OrData
  );

UINT64
EFIAPI
IoRead64 (
  IN      UINTN  Port
  );

UINT64
EFIAPI
IoWrite64 (
  IN      UINTN   Port,
  IN      UINT64  Value
  );

UINT64
EFIAPI
IoOr64 (
  IN      UINTN   Port,
  IN      UINT64  OrData
  );

UINT64
EFIAPI
IoAnd64 (
  IN      UINTN   Port,
  IN      UINT64  AndData
  );

UINT64
EFIAPI
IoAndThenOr64 (
  IN      UINTN   Port,
  IN      UINT64  AndData,
  IN      UINT64  OrData
  );

UINT64
EFIAPI
IoBitFieldRead64 (
  IN      UINTN  Port,
  IN      UINTN  StartBit,
  IN      UINTN  EndBit
  );

UINT64
EFIAPI
IoBitFieldWrite64 (
  IN      UINTN   Port,
  IN      UINTN   StartBit,
  IN      UINTN   EndBit,
  IN      UINT64  Value
  );

UINT64
EFIAPI
IoBitFieldOr64 (
  IN      UINTN   Port,
  IN      UINTN   StartBit,
  IN      UINTN   EndBit,
  IN      UINT64  OrData
  );

UINT64
EFIAPI
IoBitFieldAnd64 (
  IN      UINTN   Port,
  IN      UINTN   StartBit,
  IN      UINTN   EndBit,
  IN      UINT64  AndData
  );

UINT64
EFIAPI
IoBitFieldAndThenOr64 (
  IN      UINTN   Port,
  IN      UINTN   StartBit,
  IN      UINTN   EndBit,
  IN      UINT64  AndData,
  IN      UINT64  OrData
  );

UINT8
EFIAPI
MmioRead8 (
  IN      UINTN  Address
  );

UINT8
EFIAPI
MmioWrite8 (
  IN      UINTN  Address,
  IN      UINT8  Value
  );

UINT8
EFIAPI
MmioOr8 (
  IN      UINTN  Address,
  IN      UINT8  OrData
  );

UINT8
EFIAPI
MmioAnd8 (
  IN      UINTN  Address,
  IN      UINT8  AndData
  );

UINT8
EFIAPI
MmioAndThenOr8 (
  IN      UINTN  Address,
  IN      UINT8  AndData,
  IN      UINT8  OrData
  );

UINT8
EFIAPI
MmioBitFieldRead8 (
  IN      UINTN  Address,
  IN      UINTN  StartBit,
  IN      UINTN  EndBit
  );

UINT8
EFIAPI
MmioBitFieldWrite8 (
  IN      UINTN  Address,
  IN      UINTN  StartBit,
  IN      UINTN  EndBit,
  IN      UINT8  Value
  );

UINT8
EFIAPI
MmioBitFieldOr8 (
  IN      UINTN  Address,
  IN      UINTN  StartBit,
  IN      UINTN  EndBit,
  IN      UINT8  OrData
  );

UINT8
EFIAPI
MmioBitFieldAnd8 (
  IN      UINTN  Address,
  IN      UINTN  StartBit,
  IN      UINTN  EndBit,
  IN      UINT8  AndData
  );

UINT8
EFIAPI
MmioBitFieldAndThenOr8 (
  IN      UINTN  Address,
  IN      UINTN  StartBit,
  IN      UINTN  EndBit,
  IN      UINT8  AndData,
  IN      UINT8  OrData
  );

UINT16
EFIAPI
MmioRead16 (
  IN      UINTN  Address
  );

UINT16
EFIAPI
MmioWrite16 (
  IN      UINTN   Address,
  IN      UINT16  Value
  );

UINT16
EFIAPI
MmioOr16 (
  IN      UINTN   Address,
  IN      UINT16  OrData
  );

UINT16
EFIAPI
MmioAnd16 (
  IN      UINTN   Address,
  IN      UINT16  AndData
  );

UINT16
EFIAPI
MmioAndThenOr16 (
  IN      UINTN   Address,
  IN      UINT16  AndData,
  IN      UINT16  OrData
  );

UINT16
EFIAPI
MmioBitFieldRead16 (
  IN      UINTN  Address,
  IN      UINTN  StartBit,
  IN      UINTN  EndBit
  );

UINT16
EFIAPI
MmioBitFieldWrite16 (
  IN      UINTN   Address,
  IN      UINTN   StartBit,
  IN      UINTN   EndBit,
  IN      UINT16  Value
  );

UINT16
EFIAPI
MmioBitFieldOr16 (
  IN      UINTN   Address,
  IN      UINTN   StartBit,
  IN      UINTN   EndBit,
  IN      UINT16  OrData
  );

UINT16
EFIAPI
MmioBitFieldAnd16 (
  IN      UINTN   Address,
  IN      UINTN   StartBit,
  IN      UINTN   EndBit,
  IN      UINT16  AndData
  );

UINT16
EFIAPI
MmioBitFieldAndThenOr16 (
  IN      UINTN   Address,
  IN      UINTN   StartBit,
  IN      UINTN   EndBit,
  IN      UINT16  AndData,
  IN      UINT16  OrData
  );

UINT32
EFIAPI
MmioRead32 (
  IN      UINTN  Address
  );

UINT32
EFIAPI
MmioWrite32 (
  IN      UINTN   Address,
  IN      UINT32  Value
  );

UINT32
EFIAPI
MmioOr32 (
  IN      UINTN   Address,
  IN      UINT32  OrData
  );

UINT32
EFIAPI
MmioAnd32 (
  IN      UINTN   Address,
  IN      UINT32  AndData
  );

UINT32
EFIAPI
MmioAndThenOr32 (
  IN      UINTN   Address,
  IN      UINT32  AndData,
  IN      UINT32  OrData
  );

UINT32
EFIAPI
MmioBitFieldRead32 (
  IN      UINTN  Address,
  IN      UINTN  StartBit,
  IN      UINTN  EndBit
  );

UINT32
EFIAPI
MmioBitFieldWrite32 (
  IN      UINTN   Address,
  IN      UINTN   StartBit,
  IN      UINTN   EndBit,
  IN      UINT32  Value
  );

UINT32
EFIAPI
MmioBitFieldOr32 (
  IN      UINTN   Address,
  IN      UINTN   StartBit,
  IN      UINTN   EndBit,
  IN      UINT32  OrData
  );

UINT32
EFIAPI
MmioBitFieldAnd32 (
  IN      UINTN   Address,
  IN      UINTN   StartBit,
  IN      UINTN   EndBit,
  IN      UINT32  AndData
  );

UINT32
EFIAPI
MmioBitFieldAndThenOr32 (
  IN      UINTN   Address,
  IN      UINTN   StartBit,
  IN      UINTN   EndBit,
  IN      UINT32  AndData,
  IN      UINT32  OrData
  );

UINT64
EFIAPI
MmioRead64 (
  IN      UINTN  Address
  );

UINT64
EFIAPI
MmioWrite64 (
  IN      UINTN   Address,
  IN      UINT64  Value
  );

UINT64
EFIAPI
MmioOr64 (
  IN      UINTN   Address,
  IN      UINT64  OrData
  );

UINT64
EFIAPI
MmioAnd64 (
  IN      UINTN   Address,
  IN      UINT64  AndData
  );

UINT64
EFIAPI
MmioAndThenOr64 (
  IN      UINTN   Address,
  IN      UINT64  AndData,
  IN      UINT64  OrData
  );

UINT64
EFIAPI
MmioBitFieldRead64 (
  IN      UINTN  Address,
  IN      UINTN  StartBit,
  IN      UINTN  EndBit
  );

UINT64
EFIAPI
MmioBitFieldWrite64 (
  IN      UINTN   Address,
  IN      UINTN   StartBit,
  IN      UINTN   EndBit,
  IN      UINT64  Value
  );

UINT64
EFIAPI
MmioBitFieldOr64 (
  IN      UINTN   Address,
  IN      UINTN   StartBit,
  IN      UINTN   EndBit,
  IN      UINT64  OrData
  );

UINT64
EFIAPI
MmioBitFieldAnd64 (
  IN      UINTN   Address,
  IN      UINTN   StartBit,
  IN      UINTN   EndBit,
  IN      UINT64  AndData
  );

UINT64
EFIAPI
MmioBitFieldAndThenOr64 (
  IN      UINTN   Address,
  IN      UINTN   StartBit,
  IN      UINTN   EndBit,
  IN      UINT64  AndData,
  IN      UINT64  OrData
  );

UINT8 *
EFIAPI
MmioReadBuffer8 (
  IN  UINTN  StartAddress,
  IN  UINTN  Length,
  OUT UINT8  *Buffer
  );

UINT16 *
EFIAPI
MmioReadBuffer16 (
  IN  UINTN   StartAddress,
  IN  UINTN   Length,
  OUT UINT16  *Buffer
  );

UINT32 *
EFIAPI
MmioReadBuffer32 (
  IN  UINTN   StartAddress,
  IN  UINTN   Length,
  OUT UINT32  *Buffer
  );

UINT64 *
EFIAPI
MmioReadBuffer64 (
  IN  UINTN   StartAddress,
  IN  UINTN   Length,
  OUT UINT64  *Buffer
  );

UINT8 *
EFIAPI
MmioWriteBuffer8 (
  IN  UINTN        StartAddress,
  IN  UINTN        Length,
  IN  CONST UINT8  *Buffer
  );

UINT16 *
EFIAPI
MmioWriteBuffer16 (
  IN  UINTN         StartAddress,
  IN  UINTN         Length,
  IN  CONST UINT16  *Buffer
  );

UINT32 *
EFIAPI
MmioWriteBuffer32 (
  IN  UINTN         StartAddress,
  IN  UINTN         Length,
  IN  CONST UINT32  *Buffer
  );

UINT64 *
EFIAPI
MmioWriteBuffer64 (
  IN  UINTN         StartAddress,
  IN  UINTN         Length,
  IN  CONST UINT64  *Buffer
  );

发表回复

您的电子邮箱地址不会被公开。 必填项已用 * 标注