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】。
参考:
- https://docs.microsoft.com/zh-cn/cpp/c-runtime-library/inp-inpw-inpd?view=vs-2019这些函数已过时。 从 Visual Studio 2015 开始,CRT 中不再提供这些函数。
- 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
);