EDK2写一个UEFI程序和.inf文件,调用pci $bus $dev $fun -i命令,遍历所有pci/pcie设备,并重定向到一个文件中
时间: 2024-05-12 15:19:02 浏览: 262
首先,我们需要定义一个EFI应用程序的入口函数和一个INF文件。在EDK2中,我们可以使用C语言来编写UEFI程序,而INF文件则是一个配置文件,用于指定程序的构建选项和依赖关系。
下面是一个简单的UEFI程序的入口函数,它将打开一个文件并将所有的PCI/PCIe设备信息写入该文件:
```c
#include <Uefi.h>
#include <Library/UefiLib.h>
#include <Library/UefiBootServicesTableLib.h>
#include <Protocol/PciIo.h>
EFI_STATUS
EFIAPI
UefiMain (
IN EFI_HANDLE ImageHandle,
IN EFI_SYSTEM_TABLE *SystemTable
)
{
EFI_STATUS Status;
EFI_PCI_IO_PROTOCOL *PciIo;
UINTN Segment;
UINTN Bus;
UINTN Device;
UINTN Function;
UINTN Index;
CHAR16 FileName[] = L"\\EFI\\pci_info.txt";
EFI_FILE_PROTOCOL *File;
CHAR8 Buffer[256];
// Open the file for writing
Status = gBS->OpenProtocol(ImageHandle, &gEfiSimpleFileSystemProtocolGuid,
(VOID **)&FileSystem, ImageHandle, NULL, EFI_OPEN_PROTOCOL_GET_PROTOCOL);
if (EFI_ERROR(Status)) {
Print(L"Failed to open the file system protocol: %r\n", Status);
return Status;
}
Status = FileSystem->Open(FileSystem, &File, FileName,
EFI_FILE_MODE_READ | EFI_FILE_MODE_WRITE | EFI_FILE_MODE_CREATE, 0);
if (EFI_ERROR(Status)) {
Print(L"Failed to open the file %s: %r\n", FileName, Status);
return Status;
}
// Traverse all PCI/PCIe devices
for (Segment = 0; Segment <= 0xFFFF; Segment++) {
for (Bus = 0; Bus <= 0xFF; Bus++) {
for (Device = 0; Device <= 0x1F; Device++) {
for (Function = 0; Function <= 0x7; Function++) {
// Check if the device exists
Status = gBS->LocateProtocol(&gEfiPciIoProtocolGuid, NULL,
(VOID **)&PciIo);
if (EFI_ERROR(Status)) {
continue;
}
// Read the device's PCI configuration space
Status = PciIo->Pci.Read(PciIo, EfiPciIoWidthUint32, 0, sizeof(Buffer),
&Buffer);
if (EFI_ERROR(Status)) {
continue;
}
// Write the device information to the file
UnicodeSPrint(Buffer, sizeof(Buffer), L"%04x:%02x:%02x.%x\n",
Segment, Bus, Device, Function);
Status = File->Write(File, &sizeof(Buffer), Buffer);
if (EFI_ERROR(Status)) {
Print(L"Failed to write device information to the file: %r\n", Status);
return Status;
}
}
}
}
}
// Close the file
Status = File->Close(File);
if (EFI_ERROR(Status)) {
Print(L"Failed to close the file: %r\n", Status);
return Status;
}
return EFI_SUCCESS;
}
```
接下来,我们需要创建一个INF文件,以指定构建选项和依赖关系。下面是一个示例INF文件:
```inf
[Defines]
INF_VERSION = 0x00010006
BASE_NAME = pci_info
FILE_GUID = 12345678-1234-1234-1234-1234567890AB
MODULE_TYPE = UEFI_APPLICATION
VERSION_STRING = 1.0
ENTRY_POINT = UefiMain
[Sources]
pci_info.c
[Packages]
MdePkg/MdePkg.dec
[LibraryClasses]
UefiApplicationEntryPoint
UefiLib
UefiBootServicesTableLib
PciIo
[Protocols]
PciIo
[BuildOptions]
-D NDEBUG
```
在这个INF文件中,我们定义了以下内容:
- `BASE_NAME`: 程序的基本名称,用于构建输出文件名。
- `FILE_GUID`: 程序的GUID,用于唯一标识程序。
- `MODULE_TYPE`: 程序的类型,这里是UEFI应用程序。
- `VERSION_STRING`: 程序的版本号。
- `ENTRY_POINT`: 程序的入口函数。
- `Sources`: 程序的源代码文件。
- `Packages`: 指定依赖的EDK2软件包。
- `LibraryClasses`: 指定需要链接的库文件。
- `Protocols`: 指定需要使用的协议。
- `BuildOptions`: 指定编译选项。
现在,我们可以使用EDK2的构建工具来构建程序:
```
build -p pci_info.inf -a X64 -b RELEASE
```
这将生成一个名为pci_info.efi的可执行文件,它可以在UEFI固件中运行,并将所有PCI/PCIe设备信息写入一个名为pci_info.txt的文件。
阅读全文