UEFI(2):PPI和HOB列表(PEI->DXE)

前置步骤:

HOB(Hand-Off Block)是一个通用的结构体类型:MdePkg/Include/Pi/PiHob.h

///
/// Describes the format and size of the data inside the HOB.
/// All HOBs must contain this generic HOB header.
///
typedef struct {
  ///
  /// Identifies the HOB data structure type.
  ///
  UINT16    HobType;
  ///
  /// The length in bytes of the HOB.
  ///
  UINT16    HobLength;
  ///
  /// This field must always be set to zero.
  ///
  UINT32    Reserved;
} EFI_HOB_GENERIC_HEADER;

EFI_HOB_GENERIC_HEADER是所有HOB结构的通用头部,它包含了HOB的类型、长度以及指向下一个HOB的指针

除了通用头部,具体的HOB数据结构根据HobType的不同会有不同的定义

EFI_HOB_HANDOFF_INFO_TABLE

用于描述HOB列表的起始信息,通常是第一个HOB,用于传递PEIDXE的过渡信息:MdePkg/Include/Pi/PiHob.h

///
/// Contains general state information used by the HOB producer phase.
/// This HOB must be the first one in the HOB list.
///
typedef struct {
  ///
  /// The HOB generic header. Header.HobType = EFI_HOB_TYPE_HANDOFF.
  ///
  EFI_HOB_GENERIC_HEADER    Header;
  ///
  /// The version number pertaining to the PHIT HOB definition.
  /// This value is four bytes in length to provide an 8-byte aligned entry
  /// when it is combined with the 4-byte BootMode.
  ///
  UINT32                    Version;
  ///
  /// The system boot mode as determined during the HOB producer phase.
  ///
  EFI_BOOT_MODE             BootMode;
  ///
  /// The highest address location of memory that is allocated for use by the HOB producer
  /// phase. This address must be 4-KB aligned to meet page restrictions of UEFI.
  ///
  EFI_PHYSICAL_ADDRESS      EfiMemoryTop;
  ///
  /// The lowest address location of memory that is allocated for use by the HOB producer phase.
  ///
  EFI_PHYSICAL_ADDRESS      EfiMemoryBottom;
  ///
  /// The highest address location of free memory that is currently available
  /// for use by the HOB producer phase.
  ///
  EFI_PHYSICAL_ADDRESS      EfiFreeMemoryTop;
  ///
  /// The lowest address location of free memory that is available for use by the HOB producer phase.
  ///
  EFI_PHYSICAL_ADDRESS      EfiFreeMemoryBottom;
  ///
  /// The end of the HOB list.
  ///
  EFI_PHYSICAL_ADDRESS      EfiEndOfHobList;
} EFI_HOB_HANDOFF_INFO_TABLE;

EFI_HOB_MEMORY_ALLOCATION

描述内存分配情况的HOB,用于报告已分配的内存范围:MdePkg/Include/Pi/PiHob.h

///
/// Describes all memory ranges used during the HOB producer
/// phase that exist outside the HOB list. This HOB type
/// describes how memory is used, not the physical attributes of memory.
///
typedef struct {
  ///
  /// The HOB generic header. Header.HobType = EFI_HOB_TYPE_MEMORY_ALLOCATION.
  ///
  EFI_HOB_GENERIC_HEADER              Header;
  ///
  /// An instance of the EFI_HOB_MEMORY_ALLOCATION_HEADER that describes the
  /// various attributes of the logical memory allocation.
  ///
  EFI_HOB_MEMORY_ALLOCATION_HEADER    AllocDescriptor;
  //
  // Additional data pertaining to the "Name" Guid memory
  // may go here.
  //
} EFI_HOB_MEMORY_ALLOCATION;

EFI_HOB_GUID_TYPE

这是一个通用的HOB类型,用于存储自定义数据。它由GUID标识并携带特定数据

///
/// Allows writers of executable content in the HOB producer phase to
/// maintain and manage HOBs with specific GUID.
///
typedef struct {
  ///
  /// The HOB generic header. Header.HobType = EFI_HOB_TYPE_GUID_EXTENSION.
  ///
  EFI_HOB_GENERIC_HEADER    Header;
  ///
  /// A GUID that defines the contents of this HOB.
  ///
  EFI_GUID                  Name;
  //
  // Guid specific data goes here
  //
} EFI_HOB_GUID_TYPE;

每个HOB元素通过EFI_HOB_GENERIC_HEADER中的HobLength字段进行计算,找到下一个HOB的位置,终止HOBEFI_HOB_TYPE_END_OF_HOB_LIST类型

