ACPI

1. RSDP

Root System Description Pointer es una estructura de datos usada en la API de ACPI

1.1. Estructura

Para ACPI 1.0:

struct RSDPDescriptor {
 char Signature[8]; //String sin terminación null que ha de ser "RSDP PTR " (con el espacio)
 uint8_t Checksum; // Tomamos todos los bytes de la estructura, sumamos este y comprobamos si al castearlo a byte da 0
 char OEMID[6]; // "An OEM-supplied string that identifies the OEM"
 uint8_t Revision; // La versión, backwards compatible
 uint32_t RsdtAddress; // Dirección *FISICA* de la tabla RSDT
} __attribute__ ((packed));

Para ACPI 2.0+:

struct RSDPDescriptor20 {
 RSDPDescriptor firstPart;

 uint32_t Length; //La longitud de la tabla desde offset 0 hasta el final
 uint64_t XsdtAddress; // Dirección *FISICA* de la tabla XSDT, si tenemos ACPI 2.0 usamos esta en vez de RSDT aún en IA-32 (lo casteamos a uint32_t y ya)
 uint8_t ExtendedChecksum; // Iguak que el otro checksum
 uint8_t reserved[3]; // Para nada, no deben ser escritos
} __attribute__ ((packed));

Como vemos extiende la estructura de ACPI 1.0 para mantener compatibilidad.

1.2. Cómo se encuentra

En UEFI en la EFI_SYSTEM_TABLE, si tenemos BIOS en el primer kilobyte de memoria de la “Extended BIOS Data Area” (blablabla).

Su nombre es “RSDP PTR ”, hay que tenerlo en cuenta para encontrarla, es importante el último espacio del nombre (no es una errata).

2. RSDT

Estructura que contiene punteros a otras “SDT” (System Description Tables)

Solo la usaremos si estamos en ACPI < 2.0, si no usamos `XSDT`, de todas formas:

On 80x86 it’s likely that the RSDT and the XSDT both point to the same tables below 4 GB for compatibility reasons

2.1. Estructura

El RSDT es la SDT principal, pero hay varias.

Las SDT se dividen en dos partes, la cabecera que es común a todos los SDT y otra que es de datos, diferente para cada tipo de tabla.

La estructura de la cabecera:

struct ACPISDTHeader {
  char Signature[4]; // Todas las tablas 4bytes menos la RSDP (la root, principal)
  uint32_t Length; //tamaño total de la tabla *incluyendo la cabecera*
  uint8_t Revision;
  uint8_t Checksum; //todos los bytes de la tabla (incluyendo cabecera) sumados módulo 0x100 ha de ser 0 (alineado)
  char OEMID[6];
  char OEMTableID[8];
  uint32_t OEMRevision;
  uint32_t CreatorID;
  uint32_t CreatorRevision;
};

Lo que es la tabla es así, dependiendo si hemos usado RSDT o XSDT:

struct RSDT {
  struct ACPISDTHeader h;
  uint32_t PointerToOtherSDT[(h.Length - sizeof(h)) / 4];
};
struct XSDT {
  struct ACPISDTHeader h;
  uint64_t PointerToOtherSDT[(h.Length - sizeof(h)) / 8];
};

El 4 y el 8 mágico creo que son sizeof(uint32_t) y sizeof(uint64_t) por 32bit y 64bit de direcciones.

2.2. Uso

Teniendo la RSDT asumamos que queremos buscar la SDT “FADT”, como la “FADT” es una SDT tendrá una ACPISDTHeader con signature “FACP”:

void *findFACP(void *RootSDT)
{
    RSDT *rsdt = (RSDT *) RootSDT;
    int entries = (rsdt->h.Length - sizeof(rsdt->h)) / 4;

    for (int i = 0; i < entries; i++)
    {
        ACPISDTHeader *h = (ACPISDTHeader *) rsdt->PointerToOtherSDT[i];
        if (!strncmp(h->Signature, "FACP", 4))
            return (void *) h;
    }

    // No FACP found
    return NULL;
}

3. MCFG (PCIe)

The enhanced configuration mechanism makes use of memory mapped address space range/s to access PCI configuration space. Put simply, the memory address determines the segment group, bus, device, function and register being accessed. On x86 and x64 platforms, the address of each memory area is determined by the ACPI ’MCFG’ table.

KU4rK1.png

Source: https://wiki.osdev.org/PCI_Express