UEFI学习(四)-- SIO的Read与Write

本文详细解释了EC和SIO如何通过不同的通道访问地址空间,介绍了寄存器操作方法和进入/退出扩展模式的步骤。还提供了宏定义和代码示例以简化SIO的读写操作,后续将讨论设备和配置寄存器相关内容。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

EC与SIO都可以通过4E/4F 2E/2F去访问特定的地址空间;

EC被访问的地址空间一般是0x400,默认是通过4E/4F访问;SIO默认是通过2E/2F访问,这个访问的通道在EC/SIO里面可以通过更改寄存器来更改;

图为SIO更改访问通道的寄存器:
SIO 寄存器更改访问通道

既然知道了访问地址空间的通道是什么,接下来看Spec,查看通过通道访问的规范;
SIO 通过通道访问的方式
图中说明了寄存器的访问方式,需要先向2E写入,再从2F读取;

即:

//假设读的寄存器offset为0x01
IoWrite8(0x2E,0x01);
SIORead = IoRead8(0x2F);

因为0x2E/0x2F这两个通道地址我们需要经常用到,且有概率变更为4E/4F,所以可以定义一个宏定义,方便后续更改;
即:

#define SIO_Index       0x2E
#define SIO_Data        0x2F

IoWrite8(SIO_Index,0x01);
SIORead = IoRead8(SIO_Data);

Spec中又提到,需要往写IO地址中写入两次0x87,进入扩展模式后,才能对数据进行更新;
SIO 通过通道访问的方式2
SIO entry ExpansionMode
退出扩展模式,需要往IO地址中写入0xAA;
SIO break ExpansionMode

即:

#define SIO_Index       0x2E
#define SIO_Data        0x2F

IoWrite8(SIO_Index,0x87);
IoWrite8(SIO_Index,0x87);
IoWrite8(SIO_Index,0x01);
SIORead = IoRead8(SIO_Data);
IoWrite8(SIO_Index,0xAA);

访问SIO的方式已经知道了,接下来实际操作一下,用以上的code去访问并Print出SIO address的value;
我的code为:

//.inf
[Defines]
  INF_VERSION                    = 0x00010005
  BASE_NAME                      = SIO
  FILE_GUID                      = dd6c3ae0-296d-47d4-a491-d3c5b457059c
  MODULE_TYPE                    = UEFI_APPLICATION
  VERSION_STRING                 = 1.0
  ENTRY_POINT                    = UefiMain

[Sources]
  SIO.c

[Packages]
  MdePkg/MdePkg.dec

[LibraryClasses]
  UefiApplicationEntryPoint
  UefiLib
  IoLib
//.h
#ifndef __SIO_H__
#define __SIO_H__

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

extern UINTN ReadSIO(UINT8 offset);
extern UINTN ExpansionMode(UINT8 EMValue);

#endif //SIO_H

//.c
#include "SIO.h"

#include "SIO.h"

#define SIO_Index                   0x2E
#define SIO_Data                    0x2F

#define SIO_Entry_EM                0x01
#define SIO_Break_EM                0x00

EFI_STATUS
EFIAPI UefiMain (IN EFI_HANDLE ImageHandle, IN EFI_SYSTEM_TABLE *SystemTable)
{
    UINT8 SIO_ID_H;
    UINT8 SIO_ID_L;

    ExpansionMode(SIO_Entry_EM);
    
    SIO_ID_H = (UINT8)ReadSIO(0x20);
    SIO_ID_L = (UINT8)ReadSIO(0x21);

    ExpansionMode(SIO_Break_EM);

    Print(L"%x%x",SIO_ID_H,SIO_ID_L);

    return TRUE;
}

UINTN ReadSIO(UINT8 offset)
{
    IoWrite8(SIO_Index,offset);

    return IoRead8(SIO_Data);
}

UINTN ExpansionMode(UINT8 EMValue)
{
    if (EMValue == SIO_Entry_EM)
    {
        IoWrite8(SIO_Index,0x87);
        IoWrite8(SIO_Index,0x87);
    }
    else if (EMValue == SIO_Break_EM)
    {
        IoWrite8(SIO_Index,0xAA);
    }
    else 
    {
        //return FALSE;
    }

    return TRUE;
}

code内读取的是EC Chip ID;
SIO Chip ID
写SIO就直接调用IOWrite8,往Index里面写就行了,相对于读来说比较简单;
示例:

void WriteSIO(UINT8 offest,UINT8 value)
{
    IoWrite8(SIO_Index,offest);
    IoWrite8(SIO_Data,value);
}

下一篇继续说一下SIO的Read与Write中关于device和CONFIGURATION REGISTER的东西;

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值