当前位置:网站首页>UEFI learning 3.6 - ACPI table on ARM QEMU

UEFI learning 3.6 - ACPI table on ARM QEMU

2022-06-23 09:21:00 MyeDy

If the ACPI Unfamiliar with concept , You can refer to this article first 【UEFI Basics 】ACPI Basics
Parsing code github Address :TestPkg

ACPI Table structure

ACPI The first picture of shows RSDP(Root System Description Pointer), It contains R(X)DST The address of .RDST yes 32 Bit address ,XDST yes 64 Bit address , Its function is the same . In the back is AARCH64 framework , So I used 64 Bit address XDST.
 Insert picture description here
according to RSDP find XDST after , It can be based on XDST Find out each table item Entry, every last Entry The address of the corresponding table is recorded . There are many types of table items , Here you can refer to ACPI 6.3 SPEC. also Entry The type of will change with ACPI Version increase or change .
Be careful XDST first Entry It must be FADT.
It's just QEMU AARCH64 Examples of types used on .QEMU There are a total of 8 The table is as follows :

  • FADT (Fixed ACPI Description Table) , Mainly put some hardware information and DSDT The address of .
  • MADT(Multiple APIC Description Table ), Describes information about interrupt hardware .
  • PPTT(Processor Properties Topology Table), It describes CPU Relevant information .
  • MCFG(PCI Express memory mapped configuration space base address Description Table) PCIE Memory space first closed address .
  • GTDT(Generic Timer Description Table), It describes timer Relevant information .
  • SPCR(Serial Port Console Redirection Table), Describes the serial port related information .
  • DBG2(Debug Port Table), It describes Debug Mouth related information .
  • IORT(I/O Remapping Table), It describes IO Remap Related information .
    therefore , stay QEMU On XSDT The layout is as follows .Header Here we put 8 Addresses of tables .
    AARCH64 QEMU XSDT
    FADT Contains some hardware related information BLKs and DSDT The address of . and DSDT Contains many hardware definition blocks , The definition block describes the static and dynamic information of the hardware .  Insert picture description here

RSDP

First of all to see RSDP The definition of .

MdePkg/Include/IndustryStandard/Acpi63.h

typedef struct {
    
  UINT64    Signature;				-->  The signature is "RSD PTR "
  UINT8     Checksum;				-->  This checksum contains only the first... Of this table 20 Bytes , From 019, And include the field itself . front 20 The sum of bytes must be zero 
  UINT8     OemId[6];				--> OEM ID character string 
  UINT8     Revision;				-->  Version number 
  UINT32    RsdtAddress;			--> 32 position RSDT Address 
  UINT32    Length;					--> RSDP Table length 
  UINT64    XsdtAddress;			--> 64 position XSDT Address 
  UINT8     ExtendedChecksum;		-->  This is the checksum of the entire table , Contains two checksum fields 
  UINT8     Reserved[3];
} EFI_ACPI_6_3_ROOT_SYSTEM_DESCRIPTION_POINTER;

RSDP Store in UEFI Of configuration table in , its guid yes gEfiAcpi20TableGuid.
We can use the following code to find RSDP The address of , The principle is simple , It's traversal UEFI Of configuration table, If GUID yes ACPI surface , Just take it out . find configuration table Of VendorTable Field , It is RSDP Address

TestPkg/TestDxeAcpi.c

