diff options
author | Konstantin Aladyshev <aladyshev22@gmail.com> | 2021-07-07 19:52:33 +0300 |
---|---|---|
committer | Konstantin Aladyshev <aladyshev22@gmail.com> | 2021-07-07 19:53:08 +0300 |
commit | 5ebeafa4eff3cf73faad5cc6d8e2adecbd18d2f5 (patch) | |
tree | 4283c74d3d58b12fa5619c1a9daf466eef06f75d /Lesson_32 | |
parent | 8280cf0a39091890f029efa1b748520312698353 (diff) | |
download | UEFI-Lessons-5ebeafa4eff3cf73faad5cc6d8e2adecbd18d2f5.tar.gz UEFI-Lessons-5ebeafa4eff3cf73faad5cc6d8e2adecbd18d2f5.tar.bz2 UEFI-Lessons-5ebeafa4eff3cf73faad5cc6d8e2adecbd18d2f5.zip |
Add draft for lesson 32
Signed-off-by: Konstantin Aladyshev <aladyshev22@gmail.com>
Diffstat (limited to 'Lesson_32')
-rw-r--r-- | Lesson_32/README.md | 144 | ||||
-rw-r--r-- | Lesson_32/UefiLessonsPkg/DumpPCIroms/DumpPCIroms.c | 376 | ||||
-rw-r--r-- | Lesson_32/UefiLessonsPkg/DumpPCIroms/DumpPCIroms.inf | 22 |
3 files changed, 542 insertions, 0 deletions
diff --git a/Lesson_32/README.md b/Lesson_32/README.md new file mode 100644 index 0000000..7eea2b3 --- /dev/null +++ b/Lesson_32/README.md @@ -0,0 +1,144 @@ +https://github.com/tianocore/edk2/blob/master/MdePkg/Include/Protocol/PciRootBridgeIo.h +``` +typedef struct _EFI_PCI_IO_PROTOCOL { +EFI_PCI_IO_PROTOCOL_POLL_IO_MEM PollMem; + EFI_PCI_IO_PROTOCOL_POLL_IO_MEM PollIo; + EFI_PCI_IO_PROTOCOL_ACCESS Mem; + EFI_PCI_IO_PROTOCOL_ACCESS Io; + EFI_PCI_IO_PROTOCOL_CONFIG_ACCESS Pci; + EFI_PCI_IO_PROTOCOL_COPY_MEM CopyMem; + EFI_PCI_IO_PROTOCOL_MAP Map; + EFI_PCI_IO_PROTOCOL_UNMAP Unmap; + EFI_PCI_IO_PROTOCOL_ALLOCATE_BUFFER AllocateBuffer; + EFI_PCI_IO_PROTOCOL_FREE_BUFFER FreeBuffer; + EFI_PCI_IO_PROTOCOL_FLUSH Flush; + EFI_PCI_IO_PROTOCOL_GET_LOCATION GetLocation; + EFI_PCI_IO_PROTOCOL_ATTRIBUTES Attributes; + EFI_PCI_IO_PROTOCOL_GET_BAR_ATTRIBUTES GetBarAttributes; + EFI_PCI_IO_PROTOCOL_SET_BAR_ATTRIBUTES SetBarAttributes; + UINT64 RomSize; + VOID *RomImage; +} EFI_PCI_IO_PROTOCOL; +``` + +As you can see it is pretty simiilar to `EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL`. Here is a comparision of these two: +``` +typedef struct _EFI_PCI_IO_PROTOCOL { typedef struct _EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL { + EFI_HANDLE ParentHandle; + EFI_PCI_IO_PROTOCOL_POLL_IO_MEM PollMem; EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_POLL_IO_MEM PollMem; + EFI_PCI_IO_PROTOCOL_POLL_IO_MEM PollIo; EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_POLL_IO_MEM PollIo; + EFI_PCI_IO_PROTOCOL_ACCESS Mem; EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_ACCESS Mem; + EFI_PCI_IO_PROTOCOL_ACCESS Io; EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_ACCESS Io; + EFI_PCI_IO_PROTOCOL_CONFIG_ACCESS Pci; EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_ACCESS Pci; + EFI_PCI_IO_PROTOCOL_COPY_MEM CopyMem; EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_COPY_MEM CopyMem; + EFI_PCI_IO_PROTOCOL_MAP Map; EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_MAP Map; + EFI_PCI_IO_PROTOCOL_UNMAP Unmap; EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_UNMAP Unmap; + EFI_PCI_IO_PROTOCOL_ALLOCATE_BUFFER AllocateBuffer; EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_ALLOCATE_BUFFER AllocateBuffer; + EFI_PCI_IO_PROTOCOL_FREE_BUFFER FreeBuffer; EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_FREE_BUFFER FreeBuffer; + EFI_PCI_IO_PROTOCOL_FLUSH Flush; EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_FLUSH Flush; + EFI_PCI_IO_PROTOCOL_GET_LOCATION GetLocation; + EFI_PCI_IO_PROTOCOL_ATTRIBUTES Attributes; + EFI_PCI_IO_PROTOCOL_GET_BAR_ATTRIBUTES GetBarAttributes; EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_GET_ATTRIBUTES GetAttributes; + EFI_PCI_IO_PROTOCOL_SET_BAR_ATTRIBUTES SetBarAttributes; EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_SET_ATTRIBUTES SetAttributes; + UINT64 RomSize; + VOID *RomImage; + EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_CONFIGURATION Configuration; + UINT32 SegmentNumber; +} EFI_PCI_IO_PROTOCOL; } EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL; +``` + + + + +``` +RomSize The size, in bytes, of the ROM image. +RomImage A pointer to the in memory copy of the ROM image. The PCI Bus Driver is responsible + for allocating memory for the ROM image, and copying the contents of the ROM to memory. + The contents of this buffer are either from the PCI option ROM that can be accessed + through the ROM BAR of the PCI controller, or it is from a platformspecific location. + The Attributes() function can be used to determine from which of these two sources + the RomImage buffer was initialized +``` + +``` +GetLocation Retrieves this PCI controller’s current PCI bus number, device +number, and function number +``` + + +``` +EFI_PCI_IO_PROTOCOL.GetLocation() + +Summary: +Retrieves this PCI controller’s current PCI bus number, device number, and function number. + +Prototype: +typedef +EFI_STATUS +(EFIAPI *EFI_PCI_IO_PROTOCOL_GET_LOCATION) ( + IN EFI_PCI_IO_PROTOCOL *This, + OUT UINTN *SegmentNumber, + OUT UINTN *BusNumber, + OUT UINTN *DeviceNumber, + OUT UINTN *FunctionNumber + ); + +Parameters: +This A pointer to the EFI_PCI_IO_PROTOCOL instance. +SegmentNumber The PCI controller’s current PCI segment number. +BusNumber The PCI controller’s current PCI bus number. +DeviceNumber The PCI controller’s current PCI device number. +FunctionNumber The PCI controller’s current PCI function number. + +Description: +The GetLocation() function retrieves a PCI controller’s current location on a PCI Host Bridge. This is +specified by a PCI segment number, PCI bus number, PCI device number, and PCI function number. These +values can be used with the PCI Root Bridge I/O Protocol to perform PCI configuration cycles on the PCI +controller, or any of its peer PCI controller’s on the same PCI Host Bridge. +``` + +``` +FS0:\> DumpPCIroms.efi +Number of PCI devices in the system: 5 +00:00.00 - Vendor:8086, Device:1237 +00:01.00 - Vendor:8086, Device:7000 +00:01.01 - Vendor:8086, Device:7010 +00:01.03 - Vendor:8086, Device:7113 +00:02.00 - Vendor:1234, Device:1111 + Has OptionROM: address=6E91018, size=39424 +``` + +``` +FS0:\> dmem 6E91018 30 +Memory Address 0000000006E91018 30 Bytes + 06E91018: 55 AA 4D E9 AE 55 B4 00-00 00 00 00 00 00 00 00 *U.M..U..........* + 06E91028: 00 00 00 00 00 00 00 00-3C 98 00 00 00 00 49 42 *........<.....IB* + 06E91038: 4D 00 2E 8B 16 C6 98 85-D2 74 01 EE C2 02 00 66 *M........t.....f* +``` + +https://github.com/tianocore/edk2/blob/master/MdePkg/Include/IndustryStandard/Pci22.h +``` +#define PCI_EXPANSION_ROM_HEADER_SIGNATURE 0xaa55 + +... + +/// +/// Standard PCI Expansion ROM Header +/// Section 13.4.2, Unified Extensible Firmware Interface Specification, Version 2.1 +/// +typedef struct { + UINT16 Signature; ///< 0xaa55 + UINT8 Reserved[0x16]; + UINT16 PcirOffset; +} PCI_EXPANSION_ROM_HEADER; +``` + + + +``` +$ git clone git://git.ipxe.org/ipxe.git +$ cd ipxe/src +$ make bin-x86_64-efi/ipxe.efi # EFI app with all devices +$ make bin-x86_64-efi/808610de.efirom # EFI ROM vendev: 8086:10de +$ make bin/808610de.rom # Legacy ROM vendev: 8086:10de +``` diff --git a/Lesson_32/UefiLessonsPkg/DumpPCIroms/DumpPCIroms.c b/Lesson_32/UefiLessonsPkg/DumpPCIroms/DumpPCIroms.c new file mode 100644 index 0000000..9842a36 --- /dev/null +++ b/Lesson_32/UefiLessonsPkg/DumpPCIroms/DumpPCIroms.c @@ -0,0 +1,376 @@ +#include <Library/UefiBootServicesTableLib.h> +#include <Library/UefiLib.h> + +#include <Protocol/PciIo.h> +#include <Library/MemoryAllocationLib.h> +#include <IndustryStandard/Pci.h> +#include <Library/ShellLib.h> +#include <Library/PrintLib.h> + +#include <IndustryStandard/PeImage.h> + + +#define DESCRIPTOR_STR_MAX_SIZE 200 +#define BLOCK_READ_SIZE (1024*4) + +VOID ToLowerASCII(CHAR8* Str, UINTN Size) +{ + for (UINT8 i=0; i<Size; i++) { + if ((Str[i]>='A')&&(Str[i]<='Z')) { + Str[i]+=32; + } + } +} + +EFI_STATUS FindPCIDevDescription(UINT16 VendorId, + UINT16 DeviceId, + CHAR16* VendorDesc, + CHAR16* DeviceDesc, + UINTN DescBufferSize) +{ + EFI_STATUS Status = ShellFileExists(L"pci.ids"); + if (EFI_ERROR(Status)) + { + Print(L"No file pci.ids: %r\n", Status); + return Status; + } + + SHELL_FILE_HANDLE FileHandle; + Status = ShellOpenFileByName(L"pci.ids", + &FileHandle, + EFI_FILE_MODE_READ, + 0); + if (EFI_ERROR(Status)) + { + Print(L"Can't open file pci.ids: %r\n", Status); + return Status; + } + + UINT64 FileSize; + Status = ShellGetFileSize(FileHandle, &FileSize); + if (EFI_ERROR(Status)) + { + Print(L"Can't get file size for file pci.ids: %r\n", Status); + goto end; + } + + CHAR8 VendorStr[5]; + CHAR8 DeviceStr[5]; + AsciiValueToStringS(VendorStr, + 5, + RADIX_HEX | PREFIX_ZERO, + VendorId, + 4); + AsciiValueToStringS(DeviceStr, + 5, + RADIX_HEX | PREFIX_ZERO, + DeviceId, + 4); + ToLowerASCII(VendorStr, 4); + ToLowerASCII(DeviceStr, 4); + + CHAR8 Buffer[BLOCK_READ_SIZE]; + UINTN Size; + UINT64 FilePos = 0; + BOOLEAN Vendor_found = FALSE; + BOOLEAN Device_found = FALSE; + while (TRUE) + { + Size = BLOCK_READ_SIZE; + Status = ShellReadFile(FileHandle, &Size, Buffer); + if (EFI_ERROR(Status)) + { + Print(L"Can't read file pci.ids: %r\n", Status); + goto end; + } + UINTN StrStart = 0; + UINTN StrEnd = 0; + for (UINTN i=0; i<Size; i++) { + if (Buffer[i]=='\n') { + StrEnd=i; + if (!Vendor_found){ + // 0123456 7 + //\nXXXX |<desc>|\n + if ((StrEnd - StrStart) > 7) { + if ((Buffer[StrStart+1]==VendorStr[0]) && + (Buffer[StrStart+2]==VendorStr[1]) && + (Buffer[StrStart+3]==VendorStr[2]) && + (Buffer[StrStart+4]==VendorStr[3])) { + Buffer[StrEnd] = 0; + UnicodeSPrintAsciiFormat(VendorDesc, DescBufferSize, "%a", &Buffer[StrStart+1+4+2]); + Vendor_found = TRUE; + } + } + } else { + // 0 1234567 8 + //\n\tXXXX |<desc>|\n + if ((StrEnd - StrStart) > 8) { + if ((Buffer[StrStart+1]=='\t') && + (Buffer[StrStart+2]==DeviceStr[0]) && + (Buffer[StrStart+3]==DeviceStr[1]) && + (Buffer[StrStart+4]==DeviceStr[2]) && + (Buffer[StrStart+5]==DeviceStr[3])) { + Buffer[StrEnd] = 0; + UnicodeSPrintAsciiFormat(DeviceDesc, DescBufferSize, "%a", &Buffer[StrStart+1+1+4+2]); + Device_found = TRUE; + break; + } + } + } + StrStart = StrEnd; + } + } + + if (FilePos+Size >= FileSize) { + break; + } + FilePos += StrEnd; + Status = ShellSetFilePosition(FileHandle, FilePos); + if (EFI_ERROR(Status)) + { + Print(L"Can't set file position pci.ids: %r\n", Status); + goto end; + } + } + +end: + if (!Vendor_found) { + UnicodeSPrint(VendorDesc, DescBufferSize, L"Undefined"); + } + if (!Device_found) { + UnicodeSPrint(DeviceDesc, DescBufferSize, L"Undefined"); + } + ShellCloseFile(&FileHandle); + + return Status; +} + + +UINT64 PciConfigurationAddress(UINT8 Bus, + UINT8 Device, + UINT8 Function, + UINT32 Register) +{ + UINT64 Address = (((UINT64)Bus) << 24) + (((UINT64)Device) << 16) + (((UINT64)Function) << 8); + if (Register & 0xFFFFFF00) { + Address += (((UINT64)Register) << 32); + } else { + Address += (((UINT64)Register) << 0); + } + return Address; +} + + +EFI_STATUS PrintPCI(EFI_PCI_IO_PROTOCOL* PciIo) +{ + UINTN SegmentNumber; + UINTN BusNumber; + UINTN DeviceNumber; + UINTN FunctionNumber; + EFI_STATUS Status = PciIo->GetLocation(PciIo, + &SegmentNumber, + &BusNumber, + &DeviceNumber, + &FunctionNumber); + if (EFI_ERROR(Status)) { + Print(L"Error in getting PCI location: %r\n", Status); + return Status; + } + + PCI_DEVICE_INDEPENDENT_REGION PCIConfHdr; + Status = PciIo->Pci.Read(PciIo, + EfiPciIoWidthUint8, + 0, + sizeof(PCI_DEVICE_INDEPENDENT_REGION), + &PCIConfHdr); + + if (EFI_ERROR(Status)) { + Print(L"Error in reading PCI conf space: %r\n", Status); + return Status; + } + + if (PciIo->RomSize) { + + Print(L"%02x:%02x.%02x - Vendor:%04x, Device:%04x", BusNumber, + DeviceNumber, + FunctionNumber, + PCIConfHdr.VendorId, + PCIConfHdr.DeviceId); + + CHAR16 VendorDesc[DESCRIPTOR_STR_MAX_SIZE]; + CHAR16 DeviceDesc[DESCRIPTOR_STR_MAX_SIZE]; + Status = FindPCIDevDescription(PCIConfHdr.VendorId, + PCIConfHdr.DeviceId, + VendorDesc, + DeviceDesc, + DESCRIPTOR_STR_MAX_SIZE); + if (!EFI_ERROR(Status)) { + Print(L": %s, %s\n", VendorDesc, DeviceDesc); + } else { + Print(L"\n"); + } + Print(L"Has OptionROM at memory %p-%p\n", PciIo->RomImage, (UINT8*)PciIo->RomImage + PciIo->RomSize); + PCI_EXPANSION_ROM_HEADER* RomHeader = (PCI_EXPANSION_ROM_HEADER*) PciIo->RomImage; + UINTN RomImageIndex = 1; + while (TRUE) + { + if (RomHeader->Signature != PCI_EXPANSION_ROM_HEADER_SIGNATURE) { + Print(L"Error! OptionROM has a wrong signature\n"); + return Status; + } + PCI_DATA_STRUCTURE* RomImage = (PCI_DATA_STRUCTURE*)((UINT8*)RomHeader + RomHeader->PcirOffset); + if ((((CHAR8)((RomImage->Signature >> 0) & 0xFF)) != 'P') && + (((CHAR8)((RomImage->Signature >> 8) & 0xFF)) != 'C') && + (((CHAR8)((RomImage->Signature >> 16) & 0xFF)) != 'I') && + (((CHAR8)((RomImage->Signature >> 24) & 0xFF)) != 'R')) { + Print(L"Error! OptionROM image has wrong signature\n"); + return Status; + } + Print(L"---Code Image %d---\n", RomImageIndex); + Print(L"Address: %p-%p\n", RomHeader, (UINT8*)RomHeader + (RomImage->ImageLength)*512); + Print(L"VendorId: %04x, DeviceId: %04x\n", RomImage->VendorId, RomImage->DeviceId); + Print(L"Type: "); + switch (RomImage->CodeType) { + case 0x00: + Print(L"IA-32, PC-AT compatible\n"); + break; + case 0x01: + Print(L"Open Firmware standard for PCI\n"); + break; + case 0x02: + Print(L"Hewlett-Packard PA RISC\n"); + break; + case 0x03: + Print(L"EFI Image\n"); + break; + default: + Print(L"Unknown\n"); + break; + } + if (RomImage->CodeType == 0x03) { + EFI_PCI_EXPANSION_ROM_HEADER* EfiRomHeader = (EFI_PCI_EXPANSION_ROM_HEADER*) RomHeader; + if (EfiRomHeader->EfiSignature == EFI_PCI_EXPANSION_ROM_HEADER_EFISIGNATURE) { + Print(L"Subsystem: "); + switch (EfiRomHeader->EfiSubsystem) { + case EFI_IMAGE_SUBSYSTEM_EFI_APPLICATION: + Print(L"EFI Application\n"); + break; + case EFI_IMAGE_SUBSYSTEM_EFI_BOOT_SERVICE_DRIVER: + Print(L"EFI Boot Service Driver\n"); + break; + case EFI_IMAGE_SUBSYSTEM_EFI_RUNTIME_DRIVER: + Print(L"EFI Runtime Driver\n"); + break; + case EFI_IMAGE_SUBSYSTEM_SAL_RUNTIME_DRIVER: + Print(L"EFI SAL Runtime Driver\n"); + break; + default: + Print(L"Unknown\n"); + break; + } + Print(L"Machine type: "); + switch (EfiRomHeader->EfiMachineType) { + case IMAGE_FILE_MACHINE_I386: + Print(L"IA-32\n"); + break; + case IMAGE_FILE_MACHINE_IA64: + Print(L"Itanium\n"); + break; + case IMAGE_FILE_MACHINE_EBC: + Print(L"EFI Byte Code (EBC)\n"); + break; + case IMAGE_FILE_MACHINE_X64: + Print(L"X64\n"); + break; + case IMAGE_FILE_MACHINE_ARMTHUMB_MIXED: + Print(L"ARM\n"); + break; + case IMAGE_FILE_MACHINE_ARM64: + Print(L"ARM 64-bit\n"); + break; + case IMAGE_FILE_MACHINE_RISCV32: + Print(L"RISCV32\n"); + break; + case IMAGE_FILE_MACHINE_RISCV64: + Print(L"RISCV64\n"); + break; + case IMAGE_FILE_MACHINE_RISCV128: + Print(L"RISCV128\n"); + break; + default: + Print(L"Unknown\n"); + break; + } + switch (EfiRomHeader->CompressionType) { + case EFI_PCI_EXPANSION_ROM_HEADER_COMPRESSED: + Print(L"Compressed following the UEFI Compression Algorithm\n"); + break; + case 0: + Print(L"Uncompressed\n"); + break; + default: + Print(L"Unknown compression type\n"); + break; + } + } else { + Print(L"EFI signature is incorrect!\n"); + } + } + if ((RomImage->Indicator) & 0x80) { + break; + } + RomHeader = (PCI_EXPANSION_ROM_HEADER*)((UINT8*) RomHeader + (RomImage->ImageLength)*512); + RomImageIndex++; + } + Print(L"------------------\n"); + } + return Status; +} + +EFI_STATUS +EFIAPI +UefiMain ( + IN EFI_HANDLE ImageHandle, + IN EFI_SYSTEM_TABLE *SystemTable + ) +{ + EFI_STATUS Status; + UINTN HandleCount; + EFI_HANDLE *HandleBuffer; + Status = gBS->LocateHandleBuffer( + ByProtocol, + &gEfiPciIoProtocolGuid, + NULL, + &HandleCount, + &HandleBuffer + ); + if (EFI_ERROR (Status)) { + Print(L"Can't locate EFI_PCI_IO_PROTOCOL: %r\n", Status); + return Status; + } + + //Print(L"Number of PCI devices in the system: %d\n", HandleCount); + EFI_PCI_IO_PROTOCOL* PciIo; + for (UINTN Index = 0; Index < HandleCount; Index++) { + Status = gBS->OpenProtocol ( + HandleBuffer[Index], + &gEfiPciIoProtocolGuid, + (VOID **)&PciIo, + ImageHandle, + NULL, + EFI_OPEN_PROTOCOL_GET_PROTOCOL + ); + if (EFI_ERROR(Status)) { + Print(L"Can't open protocol: %r\n", Status); + return Status; + } + Status = PrintPCI(PciIo); + if (EFI_ERROR(Status)) { + Print(L"Error in PCI printing\n"); + } + + } + FreePool(HandleBuffer); + + return EFI_SUCCESS; +} diff --git a/Lesson_32/UefiLessonsPkg/DumpPCIroms/DumpPCIroms.inf b/Lesson_32/UefiLessonsPkg/DumpPCIroms/DumpPCIroms.inf new file mode 100644 index 0000000..213a8e4 --- /dev/null +++ b/Lesson_32/UefiLessonsPkg/DumpPCIroms/DumpPCIroms.inf @@ -0,0 +1,22 @@ +[Defines] + INF_VERSION = 1.25 + BASE_NAME = DumpPCIroms + FILE_GUID = 76f1798f-533f-49a2-b94c-96ab3dfebea0 + MODULE_TYPE = UEFI_APPLICATION + VERSION_STRING = 1.0 + ENTRY_POINT = UefiMain + +[Sources] + DumpPCIroms.c + +[Packages] + MdePkg/MdePkg.dec + ShellPkg/ShellPkg.dec + +[LibraryClasses] + UefiApplicationEntryPoint + UefiLib + ShellLib + +[Protocols] + gEfiPciIoProtocolGuid |