void acpi_resume(struct acpi_fadt *fadt) { void *wake_vec; /* Turn on ACPI mode for S3 */ enter_acpi_mode(fadt->pm1a_cnt_blk); wake_vec = acpi_find_wakeup_vector(fadt); /* * Restore the memory content starting from address 0x1000 which is * used for the real mode interrupt handler stubs. */ memcpy((void *)0x1000, (const void *)gd->arch.backup_mem, S3_RESERVE_SIZE); post_code(POST_OS_RESUME); acpi_jump_to_wakeup(wake_vec); }
/* * QEMU's version of write_acpi_tables is defined in * arch/x86/cpu/qemu/acpi_table.c */ u32 write_acpi_tables(u32 start) { u32 current; struct acpi_rsdp *rsdp; struct acpi_rsdt *rsdt; struct acpi_xsdt *xsdt; struct acpi_facs *facs; struct acpi_table_header *dsdt; struct acpi_fadt *fadt; struct acpi_mcfg *mcfg; struct acpi_madt *madt; current = start; /* Align ACPI tables to 16 byte */ current = ALIGN(current, 16); debug("ACPI: Writing ACPI tables at %x\n", start); /* We need at least an RSDP and an RSDT Table */ rsdp = (struct acpi_rsdp *)current; current += sizeof(struct acpi_rsdp); current = ALIGN(current, 16); rsdt = (struct acpi_rsdt *)current; current += sizeof(struct acpi_rsdt); current = ALIGN(current, 16); xsdt = (struct acpi_xsdt *)current; current += sizeof(struct acpi_xsdt); /* * Per ACPI spec, the FACS table address must be aligned to a 64 byte * boundary (Windows checks this, but Linux does not). */ current = ALIGN(current, 64); /* clear all table memory */ memset((void *)start, 0, current - start); acpi_write_rsdp(rsdp, rsdt, xsdt); acpi_write_rsdt(rsdt); acpi_write_xsdt(xsdt); debug("ACPI: * FACS\n"); facs = (struct acpi_facs *)current; current += sizeof(struct acpi_facs); current = ALIGN(current, 16); acpi_create_facs(facs); debug("ACPI: * DSDT\n"); dsdt = (struct acpi_table_header *)current; memcpy(dsdt, &AmlCode, sizeof(struct acpi_table_header)); current += sizeof(struct acpi_table_header); memcpy((char *)current, (char *)&AmlCode + sizeof(struct acpi_table_header), dsdt->length - sizeof(struct acpi_table_header)); current += dsdt->length - sizeof(struct acpi_table_header); current = ALIGN(current, 16); debug("ACPI: * FADT\n"); fadt = (struct acpi_fadt *)current; current += sizeof(struct acpi_fadt); current = ALIGN(current, 16); acpi_create_fadt(fadt, facs, dsdt); acpi_add_table(rsdp, fadt); debug("ACPI: * MADT\n"); madt = (struct acpi_madt *)current; acpi_create_madt(madt); current += madt->header.length; acpi_add_table(rsdp, madt); current = ALIGN(current, 16); debug("ACPI: * MCFG\n"); mcfg = (struct acpi_mcfg *)current; acpi_create_mcfg(mcfg); current += mcfg->header.length; acpi_add_table(rsdp, mcfg); current = ALIGN(current, 16); debug("current = %x\n", current); debug("ACPI: done\n"); /* * Other than waiting for OSPM to request us to switch to ACPI mode, * do it by ourselves, since SMI will not be triggered. */ enter_acpi_mode(fadt->pm1a_cnt_blk); return current; }
/* * QEMU's version of write_acpi_tables is defined in drivers/misc/qfw.c */ ulong write_acpi_tables(ulong start) { u32 current; struct acpi_rsdp *rsdp; struct acpi_rsdt *rsdt; struct acpi_xsdt *xsdt; struct acpi_facs *facs; struct acpi_table_header *dsdt; struct acpi_fadt *fadt; struct acpi_mcfg *mcfg; struct acpi_madt *madt; int i; current = start; /* Align ACPI tables to 16 byte */ current = ALIGN(current, 16); debug("ACPI: Writing ACPI tables at %lx\n", start); /* We need at least an RSDP and an RSDT Table */ rsdp = (struct acpi_rsdp *)current; current += sizeof(struct acpi_rsdp); current = ALIGN(current, 16); rsdt = (struct acpi_rsdt *)current; current += sizeof(struct acpi_rsdt); current = ALIGN(current, 16); xsdt = (struct acpi_xsdt *)current; current += sizeof(struct acpi_xsdt); /* * Per ACPI spec, the FACS table address must be aligned to a 64 byte * boundary (Windows checks this, but Linux does not). */ current = ALIGN(current, 64); /* clear all table memory */ memset((void *)start, 0, current - start); acpi_write_rsdp(rsdp, rsdt, xsdt); acpi_write_rsdt(rsdt); acpi_write_xsdt(xsdt); debug("ACPI: * FACS\n"); facs = (struct acpi_facs *)current; current += sizeof(struct acpi_facs); current = ALIGN(current, 16); acpi_create_facs(facs); debug("ACPI: * DSDT\n"); dsdt = (struct acpi_table_header *)current; memcpy(dsdt, &AmlCode, sizeof(struct acpi_table_header)); current += sizeof(struct acpi_table_header); memcpy((char *)current, (char *)&AmlCode + sizeof(struct acpi_table_header), dsdt->length - sizeof(struct acpi_table_header)); current += dsdt->length - sizeof(struct acpi_table_header); current = ALIGN(current, 16); /* Pack GNVS into the ACPI table area */ for (i = 0; i < dsdt->length; i++) { u32 *gnvs = (u32 *)((u32)dsdt + i); if (*gnvs == ACPI_GNVS_ADDR) { debug("Fix up global NVS in DSDT to 0x%08x\n", current); *gnvs = current; break; } } /* Update DSDT checksum since we patched the GNVS address */ dsdt->checksum = 0; dsdt->checksum = table_compute_checksum((void *)dsdt, dsdt->length); /* Fill in platform-specific global NVS variables */ acpi_create_gnvs((struct acpi_global_nvs *)current); current += sizeof(struct acpi_global_nvs); current = ALIGN(current, 16); debug("ACPI: * FADT\n"); fadt = (struct acpi_fadt *)current; current += sizeof(struct acpi_fadt); current = ALIGN(current, 16); acpi_create_fadt(fadt, facs, dsdt); acpi_add_table(rsdp, fadt); debug("ACPI: * MADT\n"); madt = (struct acpi_madt *)current; acpi_create_madt(madt); current += madt->header.length; acpi_add_table(rsdp, madt); current = ALIGN(current, 16); debug("ACPI: * MCFG\n"); mcfg = (struct acpi_mcfg *)current; acpi_create_mcfg(mcfg); current += mcfg->header.length; acpi_add_table(rsdp, mcfg); current = ALIGN(current, 16); debug("current = %x\n", current); acpi_rsdp_addr = (unsigned long)rsdp; debug("ACPI: done\n"); /* Don't touch ACPI hardware on HW reduced platforms */ if (fadt->flags & ACPI_FADT_HW_REDUCED_ACPI) return current; /* * Other than waiting for OSPM to request us to switch to ACPI mode, * do it by ourselves, since SMI will not be triggered. */ enter_acpi_mode(fadt->pm1a_cnt_blk); return current; }