diff options
Diffstat (limited to 'tools/firmware/acpi/acpi_build.c')
-rw-r--r-- | tools/firmware/acpi/acpi_build.c | 232 |
1 files changed, 232 insertions, 0 deletions
diff --git a/tools/firmware/acpi/acpi_build.c b/tools/firmware/acpi/acpi_build.c new file mode 100644 index 0000000000..f947d2707d --- /dev/null +++ b/tools/firmware/acpi/acpi_build.c @@ -0,0 +1,232 @@ +/* + * Copyright (c) 2004, Intel Corporation. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License along with + * this program; if not, write to the Free Software Foundation, Inc., 59 Temple + * Place - Suite 330, Boston, MA 02111-1307 USA. + * + */ + +#include "acpi2_0.h" +#include "acpi_madt.h" + +extern ACPI_2_0_RSDP Rsdp; +extern ACPI_2_0_RSDT Rsdt; +extern ACPI_2_0_XSDT Xsdt; +extern ACPI_2_0_FADT Fadt; +extern ACPI_MULTIPLE_APIC_DESCRIPTION_TABLE Madt; +extern ACPI_2_0_FACS Facs; +extern unsigned char *AmlCode; +extern int DsdtLen; + + +typedef struct _ACPI_TABLE_ALL{ + ACPI_2_0_RSDP *Rsdp; + ACPI_2_0_RSDT *Rsdt; + ACPI_2_0_XSDT *Xsdt; + ACPI_2_0_FADT *Fadt; + ACPI_MULTIPLE_APIC_DESCRIPTION_TABLE *Madt; + ACPI_2_0_FACS *Facs; + unsigned char* Dsdt; + u32 RsdpOffset; + u32 RsdtOffset; + u32 XsdtOffset; + u32 FadtOffset; + u32 MadtOffset; + u32 FacsOffset; + u32 DsdtOffset; +}ACPI_TABLE_ALL; + +static +void +MemCopy(void* src, void* dst, int len){ + + u8* src0=src; + u8* dst0=dst; + + while(len--){ + *(dst0++)=*(src0++); + } +} + +static +void +SetCheckSum( + void* Table, + u32 ChecksumOffset, + u32 Length +) +/* + * Routine Description: + * Calculate Checksum and store the result in the checksum + * filed of the table + * + * INPUT: + * Table: Start pointer of table + * ChecksumOffset: Offset of checksum field in the table + * Length: Length of Table + */ +{ + u8 Sum = 0; + u8 *Ptr; + + Ptr=Table; + Ptr[ChecksumOffset]=0; + while (Length--) { + Sum = (u8)(Sum + (*Ptr++)); + } + + Ptr = Table; + Ptr[ChecksumOffset] = (u8) (0xff - Sum + 1); +} + +// +// FIELD_OFFSET - returns the byte offset to a field within a structure +// +#define FIELD_OFFSET(TYPE,Field) ((u32)(&(((TYPE *) 0)->Field))) + +static +void +UpdateTable( + ACPI_TABLE_ALL *table +) +/* + * Update the ACPI table: + * fill in the actuall physical address of RSDT, XSDT, FADT, MADT, FACS + * Caculate the checksum + */ +{ + // RSDP Update + table->Rsdp->RsdtAddress = (u32)(ACPI_PHYSICAL_ADDRESS+ + table->RsdtOffset); + table->Rsdp->XsdtAddress = (u64)(ACPI_PHYSICAL_ADDRESS+ + table->XsdtOffset); + SetCheckSum(table->Rsdp, + FIELD_OFFSET(ACPI_1_0_RSDP, Checksum), + sizeof(ACPI_1_0_RSDP) + ); + SetCheckSum(table->Rsdp, + FIELD_OFFSET(ACPI_2_0_RSDP, + ExtendedChecksum), + sizeof(ACPI_2_0_RSDP) + ); + + + //RSDT Update + table->Rsdt->Entry[0] = (u32)(ACPI_PHYSICAL_ADDRESS + + table->FadtOffset); + table->Rsdt->Entry[1] = (u32)(ACPI_PHYSICAL_ADDRESS + + table->MadtOffset); + table->Rsdt->Header.Length = sizeof (ACPI_TABLE_HEADER) + + 2*sizeof(u32); + SetCheckSum(table->Rsdt, + FIELD_OFFSET(ACPI_TABLE_HEADER, Checksum), + table->Rsdt->Header.Length + ); + + //XSDT Update + table->Xsdt->Entry[0] = (u64)(ACPI_PHYSICAL_ADDRESS + + table->FadtOffset); + table->Xsdt->Entry[1] = (u64)(ACPI_PHYSICAL_ADDRESS + + table->MadtOffset); + table->Xsdt->Header.Length = sizeof (ACPI_TABLE_HEADER) + + 2*sizeof(u64); + SetCheckSum(table->Xsdt, + FIELD_OFFSET(ACPI_TABLE_HEADER, Checksum), + table->Xsdt->Header.Length + ); + + // FADT Update + table->Fadt->Dsdt = (u32)(ACPI_PHYSICAL_ADDRESS + + table->DsdtOffset); + table->Fadt->XDsdt = (u64)(ACPI_PHYSICAL_ADDRESS + + table->DsdtOffset); + table->Fadt->FirmwareCtrl = (u32)(ACPI_PHYSICAL_ADDRESS + + table->FacsOffset); + table->Fadt->XFirmwareCtrl = (u64)(ACPI_PHYSICAL_ADDRESS + + table->FacsOffset); + SetCheckSum(table->Fadt, + FIELD_OFFSET(ACPI_TABLE_HEADER, Checksum), + sizeof(ACPI_2_0_FADT) + ); + + // MADT update + SetCheckSum(table->Madt, + FIELD_OFFSET(ACPI_TABLE_HEADER, Checksum), + sizeof(ACPI_MULTIPLE_APIC_DESCRIPTION_TABLE) + ); +} + +void +AcpiBuildTable(u8* buf) +/* + * Copy all the ACPI table to buffer + * Buffer Layout: + * FACS + * RSDP + * RSDT + * XSDT + * FADT + * MADT + * DSDT + * + */ +{ + ACPI_TABLE_ALL table; + int offset=0; + + // FACS: should be 64-bit alignment + // so it is put at the start of buffer + // as the buffer is 64 bit alignment + table.FacsOffset = offset; + table.Facs = (ACPI_2_0_FACS*)(&buf[offset]); + MemCopy(&Facs, table.Facs, sizeof(ACPI_2_0_FACS)); + offset += sizeof(ACPI_2_0_FACS); + + // RSDP + table.RsdpOffset = offset; + table.Rsdp = (ACPI_2_0_RSDP*)(&buf[offset]); + MemCopy(&Rsdp, table.Rsdp, sizeof(ACPI_2_0_RSDP)); + offset+=sizeof(ACPI_2_0_RSDP); + + // RSDT + table.RsdtOffset = offset; + table.Rsdt = (ACPI_2_0_RSDT*)(&buf[offset]); + MemCopy(&Rsdt, table.Rsdt, sizeof(ACPI_2_0_RSDT)); + offset+=sizeof(ACPI_2_0_RSDT); + + // XSDT + table.XsdtOffset = offset; + table.Xsdt = (ACPI_2_0_XSDT*)(&buf[offset]); + MemCopy(&Xsdt, table.Xsdt, sizeof(ACPI_2_0_XSDT)); + offset+=sizeof(ACPI_2_0_XSDT); + + // FADT + table.FadtOffset = offset; + table.Fadt = (ACPI_2_0_FADT*)(&buf[offset]); + MemCopy(&Fadt, table.Fadt, sizeof(ACPI_2_0_FADT)); + offset+=sizeof(ACPI_2_0_FADT); + + // MADT + table.MadtOffset = offset; + table.Madt = (ACPI_MULTIPLE_APIC_DESCRIPTION_TABLE*)(&buf[offset]); + MemCopy(&Madt, table.Madt, sizeof(ACPI_MULTIPLE_APIC_DESCRIPTION_TABLE)); + offset+=sizeof(ACPI_MULTIPLE_APIC_DESCRIPTION_TABLE); + + // DSDT + table.DsdtOffset = offset; + table.Dsdt = (unsigned char*)(&buf[offset]); + MemCopy(&AmlCode, table.Dsdt, DsdtLen); + offset+=DsdtLen; + + UpdateTable(&table); +} |