EFIAPI
EFI_STATUS 
TestDxeDumpAcpi()
{
    
    UINTN i, j = 0, EntryCount;
    UINT8 Temp = 0;
    EFI_CONFIGURATION_TABLE *configTab = NULL;
    EFI_ACPI_DESCRIPTION_HEADER           *XSDT, *Entry, *DSDT;
    UINT64 *EntryPtr;
    EFI_ACPI_6_3_FIXED_ACPI_DESCRIPTION_TABLE   *FADT;

    EFI_ACPI_6_3_ROOT_SYSTEM_DESCRIPTION_POINTER  *Root;

    DEBUG((DEBUG_INFO, "Dump ACPI\n"));

    configTab = gST->ConfigurationTable;
    // Traverse the system configuration table 
    for(i=0; i<gST->NumberOfTableEntries;i++)
    {
    
        if ((CompareGuid(&configTab->VendorGuid, &gEfiAcpiTableGuid) == TRUE) ||
        (CompareGuid(&configTab->VendorGuid, &gEfiAcpi20TableGuid) == TRUE))
        {
    	
            // If it is ACPI The table takes out its address 
            DEBUG((DEBUG_INFO, "Found ACPI table\n")); 
            DEBUG((DEBUG_INFO, "Address: @[0x%p]\n",configTab));

            Root = configTab->VendorTable;								--> find RSDP
            // Print RSDP Related fields 
            DEBUG((DEBUG_INFO, "RSDP @[0x%p]\n", Root));
            DEBUG((DEBUG_INFO, " Signature:"));
            for(j = 0; j < 8; j++) {
    
                Temp = (Root->Signature >> (j * 8)) & 0xff;
                DEBUG((DEBUG_INFO, "%c", Temp));
            }
            DEBUG((DEBUG_INFO, "\n"));
        
            DEBUG((DEBUG_INFO, " Revision:%d\n", Root->Revision));
        
            DEBUG((DEBUG_INFO, " OEM_ID:"));
            for (j = 0; j < 6; j++) {
    
                DEBUG((DEBUG_INFO, "%c", Root->OemId[j]));
            }
            DEBUG((DEBUG_INFO, "\n"));

            DEBUG((DEBUG_INFO, " Length=[0x%x]\n", Root->Length));
            DEBUG((DEBUG_INFO, " XSDT address=[0x%p]\n", Root->XsdtAddress));
            DEBUG((DEBUG_INFO, " RSDT address=[0x%p]\n", Root->RsdtAddress));
            ...
 }
Dump ACPI
Found ACPI table
Address: @[0x43FDFBD8]
RSDP @[0x405C0018]
  Signature:RSD PTR					--> Singautre accord with RSD PTR
  Revision:2
  OEM_ID:BOCHS
  Length=[0x24]						--> Length is EFI_ACPI_6_3_ROOT_SYSTEM_DESCRIPTION_POINTER The length of 
  XSDT address=[0x405CFE98]			--> It uses XSDT
  RSDT address=[0x0]				-->RSDT non-existent 

XSDT

 Insert picture description here
XSDT There is no proprietary structure definition , It's just APCI Header, Then there is a string Entry Address .XSDT Of Header The definition is as follows . This is also used for other tables Header, It's a ACPI Generic description header .
MdePkg/Include/IndustryStandard/Acpi10.h

typedef struct {
    
  UINT32    Signature;		
  UINT32    Length;
  UINT8     Revision;
  UINT8     Checksum;
  UINT8     OemId[6];
  UINT64    OemTableId;
  UINT32    OemRevision;
  UINT32    CreatorId;
  UINT32    CreatorRevision;
} EFI_ACPI_DESCRIPTION_HEADER;

When it finds XSDT after , You can traverse the following Entry Address , Then find the corresponding Entry
TestPkg/TestDxeAcpi.c

            if (Root->Revision >= EFI_ACPI_6_3_ROOT_SYSTEM_DESCRIPTION_POINTER_REVISION) {
    
                // from RSDP Get in the XSDT The address of 
                XSDT = (EFI_ACPI_DESCRIPTION_HEADER *)(UINTN) Root->XsdtAddress;
                // Count how many Entry, Here you are 8 individual Entry
                EntryCount = (XSDT->Length - sizeof(EFI_ACPI_DESCRIPTION_HEADER)) 
                      / sizeof(UINT64);
                DEBUG((DEBUG_INFO, " XSDT @[0x%p]\n", XSDT));
                // Print XSDT The signature of should be a string "XSDT"
                DEBUG((DEBUG_INFO, " Signature:"));
                for(j = 0; j < 4; j++) {
    
                    Temp = (XSDT->Signature >> (j * 8)) & 0xff;
                    DEBUG((DEBUG_INFO, "%c", Temp));
                }
                DEBUG((DEBUG_INFO, "\n"));
          
                DEBUG((DEBUG_INFO, " Length=[%d]\n", XSDT->Length));
                DEBUG((DEBUG_INFO, " Entry Count=[%d]\n", EntryCount));
                DEBUG((DEBUG_INFO, " OEM_ID:"));
                for (j = 0; j < 6; j++) {
    
                    DEBUG((DEBUG_INFO, "%c", Root->OemId[j]));
                }
                DEBUG((DEBUG_INFO, "\n"));
        
                EntryPtr=(UINT64 *)(XSDT+1);
                // Traverse XSDT Medium Entry, hold Entry Print out your signature 
                for (j = 0; j < EntryCount; j++, EntryPtr++) {
    
           
                    Entry = (EFI_ACPI_DESCRIPTION_HEADER *)((UINTN)(*EntryPtr));
                    if (Entry == NULL) {
    
                    continue;
                    }
                    DEBUG((DEBUG_INFO, " Signature:"));
                    for(j = 0; j < 4; j++) {
    
                    Temp = (Entry->Signature >> (j * 8)) & 0xff;
                    DEBUG((DEBUG_INFO, "%c", Temp));
                    }
                    DEBUG((DEBUG_INFO, "\n"));
                }
            }

You can see the final print as follows

  XSDT @[0x405CFE98]
    Signature:XSDT				-->  Signature is "XSDT"
    Length=[100]				-->  The length is 100 =  Meter length 36 +  Table item Entry length 64
    Entry Count=[8]				--> Entry Count = 8 = 64 / 8
    OEM_ID:BOCHS				--> OEM ID and RSDP The same is BOCHS
    Signature:FACP				-->  The first table FADT The signature of the "FACP"
    Signature:APIC				-->  Second sheet MADT The signature of the "APIC"
	Signature:PPTT				--> .
	Signature:GTDT 					.
	Signature:MCFG					.
    Signature:SPCR					.
    Signature:DBG2				--> .
    Signature:IORT				-->  The signature of the last table "IORT"

FADT

FADT It's a long definition , as follows
MdePkg/Include/IndustryStandard/Acpi63.h

typedef struct {
    
  EFI_ACPI_DESCRIPTION_HEADER               Header;					-->  Universal Header
  UINT32                                    FirmwareCtrl;			--> FACS The address of , OSPM And firmware use this field to exchange control information .
  UINT32                                    Dsdt;					--> DSDT The address of 
  UINT8                                     Reserved0;
  
  ----------------------
  * Power management type 
  *0 - Unspecified
  *1 - Desktp
  *2 - Mobile
  *3 - Wokrstation
  *4 - Enterprise Server
  *5 - SOHO Server
  *6 - Applicance PC
  *7 - Performance Server
  *8 - Tablet
  *>8 Reserved
  -----------------------
  UINT8                                     PreferredPmProfile;
  
  --> stay 8259 In mode SCI Break the system vector of the binding . In the absence of 8269 In the system , This field contains SCI The global system interrupt number of the interrupt .
  -->OSPM Need to put ACPI SCI Interrupts are considered sharable 、 Level trigger 、 Low effective interrupt .
  UINT16                                    SciInt;	
  UINT32                                    SmiCmd;				--> SMI The port where the command is located 
  UINT8                                     AcpiEnable;			-->  Write this value to SMI_CMD To re enable ACPI Hardware register SMI ownership . In systems that do not support legacy patterns , This field is reserved .
  UINT8                                     AcpiDisable;		-->  Write this value to SMI_CMD To re shield ACPI Hardware register SMI ownership . In systems that do not support legacy patterns , This field is reserved .
  UINT8                                     S4BiosReq;			-->  In order to enter S4BIOS The status needs to write this value to SM1_CMD in .
  UINT8                                     PstateCnt;			-->  If this field value is non-zero , that OPSM Write this value to SM1_CMD Register will assume the responsibility of processor performance state control 
  UINT32                                    Pm1aEvtBlk;			--> PM1a The system port address of the event register block 
  UINT32                                    Pm1bEvtBlk;			--> PM1b The system port address of the event register block 
  UINT32                                    Pm1aCntBlk;			--> PM1a The system port address of the control register block 
  UINT32                                    Pm1bCntBlk;			--> PM1b The system port address of the control register block 
  UINT32                                    Pm2CntBlk;			--> PM2 The system port address of the event register block 
  UINT32                                    PmTmrBlk;			-->  The system port address of the power management timer control register 
  UINT32                                    Gpe0Blk;			-->  General purpose events 0 The system port address of the register block 
  UINT32                                    Gpe1Blk;			-->  General purpose events 1 The system port address of the register block 
  UINT8                                     Pm1EvtLen;			-->  from PM1a_EVT_BLK and PM1b_EVT_BLK Number of bytes decoded 
  UINT8                                     Pm1CntLen;			-->  from PM1a_CNT_BLK and PM1b_CNT_BLK Number of bytes decoded 
  UINT8                                     Pm2CntLen;			-->  from PM2_CNT_BLK Number of bytes decoded 
  UINT8                                     PmTmrLen;			-->  from PM_TMR_BLK Number of bytes decoded 
  UINT8                                     Gpe0BlkLen;			-->  from GEP0_BLK Number of bytes decoded 
  UINT8                                     Gpe1BlkLen;			-->  from GPE1_BLK Number of bytes decoded 
  UINT8                                     Gpe1Base;			-->  stay ACPI Common event model GPE1 The offset at the beginning of the event 
  UINT8                                     CstCnt;				--> OSPM Write this value to SMI_CMD Register to OS Show that you are right _CST Objects and C Support for state change notification 
  UINT16                                    PLvl2Lat;			-->  Enter and exit C2 The longest hardware delay of the state 
  UINT16                                    PLvl3Lat;			-->  Enter and exit C3 The longest hardware delay of the state 
  UINT16                                    FlushSize;			-->  Cache refresh step size 
  UINT16                                    FlushStride;		-->  The cache line width of the processor memory cache 
  UINT8                                     DutyOffset;			-->  On the processor's P_CNT In the register , Indicates the zero based index where the processor duty cycle is located 
  UINT8                                     DutyWidth;
  UINT8                                     DayAlrm;			-->  Corresponding to the date warning value RTC_CMOS_RAM Indexes .
  UINT8                                     MonAlrm;			-->  Corresponding to the month warning value RTC_CMOS_RAM Indexes .
  UINT8                                     Century;			-->  Date century value corresponds to RTC_CMOS_RAM Indexes .
  UINT16                                    IaPcBootArch;		--> IA-PC Start schema flag 
  UINT8                                     Reserved1;
  UINT32                                    Flags;				-->  Fixed feature mark 
  EFI_ACPI_6_3_GENERIC_ADDRESS_STRUCTURE    ResetReg;			-->  Reset the address of the register 
  UINT8                                     ResetValue;			-->  To restart the system , This value is written to RESET_REG port 
  UINT16                                    ArmBootArch;		--> ARM Schema start flag 
  UINT8                                     MinorVersion;		-->  This version number 
  UINT64                                    XFirmwareCtrl;		--> EACS Of 64 Bit physical address 
  UINT64                                    XDsdt;				--> DSDT Of 64 Bit physical address 
  EFI_ACPI_6_3_GENERIC_ADDRESS_STRUCTURE    XPm1aEvtBlk;		--> PM1a  Extended address of the event register block 
  EFI_ACPI_6_3_GENERIC_ADDRESS_STRUCTURE    XPm1bEvtBlk;		--> PM1b  Extended address of the event register block 
  EFI_ACPI_6_3_GENERIC_ADDRESS_STRUCTURE    XPm1aCntBlk;		--> PM1a  The extended address of the control register block 
  EFI_ACPI_6_3_GENERIC_ADDRESS_STRUCTURE    XPm1bCntBlk;		--> PM1b  The extended address of the control register block 
  EFI_ACPI_6_3_GENERIC_ADDRESS_STRUCTURE    XPm2CntBlk;			--> PM2  The extended address of the control register block 
  EFI_ACPI_6_3_GENERIC_ADDRESS_STRUCTURE    XPmTmrBlk;			--> PM TMR  Extended address of register block 
  EFI_ACPI_6_3_GENERIC_ADDRESS_STRUCTURE    XGpe0Blk;			--> GEP0  Extended address of register block 
  EFI_ACPI_6_3_GENERIC_ADDRESS_STRUCTURE    XGpe1Blk;			--> GEP1  Extended address of register block 
  EFI_ACPI_6_3_GENERIC_ADDRESS_STRUCTURE    SleepControlReg;	-->  Address of sleep control register 
  EFI_ACPI_6_3_GENERIC_ADDRESS_STRUCTURE    SleepStatusReg;		-->  Address of sleep status register 
  UINT64                                    HypervisorVendorIdentity; --> Hypevisor ID
} EFI_ACPI_6_3_FIXED_ACPI_DESCRIPTION_TABLE;

analysis FADT Code , It is to parse the structure of a table and print it according to its definition
TestPkg/TestDxeAcpi.c

                 switch (Entry->Signature) {
    
                        case EFI_ACPI_6_3_FIXED_ACPI_DESCRIPTION_TABLE_SIGNATURE:

                            FADT = (EFI_ACPI_6_3_FIXED_ACPI_DESCRIPTION_TABLE *)(UINTN) Entry;
                            DumpFADT(FADT);
                            DSDT = (EFI_ACPI_DESCRIPTION_HEADER *)(UINTN)(FADT->Dsdt);
VOID
DumpFADT(EFI_ACPI_6_3_FIXED_ACPI_DESCRIPTION_TABLE *FADT)
{
    
    char *PMProfiles[] = {
    
        "Unspecified",
        "Desktop",
        "Mobile",
        "WorkStation",
        "Enterprise Server",
        "SOHO Server",
        "Applicance PC",
        "Performance Server",
        "Tablet"
    };

    DEBUG((DEBUG_INFO, "\n#########Start Dump FADT##########\n"));

    DumpACPIHeader(&FADT->Header);

    DEBUG((DEBUG_INFO, "FACS:0x%x\n", FADT->FirmwareCtrl));
    DEBUG((DEBUG_INFO, "Dsdt:0x%x\n", FADT->Dsdt));
    DEBUG((DEBUG_INFO, "", FADT->PreferredPmProfile));

    if (FADT->PreferredPmProfile > 8) {
    
        DEBUG((DEBUG_INFO, "PreferredPmProfile: Reserved\n"));
    } else {
    
        DEBUG((DEBUG_INFO, "PreferredPmProfile: %a\n", PMProfiles[FADT->PreferredPmProfile]));
    }

    DEBUG((DEBUG_INFO, "SCI INT:0x%04x\n", FADT->SciInt));
    DEBUG((DEBUG_INFO, "SMI CMD:0x%08x\n", FADT->SmiCmd));
    DEBUG((DEBUG_INFO, "ACPI ENABLE:0x%02x\n", FADT->AcpiEnable));
    DEBUG((DEBUG_INFO, "ACPI DISABLE:0x%02x\n", FADT->AcpiDisable));
    DEBUG((DEBUG_INFO, "S4BIOS REQ:0x%02x\n", FADT->S4BiosReq));
    DEBUG((DEBUG_INFO, "PSTATE CNT:0x%02x\n", FADT->PstateCnt));
    DEBUG((DEBUG_INFO, "PM1a EVT BLK:0x%08x\n", FADT->Pm1aEvtBlk));
    DEBUG((DEBUG_INFO, "PM1b EVT BLK:0x%08x\n", FADT->Pm1bEvtBlk));
    DEBUG((DEBUG_INFO, "PM1a CNT BLK:0x%08x\n", FADT->Pm1aCntBlk));
    DEBUG((DEBUG_INFO, "PM1b CNT BLK:0x%08x\n", FADT->Pm1bCntBlk));
    DEBUG((DEBUG_INFO, "PM TMR BLK:0x%08x\n", FADT->PmTmrBlk));
    DEBUG((DEBUG_INFO, "GPE0 BLK:0x%08x\n", FADT->Gpe0Blk));
    DEBUG((DEBUG_INFO, "GPE1 BLK:0x%08x\n", FADT->Gpe1Blk));
    DEBUG((DEBUG_INFO, "PM1 EVT LEN:0x%02x\n", FADT->Pm1EvtLen));
    DEBUG((DEBUG_INFO, "PM1 CNT LEN:0x%02x\n", FADT->Pm1CntLen));
    DEBUG((DEBUG_INFO, "PM2 CNT LEN:0x%02x\n", FADT->Pm2CntLen));
    DEBUG((DEBUG_INFO, "PM TMR LEN:0x%02x\n", FADT->PmTmrLen));
    DEBUG((DEBUG_INFO, "GPE0 BLK LEN:0x%02x\n", FADT->Gpe0BlkLen));
    DEBUG((DEBUG_INFO, "GPE1 BLK LEN:0x%02x\n", FADT->Gpe1BlkLen));
    DEBUG((DEBUG_INFO, "GPE1 BASE:0x%02x\n", FADT->Gpe1Base));
    DEBUG((DEBUG_INFO, "CST CNT:0x%02x\n", FADT->CstCnt));
    DEBUG((DEBUG_INFO, "P LVL2 LAT:0x%04x\n", FADT->PLvl2Lat));
    DEBUG((DEBUG_INFO, "P LVL3 LAT:0x%04x\n", FADT->PLvl3Lat));
    DEBUG((DEBUG_INFO, "Flush Size:0x%04x\n", FADT->FlushSize));
    DEBUG((DEBUG_INFO, "FLUSH STRIDE:0x%04x\n", FADT->FlushStride));
    DEBUG((DEBUG_INFO, "DUTY OFFSET:0x%02x\n", FADT->DutyOffset));
    DEBUG((DEBUG_INFO, "DUTY WIDTH:0x%02x\n", FADT->DutyWidth));
    DEBUG((DEBUG_INFO, "DAY ALARM:0x%02x\n", FADT->DayAlrm));
    DEBUG((DEBUG_INFO, "MON ALARM:0x%02x\n", FADT->MonAlrm));
    DEBUG((DEBUG_INFO, "CENTURY:0x%02x\n", FADT->Century));
    DEBUG((DEBUG_INFO, "IAPC_BOOT_ARCH:0x%04x\n", FADT->IaPcBootArch));
    DEBUG((DEBUG_INFO, "Flags:0x%08x\n", FADT->Flags));
    DumpGenericAddress("Reset Reg", &FADT->ResetReg);
    DEBUG((DEBUG_INFO, "Reset Value:0x%02x\n", FADT->ResetValue));
    DEBUG((DEBUG_INFO, "ARM BOOT ARCH:0x%04x\n", FADT->ArmBootArch));
    DEBUG((DEBUG_INFO, "FADT MINOR VERSION:0x%02x\n", FADT->MinorVersion));
    DEBUG((DEBUG_INFO, "X FIRMWARE CTRL:0x%p", FADT->XFirmwareCtrl));
    DEBUG((DEBUG_INFO, "X DSDT:0x%p\n", FADT->XDsdt));
    DumpGenericAddress("X PM1a EVT BLK", &FADT->XPm1aEvtBlk);
    DumpGenericAddress("X PM1b EVT BLK", &FADT->XPm1bEvtBlk);
    DumpGenericAddress("X PM1a CNT BLK", &FADT->XPm1aCntBlk);
    DumpGenericAddress("X PM1b CNT BLK", &FADT->XPm1bCntBlk);
    DumpGenericAddress("X PM TMR BLK", &FADT->XPmTmrBlk);
    DumpGenericAddress("GPE0 BLK", &FADT->XGpe0Blk);
    DumpGenericAddress("GPE1 BLK", &FADT->XGpe1Blk);
    DumpGenericAddress("SLEEP CONTROL", &FADT->SleepControlReg);
    DumpGenericAddress("SLEEP STATUS", &FADT->SleepStatusReg);

    DEBUG((DEBUG_INFO, "###########End Dump FADT###########\n\n"));
}

log analysis

#########Start Dump FADT##########
Signature:FACP							--> The signature is "FACP"
Length:0x10C							--> Length is FADT The length of the structure 
Revision:0x05							--> Here are some version information 
Checksum:0x03
OemID:BOCHS 
OemTableId:0x2020202043505842			-
OemRevision:0x1
CreatorId:0x43505842
CreatorRevision:0x1
FACS:0x0								-->FACS The address is 0, It just doesn't exist 
Dsdt:0x405C7518							-->DSDT The address of 
PreferredPmProfile: Unspecified			--> No power management is specified Profile
--> Because of the ARM AARCH64 Structure , The following hardware is in AARCH64 There is no architecture ,  So the following hardware information AARCH64 No need 
--> So the following hardware information is 0, It just doesn't exist . about X86/X64 Architecture is needed .
SCI INT:0x0000							
SMI CMD:0x00000000
ACPI ENABLE:0x00
ACPI DISABLE:0x00
S4BIOS REQ:0x00
PSTATE CNT:0x00
PM1a EVT BLK:0x00000000
PM1b EVT BLK:0x00000000
PM1a CNT BLK:0x00000000
PM1b CNT BLK:0x00000000
PM TMR BLK:0x00000000
GPE0 BLK:0x00000000
GPE1 BLK:0x00000000
PM1 EVT LEN:0x00
PM1 CNT LEN:0x00
PM2 CNT LEN:0x00
PM TMR LEN:0x00
GPE0 BLK LEN:0x00
GPE1 BLK LEN:0x00
GPE1 BASE:0x00
CST CNT:0x00
P LVL2 LAT:0x0000
P LVL3 LAT:0x0000
Flush Size:0x0000
FLUSH STRIDE:0x0000
DUTY OFFSET:0x00
DUTY WIDTH:0x00
DAY ALARM:0x00
MON ALARM:0x00
CENTURY:0x00
IAPC_BOOT_ARCH:0x0000
Flags:0x00100000
Reset Reg: AddressSpaceId:0x00, RegisterBitWidth:0x00, RegisterBitOffset:0x00, AccessSize:0x00, Address:0x00000000000
Reset Value:0x00
ARM BOOT ARCH:0x0003					--> ARM BOOT framework 
FADT MINOR VERSION:0x01					-->  Sub version number 
X FIRMWARE CTRL:0x0
X DSDT:0x405C7518						--> XDSDT The address of 
X PM1a EVT BLK: AddressSpaceId:0x00, RegisterBitWidth:0x00, RegisterBitOffset:0x00, AccessSize:0x00, Address:0x00000000000
X PM1b EVT BLK: AddressSpaceId:0x00, RegisterBitWidth:0x00, RegisterBitOffset:0x00, AccessSize:0x00, Address:0x00000000000
X PM1a CNT BLK: AddressSpaceId:0x00, RegisterBitWidth:0x00, RegisterBitOffset:0x00, AccessSize:0x00, Address:0x00000000000
X PM1b CNT BLK: AddressSpaceId:0x00, RegisterBitWidth:0x00, RegisterBitOffset:0x00, AccessSize:0x00, Address:0x00000000000
X PM TMR BLK: AddressSpaceId:0x00, RegisterBitWidth:0x00, RegisterBitOffset:0x00, AccessSize:0x00, Address:0x00000000000
GPE0 BLK: AddressSpaceId:0x00, RegisterBitWidth:0x00, RegisterBitOffset:0x00, AccessSize:0x00, Address:0x00000000000
GPE1 BLK: AddressSpaceId:0x00, RegisterBitWidth:0x00, RegisterBitOffset:0x00, AccessSize:0x00, Address:0x00000000000
SLEEP CONTROL: AddressSpaceId:0x00, RegisterBitWidth:0x00, RegisterBitOffset:0x00, AccessSize:0x00, Address:0x00000000000
SLEEP STATUS: AddressSpaceId:0x00, RegisterBitWidth:0x00, RegisterBitOffset:0x00, AccessSize:0x00, Address:0x00000000000
###########End Dump FADT###########

DSDT

The above has been based on FADT eureka DSDT The address of . Then we can parse it out . Talked about before DSDT There is only one head , Then there are one by one AML Definition block . and AML Definition blocks exist as raw data , So we need to dump Out of this AML The data of , Then use tools to parse . The print code is as follows .
TestPkg/TestDxeAcpi.c

DSDT = (EFI_ACPI_DESCRIPTION_HEADER *)(UINTN)(FADT->Dsdt);
DEBUG((DEBUG_INFO, "\n#########Start Dump DSDT##########\n"));
UINT32 *temp = (UINT32 *)DSDT;
for (UINTN k = 0; k < DSDT->Length; k += 4) {
    
    DEBUG((DEBUG_INFO, "0x%08x\n", *temp++));
}
DEBUG((DEBUG_INFO, "#########End Dump DSDT##########\n\n"));
break;

stay EDK2 I haven't found a ready-made one to put AML Code that parses into strings , So here I will DSDT and AML Define the data of the block to 16 I print it out , Then manually save to a file dsdt.txt in , Reuse scripts in ubuntu On the call iasl Parsing DSDT.

0x54445344				--> DSDT The raw data of is as follows 
0x0000144C
0x4F429F02
0x20534843
...
0x00444955

Parsing script

import os
import sys

f = open('dsdt.txt')
out = open('dsdt.dat', 'wb+')
for line in f:
    line = line.replace('\n', '')
    val = int(line, 16) 
    print(val)
    out.write(val.to_bytes(4,  byteorder='little'))

f.close()
out.close()

os.system('iasl -d dsdt.dat')

Finally, it is resolved dsdt.dsl as follows .

/* * Intel ACPI Component Architecture * AML/ASL+ Disassembler version 20200925 (64-bit version) * Copyright (c) 2000 - 2020 Intel Corporation * * Disassembling to symbolic ASL+ operators * * Disassembly of dsdt.dat, Wed May 25 09:14:56 2022 */
 --------------->DSDT Of Header
 * Original Table Header:
 *     Signature        "DSDT"
 *     Length           0x0000144C (5196)
 *     Revision         0x02
 *     Checksum         0x9F
 *     OEM ID           "BOCHS "
 *     OEM Table ID     "BXPC "
 *     OEM Revision     0x00000001 (1)
 *     Compiler ID      "BXPC"
 *     Compiler Version 0x00000001 (1)
 *
DefinitionBlock ("", "DSDT", 2, "BOCHS ", "BXPC ", 0x00000001)
{
    
    Scope (\_SB)
    {
    
    	// CPU Device Information about 
        Device (C000)
        {
    
            Name (_HID, "ACPI0007" /* Processor Device */)  // _HID: Hardware ID
            Name (_UID, Zero)  // _UID: Unique ID
        }
		// Serial port information 
        Device (COM0)
        {
    
            Name (_HID, "ARMH0011") ARMH0011 representative ARM PL011 IP // _HID: Hardware ID 
            Name (_UID, Zero)  // _UID: Unique ID
            Name (_CRS, ResourceTemplate ()  // _CRS: Current Resource Settings
            {
    
                Memory32Fixed (ReadWrite,
                    0x09000000,         //  Starting address of serial port register 
                    0x00001000,         //  Length of serial port register 
                    )
                // Interrupt related information .
                Interrupt (ResourceConsumer, Level, ActiveHigh, Exclusive, ,, )
                {
    
                    0x00000021,
                }
            })
        }
		// FW CFG Information about 
        Device (FWCF)
        {
    
            Name (_HID, "QEMU0002") QEMU0002 representative QMEU FW CFG equipment  // _HID: Hardware ID 
            Name (_STA, 0x0B)  // _STA: Status
            Name (_CCA, One)  // _CCA: Cache Coherency Attribute
            Name (_CRS, ResourceTemplate ()  // _CRS: Current Resource Settings
            {
    
                Memory32Fixed (ReadWrite,
                    0x09020000,         // FW CFG  From 
                    0x00000018,         // FW CFG  The length of 
                    )
            })
        }
		//  There is a pile of VIRT IO Information about , Only the head and tail are left here ,  It's all the same thing 
        Device (VR00)
        {
    
            Name (_HID, "LNRO0005")  // _HID: Hardware ID
            Name (_UID, Zero)  // _UID: Unique ID
            Name (_CCA, One)  // _CCA: Cache Coherency Attribute
            Name (_CRS, ResourceTemplate ()  // _CRS: Current Resource Settings
            {
    
                Memory32Fixed (ReadWrite,
                    0x0A000000,         // VIRT IO0  From 
                    0x00000200,         // VIRT IO0  The length of 
                    )
                Interrupt (ResourceConsumer, Level, ActiveHigh, Exclusive, ,, )
                {
    
                    0x00000030,
                }
            })
        }

 		...
        Device (VR31)
        {
    
			...
        }
		//PCI0 Information about   Not very well understood QEMU On PCI Usage of , There is no explanation here 
        Device (PCI0)
        {
    
            Name (_HID, "PNP0A08" /* PCI Express Bus */)  // _HID: Hardware ID
            Name (_CID, "PNP0A03" /* PCI Bus */)  // _CID: Compatible ID
            Name (_SEG, Zero)  // _SEG: PCI Segment
            Name (_BBN, Zero)  // _BBN: BIOS Bus Number
            Name (_UID, Zero)  // _UID: Unique ID
            Name (_STR, Unicode ("PCIe 0 Device"))  // _STR: Description String
            Name (_CCA, One)  // _CCA: Cache Coherency Attribute
            Name (_PRT, Package (0x80)  // _PRT: PCI Routing Table
            {
    
                Package (0x04)
                {
    
                    0xFFFF, 
                    Zero, 
                    GSI0, 
                    Zero
                }, 
				...
                Package (0x04)
                {
    
                    0x001FFFFF, 
                    One, 
                    GSI0, 
                    Zero
                }, 

                Package (0x04)
                {
    
                    0x001FFFFF, 
                    0x02, 
                    GSI1, 
                    Zero
                }, 

                Package (0x04)
                {
    
                    0x001FFFFF, 
                    0x03, 
                    GSI2, 
                    Zero
                }
            })
			...
        }
		//  describe Generic Evenet Device Information about 
        Device (\_SB.GED)
        {
    
            Name (_HID, "ACPI0013" /* Generic Event Device */)  // _HID: Hardware ID
            Name (_UID, "GED")  // _UID: Unique ID
            Name (_CRS, ResourceTemplate ()  // _CRS: Current Resource Settings
            {
    
                // Interrupt message 
                Interrupt (ResourceConsumer, Edge, ActiveHigh, Exclusive, ,, )
                {
    
                    0x00000029,
                }
            })
            // Register address and length 
            OperationRegion (EREG, SystemMemory, 0x09080000, 0x04)
            //32 Bit register definition 
            Field (EREG, DWordAcc, NoLock, WriteAsZeros)
            {
    
                ESEL,   32
            }
			// How to operate 
            Method (_EVT, 1, Serialized)  // _EVT: Event
            {
    
                Local0 = ESEL /* \_SB_.GED_.ESEL */
                If (((Local0 & 0x02) == 0x02))
                {
    
                    Notify (PWRB, 0x80) // Status Change
                }
            }
        }
		// Key information 
        Device (PWRB)
        {
    
            Name (_HID, "PNP0C0C" /* Power Button Device */)  // _HID: Hardware ID
            Name (_UID, Zero)  // _UID: Unique ID
        }
    }
}

MADT

MADT Used to describe interrupt hardware information .
MdePkg/Include/IndustryStandard/Acpi63.h

typedef struct {
    
  EFI_ACPI_DESCRIPTION_HEADER    Header;				--> ACPI Header
  UINT32                         LocalApicAddress;		-->  The address of the processor local interrupt processor 
  UINT32                         Flags;					-->  Sign a .
} EFI_ACPI_6_3_MULTIPLE_APIC_DESCRIPTION_TABLE_HEADER;

stay MADT(EFI_ACPI_6_3_MULTIPLE_APIC_DESCRIPTION_TABLE_HEADER) Followed by a series of interrupt controller structures , Its size is not constant , It needs to be dynamically resolved . The following code can parse MADT Information about .

switch (Entry->Signature) {
    
...
case EFI_ACPI_6_3_MULTIPLE_APIC_DESCRIPTION_TABLE_SIGNATURE:
    DumpMADT((EFI_ACPI_6_3_MULTIPLE_APIC_DESCRIPTION_TABLE_HEADER *)Entry);
    break;
...

DumpMADT First of all, analyze out Header Information in , Then traverse the interrupt controller structure , Analyze the corresponding interrupt hardware information .AARCH64 There is only GIC,GICD and GIC MSI. So only dump These three interrupt controllers are designed .
TestPkg/TestDxeAcpi.c

VOID
DumpMADT(
    IN EFI_ACPI_6_3_MULTIPLE_APIC_DESCRIPTION_TABLE_HEADER *MADT
)
{
    
    UINT8 *TempPtr; 
    UINT8 Type, Length;
    UINTN Len = 0;
    DEBUG((DEBUG_INFO, "\n###########Start Dump MADT###########\n"));
    DumpACPIHeader(&MADT->Header);							// analysis ACPI  head 
    DEBUG((DEBUG_INFO, "Local APIC Address:0x%08x\n", MADT->LocalApicAddress));
    DEBUG((DEBUG_INFO, "Flags:0x%08x\n", MADT->Flags));

    TempPtr = (UINT8 *)(MADT + 1);
    Len = MADT->Header.Length - sizeof(EFI_ACPI_6_3_MULTIPLE_APIC_DESCRIPTION_TABLE_HEADER);
	// Traverse the interrupt controller structure .
    while (Len > 0) {
    
        Type = *TempPtr;			// The first byte of each interrupt controller structure is the type 
        Length = *(TempPtr + 1);	// The second byte is the length 
        switch(Type)
        {
    
        // Resolve the corresponding interrupt structure information according to different types .
        case EFI_ACPI_6_3_PROCESSOR_LOCAL_APIC:
        case EFI_ACPI_6_3_IO_APIC:
        case EFI_ACPI_6_3_INTERRUPT_SOURCE_OVERRIDE:
        case EFI_ACPI_6_3_NON_MASKABLE_INTERRUPT_SOURCE:
        case EFI_ACPI_6_3_LOCAL_APIC_NMI:
        case EFI_ACPI_6_3_LOCAL_APIC_ADDRESS_OVERRIDE:
        case EFI_ACPI_6_3_IO_SAPIC:
        case EFI_ACPI_6_3_LOCAL_SAPIC:
        case EFI_ACPI_6_3_PROCESSOR_LOCAL_X2APIC:
        case EFI_ACPI_6_3_LOCAL_X2APIC_NMI:
        case EFI_ACPI_6_3_GICR:
        case EFI_ACPI_6_3_GIC_ITS:
            DEBUG((DEBUG_INFO, "Parser not implemented for Type:0x%02x\n", Type));
            break;
        case EFI_ACPI_6_3_GIC:
            DumpMadtGIC((EFI_ACPI_6_3_GIC_STRUCTURE *)TempPtr);
            break;
        case EFI_ACPI_6_3_GICD:
            DumpMadtGICD((EFI_ACPI_6_3_GIC_DISTRIBUTOR_STRUCTURE *)TempPtr);
            break;
        case EFI_ACPI_6_3_GIC_MSI_FRAME:
            DumpMadtGICMSI((EFI_ACPI_6_3_GIC_MSI_FRAME_STRUCTURE *)TempPtr);
            break;
        default:
            DEBUG((DEBUG_INFO, "Unknown Type:0x%02x\n", Type));
            break;
        }

        Len = Len - Length;
        TempPtr = TempPtr + Length;
    }
    DEBUG((DEBUG_INFO, "###########End Dump MADT###########\n\n"));
}

 Insert picture description here
 Insert picture description here

VOID
DumpMadtGIC(EFI_ACPI_6_3_GIC_STRUCTURE *GIC)
{
    
    DEBUG((DEBUG_INFO, "GIC Information:\n"));
    DEBUG((DEBUG_INFO, " CPU Interface Number:%d\n", GIC->CPUInterfaceNumber));
    DEBUG((DEBUG_INFO, " Acpi Processor Uid:0x%08x\n", GIC->AcpiProcessorUid));
    DEBUG((DEBUG_INFO, " Flags:0x%08x\n", GIC->Flags));
    DEBUG((DEBUG_INFO, " Parking Protoco lVersion:0x%08x\n", GIC->ParkingProtocolVersion));
    DEBUG((DEBUG_INFO, " Performance Interrupt Gsiv:0x%08x\n", GIC->PerformanceInterruptGsiv));
    DEBUG((DEBUG_INFO, " Parked Address:0x%p\n", GIC->ParkedAddress));
    DEBUG((DEBUG_INFO, " Physical Base Address:0x%p\n", GIC->PhysicalBaseAddress));
    DEBUG((DEBUG_INFO, " GICV:0x%11p\n", GIC->GICV));
    DEBUG((DEBUG_INFO, " GICH:0x%11p\n", GIC->GICH));
    DEBUG((DEBUG_INFO, " VGIC Maintenance Interrupt:0x%x\n", GIC->VGICMaintenanceInterrupt));
    DEBUG((DEBUG_INFO, " GICR Base Address:0x%11p\n", GIC->GICRBaseAddress));
    DEBUG((DEBUG_INFO, " MPIDR:%11p\n", GIC->MPIDR));
    DEBUG((DEBUG_INFO, " Processor Power Efficiency Class:0x%02x\n", GIC->ProcessorPowerEfficiencyClass));
    DEBUG((DEBUG_INFO, " Spe Overflow Interrupt:0x%04x\n", GIC->SpeOverflowInterrupt));
}

 Insert picture description here

VOID
DumpMadtGICD(
    IN EFI_ACPI_6_3_GIC_DISTRIBUTOR_STRUCTURE *GICD
)
{
    
    DEBUG((DEBUG_INFO, "GIC Distributor Information:\n"));
    DEBUG((DEBUG_INFO, " Gic Id:0x%08x\n", GICD->GicId ));
    DEBUG((DEBUG_INFO, " Physical Base Address:0x%11p\n", GICD->PhysicalBaseAddress));
    DEBUG((DEBUG_INFO, " System Vector Base:0x%x\n", GICD->SystemVectorBase));
    DEBUG((DEBUG_INFO, " Gic Version:0x%02x\n", GICD->GicVersion));
}

 Insert picture description here


VOID 
DumpMadtGICMSI(EFI_ACPI_6_3_GIC_MSI_FRAME_STRUCTURE *GICMSI)
{
    
    DEBUG((DEBUG_INFO, "GIC MSI Information:\n"));
    DEBUG((DEBUG_INFO, " Gic Msi Frame Id:0x%08x\n", GICMSI->GicMsiFrameId));
    DEBUG((DEBUG_INFO, " Physical Base Address:0x%11p\n", GICMSI->PhysicalBaseAddress));
    DEBUG((DEBUG_INFO, " Flags:0x%08x\n", GICMSI->Flags));
    DEBUG((DEBUG_INFO, " SPI Count:0x%04x\n", GICMSI->SPICount));
    DEBUG((DEBUG_INFO, " SPI Base:0x%04x\n", GICMSI->SPIBase));
}

Final dump Coming out log as follows

###########Start Dump MADT###########
Signature:APIC									--> Header information 
Length:0xA8
Revision:0x03
Checksum:0x50
OemID:BOCHS 
OemTableId:0x2020202043505842
OemRevision:0x1
CreatorId:0x43505842
CreatorRevision:0x1
Local APIC Address:0x00000000					-->  non-existent Local APIC
Flags:0x00000000								
GIC Distributor Information:						
  Gic Id:0x00000000								--> GIC Distrubtor ID by 0
  Physical Base Address:0x00008000000			--> GIC Distributor The physical address of 
  System Vector Base:0x0						-->  It has to be for 0
  Gic Version:0x02								--> GIC V2
GIC Information:								
  CPU Interface Number:0						--> CPU Interface does not exist , by 0
  Acpi Processor Uid:0x00000000					-->  non-existent 
  Flags:0x00000001								--> GIC You can make 
  Parking Protoco lVersion:0x00000000			--> ARM-Processor Parking Protocol  Version number 
  Performance Interrupt Gsiv:0x00000017			-->  Performance monitoring GIV Interrupt number 
  Parked Address:0x0
  Physical Base Address:0x8010000				--> GIC The physical address of 
  GICV:0x00008040000							--> GIC virtual CPU interface Register address 
  GICH:0x00008030000							--> GIC virtual interface control block Register address 
  VGIC Maintenance Interrupt:0x0				-->  non-existent 
  GICR Base Address:0x00000000000				-->  Here is GIC V2, therefore GICR non-existent 
  MPIDR:00000000000								
  Processor Power Efficiency Class:0x0D			-->  Power consumption level 
  Spe Overflow Interrupt:0x0000					-->  by 0,  I won't support it Spe Overflow
GIC MSI Information:
  Gic Msi Frame Id:0x00000000					--> ID by 0 
  Physical Base Address:0x00008020000			--> GIC MSI The physical address of 
  Flags:0x00000001								--> The SPI Count and Base values override the values specified in the MSI_TYPER register in the associated GIC MSI frame.
  SPI Count:0x0040								--> SPI Number 
  SPI Base:0x0050								
###########End Dump MADT###########

SPCR

SPCR(Serial Port Console Redirection) Provides information about serial ports or non legacy UART Interface configuration and usage information .. stay BIOS Use this serial port as console input / In the output system , You should use this table to pass information about these settings , Make sure BIOS Console output and Windows EMS(Emergency Management Serivces) Smooth transition between outputs .
 Insert picture description here
 Insert picture description here
 Insert picture description here
MdePkg/Include/IndustryStandard/SerialPortConsoleRedirection.h

typedef struct {
    
  EFI_ACPI_DESCRIPTION_HEADER               Header;
  UINT8                                     InterfaceType;
  UINT8                                     Reserved1[3];
  EFI_ACPI_5_0_GENERIC_ADDRESS_STRUCTURE    BaseAddress;
  UINT8                                     InterruptType;
  UINT8                                     Irq;
  UINT32                                    GlobalSystemInterrupt;
  UINT8                                     BaudRate;
  UINT8                                     Parity;
  UINT8                                     StopBits;
  UINT8                                     FlowControl;
  UINT8                                     TerminalType;
  UINT8                                     Reserved2;
  UINT16                                    PciDeviceId;
  UINT16                                    PciVendorId;
  UINT8                                     PciBusNumber;
  UINT8                                     PciDeviceNumber;
  UINT8                                     PciFunctionNumber;
  UINT32                                    PciFlags;
  UINT8                                     PciSegment;
  UINT32                                    Reserved3;
} EFI_ACPI_SERIAL_PORT_CONSOLE_REDIRECTION_TABLE;

Dump SPCR The code for is as follows

switch (Entry->Signature) {
    
...
case EFI_ACPI_6_3_SERIAL_PORT_CONSOLE_REDIRECTION_TABLE_SIGNATURE:
                            DumpSPCR((EFI_ACPI_SERIAL_PORT_CONSOLE_REDIRECTION_TABLE *)Entry);
                            break;
...
}
VOID
DumpSPCR(
    IN EFI_ACPI_SERIAL_PORT_CONSOLE_REDIRECTION_TABLE *SPCR
)
{
    
    char *TempStr;
    DEBUG((DEBUG_INFO, "\n#########Start Dump SPCR##########\n"));
    DumpACPIHeader(&SPCR->Header);
    switch(SPCR->InterfaceType) {
    
    case EFI_ACPI_SERIAL_PORT_CONSOLE_REDIRECTION_TABLE_INTERFACE_TYPE_16550:
        TempStr = "16550";
        break;
    case EFI_ACPI_SERIAL_PORT_CONSOLE_REDIRECTION_TABLE_INTERFACE_TYPE_16450:
        TempStr = "16450";
        break;
    case EFI_ACPI_SERIAL_PORT_CONSOLE_REDIRECTION_TABLE_INTERFACE_TYPE_ARM_PL011_UART:
        TempStr = "ARM PL011 UART";
        break;
    case EFI_ACPI_SERIAL_PORT_CONSOLE_REDIRECTION_TABLE_INTERFACE_TYPE_NVIDIA_16550_UART:
        TempStr = "NVIDIA 16550 UART";
        break;
    case EFI_ACPI_SERIAL_PORT_CONSOLE_REDIRECTION_TABLE_INTERFACE_TYPE_ARM_SBSA_GENERIC_UART_2X:
        TempStr = "ARM SBSA Generic UART 2.x";
        break;
    case EFI_ACPI_SERIAL_PORT_CONSOLE_REDIRECTION_TABLE_INTERFACE_TYPE_ARM_SBSA_GENERIC_UART:
        TempStr = "ARM SBSA Generic UART";
        break;
    case EFI_ACPI_SERIAL_PORT_CONSOLE_REDIRECTION_TABLE_INTERFACE_TYPE_DCC:
        TempStr = "ARM DCC";
        break;
    case EFI_ACPI_SERIAL_PORT_CONSOLE_REDIRECTION_TABLE_INTERFACE_TYPE_BCM2835_UART:
        TempStr = "BCM2835";
        break;
    case EFI_ACPI_SERIAL_PORT_CONSOLE_REDIRECTION_TABLE_INTERFACE_TYPE_16550_WITH_GAS:
        TempStr = "16550-compatible";
        break;
    default:
        TempStr = "Reserved";
        break;
    }
    DEBUG((DEBUG_INFO, "Interface:%a\n", TempStr));

    DumpGenericAddress("Base Address", (EFI_ACPI_6_3_GENERIC_ADDRESS_STRUCTURE *)&SPCR->BaseAddress);
    
    switch (SPCR->InterruptType)
    {
    
    case EFI_ACPI_SERIAL_PORT_CONSOLE_REDIRECTION_TABLE_INTERRUPT_TYPE_8259:
        TempStr = "8259";
        break;
    case EFI_ACPI_SERIAL_PORT_CONSOLE_REDIRECTION_TABLE_INTERRUPT_TYPE_APIC:
        TempStr = "APIC";
        break;
    case EFI_ACPI_SERIAL_PORT_CONSOLE_REDIRECTION_TABLE_INTERRUPT_TYPE_SAPIC:
        TempStr = "SAPIC";
        break;
    case EFI_ACPI_SERIAL_PORT_CONSOLE_REDIRECTION_TABLE_INTERRUPT_TYPE_GIC:
        TempStr = "GIC";
        break;
    default:
        
        TempStr = "Not Supported";
        break;
    }
    DEBUG((DEBUG_INFO, "Interrupt Type: %a\n", TempStr));

    DEBUG((DEBUG_INFO, "IRQ:%d\n", SPCR->Irq));
    DEBUG((DEBUG_INFO, "Global System Interrupt:0x%x\n", SPCR->GlobalSystemInterrupt));
   
    switch (SPCR->BaudRate)
    {
    
    case EFI_ACPI_SERIAL_PORT_CONSOLE_REDIRECTION_TABLE_BAUD_RATE_9600: 
        TempStr = "9600";
        break;
    case EFI_ACPI_SERIAL_PORT_CONSOLE_REDIRECTION_TABLE_BAUD_RATE_19200:
        TempStr = "19200";
        break;
    case EFI_ACPI_SERIAL_PORT_CONSOLE_REDIRECTION_TABLE_BAUD_RATE_57600:
        TempStr = "57600";
        break;
    case EFI_ACPI_SERIAL_PORT_CONSOLE_REDIRECTION_TABLE_BAUD_RATE_115200:
        TempStr = "115200";
        break;
    default:
        TempStr = "Reserved";
        break;
    }
    DEBUG((DEBUG_INFO, "Baud Rate:%a\n", TempStr));

    switch (SPCR->Parity)
    {
    
    case EFI_ACPI_SERIAL_PORT_CONSOLE_REDIRECTION_TABLE_PARITY_NO_PARITY:
        DEBUG((DEBUG_INFO, "Parity: No Parity\n"));
        break;
    default:
        DEBUG((DEBUG_INFO, "Parity: Reserved\n"));
        break;
    }
    
    switch (SPCR->StopBits)
    {
    
    case EFI_ACPI_SERIAL_PORT_CONSOLE_REDIRECTION_TABLE_STOP_BITS_1:
        DEBUG((DEBUG_INFO, "Stop Bits:%d\n", SPCR->StopBits));
        break;
    default:
        DEBUG((DEBUG_INFO, "Stop Bits: No Stop Bits\n"));
        break;
    }


    DEBUG((DEBUG_INFO, "Flow Control: \n"));
    if (SPCR->FlowControl & EFI_ACPI_SERIAL_PORT_CONSOLE_REDIRECTION_TABLE_FLOW_CONTROL_DCD) {
    
        DEBUG((DEBUG_INFO, " Support DCD\n"));
    }

    if (SPCR->FlowControl & EFI_ACPI_SERIAL_PORT_CONSOLE_REDIRECTION_TABLE_FLOW_CONTROL_RTS_CTS) {
    
        DEBUG((DEBUG_INFO, " Support RTS/CTS\n"));
    }

    if (SPCR->FlowControl & EFI_ACPI_SERIAL_PORT_CONSOLE_REDIRECTION_TABLE_FLOW_CONTROL_XON_XOFF) {
    
        DEBUG((DEBUG_INFO, " Support XON/XOFF\n"));
    }
    
    switch (SPCR->TerminalType)
    {
    
    case EFI_ACPI_SERIAL_PORT_CONSOLE_REDIRECTION_TABLE_TERMINAL_TYPE_VT100:
        TempStr = "VT100";
        break;
    case EFI_ACPI_SERIAL_PORT_CONSOLE_REDIRECTION_TABLE_TERMINAL_TYPE_VT100_PLUS:
        TempStr = "VT100+";
        break;
    case EFI_ACPI_SERIAL_PORT_CONSOLE_REDIRECTION_TABLE_TERMINAL_TYPE_VT_UTF8:
        TempStr = "VI-UTF8";
        break;
    case EFI_ACPI_SERIAL_PORT_CONSOLE_REDIRECTION_TABLE_TERMINAL_TYPE_ANSI:
        TempStr = "ANSI";
        break;
    default:
        
        TempStr = "Reserved";
        break;
    }
    DEBUG((DEBUG_INFO, "Termial Type:%a\n", TempStr));
    
    DEBUG((DEBUG_INFO, "PCI Device ID:0x%04x\n", SPCR->PciDeviceId));
    DEBUG((DEBUG_INFO, "PCI Vendor ID:0x%04x\n", SPCR->PciVendorId));
    DEBUG((DEBUG_INFO, "PCI Bus Number:0x%02x\n", SPCR->PciBusNumber));
    DEBUG((DEBUG_INFO, "PCI Device Number:0x%02x\n", SPCR->PciDeviceNumber));
    DEBUG((DEBUG_INFO, "PCI Function Number:0x%02x\n", SPCR->PciFunctionNumber));
    DEBUG((DEBUG_INFO, "PCI Flags:0x%08x\n", SPCR->PciFlags));
    DEBUG((DEBUG_INFO, "PCI Segment:0x%02x\n", SPCR->PciSegment));
    DEBUG((DEBUG_INFO, "###########End Dump SPCR###########\n\n"));
}

dump Out of log

#########Start Dump SPCR##########
Signature:SPCR
Length:0x50
Revision:0x02
Checksum:0xCB
OemID:BOCHS 
OemTableId:0x2020202043505842
OemRevision:0x1
CreatorId:0x43505842
CreatorRevision:0x1
Interface:ARM PL011 UART				-->  The type is ARM PL011 IP
-->  The physical address of the serial port is 0x00009000000.
Base Address: AddressSpaceId:0x00, RegisterBitWidth:0x08, RegisterBitOffset:0x00, AccessSize:0x01, Address:0x00009000000
Interrupt Type: GIC						-->  The interrupt type is ARM GIC
IRQ:0						
Global System Interrupt:0x21			-->  The interrupt number is 0x21
Baud Rate:9600							-->  The baud rate is 9600
Parity: No Parity						-->  No parity 
Stop Bits:1								-->  Stop bit is 1 position 
Flow Control: 							-->  Support RTS/CTS
  Support RTS/CTS
Termial Type:VT100						--> Console The type is VT100
PCI Device ID:0xFFFF					-->  No PCI  equipment , The following fields are all invalid 
PCI Vendor ID:0xFFFF
PCI Bus Number:0x00
PCI Device Number:0x00
PCI Function Number:0x00
PCI Flags:0x00000000
PCI Segment:0x00
###########End Dump SPCR###########
原网站

版权声明
本文为[MyeDy]所创,转载请带上原文链接,感谢
https://yzsam.com/2022/174/202206230912174437.html