//
// HobType of EFI_HOB_GENERIC_HEADER.
//
#define EFI_HOB_TYPE_HANDOFF              0x0001
#define EFI_HOB_TYPE_MEMORY_ALLOCATION    0x0002
#define EFI_HOB_TYPE_RESOURCE_DESCRIPTOR  0x0003
#define EFI_HOB_TYPE_GUID_EXTENSION       0x0004
#define EFI_HOB_TYPE_FV                   0x0005
#define EFI_HOB_TYPE_CPU                  0x0006
#define EFI_HOB_TYPE_MEMORY_POOL          0x0007
#define EFI_HOB_TYPE_FV2                  0x0009
#define EFI_HOB_TYPE_LOAD_PEIM_UNUSED     0x000A
#define EFI_HOB_TYPE_UEFI_CAPSULE         0x000B
#define EFI_HOB_TYPE_FV3                  0x000C
#define EFI_HOB_TYPE_UNUSED               0xFFFE
#define EFI_HOB_TYPE_END_OF_HOB_LIST      0xFFFF

MdeModulePkg/Core/Dxe/DxeMain/DxeMain.c中有一段代码:

/**
  Main entry point to DXE Core.

  @param  HobStart               Pointer to the beginning of the HOB List from PEI.

  @return This function should never return.

**/
VOID
EFIAPI
DxeMain (
  IN  VOID  *HobStart // 由PEI阶段传递的HOB(Handoff Block)列表开始地址
  )
{
  EFI_STATUS                    Status;
  EFI_PHYSICAL_ADDRESS          MemoryBaseAddress;
  UINT64                        MemoryLength;
  PE_COFF_LOADER_IMAGE_CONTEXT  ImageContext;
  UINTN                         Index;
  EFI_HOB_GUID_TYPE             *GuidHob;
  EFI_VECTOR_HANDOFF_INFO       *VectorInfoList;
  EFI_VECTOR_HANDOFF_INFO       *VectorInfo;
  VOID                          *EntryPoint;

  //
  // Setup the default exception handlers
  //
  VectorInfoList = NULL;
  GuidHob        = GetNextGuidHob (&gEfiVectorHandoffInfoPpiGuid, HobStart);
 //
}

此处的gEfiVectorHandoffInfoPpiGuid位置:MdePkg/MdePkg.dec

[Ppis]
  ## Include/Ppi/VectorHandoffInfo.h
  gEfiVectorHandoffInfoPpiGuid       = { 0x3cd652b4, 0x6d33, 0x4dce, { 0x89, 0xdb, 0x83, 0xdf, 0x97, 0x66, 0xfc, 0xca }}

由此可知,gEfiVectorHandoffInfoPpiGuidPPI GUIDPPI接口头文件路径:Include/Ppi/VectorHandoffInfo.h

MdePkg/Include/Ppi/VectorHandoffInfo.h进行访问该PPI GUID

extern EFI_GUID  gEfiVectorHandoffInfoPpiGuid;

在其中查看该PPI接口:MdePkg/Include/Ppi/VectorHandoffInfo.h

///
/// EFI_VECTOR_HANDOFF_INFO entries that describes the interrupt and/or
/// exception vectors in use in the PEI Phase.
///
typedef struct {
  //
  // The interrupt or exception vector that is in use and must be preserved.
  //
  UINT32      VectorNumber;
  //
  // A bitmask that describes the attributes of the interrupt or exception vector.
  //
  UINT32      Attribute;
  //
  // The GUID identifies the party who created the entry. For the
  // EFI_VECTOR_HANDOFF_DO_NOT_HOOK case, this establishes the single owner.
  //
  EFI_GUID    Owner;
} EFI_VECTOR_HANDOFF_INFO;

///
/// Provides a description of the interrupt and/or exception vectors that
/// were established in the SEC Phase and need to persist into PEI and DXE.
///
typedef struct _EFI_PEI_VECTOR_HANDOFF_INFO_PPI {
  //
  // Pointer to an array of interrupt and /or exception vectors.
  //
  EFI_VECTOR_HANDOFF_INFO    *Info;
} EFI_PEI_VECTOR_HANDOFF_INFO_PPI;

