qemu中建立spcr的acpi table

在qemu/hw/arm/virt-apci-build.c 中会创建传给guest的acpi table。这里我们以组建spcr为例
virt_acpi_build->build_spcr
static void
build_spcr(GArray *table_data, BIOSLinker *linker, VirtMachineState *vms)
{
    AcpiSerialPortConsoleRedirection *spcr;
    const MemMapEntry *uart_memmap = &vms->memmap[VIRT_UART];
    int irq = vms->irqmap[VIRT_UART] + ARM_SPI_BASE;
    int spcr_start = table_data->len;
#得到spcr的首地址指针
    spcr = acpi_data_push(table_data, sizeof(*spcr));
#下面就是spcr的个个成员变量的赋值
    spcr->interface_type = 0x3;    /* ARM PL011 UART */

    spcr->base_address.space_id = AML_SYSTEM_MEMORY;
    spcr->base_address.bit_width = 8;
    spcr->base_address.bit_offset = 0;
    spcr->base_address.access_width = 1;
    spcr->base_address.address = cpu_to_le64(uart_memmap->base);

    spcr->interrupt_types = (1 << 3); /* Bit[3] ARMH GIC interrupt */
    spcr->gsi = cpu_to_le32(irq);  /* Global System Interrupt */

    spcr->baud = 3;                /* Baud Rate: 3 = 9600 */
    spcr->parity = 0;              /* No Parity */
    spcr->stopbits = 1;            /* 1 Stop bit */
    spcr->flowctrl = (1 << 1);     /* Bit[1] = RTS/CTS hardware flow control */
    spcr->term_type = 0;           /* Terminal Type: 0 = VT100 */

    spcr->pci_device_id = 0xffff;  /* PCI Device ID: not a PCI device */
    spcr->pci_vendor_id = 0xffff;  /* PCI Vendor ID: not a PCI device */
#将创建spcr table 的头信息
    build_header(linker, table_data, (void *)(table_data->data + spcr_start),
                 "SPCR", table_data->len - spcr_start, 2, NULL, NULL);
}

build_header(BIOSLinker *linker, GArray *table_data,
             AcpiTableHeader *h, const char *sig, int len, uint8_t rev,
             const char *oem_id, const char *oem_table_id)
{
    unsigned tbl_offset = (char *)h - table_data->data;
    unsigned checksum_offset = (char *)&h->checksum - table_data->data;
    memcpy(&h->signature, sig, 4);
    h->length = cpu_to_le32(len);
    h->revision = rev;
#scpr是否包括oem id
    if (oem_id) {
        strncpy((char *)h->oem_id, oem_id, sizeof h->oem_id);
    } else {
        memcpy(h->oem_id, ACPI_BUILD_APPNAME6, 6);
    }

    if (oem_table_id) {
        strncpy((char *)h->oem_table_id, oem_table_id, sizeof(h->oem_table_id));
    } else {
        memcpy(h->oem_table_id, ACPI_BUILD_APPNAME4, 4);
        memcpy(h->oem_table_id + 4, sig, 4);
    }

    h->oem_revision = cpu_to_le32(1);
    memcpy(h->asl_compiler_id, ACPI_BUILD_APPNAME4, 4);
    h->asl_compiler_revision = cpu_to_le32(1);
    /* Checksum to be filled in by Guest linker */
ask guest to add checksum of ACPI  * table in the specified file at the specified offset.
#在表中加入check sum信息,这段组建spcr table的逻辑和bios中的类似
    bios_linker_loader_add_checksum(linker, ACPI_BUILD_TABLE_FILE,
        tbl_offset, len, checksum_offset);
}

 

你可能感兴趣的:(qemu)