EFI_PEI_VECTOR_HANDOFF_INFO_PPI的作用为:将向量表信息从PEI阶段传递到DXE阶段,用于在不同固件阶段之间传递与中断向量相关的信息

  • 6
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
static int sbsa_uart_probe(struct platform_device *pdev) { struct uart_amba_port *uap; struct resource r; int portnr, ret; int baudrate; / * Check the mandatory baud rate parameter in the DT node early * so that we can easily exit with the error. */ if (pdev->dev.of_node) { struct device_node *np = pdev->dev.of_node; ret = of_property_read_u32(np, "current-speed", &baudrate); if (ret) return ret; } else { baudrate = 115200; } portnr = pl011_find_free_port(); if (portnr < 0) return portnr; uap = devm_kzalloc(&pdev->dev, sizeof(struct uart_amba_port), GFP_KERNEL); if (!uap) return -ENOMEM; ret = platform_get_irq(pdev, 0); if (ret < 0) { if (ret != -EPROBE_DEFER) dev_err(&pdev->dev, "cannot obtain irq\n"); return ret; } uap->port.irq = ret; #ifdef CONFIG_ACPI_SPCR_TABLE if (qdf2400_e44_present) { dev_info(&pdev->dev, "working around QDF2400 SoC erratum 44\n"); uap->vendor = &vendor_qdt_qdf2400_e44; } else #endif uap->vendor = &vendor_sbsa; uap->reg_offset = uap->vendor->reg_offset; uap->fifosize = 32; uap->port.iotype = uap->vendor->access_32b ? UPIO_MEM32 : UPIO_MEM; uap->port.ops = &sbsa_uart_pops; uap->fixed_baud = baudrate; snprintf(uap->type, sizeof(uap->type), "SBSA"); r = platform_get_resource(pdev, IORESOURCE_MEM, 0); ret = pl011_setup_port(&pdev->dev, uap, r, portnr); if (ret) return ret; platform_set_drvdata(pdev, uap); return pl011_register_port(uap); }在上述代码中,我需要添加一个功能:在以uefi方式启动系统时,uart驱动读取通用acpi表内有关波特率的设置值,并以这个值进行串口波特率设置,请根据我的要求,在原代码中添加这一功能,并给出acpi表的描述
06-07
为了实现在UEFI方式启动系统时,UART驱动可以读取通用ACPI表中有关波特率的设置值,并以该值进行串口波特率设置,可以在sbsa_uart_probe函数中进行以下修改: ```c static int sbsa_uart_probe(struct platform_device *pdev) { struct uart_amba_port *uap; struct resource r; int portnr, ret; int baudrate; // 添加以下代码以读取ACPI表中的波特率设置值 struct acpi_table_header *header; header = acpi_table_find("SPCR"); if (header) { struct acpi_spcr_table *spcr = (struct acpi_spcr_table *)header; baudrate = spcr->baudrate; } else { baudrate = 115200; } portnr = pl011_find_free_port(); if (portnr < 0) return portnr; uap = devm_kzalloc(&pdev->dev, sizeof(struct uart_amba_port), GFP_KERNEL); if (!uap) return -ENOMEM; ret = platform_get_irq(pdev, 0); if (ret < 0) { if (ret != -EPROBE_DEFER) dev_err(&pdev->dev, "cannot obtain irq\n"); return ret; } uap->port.irq = ret; #ifdef CONFIG_ACPI_SPCR_TABLE if (qdf2400_e44_present) { dev_info(&pdev->dev, "working around QDF2400 SoC erratum 44\n"); uap->vendor = &vendor_qdt_qdf2400_e44; } else #endif uap->vendor = &vendor_sbsa; uap->reg_offset = uap->vendor->reg_offset; uap->fifosize = 32; uap->port.iotype = uap->vendor->access_32b ? UPIO_MEM32 : UPIO_MEM; uap->port.ops = &sbsa_uart_pops; uap->fixed_baud = baudrate; snprintf(uap->type, sizeof(uap->type), "SBSA"); r = platform_get_resource(pdev, IORESOURCE_MEM, 0); ret = pl011_setup_port(&pdev->dev, uap, r, portnr); if (ret) return ret; platform_set_drvdata(pdev, uap); return pl011_register_port(uap); } ``` ACPI SPCR表(System Product Compatibility Report)提供了系统的硬件配置和兼容性信息,包括处理器、内存、I/O端口和中断控制器等。在该表中,波特率设置值可以通过baudrate字段获取。因此,我们可以使用acpi_table_find函数来查找SPCR表,然后获取该字段的值,并将其用作串口波特率设置。请注意,在代码中,如果找不到SPCR表,则默认将波特率设置为115200。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

妖怪喜欢风

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值