Index: trunk/i386/libsaio/cpu.c =================================================================== --- trunk/i386/libsaio/cpu.c (revision 2030) +++ trunk/i386/libsaio/cpu.c (revision 2031) @@ -238,6 +238,12 @@ do_cpuid(0x00000003, p->CPU.CPUID[CPUID_3]); do_cpuid2(0x00000004, 0, p->CPU.CPUID[CPUID_4]); do_cpuid(0x80000000, p->CPU.CPUID[CPUID_80]); + if (p->CPU.CPUID[CPUID_0][0] >= 0x5) { + do_cpuid(5, p->CPU.CPUID[CPUID_5]); + } + if (p->CPU.CPUID[CPUID_0][0] >= 6) { + do_cpuid(6, p->CPU.CPUID[CPUID_6]); + } if ((p->CPU.CPUID[CPUID_80][0] & 0x0000000f) >= 8) { do_cpuid(0x80000008, p->CPU.CPUID[CPUID_88]); do_cpuid(0x80000001, p->CPU.CPUID[CPUID_81]); Index: trunk/i386/libsaio/platform.h =================================================================== --- trunk/i386/libsaio/platform.h (revision 2030) +++ trunk/i386/libsaio/platform.h (revision 2031) @@ -23,11 +23,12 @@ #define CPUID_2 2 #define CPUID_3 3 #define CPUID_4 4 -#define CPUID_6 5 -#define CPUID_80 6 -#define CPUID_81 7 -#define CPUID_88 8 -#define CPUID_MAX 9 +#define CPUID_5 5 +#define CPUID_6 6 +#define CPUID_80 7 +#define CPUID_81 8 +#define CPUID_88 9 +#define CPUID_MAX 10 #define CPU_MODEL_DOTHAN 0x0D // Dothan #define CPU_MODEL_YONAH 0x0E // Sossaman, Yonah Index: trunk/i386/modules/Cconfig =================================================================== --- trunk/i386/modules/Cconfig (revision 2030) +++ trunk/i386/modules/Cconfig (revision 2031) @@ -9,4 +9,5 @@ source "i386/modules/HelloWorld/Cconfig" source "i386/modules/Sata/Cconfig" source "i386/modules/Keylayout/Cconfig" +source "i386/modules/ACPIcodec/Cconfig" endmenu Index: trunk/i386/modules/Sata/include/acpidecode.c =================================================================== --- trunk/i386/modules/Sata/include/acpidecode.c (revision 0) +++ trunk/i386/modules/Sata/include/acpidecode.c (revision 2031) @@ -0,0 +1,918 @@ +/* + Copyright (c) 2010, Intel Corporation + All rights reserved. + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + * Neither the name of Intel Corporation nor the names of its contributors + may be used to endorse or promote products derived from this software + without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND + ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR + ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "acpi.h" +#include "acpidecode.h" + +#define DEBUG_ACPI_DECODE 0 + +#if DEBUG_ACPI_DECODE==1 +#include "libsaio.h" +#define DBG(x...) printf(x) +#else +#define DBG(x...) +#endif + +static U8 *parse_acpi_dataobject(const struct acpi_namespace *ns, U8 * current, U8 * end); +static U8 *parse_acpi_package(const struct acpi_namespace *ns, U8 * current, U8 * end); +static U8 *parse_acpi_termarg(const struct acpi_namespace *ns, U8 * current, U8 * end); +static U8 *parse_acpi_termarglist(const struct acpi_namespace *ns, U8 * current, U8 * end); +static U8 *parse_acpi_objectlist(const struct acpi_namespace *ns, U8 * current, U8 * end); +U8* UIDPointer = (U8*)0; + +void *decodeTableHeader(void *current, ACPI_TABLE_HEADER ** tableHeader) +{ + *tableHeader = current; + current = *tableHeader + 1; + return current; +} +void dprint_nameseg(U32 i) +{ + DBG("%c%c%c%c", + (int)(i & 0x000000ff), + (int)((i & 0x0000ff00) >> 8), + (int)((i & 0x00ff0000) >> 16), + (int)(i >> 24)); +} + +#if DEBUG_ACPI_DECODE +static void dprint_namespace(const struct acpi_namespace *ns) +{ + U32 i; + DBG( "\\"); + for (i = 0; i < ns->depth; i++) { + if (i != 0) + DBG( "."); + dprint_nameseg(ns->nameseg[i]); + } +} +#endif + +static void parsePackageLength(U8 * current, U32 * length, U32 * lengthEncoding) +{ + U32 i; + U8 len0 = *current; + U8 numBytes = len0 >> 6; + U32 total = 0; + + for (i = numBytes; i > 0; i--) { + total <<= 8; + total |= current[i]; + } + + total <<= 4; + total |= len0 & 0x3f; + *length = total; + *lengthEncoding = numBytes + 1; + DBG("Package length=0x%02x\n", *length); +} + +#if UNUSED +static bool ns_match(struct acpi_namespace *ns1, struct acpi_namespace *ns2) +{ + U32 i; + if (ns1->depth != ns2->depth) + return false; + + for (i = 0; i < ns1->depth; i++) + if (ns1->nameseg[i] != ns2->nameseg[i]) + return false; + + return true; +} + +U32 acpi_ns_found; +#endif + +static U8 *parse_acpi_namestring(const struct acpi_namespace *ns_context, struct acpi_namespace *ns, U8 * current, U8 * end) +{ + U8 *temp = current; + struct acpi_namespace dummy_ns; + + (void)end; + + if (!ns) + ns = &dummy_ns; + *ns = *ns_context; + + if (*current == AML_ROOT_PREFIX) { + ns->depth = 0; + current++; + } else + while (*current == AML_PARENT_PREFIX) { + if (ns->depth == 0) { + DBG( "Attempt to use parent prefix with no namespace left\n"); + return temp; + } + current++; + ns->depth--; + } + + switch (*current) { + case AML_DUAL_NAME_PREFIX: + if (ns->depth + 2 > ACPI_NAMESPACE_MAX_DEPTH) { + DBG( "Namespace got too deep\n"); + return temp; + } + current++; + ns->nameseg[ns->depth++] = *(U32 *) current; + current += 4; + ns->nameseg[ns->depth++] = *(U32 *) current; + current += 4; + break; + case AML_MULTI_NAME_PREFIX: + { + U8 nameseg_count; + current++; + nameseg_count = *current++; + if (ns->depth + nameseg_count > ACPI_NAMESPACE_MAX_DEPTH) { + DBG( "Namespace got too deep\n"); + return temp; + } + while (nameseg_count--) { + ns->nameseg[ns->depth++] = *(U32 *) current; + current += 4; + } + break; + } + case AML_NULL_NAME: + current++; + break; + default: + if (*current != '_' && (*current < 'A' || *current > 'Z')) { + DBG( "Invalid nameseg lead character: 0x%02x\n", *current); + return temp; + } + if (ns->depth + 1 > ACPI_NAMESPACE_MAX_DEPTH) { + DBG( "Namespace got too deep\n"); + return temp; + } + ns->nameseg[ns->depth++] = *(U32 *) current; + current += 4; + break; + } +#if DEBUG_ACPI_DECODE + DBG( "Found NameString: "); + dprint_namespace(ns); + DBG("\n"); +#endif + if (ns->nameseg[1] == NAMESEG("PCI0") && ns->nameseg[2] == NAMESEG("_UID")) { + UIDPointer = current; + } + +#if UNUSED + if (!acpi_ns_found) { + U32 index; + + for (index = 0; index < acpi_processor_count; index++) + if (ns_match(ns, &acpi_processors[index].ns)) { + acpi_ns_found = 1; + break; + } + } +#endif + return current; +} + +static U8 *parse_acpi_buffer(const struct acpi_namespace *ns, U8 * current, U8 * end) +{ + U32 pkglen = 0, lengthEncoding = 0; + (void)ns; + (void)end; + if (*current != AML_BUFFER_OP) + return current; + current++; + parsePackageLength(current, &pkglen, &lengthEncoding); + current += pkglen; + return current; +} + +static U8 *parse_acpi_computationaldata(const struct acpi_namespace *ns, U8 * current, U8 * end) +{ + U8 *temp = current; + + current = parse_acpi_buffer(ns, current, end); + if (current != temp) + return current; + + switch (*current) { + case AML_BYTE_OP: + DBG("Found ByteOp\n"); + current += 1 + 1; + break; + case AML_WORD_OP: + DBG( "Found WordOp\n"); + current += 1 + 2; + break; + case AML_DWORD_OP: + DBG("Found DwordOp\n"); + current += 1 + 4; + break; + case AML_QWORD_OP: + DBG( "Found QwordOp\n"); + current += 1 + 8; + break; + case AML_STRING_OP: + DBG( "Found StringOp: \""); + current++; + while (*current) +#if DEBUG_ACPI_DECODE + if (*current < ' ' || *current > 0x7e) + printf( "\\x%02x", *current++); + else + printf( "%c", *current++); +#else + current++; +#endif + current++; /* Skip the \0 */ + DBG( "\"\n"); + break; + case AML_ZERO_OP: + DBG( "Found ZeroOp\n"); + current += 1; + break; + case AML_ONE_OP: + DBG( "Found OneOp\n"); + current += 1; + break; + case AML_ONES_OP: + DBG( "Found OneOp\n"); + current += 1; + break; + case AML_EXT_OP_PREFIX: + if (*(current + 1) == AML_REVISION_OP) + current += 2; + default: + break; + } + + return current; +} + +static U8 *parse_acpi_argobj(const struct acpi_namespace *ns, U8 * current, U8 * end) +{ + (void)ns; + (void)end; + switch (*current) { + case AML_ARG0_OP: + DBG( "Found Arg0Op\n"); + current++; + break; + case AML_ARG1_OP: + DBG( "Found Arg1Op\n"); + current++; + break; + case AML_ARG2_OP: + DBG( "Found Arg2Op\n"); + current++; + break; + case AML_ARG3_OP: + DBG( "Found Arg3Op\n"); + current++; + break; + case AML_ARG4_OP: + DBG( "Found Arg4Op\n"); + current++; + break; + case AML_ARG5_OP: + DBG( "Found Arg5Op\n"); + current++; + break; + case AML_ARG6_OP: + DBG( "Found Arg6Op\n"); + current++; + break; + default: + break; + } + return current; +} + +static U8 *parse_acpi_localobj(const struct acpi_namespace *ns, U8 * current, U8 * end) +{ + (void)ns; + (void)end; + switch (*current) { + case AML_LOCAL0_OP: + DBG( "Found Local0Op\n"); + current++; + break; + case AML_LOCAL1_OP: + DBG( "Found Local1Op\n"); + current++; + break; + case AML_LOCAL2_OP: + DBG( "Found Local2Op\n"); + current++; + break; + case AML_LOCAL3_OP: + DBG("Found Local3Op\n"); + current++; + break; + case AML_LOCAL4_OP: + DBG( "Found Local4Op\n"); + current++; + break; + case AML_LOCAL5_OP: + DBG( "Found Local5Op\n"); + current++; + break; + case AML_LOCAL6_OP: + DBG( "Found Local6Op\n"); + current++; + break; + case AML_LOCAL7_OP: + DBG( "Found Local7Op\n"); + current++; + break; + default: + break; + } + return current; +} + +static U8 *parse_acpi_debugobj(const struct acpi_namespace *ns, U8 * current, U8 * end) +{ + (void)ns; + (void)end; + if ((*current == AML_EXT_OP_PREFIX) && (*(current + 1) == AML_DEBUG_OP)) { + current += 2; + DBG( "Found DebugOp\n"); + } + + return current; +} + +static U8 *parse_acpi_datarefobject(const struct acpi_namespace *ns, U8 * current, U8 * end) +{ + U8 *temp = current; + + DBG( "Beginning datarefobject: 0x%02x at memory location %p\n", *current, current); + current = parse_acpi_dataobject(ns, current, end); + if (current != temp) + return current; + + return current; +} + +static U8 *parse_acpi_simplename(const struct acpi_namespace *ns, U8 * current, U8 * end) +{ + U8 *temp = current; + + current = parse_acpi_namestring(ns, NULL, current, end); + if (current != temp) + return current; + + current = parse_acpi_argobj(ns, current, end); + if (current != temp) + return current; + + current = parse_acpi_localobj(ns, current, end); + if (current != temp) + return current; + + return current; +} + +static U8 *parse_acpi_supername(const struct acpi_namespace *ns, U8 * current, U8 * end) +{ + U8 *temp = current; + + current = parse_acpi_simplename(ns, current, end); + if (current != temp) + return current; + + current = parse_acpi_debugobj(ns, current, end); + if (current != temp) + return current; + + return current; +} + +static U8 *parse_acpi_target(const struct acpi_namespace *ns, U8 * current, U8 * end) +{ + U8 *temp = current; + + current = parse_acpi_supername(ns, current, end); + if (current != temp) + return current; + + if (*current == AML_NULL_NAME) + current++; + + return current; +} + +static U8 *parse_acpi_method(const struct acpi_namespace *ns, U8 * current, U8 * end) +{ + U8 *new_end = current; + U8 *temp; + U32 pkglen = 0; + U32 lengthEncoding = 0; + struct acpi_namespace new_ns; + + (void)end; + + parsePackageLength(current, &pkglen, &lengthEncoding); + current += lengthEncoding; + new_end += pkglen; + + temp = current; + current = parse_acpi_namestring(ns, &new_ns, current, new_end); + if (current == temp) + return new_end; + +#if DEBUG_ACPI_DECODE + DBG( "Found Method: "); + dprint_namespace(&new_ns); + DBG( "\n"); +#endif + // U8 methodFlags + current++; + + parse_acpi_termlist(&new_ns, current, new_end); + +#if DEBUG_ACPI_DECODE + DBG( "End of Method: "); + dprint_namespace(&new_ns); + DBG( "\n"); +#endif + + return new_end; +} + +U32 acpi_processor_count; +struct acpi_processor acpi_processors[CPU_MAP_LIMIT]; + +static void add_processor(const struct acpi_namespace *ns, U8 id, U32 pmbase) +{ + if (acpi_processor_count == CPU_MAP_LIMIT) { + DBG( "No more room for ACPI processor structures\n"); + return; + } + acpi_processors[acpi_processor_count].ns = *ns; + acpi_processors[acpi_processor_count].id = id; + acpi_processors[acpi_processor_count].pmbase = pmbase; + acpi_processor_count++; +} + +static U8 *parse_acpi_processor(const struct acpi_namespace *ns, U8 * current, U8 * end) +{ + U8 *new_end = current; + U8 *temp; + U32 pkglen = 0; + U32 lengthEncoding = 0; + struct acpi_namespace new_ns; + U8 id; + U32 pmbase; + + (void)end; + + parsePackageLength(current, &pkglen, &lengthEncoding); + current += lengthEncoding; + new_end += pkglen; + + temp = current; + current = parse_acpi_namestring(ns, &new_ns, current, new_end); + if (current == temp) + return new_end; + + id = *current++; + pmbase = *(U32 *) current; + current += 4; + (void)current; // Silent a warning reported by the clang static analizer . + +#if DEBUG_ACPI_DECODE + DBG( "Found CPU object: "); + dprint_namespace(&new_ns); + DBG( " id = 0x%x pmbase = 0x%x\n", id, pmbase); +#endif + add_processor(&new_ns, id, pmbase); + + return new_end; +} + +static U8 *parse_acpi_namedobj(const struct acpi_namespace *ns, U8 * current, U8 * end) +{ + DBG( "Beginning namedobj: 0x%02x at memory location %p\n", *current, current); + switch (*current) { + case AML_EXT_OP_PREFIX: + { + if (*(current + 1) == AML_MUTEX_OP) { + struct acpi_namespace new_ns; + + current += 2; + current = parse_acpi_namestring(ns, &new_ns, current, end); +#if DEBUG_ACPI_DECODE + DBG( "Mutex: "); + dprint_namespace(&new_ns); + DBG( "\n"); +#endif + current++; /* SyncFlags */ + } else if (*(current + 1) == AML_OPREGION_OP) { + struct acpi_namespace new_ns; + + current += 2; + DBG( "OpRegion at memory location %p\n", current); + current = parse_acpi_namestring(ns, &new_ns, current, end); +#if DEBUG_ACPI_DECODE + DBG( "OpRegion name: "); + dprint_namespace(&new_ns); + DBG( "\n"); +#endif + current++; + current = parse_acpi_termarg(ns, current, end); + current = parse_acpi_termarg(ns, current, end); +#if DEBUG_ACPI_DECODE + DBG( "End OpRegion: "); + dprint_namespace(&new_ns); + DBG( "\n"); +#endif + } else if (*(current + 1) == AML_FIELD_OP) { + U32 pkglen = 0; + U32 lengthEncoding = 0; + + current += 2; + DBG( "FieldOp at memory location %p\n", current); + parsePackageLength(current, &pkglen, &lengthEncoding); + current += pkglen; + } else if (*(current + 1) == AML_DEVICE_OP) { + U8 *new_end; + U32 pkglen = 0; + U32 lengthEncoding = 0; + struct acpi_namespace new_ns; + + current += 2; + new_end = current; + DBG( "DeviceOp at memory location %p\n", current); + parsePackageLength(current, &pkglen, &lengthEncoding); + current += lengthEncoding; + new_end += pkglen; + current = parse_acpi_namestring(ns, &new_ns, current, new_end); +#if DEBUG_ACPI_DECODE + DBG( "DeviceOp name: "); + dprint_namespace(&new_ns); + DBG( "\n"); +#endif + + parse_acpi_objectlist(&new_ns, current, new_end); + current = new_end; + } else if (*(current + 1) == AML_PROCESSOR_OP) { + current += 2; + current = parse_acpi_processor(ns, current, end); + } else if (*(current + 1) == AML_INDEXFIELD_OP) { + U8 *new_end; + U32 pkglen = 0; + U32 lengthEncoding = 0; + struct acpi_namespace new_ns; + + current += 2; + new_end = current; + DBG( "IndexFieldOp at memory location %p\n", current); + parsePackageLength(current, &pkglen, &lengthEncoding); + current += lengthEncoding; + new_end += pkglen; + current = parse_acpi_namestring(ns, &new_ns, current, new_end); +#if DEBUG_ACPI_DECODE + DBG( "IndexFieldOp name: "); + dprint_namespace(&new_ns); + DBG( "\n"); +#endif + parse_acpi_objectlist(&new_ns, current, new_end); + current = new_end; + } + break; + } + case AML_METHOD_OP: + { + current++; + current = parse_acpi_method(ns, current, end); + break; + } + default: + break; + } + return current; +} + +static U8 *parse_acpi_type1opcode(const struct acpi_namespace *ns, U8 * current, U8 * end) +{ + DBG( "Beginning type1opcode: 0x%02x at memory location %p\n", *current, current); + switch (*current) { + case AML_IF_OP: + { + U8 *new_end; + U32 pkgLen = 0; + U32 lengthEncoding = 0; + + DBG( "Found IfOp\n"); + current++; + parsePackageLength(current, &pkgLen, &lengthEncoding); + new_end = current + pkgLen; + current += lengthEncoding; + + current = parse_acpi_termarg(ns, current, new_end); + parse_acpi_termlist(ns, current, new_end); + current = new_end; + break; + } + case AML_ELSE_OP: + { + U8 *new_end; + U32 pkgLen = 0; + U32 lengthEncoding = 0; + + DBG( "Found ElseOp\n"); + current++; + parsePackageLength(current, &pkgLen, &lengthEncoding); + new_end = current + pkgLen; + current += lengthEncoding; + + parse_acpi_termlist(ns, current, new_end); + current = new_end; + break; + } + case AML_RETURN_OP: + { + DBG( "Found ReturnOp\n"); + current++; + current = parse_acpi_termarg(ns, current, end); + break; + } + default: + break; + } + return current; +} + +static U8 *parse_acpi_type2opcode(const struct acpi_namespace *ns, U8 * current, U8 * end) +{ + U8 *temp = current; + + DBG( "Beginning type2opcode: 0x%02x at memory location %p\n", *current, current); + + current = parse_acpi_package(ns, current, end); + if (current != temp) + return current; + + switch (*current) { + case AML_LNOT_OP: + current++; + DBG( "Found logical not operator\n"); + current = parse_acpi_termarg(ns, current, end); + break; + + case AML_LAND_OP: + case AML_LOR_OP: + case AML_LEQUAL_OP: + case AML_LGREATER_OP: + case AML_LLESS_OP: + DBG( "Found logical binary operator: %c\n", "&|!=><"[*current - AML_LAND_OP]); + current++; + current = parse_acpi_termarg(ns, current, end); + current = parse_acpi_termarg(ns, current, end); + break; + + case AML_EXT_OP_PREFIX: + { + if (*(current + 1) == AML_COND_REF_OF_OP) { + DBG( "Found CondRefOf\n"); + current += 2; + current = parse_acpi_supername(ns, current, end); + current = parse_acpi_target(ns, current, end); + } + break; + } + case AML_STORE_OP: + { + DBG( "Found StoreOp\n"); + current++; + current = parse_acpi_termarg(ns, current, end); + current = parse_acpi_supername(ns, current, end); + break; + } + default: + { + current = parse_acpi_namestring(ns, NULL, current, end); + if (current == temp) + break; + current = parse_acpi_termarglist(ns, current, end); + } + } + return current; +} + +static U8 *parse_acpi_package(const struct acpi_namespace *ns, U8 * current, U8 * end) +{ + (void)ns; + (void)end; + if (*current == AML_PACKAGE_OP) { + U32 pkglen = 0; + U32 lengthEncoding = 0; + + DBG( "Found PackageOp\n"); + current++; + parsePackageLength(current, &pkglen, &lengthEncoding); + current += pkglen; + } + return current; +} + +static U8 *parse_acpi_dataobject(const struct acpi_namespace *ns, U8 * current, U8 * end) +{ + U8 *temp = current; + + current = parse_acpi_computationaldata(ns, current, end); + if (current != temp) + return current; + + current = parse_acpi_package(ns, current, end); + if (current != temp) + return current; + + return current; +} + +static U8 *parse_acpi_termarg(const struct acpi_namespace *ns, U8 * current, U8 * end) +{ + U8 *temp = current; + + DBG( "Beginning termarg: 0x%02x at memory location %p\n", *current, current); + + current = parse_acpi_type2opcode(ns, current, end); + if (current != temp) + return current; + + current = parse_acpi_dataobject(ns, current, end); + if (current != temp) + return current; + + current = parse_acpi_argobj(ns, current, end); + if (current != temp) + return current; + + current = parse_acpi_localobj(ns, current, end); + if (current != temp) + return current; + + return current; +} + +static U8 *parse_acpi_namespacemodifierobj(const struct acpi_namespace *ns, U8 * current, U8 * end) +{ + DBG( "Beginning namespacemodifierobj: 0x%02x at memory location %p\n", *current, current); + switch (*current) { + case AML_SCOPE_OP: + { + U8 *new_end; + struct acpi_namespace new_ns; + U32 scopeLen = 0; + U32 lengthEncoding = 0; + + current++; + parsePackageLength(current, &scopeLen, &lengthEncoding); + new_end = current + scopeLen; + + current = parse_acpi_namestring(ns, &new_ns, current + lengthEncoding, new_end); +#if DEBUG_ACPI_DECODE + DBG( "Found Scope: "); + dprint_namespace(&new_ns); + DBG( "\n"); +#endif + parse_acpi_termlist(&new_ns, current, new_end); +#if DEBUG_ACPI_DECODE + DBG( "End Scope: "); + dprint_namespace(&new_ns); + DBG( "\n"); +#endif + current = new_end; + break; + } + case AML_NAME_OP: + current++; + current = parse_acpi_namestring(ns, NULL, current, end); + current = parse_acpi_datarefobject(ns, current, end); + break; + case AML_ALIAS_OP: + current++; + current = parse_acpi_namestring(ns, NULL, current, end); + current = parse_acpi_namestring(ns, NULL, current, end); + break; + default: + break; + } + return current; +} + +static U8 *parse_acpi_objectlist(const struct acpi_namespace *ns, U8 * current, U8 * end) +{ + DBG( "Beginning objectlist: 0x%02x at memory location %p end=%p\n", *current, current, end); + while (current < end) { + U8 *temp = current; + + DBG( "New iteration of objectlist: 0x%02x at memory location %p end=%p\n", *current, current, end); + + current = parse_acpi_namespacemodifierobj(ns, current, end); + if (current != temp) + continue; + + current = parse_acpi_namedobj(ns, current, end); + if (current != temp) + continue; + + if (current == temp) { + DBG( "Unhandled object in object list: 0x%02x at memory location %p\n", *current, current); +#if DEBUG_ACPI_DECODE + DBG( "namespace: "); + dprint_namespace(ns); + DBG( "\n"); +#endif + break; + } + } + DBG( "Ending objectlist: 0x%02x at memory location %p\n", *current, current); + return current; +} + +static U8 *parse_acpi_termarglist(const struct acpi_namespace *ns, U8 * current, U8 * end) +{ + DBG( "Beginning termarglist: 0x%02x at memory location %p\n", *current, current); + while (current < end) { + U8 *temp = current; + + current = parse_acpi_termarg(ns, current, end); + if (current == temp) { + DBG( "Unhandled item in term arg list: 0x%02x at memory location %p\n", *current, current); +#if DEBUG_ACPI_DECODE + DBG( "namespace: "); + dprint_namespace(ns); + DBG( "\n"); +#endif + break; + } + } + return current; +} + +void parse_acpi_termlist(const struct acpi_namespace *ns, U8 * current, U8 * end) +{ + while (current < end) { + U8 *temp = current; + + DBG( "Beginning new term in term list: 0x%02x at memory location %p\n", *current, current); + + current = parse_acpi_namespacemodifierobj(ns, current, end); + if (current != temp) + continue; + + current = parse_acpi_namedobj(ns, current, end); + if (current != temp) + continue; + + current = parse_acpi_type1opcode(ns, current, end); + if (current != temp) + continue; + + current = parse_acpi_type2opcode(ns, current, end); + if (current != temp) + continue; + + switch (*current) { + default: + { + DBG( "Unhandled item in term list: 0x%02x at memory location %p\n", *current, current); +#if DEBUG_ACPI_DECODE + DBG( "namespace: "); + dprint_namespace(ns); + DBG( "\n"); +#endif + return; + } + } + } +} Property changes on: trunk/i386/modules/Sata/include/acpidecode.c ___________________________________________________________________ Added: svn:executable + * Index: trunk/i386/modules/Sata/include/include/acpi_codec.h =================================================================== --- trunk/i386/modules/Sata/include/include/acpi_codec.h (revision 0) +++ trunk/i386/modules/Sata/include/include/acpi_codec.h (revision 2031) @@ -0,0 +1,77 @@ +/* + * Copyright 2008 mackerintel + */ + +/* + * Copyright (c) 2011 cparm . All rights reserved. + * + */ + +#ifndef __LIBSAIO_ACPI_CODEC_H +#define __LIBSAIO_ACPI_CODEC_H + +#include "libsaio.h" +#include "efi.h" + +#define OEMOPT_TEMPLATE "oemXXXX" +#define OEMOPT_SIZE sizeof(OEMOPT_TEMPLATE) + +#define kOEMDSDT "oemDSDT" /* acpi_codec.c */ +#define kOEMFADT "oemFADT" /* acpi_codec.c */ +#define kOEMAPIC "oemAPIC" /* acpi_codec.c */ + +#define KIntelFADT "IntelFADTSpec" /* acpi_codec.c */ + +#define kSTRIPAPIC "StripAPICTable" /* acpi_codec.c */ + +#define kRestartFix "RestartFix" /* acpi_codec.c */ +#define KResetType "ResetType" /* acpi_codec.c */ +#define PCI_RESET_TYPE 0 // (default) +#define KEYBOARD_RESET_TYPE 1 + +#define kGeneratePStates "GeneratePStates" /* acpi_codec.c */ +#define kGenerateCStates "GenerateCStates" /* acpi_codec.c */ +#define kGenerateTStates "GenerateTStates" /* acpi_codec.c */ + +#define kMaxRatio "MaxBusRatio" /* acpi_codec.c */ +#define kMinRatio "MinBusRatio" /* acpi_codec.c */ +#define kSpeedstep "EnableSpeedStep" /* acpi_codec.c */ +#define kEnableC2State "EnableC2State" /* acpi_codec.c */ +#define kEnableC3State "EnableC3State" /* acpi_codec.c */ +#define kEnableC4State "EnableC4State" /* acpi_codec.c */ +#define kEnableC6State "EnableC6State" /* acpi_codec.c */ +#define kEnableC7State "EnableC7State" /* acpi_codec.c */ +#define KEnableMwait "EnableMwait" /* acpi_codec.c */ +#define KForceSSDT "ForceGenSSDT" /* acpi_codec.c */ +#define KAcpiCoordType "PstateCoordination" /* acpi_codec.c */ +#define kCoreTurbo "EnableTurbo" /* acpi_codec.c */ + +#define kUpdateACPI "UpdateACPI" /* acpi_codec.c */ +//#define kUnsafeACPI "UnsafeACPI" /* acpi_codec.c */ // DEPRECATED, replaced by nacpi=0x2000 + +#define kOnlySignedAml "LoadSignedAmlOnly" /* acpi_codec.c */ + +#if UNUSED +#define kGenerateFACS "GenerateFACS" /* acpi_codec.c */ +#define kOEMFACS "oemFACS" /* acpi_codec.c */ +#endif + +extern int AcpiSetup(void); + +struct p_state +{ + union + { + uint16_t Control; + struct + { + uint8_t VID; // Voltage ID + uint8_t FID; // Frequency ID + }; + }; + + uint8_t CID; // Compare ID + uint32_t Frequency; +}; + +#endif /* !__LIBSAIO_ACPI_CODEC_H */ Property changes on: trunk/i386/modules/Sata/include/include/acpi_codec.h ___________________________________________________________________ Added: svn:executable + * Index: trunk/i386/modules/Sata/include/include/datatype.h =================================================================== --- trunk/i386/modules/Sata/include/include/datatype.h (revision 0) +++ trunk/i386/modules/Sata/include/include/datatype.h (revision 2031) @@ -0,0 +1,54 @@ +/* +Copyright (c) 2010, Intel Corporation +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + * Neither the name of Intel Corporation nor the names of its contributors + may be used to endorse or promote products derived from this software + without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR +ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON +ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + +#ifndef DATATYPE_H +#define DATATYPE_H + +#include "libsa.h" + +typedef uint8_t U8; +typedef uint16_t U16; +typedef uint32_t U32; +typedef uint64_t U64; + +#if 0 +typedef uint32_t bool; +#ifndef false +#define true 1 +#endif + +#ifndef false +#define false 0 +#endif + +#ifndef NULL +#define NULL ((void *) 0) +#endif +#endif + +#endif /* DATATYPE_H */ Property changes on: trunk/i386/modules/Sata/include/include/datatype.h ___________________________________________________________________ Added: svn:executable + * Index: trunk/i386/modules/Sata/include/include/acpi.h =================================================================== --- trunk/i386/modules/Sata/include/include/acpi.h (revision 0) +++ trunk/i386/modules/Sata/include/include/acpi.h (revision 2031) @@ -0,0 +1,25 @@ +#ifndef __LIBSAIO_ACPI_H +#define __LIBSAIO_ACPI_H + +#include "acpi_tools.h" + +#define ACPI_RANGE_START (0x0E0000) +#define ACPI_RANGE_END (0x0FFFFF) + + +#define Unspecified 0 +#define Desktop 1 +#define Mobile 2 +#define Workstation 3 +#define EnterpriseServer 4 +#define SOHOServer 5 +#define AppliancePC 6 +#define PerformanceServer 7 + +#define MaxSupportedPMProfile PerformanceServer // currently max profile supported +#define PMProfileError MaxSupportedPMProfile + 1 + +#define kAcpiMethod "Acpi2Method" // 2 (= method 2) for some machines that may hang on acpi 2 (aka acpi 64 bit) detection (replace the old kUnsafeACPI "UnsafeACPI") + + +#endif /* !__LIBSAIO_ACPI_H */ Index: trunk/i386/modules/Sata/include/include/acpi_tools.h =================================================================== --- trunk/i386/modules/Sata/include/include/acpi_tools.h (revision 0) +++ trunk/i386/modules/Sata/include/include/acpi_tools.h (revision 2031) @@ -0,0 +1,41 @@ +/* +Copyright (c) 2010, Intel Corporation +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + * Neither the name of Intel Corporation nor the names of its contributors + may be used to endorse or promote products derived from this software + without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR +ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON +ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + +#ifndef acpi_tools_h +#define acpi_tools_h + +#include "datatype.h" +#include "intel_acpi.h" +#include "ppm.h" + +U32 get_num_tables(ACPI_TABLE_RSDT * rsdt); +U32 get_num_tables64(ACPI_TABLE_XSDT * xsdt); +U32 FindAcpiTables(ACPI_TABLES * acpi_tables); +U8 GetChecksum(void *mem_addr, U32 mem_size); + +#endif // acpi_tools_h Property changes on: trunk/i386/modules/Sata/include/include/acpi_tools.h ___________________________________________________________________ Added: svn:executable + * Index: trunk/i386/modules/Sata/include/include/ppm.h =================================================================== --- trunk/i386/modules/Sata/include/include/ppm.h (revision 0) +++ trunk/i386/modules/Sata/include/include/ppm.h (revision 2031) @@ -0,0 +1,289 @@ +/* +Copyright (c) 2010, Intel Corporation +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + * Neither the name of Intel Corporation nor the names of its contributors + may be used to endorse or promote products derived from this software + without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR +ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON +ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + +#ifndef ppm_h +#define ppm_h + +#include "datatype.h" + +#define PROFILE_ALL +//#define PROFILE_NEHALEM_EP_DP +//#define PROFILE_WESTMERE_EP_UP_DP +//#define PROFILE_NEHALEM_EX_MP +//#define PROFILE_WESTMERE_EX_MP +//#define PROFILE_SANDYBRIDGE_UP + +#if defined(PROFILE_ALL) || defined(PROFILE_WESTMERE_EX_MP) + +#define MAX_CPU_SOCKETS 8 // max count of cpu packages (any range of APIC IDs is ok) +#define MAX_LOGICAL_CPU 256 // max count of cpu found in MADT +#define MAX_CORES 32 // Based on full range of Core APID ID values (max of 5 bits for core APIC ID mask) + +#elif defined(PROFILE_NEHALEM_EX_MP) + +#define MAX_CPU_SOCKETS 8 // max count of cpu packages (any range of APIC IDs is ok) +#define MAX_LOGICAL_CPU 128 // max count of cpu found in MADT +#define MAX_CORES 16 // Based on full range of Core APID ID values (max of 4 bits for core APIC ID mask) + +#elif defined(PROFILE_WESTMERE_EP_UP_DP) + +#define MAX_CPU_SOCKETS 2 // max count of cpu packages (any range of APIC IDs is ok) +#define MAX_LOGICAL_CPU 64 // max count of cpu found in MADT +#define MAX_CORES 16 // Based on full range of Core APID ID values (max of 4 bits for core APIC ID mask) + +#elif defined(PROFILE_NEHALEM_EP_UP_DP) + +#define MAX_CPU_SOCKETS 2 // max count of cpu packages (any range of APIC IDs is ok) +#define MAX_LOGICAL_CPU 32 // max count of cpu found in MADT +#define MAX_CORES 8 // Based on full range of Core APID ID values (max of 3 bits for core APIC ID mask) + +#elif defined(PROFILE_SANDY_BRIDGE_UP) + +#define MAX_CPU_SOCKETS 1 // max count of cpu packages (any range of APIC IDs is ok) +#define MAX_LOGICAL_CPU 8 // max count of cpu found in MADT +#define MAX_CORES 4 + +#endif + +#define MAX_PSTATES 16 +#define MAX_CSTATES 4 +#define MAX_TSTATES 15 + +//Define ACPI_CSD to force building ACPI _CSD +//#define BUILD_ACPI_CSD + +#ifndef DWORD_REGS_TYPEDEF +#define DWORD_REGS_TYPEDEF +typedef struct dword_regs { + U32 _eax; + U32 _ebx; + U32 _ecx; + U32 _edx; +} DWORD_REGS; +#endif + +typedef struct acpi_tables { + // Define the Storage Locations for all the ACPI Table Pointers. + ACPI_TABLE_DSDT *DsdtPointer; // Differentiated System Description Table (RSDP->RSDT->FACP->DSDT) + ACPI_TABLE_DSDT *DsdtPointer64; // Differentiated System Description Table (RSDP->XSDT->FACP->XDSDT) + ACPI_TABLE_FADT *FacpPointer; // Fixed ACPI Description Table (RSDP->RSDT->FACP) + ACPI_TABLE_FACS *FacsPointer; // Firmware ACPI Control Structure (RSDP->RSDT->FACP->FACS) + ACPI_TABLE_FACS *FacsPointer64; // Firmware ACPI Control Structure (RSDP->XSDT->FACP->XFACS) + ACPI_TABLE_RSDP *RsdPointer; // Root System Description Pointer Structure (RSDP) + ACPI_TABLE_RSDT *RsdtPointer; // Root System Description Table (RSDP->RSDT) + ACPI_TABLE_MADT *MadtPointer; // Multiple APIC Description Table (RSDP->RSDT->APIC) + ACPI_TABLE_MADT *MadtPointer64; // Multiple APIC Description Table (RSDP->XSDT->APIC) + ACPI_TABLE_XSDT *XsdtPointer; // Extended Root System Description Table (RSDP->XSDT) + ACPI_TABLE_FADT *FacpPointer64; // Fixed ACPI Description Table (RSDP->XSDT->FACP) +} ACPI_TABLES; + +typedef struct pstate { + U32 frequency; + U32 power; + U32 ratio; + U32 translatency; + U32 bmlatency; + U32 control; + U32 status; +} PSTATE; + +typedef struct pkg_pstates { + U32 num_pstates; + PSTATE pstate[MAX_PSTATES]; +} PKG_PSTATES; + +typedef struct tstate { + U32 freqpercent; + U32 power; + U32 latency; + U32 control; + U32 status; +} TSTATE; + +typedef struct pkg_tstates { + U32 num_tstates; + TSTATE tstate[MAX_TSTATES]; +} PKG_TSTATES; + +typedef enum cstate_encoding { + IO_REDIRECTION = 0, + NATIVE_MWAIT = 1, +} CSTATE_ENCODING; + +typedef enum cpu_cstate { + CPU_C1 = 1, + //CPU_C2 = 2, + CPU_C3_ACPI_C2 = 3, + CPU_C3_ACPI_C3 = 4, + CPU_C4 = 5, + CPU_C6 = 6, + CPU_C7 = 7, +} CPU_CSTATE; + +typedef struct cstate { + U8 type; + U16 latency; + U32 power; +} CSTATE; + +typedef struct pkg_cstates { + U32 num_cstates; + CSTATE cstate[MAX_CSTATES]; + ACPI_GENERIC_ADDRESS gas[MAX_CSTATES]; +} PKG_CSTATES; + +typedef struct cpu_details { + U32 present; + U32 x2apic_id; + U32 socket_id; + U32 intra_package_mask_width; + U32 intra_package_mask; + U32 smt_mask_width; + U32 smt_select_mask; + U32 core_select_mask; + DWORD_REGS cpuid1; + DWORD_REGS cpuid5; + DWORD_REGS cpuid6; + DWORD_REGS cpuidB_0; + DWORD_REGS cpuidB_1; + U32 eist_cpuid_feature_flag; + U32 turbo_cpuid_feature_flag; + U32 turbo_misc_enables_feature_flag; + U32 invariant_apic_timer_flag; + U32 tdc_limit; + U32 tdp_limit; + U32 turbo_available; + U32 max_ratio_as_mfg; + U32 max_ratio_as_cfg; + U32 min_ratio; + U32 tdc_tdp_limits_for_turbo_flag; + U32 ratio_limits_for_turbo_flag; + U32 xe_available; + U32 logical_processor_count_from_madt; + U32 core_logical_processor_count_from_madt[MAX_CORES]; + + PKG_PSTATES pkg_pstates; + + PKG_CSTATES pkg_mwait_cstates; + PKG_CSTATES pkg_io_cstates; + + PKG_TSTATES pkg_tstates; + + U32 package_cstate_limit; + U32 core_c1_supported; + U32 core_c2_supported; + U32 core_c3_supported; + U32 core_c4_supported; + U32 core_c6_supported; + U32 core_c7_supported; + U32 mwait_supported; + U32 acpi_support_cpuid_feature_flag; + U32 energy_perf_bias_supported; + + U64 package_power_limit; + U64 package_power_sku_unit; +} CPU_DETAILS; + +typedef struct socket_info { + U32 signature; + U32 socket_count; + CPU_DETAILS cpu[MAX_CPU_SOCKETS]; +} SOCKET_INFO; + +typedef struct lapic_info { + U32 processorId; + U32 apicId; + U32 pkg_index; + U32 core_apic_id; + U32 core_index; + PROCESSOR_NUMBER_TO_NAMESEG *namepath; + U32 madt_type; + U32 uid; +} LAPIC_INFO; + +typedef struct proc_info { + U32 processorId; + U32 apicId; +} PROC_INFO; + +typedef struct madt_info { + U32 lapic_count; + LAPIC_INFO lapic[MAX_LOGICAL_CPU]; +} MADT_INFO; + +typedef struct rsdt_info { + U32 proc_count; + PROC_INFO processor[MAX_LOGICAL_CPU]; +} RSDT_INFO; + +typedef struct smp_exit_state { + U32 signature; + + // Number of Failure or Informative codes included in the buffer + U32 error_code_count; + + // Buffer of Failure or Informative codes + U32 error_codes[10]; +} SMP_EXIT_STATE; + +typedef enum smp_exit_code { + // Generic successful + SMP_EXIT_CODE_OK = 1, + + // Generic failure + EXIT_CODE_FAILED = 2, + + // First logical processor for this socket unable to find available structure + EXIT_CODE_FAILED_SOCKET_PROXY_SAVE = 3, +} SMP_EXIT_CODE; + +typedef struct ppm_host { + U32 signature; + + U32 pstates_enabled; + U32 pstate_coordination; + U32 turbo_enabled; + U32 cstates_enabled; + U32 tstates_enabled; + U32 performance_per_watt; + + ACPI_TABLES acpi_tables; + + + RSDT_INFO rsdt_info; + MADT_INFO madt_info; + SOCKET_INFO skt_info; + + PPM_SETUP_OPTIONS *options; + + SMP_EXIT_STATE smp_exit_state; + + U32 detected_cpu_family; +} PPM_HOST; + +#endif // ppm_h Property changes on: trunk/i386/modules/Sata/include/include/ppm.h ___________________________________________________________________ Added: svn:executable + * Index: trunk/i386/modules/Sata/include/include/ppmsetup.h =================================================================== --- trunk/i386/modules/Sata/include/include/ppmsetup.h (revision 0) +++ trunk/i386/modules/Sata/include/include/ppmsetup.h (revision 2031) @@ -0,0 +1,371 @@ +/* +Copyright (c) 2010, Intel Corporation +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + * Neither the name of Intel Corporation nor the names of its contributors + may be used to endorse or promote products derived from this software + without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR +ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON +ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + +#ifndef ppmsetup_h +#define ppmsetup_h + +#include "datatype.h" + +#define CURRENT_PPM_RCM_INTERFACE_SPECIFICATION 11 + +#ifndef nameseg_defined +#define nameseg_defined +#define NAMESEG(s) (((U32)(s[0]) << 0) \ + |((U32)(s[1]) << 8) \ + |((U32)(s[2]) << 16) \ + |((U32)(s[3]) << 24)) +#endif + +typedef enum ssdt_loc_flag { + // Flag indicating the SSDT ACPI structure should be built in a stack-based + // buffer. If the SSDT is successfully created, then the following occurs: + // (1) the RSDT ACPI structure is moved lower in memory and updated to + // include a pointer to the new SSDT. + // (2) the SSDT APCI structure is copied into memory just above the moved + // RSDT structure + // (3) the RSD ACPI structure is updated to included the new location of + // the just moved RSDT ACPI structure + // Note: The XSDT is not updated! + // + // NOTE: THIS OPTION WILL DEPRECATED AND REMOVED + // IN A FUTURE VERSION OF THIS SPECIFICATION. + SSDT_LOC_FLAG_ACPI_RECLAIM = 0, + + // Flag indicating the SSDT should be built directly in the memory region + // provided by the ssdt_mem_addr option parameter. + // If the SSDT is successfully created, then the following occurs: + // (1) the RSDT ACPI structure is moved lower in memory and updated to + // include a pointer to the new SSDT. + // (2) the RSD ACPI structure is updated to include the new location of the + // RSDT ACPI structure. + // Note: The XSDT is not updated! + // + // NOTE: THIS OPTION WILL DEPRECATED AND REMOVED + // IN A FUTURE VERSION OF THIS SPECIFICATION. + SSDT_LOC_FLAG_ADDR_PROVIDED = 1, + + // Flag indicating the SSDT should be built directly in the memory region + // provided by the ssdt_mem_addr option parameter. + // After SSDT is successfully created, no further processing occurs. + SSDT_LOC_FLAG_ADDR_PROVIDED_NO_INSERT = 2, + + // Flag indicating the SSDT should be built directly in the memory region + // provided by the ssdt_mem_addr option parameter. + // After SSDT is successfully created, then the following occurs: + // (1) the RSDT ACPI structure is not moved but is updated to + // include a 32-bit pointer to the new SSDT. + // (2) If the XSDT exists, it is not moved but is updated to + // include a 64-bit pointer to the new SSDT. + SSDT_LOC_FLAG_ADDR_PROVIDED_INSERT = 3, +} SSDT_LOC_FLAG; + +typedef enum exit_code { + // PPM RCM completed all initialization successfully + EXIT_CODE_PPM_COMPLETED = 1, + + // Failed building P-state table + EXIT_CODE_FAILED_BUILD_PSTATES = 2, + + EXIT_CODE_PPM_EIST_DISABLED = 3, + + // Failed to find ACPI tables + EXIT_CODE_FAILED_FIND_ACPI_TABLES = 4, + + // Failed to process the ACPI MADT structure + EXIT_CODE_FAILED_PROCESS_MADT = 5, + + // Failed to resolve ACPI MADT structure against available logical + // processors + EXIT_CODE_FAILED_PROCESS_MADT_INFO = 6, + + // Failed to build ACPI SSDT structure + EXIT_CODE_FAILED_PROCESS_SSDT = 7, + + // Failed to build and intialize HOST structure + EXIT_CODE_FAILED_HOST_INIT = 8, + + // Failed during wake of all NBSP to gather processor information + EXIT_CODE_FAILED_COLLECT_SOCKET_INFO = 9, + + // Failed to resolve target configuration between desired options and + // processor features + EXIT_CODE_FAILED_DETERMINE_CONFIGURATION = 0x0a, + + // No SSDT ACPI struture was created + EXIT_CODE_NO_SSDT_CREATED = 0x0b, + + // Failed to build Cstates correctly + EXIT_CODE_FAILED_BUILD_CSTATES = 0x0c, + + // Failed to build Tstates correctly + EXIT_CODE_FAILED_BUILD_TSTATES = 0x0d, + + // Failed to find package index of logical processor listed in MADT ACPI table + EXIT_CODE_FAILED_FIND_PKG_INDEX_FROM_LAPIC = 0x0e, + + // Failed with invalid input provided for SSDT location flag + EXIT_CODE_FAILED_INVALID_SSDT_LOCATION_FLAG = 0x0f, + + // Failed with no logical processors found in MADT + EXIT_CODE_FAILED_NO_LAPIC_FOUND_IN_MADT = 0x10, + + // Failed with SSDT size exceeded during SSDT creation + EXIT_CODE_FAILED_SSDT_SIZE_EXCEEDED = 0x11, + + // Failed to build ACPI SSDT structure + EXIT_CODE_FAILED_BUILD_SSDT = 0x12, + + // Failed with core index of logical processor listed in MADT ACPI table exceeding max + EXIT_CODE_MAX_CORES_EXCEEDED = 0x13, + + // Failed to find CPU Scope from array of ACPI processor number to ACPI CPU NameSeg structures + EXIT_CODE_FAILED_FIND_CPU_SCOPE_NAME_SEG = 0x14, + + // Failed to update FADT + EXIT_CODE_FAILED_UPDATE_FADT = 0x15, + + // GPF detected + EXIT_CODE_GPF_DETECTED = 0x16, + + // Failed with invalid SSDT buffer address + EXIT_CODE_INVALID_SSDT_ADDR = 0x17, + + // Failed with invalid SSDT buffer length + EXIT_CODE_INVALID_SSDT_LEN = 0x18, +} EXIT_CODE; + +typedef struct exit_state { + // 1 = success, 0 = failure + U32 return_status; + + // Number of Failure or Informative codes included in the buffer + U32 error_code_count; + + // Buffer of Failure or Informative codes + U32 error_codes[10]; + + // This 32-bit physical memory address specifies the final location for the + // SSDT ACPI structure built by the PPM RC. + U32 ssdt_mem_addr; + + // This value specifies the final size of the SSDT ACPI structure for the + // SSDT ACPI structure built by the PPM RC. + U32 ssdt_mem_size; + + // The final state for the P-state initialization + // 1=enabled; 0=disabled + U32 pstates_enabled; + + // The final state for the Turbo feature initialization + // 1=enabled; 0=disabled + U32 turbo_enabled; + + // The final state for the C-state initialization + // 1=enabled; 0=disabled + U32 cstates_enabled; + + // The final state for the T-state initialization + // 1=enabled; 0=disabled + U32 tstates_enabled; +} EXIT_STATE; + +typedef enum cpu_namespace_flag { + // Flag indicating the SSDT ACPI structure should be built + // using ACPI 1.0 compliant processor namespace "_PR" + CPU_NAMESPACE_PR = 0, + + // Flag indicating the SSDT ACPI structure should be built + // using ACPI 2.0+ compliant processor namespace "_SB" + CPU_NAMESPACE_SB = 1, +} CPU_NAMESPACE_FLAG; + +// Define the total number of required NameSegs to reach the DSDT processor +// device or object declarations +#define MAX_SUPPORTED_CPU_NAMESEGS 3 + +typedef struct processor_number_to_nameseg { + // Contains one of the ACPI processor ID values used in a + // ACPI Declare Processor statement in the DSDT or XSDT + U32 acpi_processor_number; + + // Number of NameSpace segments in NamePath to processor devices/objects + U32 seg_count; + + // Contains the corresponding ACPI Name Scope in the form + // of a series of NameSegs constituting the NamePath to a + // processor device or object declaration + U32 nameseg[MAX_SUPPORTED_CPU_NAMESEGS]; +} PROCESSOR_NUMBER_TO_NAMESEG; + +typedef struct ppm_setup_options { + // This 32-bit physical memory address specifies a read-write memory region + // below 1MB. Minimum size is 8KB. This memory is used by the callback as + // the SIPI target and stack for each AP. This region is not required to be + // cacheable. + U32 mem_region_below_1M; + + // Number of CPU sockets which exist on the platform + U32 num_sockets; + + // Desired state for the P-state initialization + // 1=enabled; 0=disabled + U32 pstates_enabled; + + // Desired state for the P-state hardware coordination + // ACPI_PSD_COORD_TYPE_SW_ALL = 0xFC + // ACPI_PSD_COORD_TYPE_SW_ANY = 0xFD + // ACPI_PSD_COORD_TYPE_HW_ALL = 0xFE + U32 pstate_coordination; + + // Desired state for the Turbo state initialization + // 1=enabled; 0=disabled + U32 turbo_enabled; + + // Desired state for the C-state initialization + // 1=enabled; 0=disabled + U32 cstates_enabled; + + // Desired state for the C1E initialization + // 1=enabled; 0=disabled + U32 c1e_enabled; + + // Desired state for the processor core C3 state included in the _CST + // 0= processor core C3 cannot be used as an ACPI C state + // 2= processor core C3 can be used as an ACPI C2 state + // 3= processor core C3 can be used as an ACPI C3 state + // 4= processor core C3 can be used as an ACPI C2 state + // if Invariant APIC Timer detected, else not used as ACPI C state + // 5= processor core C3 can be used as an ACPI C2 state + // if Invariant APIC Timer detected, else APIC C3 state + U32 c3_enabled; + + // Desired state for the processor core C6 state included in the _CST as an + // ACPI C3 state. + // 1= processor core C6 can be used as an ACPI C3 state + // 0= processor core C6 cannot be used as an ACPI C3 state + U32 c6_enabled; + + // Desired state for the processor core C7 state included in the _CST as an + // ACPI C3 state. + // 1= processor core C7 can be used as an ACPI C7 state + // 0= processor core C7 cannot be used as an ACPI C7 state + U32 c7_enabled; + + // Desired state for providing alternate ACPI _CST structure using MWAIT + // extensions + // 1= Alternate _CST using MWAIT extension is enabled for OSPM use + // 0= Alternate _CST using MWAIT extension is disabled for OSPM use + U32 mwait_enabled; + + // Power management base address used for processors + U32 pmbase; + + // Desired state for the C-state package limit. + // Note: The C-state package limit may be further limited by the + // capabilities of the processor + // 000b = C0 (No package C-state support) + // 001b = C1 (Behavior is the same as 000b) + // 010b = C3 + // 011b = C6 + // 100b = C7 + // 111b = No package C-state limit + U32 package_cstate_limit; + + // Desired state for the T-state initialization + // 1=enabled; 0=disabled + U32 tstates_enabled; + + // This 32-bit physical memory address specifies a read-write memory region + // for the SSDT ACPI structure built by the PPM RC. Minimum size is 16KB. + U32 ssdt_mem_addr; + + // This value specifies the size of the SSDT memory region. Minimum size is + // 16KB. + U32 ssdt_mem_size; + + // This value specifies the PPM RCM behavior related to creation and + // incorporation of the new SSDT ACPI structure. See definition of the + // SSDT_LOC_FLAG for acceptable values. + U32 ssdt_loc_flag; + + // This value specifies the PPM RCM behavior related to creation and + // incorporation of the new SSDT ACPI structure. If all power management + // features are disabled by input options, the SSDT can still be created + // for debug review. + // 1 = Create SSDT even if all power management features are disabled + // 0 = Do not create SSDT if all power management features are disabled + U32 ssdt_force_creation; + + // Exit structure intended to convey state to the caller and/or subsequent + // init code + EXIT_STATE exit_state; + + // Flag indicating the processor namespace that should be used in the + // SSDT ACPI structure for each CPU. + // See definition of the CPU_NAMESPACE_FLAG for acceptable values. + U32 cpu_namespace_flag; + + // This version number identifies the PPM RCM specification. + // Specifically denotes the version of this structure definition is compliant + // with with file nehalem-ppm-rcm-vX.txt where X is the version number. + // PPMSETUP.C should always use the version definition from the top of + // this file called CURRENT_PPM_RCM_INTERFACE_SPECIFICATION. + U32 ppm_rcm_interface_specification; + + // This flag indicates whether or not after all AP Wakes are completed, + // that the AP should be forced to jump to the real mode address specified + // in the realmode_callback_address field below. + // realmode_callback = 0 means leave AP in INIT or Wait For SIPI (WFS) state + // realmode_callback = 1 means AP should jump to real mode address specified below + U32 realmode_callback_flag; + + // This file contains the real mode callback address which AP must jump to after + // INIT_SIPI_SIPI sequences used to force AP initalization for PPM. + // Upper 16-bits specify target real mode segment for a far 16-bit jump instruction + // Lower 16-bits specify target real mode offset for a far 16-bit jump instruction + U32 realmode_callback_address; + + // Number of ACPI processor number to ACPI CPU NameSeg structures + U32 cpu_map_count; + + // Array of ACPI processor number to ACPI CPU NameSeg structures + PROCESSOR_NUMBER_TO_NAMESEG *cpu_map; + + // This flag indicates whether or not PPM RC should update an existing ACPI FADT. + // modify_fadt_flag = 0 means do not modify existing ACPI FADT structure + // modify_fadt_flag = 1 means do check and if needed, modify existing ACPI FADT structure + U32 modify_fadt_flag; + + // Desired state for the performance_per_watt optimizations + // performance_per_watt = 2 means "Low Power" + // performance_per_watt = 1 means "Power Optimized or Power Balanced" + // performance_per_watt = 0 means "Traditional or Max Performance" + U32 performance_per_watt; +} PPM_SETUP_OPTIONS; + +#endif // ppmsetup_h Property changes on: trunk/i386/modules/Sata/include/include/ppmsetup.h ___________________________________________________________________ Added: svn:executable + * Index: trunk/i386/modules/Sata/include/include/acpidecode.h =================================================================== --- trunk/i386/modules/Sata/include/include/acpidecode.h (revision 0) +++ trunk/i386/modules/Sata/include/include/acpidecode.h (revision 2031) @@ -0,0 +1,69 @@ +/* +Copyright (c) 2010, Intel Corporation +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + * Neither the name of Intel Corporation nor the names of its contributors + may be used to endorse or promote products derived from this software + without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR +ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON +ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + +#ifndef ACPI_DECODE_H +#define ACPI_DECODE_H + +#include "acpi_tools.h" + +/* acpidecode.h contains functions needed only for decoding ACPI to produce the + * inputs to the PPM code, but not needed for encoding ACPI as done inside the + * PPM code. */ + +#define ACPI_NAMESPACE_MAX_DEPTH 10 + +struct acpi_namespace { + U32 nameseg[ACPI_NAMESPACE_MAX_DEPTH]; + U32 depth; +}; + +void dprint_nameseg(U32 i); +void *decodeTableHeader(void *current, ACPI_TABLE_HEADER ** tableHeader); +void parse_acpi_termlist(const struct acpi_namespace *ns, U8 * current, U8 * end); + +/* Globals used for retrieving ACPI processor structures from the DSDT */ + +#define CPU_MAP_LIMIT 256 /* Any bigger than 256 and we'd have to support the x2APIC structures, which we don't yet anyway. */ + +struct acpi_processor { + struct acpi_namespace ns; + U8 id; + U32 pmbase; +}; + +extern U32 acpi_processor_count; +extern struct acpi_processor acpi_processors[CPU_MAP_LIMIT]; + +#if UNUSED +/* If 0, look for a processor namespace and set to 1 if found. */ +extern U32 acpi_ns_found; +#endif + +extern U8* UIDPointer; + +#endif /* ACPI_DECODE_H */ Property changes on: trunk/i386/modules/Sata/include/include/acpidecode.h ___________________________________________________________________ Added: svn:executable + * Index: trunk/i386/modules/Sata/include/include/acpicode.h =================================================================== --- trunk/i386/modules/Sata/include/include/acpicode.h (revision 0) +++ trunk/i386/modules/Sata/include/include/acpicode.h (revision 2031) @@ -0,0 +1,75 @@ +/* +Copyright (c) 2010, Intel Corporation +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + * Neither the name of Intel Corporation nor the names of its contributors + may be used to endorse or promote products derived from this software + without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR +ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON +ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + +#ifndef acpi_code_h +#define acpi_code_h + +#include "datatype.h" +#include "acpi.h" +#include "ppm.h" + +void setRsdpchecksum(ACPI_TABLE_RSDP *rsdp); +void setRsdpXchecksum(ACPI_TABLE_RSDP *rsdp); +U32 update_rsdp_with_xsdt(ACPI_TABLE_RSDP *rsdp, ACPI_TABLE_XSDT *xsdt); +U32 update_rsdp_with_rsdt(ACPI_TABLE_RSDP *rsdp, ACPI_TABLE_RSDT *rsdt); + +void SetChecksum(struct acpi_table_header *header); +U32 ProcessMadtInfo(ACPI_TABLE_MADT * madt, MADT_INFO * madt_info); +void MoveRsdtInsertSsdt(ACPI_TABLE_RSDP * RsdPointer, ACPI_TABLE_RSDT * OldRsdtPointer, ACPI_TABLE_RSDT * NewRsdtPointer, ACPI_TABLE_SSDT * SsdtPointer); +void InsertSsdt(ACPI_TABLE_RSDT * RsdtPointer, ACPI_TABLE_SSDT * SsdtPointer); +void InsertSsdt64(ACPI_TABLE_XSDT * XsdtPointer, ACPI_TABLE_SSDT * SsdtPointer); +U32 ProcessFadt(ACPI_TABLE_FADT * FadtPointer, U32 pmbase); +U32 ProcessDsdt(ACPI_TABLE_DSDT * DsdtPointer, U8 * PCIUIDPointer, U8 uid); + +void setByteConst(ACPI_BYTE_CONST * byteConst, U8 byteData); +void *buildByteConst(void *current, U8 byteData); +void setWordConst(ACPI_WORD_CONST * wordConst, U16 wordData); +void *buildWordConst(void *current, U16 wordData); +void setDwordConst(ACPI_DWORD_CONST * dwordConst, U32 dwordData); +void *buildDwordConst(void *current, U32 dwordData); +void *buildSmallBuffer(void *current); +void *buildEndTag(void *current); +void *buildGenericRegister(void *current, const ACPI_GENERIC_ADDRESS * gas); + +void *buildSmallMethod(void *current, U32 name, U8 methodFlags); +void *buildMethod(void *current, U32 name, U8 methodFlags); +void *buildReturnZero(void *current); +void *buildReturnOpcode(void *current, U8 opcodeToReturn); +void *buildReturnPackage(void *current, U8 numElements); +void *buildNamedDword(void *current, U32 name, U32 dword); +void *buildOpCode(void *current, U8 opCode); + +void *buildNameSeg(void *current, U32 name); +void setSmallPackage(ACPI_SMALL_PACKAGE * package, U8 numElements); +void *buildSmallPackage(void *current, U8 numElements); +void setPackageLength(ACPI_PACKAGE_LENGTH * packageLength, U32 length); +void *buildPackageLength(void *current, U32 Length); +void *buildNamePath(void *current, U32 name); +void *buildTableHeader(void *current, U32 signature, U64 oemTableId); + +#endif // acpi_code_h Index: trunk/i386/modules/Sata/include/include/intel_acpi.h =================================================================== --- trunk/i386/modules/Sata/include/include/intel_acpi.h (revision 0) +++ trunk/i386/modules/Sata/include/include/intel_acpi.h (revision 2031) @@ -0,0 +1,692 @@ +/* Per ACPI 3.0a spec */ + +/* + Copyright (c) 2010, Intel Corporation + All rights reserved. + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + * Neither the name of Intel Corporation nor the names of its contributors + may be used to endorse or promote products derived from this software + without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND + ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR + ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +#ifndef __LIBSAIO_INTEL_ACPI_H +#define __LIBSAIO_INTEL_ACPI_H + +#include "datatype.h" +#include "ppmsetup.h" +// +// All tables and structures must be byte-packed to match the ACPI specification +//#pragma pack(1) + +#define ACPI_SIG_DSDT "DSDT" // Differentiated System Description Table +#define ACPI_SIG_FADT "FACP" // Fixed ACPI Description Table +#define ACPI_SIG_FACS "FACS" // Firmware ACPI Control Structure +#define ACPI_SIG_PSDT "PSDT" // Persistent System Description Table +#define ACPI_SIG_RSDP "RSD PTR " // Root System Description Pointer +#define ACPI_SIG_RSDT "RSDT" // Root System Description Table +#define ACPI_SIG_XSDT "XSDT" // Extended System Description Table +#define ACPI_SIG_SSDT "SSDT" // Secondary System Description Table +#define ACPI_RSDP_NAME "RSDP" // Short name for RSDP, not signature +#define ACPI_SIG_MADT "APIC" // Multiple APIC Description Table +#define ACPI_SIG_SBST "SBST" // Smart Battery Specification Table +#define ACPI_SIG_ECDT "ECDT" // Embedded Controller Boot Resources Table +#define ACPI_SIG_ASF "ASF!" // Alert Standard Format table +#define ACPI_SIG_DMAR "DMAR" // DMA Remapping table +#define ACPI_SIG_HPET "HPET" // High Precision Event Timer table +#define ACPI_SIG_MCFG "MCFG" // PCI Memory Mapped Configuration table +#define ACPI_SIG_UEFI "UEFI" // Uefi Boot Optimization Table + + +#ifndef nameseg_defined +#define nameseg_defined +#define NAMESEG(s) (((U32)(s[0]) << 0) \ +|((U32)(s[1]) << 8) \ +|((U32)(s[2]) << 16) \ +|((U32)(s[3]) << 24)) +#endif + +#define NAMESEG64(s) (((U64)(s[0]) << 0) \ +|((U64)(s[1]) << 8) \ +|((U64)(s[2]) << 16) \ +|((U64)(s[3]) << 24) \ +|((U64)(s[4]) << 32) \ +|((U64)(s[5]) << 40) \ +|((U64)(s[6]) << 48) \ +|((U64)(s[7]) << 56)) \ + + +// Data Objects Encoding values. +#define AML_EXT_OP_PREFIX 0x5B + +// Name Space Modifier Objects Encoding values. +#define AML_NAME_OP 0x08 // Name operator. +#define AML_SCOPE_OP 0x10 // Scope operator. + +// Named Objects Encoding values. +#define AML_MUTEX_OP 0x01 +#define AML_METHOD_OP 0x14 // Method operator. +#define AML_OPREGION_OP 0x80 // Operation Region operator. +#define AML_FIELD_OP 0x81 +#define AML_DEVICE_OP 0x82 +#define AML_PROCESSOR_OP 0x83 // Processor operator. + +// Type2 Opcodes Encoding values. +#define AML_NULL_NAME 0x00 +#define AML_ZERO_OP 0x00 +#define AML_ALIAS_OP 0x06 +#define AML_ONE_OP 0x01 +#define AML_BYTE_OP 0x0a +#define AML_WORD_OP 0x0b +#define AML_DWORD_OP 0x0c +#define AML_STRING_OP 0x0d +#define AML_QWORD_OP 0x0e +#define AML_BUFFER_OP 0x11 +#define AML_PACKAGE_OP 0x12 +#define AML_COND_REF_OF_OP 0x12 // Requires AML_EXT_OP_PREFIX +#define AML_CREATE_FIELD_OP 0x13 // Requires AML_EXT_OP_PREFIX +#define AML_DUAL_NAME_PREFIX 0x2e +#define AML_MULTI_NAME_PREFIX 0x2f +#define AML_REVISION_OP 0x30 // Requires AML_EXT_OP_PREFIX +#define AML_DEBUG_OP 0x31 +#define AML_ROOT_PREFIX 0x5c +#define AML_PARENT_PREFIX 0x5e +#define AML_LOCAL0_OP 0x60 +#define AML_LOCAL1_OP 0x61 +#define AML_LOCAL2_OP 0x62 +#define AML_LOCAL3_OP 0x63 +#define AML_LOCAL4_OP 0x64 +#define AML_LOCAL5_OP 0x65 +#define AML_LOCAL6_OP 0x66 +#define AML_LOCAL7_OP 0x67 +#define AML_ARG0_OP 0x68 +#define AML_ARG1_OP 0x69 +#define AML_ARG2_OP 0x6A +#define AML_ARG3_OP 0x6B +#define AML_ARG4_OP 0x6C +#define AML_ARG5_OP 0x6D +#define AML_ARG6_OP 0x6E +#define AML_STORE_OP 0x70 +#define AML_CONCAT_OP 0x73 +#define AML_SUBTRACT_OP 0x74 +#define AML_MULTIPLY_OP 0x77 +#define AML_AND_OP 0x7B +#define AML_END_TAG_OP 0x79 +#define AML_GEN_REG_FIELD 0x82 +#define AML_PROCESSOR_OP 0x83 +#define AML_INDEXFIELD_OP 0x86 // Requires AML_EXT_OP_PREFIX +#define AML_SIZEOF_OP 0x87 +#define AML_INDEX_OP 0x88 +#define AML_CREATE_DWORD_FIELD_OP 0x8A +#define AML_LAND_OP 0x90 +#define AML_LOR_OP 0x91 +#define AML_LNOT_OP 0x92 +#define AML_LEQUAL_OP 0x93 +#define AML_LGREATER_OP 0x94 +#define AML_LLESS_OP 0x95 +#define AML_IF_OP 0xA0 +#define AML_ELSE_OP 0xA1 +#define AML_RETURN_OP 0xA4 +#define AML_ONES_OP 0xFF + +#define GAS_TYPE_FFH 0x7f +#define GAS_TYPE_SYSTEM_IO 0x01 +#define GAS_VENDOR_INTEL 0x01 +#define GAS_CLASS_CODE_NATIVE 0x02 + +// Define the Generic System Description Table Structure. +// This common header is used by all tables except the RSDP and FACS. +// The define is used for direct inclusion of header into other ACPI tables +typedef struct acpi_table_header { + U8 Signature[4]; // ASCII table signature + U32 Length; // Length of table in bytes, including this header + U8 Revision; // ACPI Specification minor version # + U8 Checksum; // To make checksum of entire table == 0 + U8 OemId[6]; // ASCII OEM identification + U8 OemTableId[8]; // ASCII OEM table identification + U32 OemRevision; // OEM revision number + U8 AslCompilerId[4]; // ASCII ASL compiler vendor ID + U32 AslCompilerRevision; // ASL compiler version +} __attribute__((packed))ACPI_TABLE_HEADER; + +// GAS - Generic Address Structure (ACPI 2.0+) +typedef struct acpi_generic_address { + U8 SpaceId; // Address space where struct or register exists + U8 BitWidth; // Size in bits of given register + U8 BitOffset; // Bit offset within the register + U8 AccessWidth; // Minimum Access size (ACPI 3.0) + U64 Address; // 64-bit address of struct or register +} __attribute__((packed))ACPI_GENERIC_ADDRESS; + +// RSDP - Root System Description Pointer (Signature is "RSD PTR ") +typedef struct acpi_table_rsdp { + U8 Signature[8]; // ACPI signature, contains "RSD PTR " + U8 Checksum; // ACPI 1.0 checksum + U8 OemId[6]; // OEM identification + U8 Revision; // Must be (0) for ACPI 1.0 or (2) for ACPI 2.0+ + U32 RsdtPhysicalAddress; // 32-bit physical address of the RSDT + U32 Length; // Table length in bytes, including header (ACPI 2.0+) + U64 XsdtPhysicalAddress; // 64-bit physical address of the XSDT (ACPI 2.0+) + U8 ExtendedChecksum; // Checksum of entire table (ACPI 2.0+) + U8 Reserved[3]; // Reserved, must be zero +} __attribute__((packed))ACPI_TABLE_RSDP; + +#define ACPI_RSDP_REV0_SIZE 20 // Size of original ACPI 1.0 RSDP + +// RSDT - Root System Description Table +typedef struct acpi_table_rsdt { + ACPI_TABLE_HEADER Header; // Common ACPI table header + U32 TableOffsetEntry[1]; // Array of pointers to ACPI tables +} __attribute__((packed))ACPI_TABLE_RSDT; + + +// XSDT - Root System Description Table +typedef struct acpi_table_xsdt { + ACPI_TABLE_HEADER Header; // Common ACPI table header + U64 TableOffsetEntry[1]; // Array of pointers to ACPI tables +} __attribute__((packed))ACPI_TABLE_XSDT; + +// DSDT - Differentiated System Description Table +typedef struct acpi_table_dsdt { + ACPI_TABLE_HEADER Header; // Common ACPI table header + U32 EntryStart; +} __attribute__((packed))ACPI_TABLE_DSDT; + +// FACS - Firmware ACPI Control Structure (FACS) +typedef struct acpi_table_facs { + U8 Signature[4]; // ASCII table signature + U32 Length; // Length of structure, in bytes + U32 HardwareSignature; // Hardware configuration signature + U32 FirmwareWakingVector; // 32-bit physical address of the Firmware Waking Vector + U32 GlobalLock; // Global Lock for shared hardware resources + U32 Flags; + U64 XFirmwareWakingVector; // 64-bit version of the Firmware Waking Vector (ACPI 2.0+) + U8 Version; // Version of this table (ACPI 2.0+) + U8 Reserved[31]; // Reserved, must be zero +} __attribute__((packed))ACPI_TABLE_FACS; + +// SBST - Smart Battery Specification Table - Version 1 +typedef struct acpi_table_sbst +{ + ACPI_TABLE_HEADER Header; /* Common ACPI table header */ + U32 WarningLevel; + U32 LowLevel; + U32 CriticalLevel; + +} __attribute__((packed))ACPI_TABLE_SBST; + +// ASF - Alert Standard Format table (Signature "ASF!") +typedef struct acpi_table_asf +{ + ACPI_TABLE_HEADER Header; /* Common ACPI table header */ + +} ACPI_TABLE_ASF; + +// DMAR - DMA Remapping table - Version 1 +typedef struct acpi_table_dmar +{ + ACPI_TABLE_HEADER Header; /* Common ACPI table header */ + U8 Width; /* Host Address Width */ + U8 Flags; + U8 Reserved[10]; + +} __attribute__((packed))ACPI_TABLE_DMAR; + +// HPET - High Precision Event Timer table - Version 1 +typedef struct acpi_table_hpet +{ + ACPI_TABLE_HEADER Header; /* Common ACPI table header */ + U32 Id; /* Hardware ID of event timer block */ + ACPI_GENERIC_ADDRESS Address; /* Address of event timer block */ + U8 Sequence; /* HPET sequence number */ + U16 MinimumTick; /* Main counter min tick, periodic mode */ + U8 Flags; + +} __attribute__((packed))ACPI_TABLE_HPET; + +//MCFG - PCI Memory Mapped Configuration table and sub-table - Version 1 +typedef struct acpi_table_mcfg +{ + ACPI_TABLE_HEADER Header; /* Common ACPI table header */ + U8 Reserved[8]; + +} ACPI_TABLE_MCFG; + +//UEFI - UEFI Boot optimization Table - Version 1 +typedef struct acpi_table_uefi +{ + ACPI_TABLE_HEADER Header; /* Common ACPI table header */ + U8 Identifier[16]; /* UUID identifier */ + U16 DataOffset; /* Offset of remaining data in table */ + +} __attribute__((packed))ACPI_TABLE_UEFI; + +// ECDT - Embedded Controller Boot Resources Table - Version 1 +typedef struct acpi_table_ecdt +{ + ACPI_TABLE_HEADER Header; /* Common ACPI table header */ + ACPI_GENERIC_ADDRESS Control; /* Address of EC command/status register */ + ACPI_GENERIC_ADDRESS Data; /* Address of EC data register */ + U32 Uid; /* Unique ID - must be same as the EC _UID method */ + U8 Gpe; /* The GPE for the EC */ + U8 Id[1]; /* Full namepath of the EC in the ACPI namespace */ + +} __attribute__((packed))ACPI_TABLE_ECDT; + +// FADT - Fixed ACPI Description Table (Signature "FACP") +typedef struct acpi_table_fadt { + ACPI_TABLE_HEADER Header; // Common ACPI table header + U32 Facs; // 32-bit physical address of FACS + U32 Dsdt; // 32-bit physical address of DSDT + U8 Model; // System Interrupt Model (ACPI 1.0) - not used in ACPI 2.0+ + U8 PreferredProfile; // Conveys preferred power management profile to OSPM. + U16 SciInterrupt; // System vector of SCI interrupt + U32 SmiCommand; // 32-bit Port address of SMI command port + U8 AcpiEnable; // Value to write to smi_cmd to enable ACPI + U8 AcpiDisable; // Value to write to smi_cmd to disable ACPI + U8 S4BiosRequest; // Value to write to SMI CMD to enter S4BIOS state + U8 PstateControl; // Processor performance state control + U32 Pm1aEventBlock; // 32-bit Port address of Power Mgt 1a Event Reg Blk + U32 Pm1bEventBlock; // 32-bit Port address of Power Mgt 1b Event Reg Blk + U32 Pm1aControlBlock; // 32-bit Port address of Power Mgt 1a Control Reg Blk + U32 Pm1bControlBlock; // 32-bit Port address of Power Mgt 1b Control Reg Blk + U32 Pm2ControlBlock; // 32-bit Port address of Power Mgt 2 Control Reg Blk + U32 PmTimerBlock; // 32-bit Port address of Power Mgt Timer Ctrl Reg Blk + U32 Gpe0Block; // 32-bit Port address of General Purpose Event 0 Reg Blk + U32 Gpe1Block; // 32-bit Port address of General Purpose Event 1 Reg Blk + U8 Pm1EventLength; // Byte Length of ports at Pm1xEventBlock + U8 Pm1ControlLength; // Byte Length of ports at Pm1xControlBlock + U8 Pm2ControlLength; // Byte Length of ports at Pm2ControlBlock + U8 PmTimerLength; // Byte Length of ports at PmTimerBlock + U8 Gpe0BlockLength; // Byte Length of ports at Gpe0Block + U8 Gpe1BlockLength; // Byte Length of ports at Gpe1Block + U8 Gpe1Base; // Offset in GPE number space where GPE1 events start + U8 CstControl; // Support for the _CST object and C States change notification + U16 C2Latency; // Worst case HW latency to enter/exit C2 state + U16 C3Latency; // Worst case HW latency to enter/exit C3 state + U16 FlushSize; // Processor's memory cache line width, in bytes + U16 FlushStride; // Number of flush strides that need to be read + U8 DutyOffset; // Processor duty cycle index in processor's P_CNT reg + U8 DutyWidth; // Processor duty cycle value bit width in P_CNT register. + U8 DayAlarm; // Index to day-of-month alarm in RTC CMOS RAM + U8 MonthAlarm; // Index to month-of-year alarm in RTC CMOS RAM + U8 Century; // Index to century in RTC CMOS RAM + U16 BootFlags; // IA-PC Boot Architecture Flags. See Table 5-10 for description + U8 Reserved; // Reserved, must be zero + U32 Flags; // Miscellaneous flag bits (see below for individual flags) + ACPI_GENERIC_ADDRESS ResetRegister; // 64-bit address of the Reset register + U8 ResetValue; // Value to write to the ResetRegister port to reset the system + U8 Reserved4[3]; // Reserved, must be zero + U64 XFacs; // 64-bit physical address of FACS + U64 XDsdt; // 64-bit physical address of DSDT + ACPI_GENERIC_ADDRESS XPm1aEventBlock; // 64-bit Extended Power Mgt 1a Event Reg Blk address + ACPI_GENERIC_ADDRESS XPm1bEventBlock; // 64-bit Extended Power Mgt 1b Event Reg Blk address + ACPI_GENERIC_ADDRESS XPm1aControlBlock; // 64-bit Extended Power Mgt 1a Control Reg Blk address + ACPI_GENERIC_ADDRESS XPm1bControlBlock; // 64-bit Extended Power Mgt 1b Control Reg Blk address + ACPI_GENERIC_ADDRESS XPm2ControlBlock; // 64-bit Extended Power Mgt 2 Control Reg Blk address + ACPI_GENERIC_ADDRESS XPmTimerBlock; // 64-bit Extended Power Mgt Timer Ctrl Reg Blk address + ACPI_GENERIC_ADDRESS XGpe0Block; // 64-bit Extended General Purpose Event 0 Reg Blk address + ACPI_GENERIC_ADDRESS XGpe1Block; // 64-bit Extended General Purpose Event 1 Reg Blk address +} __attribute__((packed))ACPI_TABLE_FADT; + +// SSDT - Secondary System Description Table +typedef struct acpi_table_ssdt { + ACPI_TABLE_HEADER Header; // Common ACPI table header +} __attribute__((packed))ACPI_TABLE_SSDT; + +//MADT - Multiple APIC Description Table +typedef struct acpi_table_madt { + ACPI_TABLE_HEADER Header; // Common ACPI table header + U32 Address; // Physical address of local APIC + U32 Flags; +} __attribute__((packed))ACPI_TABLE_MADT; + + +// Values for subtable type in ACPI_SUBTABLE_HEADER +enum AcpiMadtType { + ACPI_MADT_TYPE_LOCAL_APIC = 0, + ACPI_MADT_TYPE_IO_APIC = 1, + ACPI_MADT_TYPE_INTERRUPT_OVERRIDE = 2, + ACPI_MADT_TYPE_NMI_SOURCE = 3, + ACPI_MADT_TYPE_LOCAL_APIC_NMI = 4, + ACPI_MADT_TYPE_LOCAL_APIC_OVERRIDE = 5, + ACPI_MADT_TYPE_IO_SAPIC = 6, + ACPI_MADT_TYPE_LOCAL_SAPIC = 7, + ACPI_MADT_TYPE_INTERRUPT_SOURCE = 8, + ACPI_MADT_TYPE_X2APIC = 9, + ACPI_MADT_TYPE_RESERVED = 10 // 10 and greater are reserved +}; + +// Common Sub-table header (used in MADT, SRAT, etc.) +typedef struct acpi_subtable_header { + U8 Type; + U8 Length; +} __attribute__((packed))ACPI_SUBTABLE_HEADER; + +// MADT Sub-tables, correspond to Type in ACPI_SUBTABLE_HEADER + +// 0: Processor Local APIC +typedef struct acpi_madt_local_apic { + ACPI_SUBTABLE_HEADER Header; + U8 ProcessorId; // ACPI processor id + U8 Id; // Processor's local APIC id + U32 LapicFlags; +} __attribute__((packed))ACPI_MADT_LOCAL_APIC; + +// 1: IO APIC +typedef struct acpi_madt_io_apic { + ACPI_SUBTABLE_HEADER Header; + U8 Id; // I/O APIC ID + U8 Reserved; // Reserved - must be zero + U32 Address; // APIC physical address + U32 GlobalIrqBase; // Global system interrupt where INTI lines start +} __attribute__((packed))ACPI_MADT_IO_APIC; + +// 2: Interrupt Override +typedef struct acpi_madt_interrupt_override { + ACPI_SUBTABLE_HEADER Header; + U8 Bus; // 0 - ISA + U8 SourceIrq; // Interrupt source (IRQ) + U32 GlobalIrq; // Global system interrupt + U16 IntiFlags; +} __attribute__((packed))ACPI_MADT_INTERRUPT_OVERRIDE; + +// 3: NMI Source +typedef struct acpi_madt_nmi_source { + ACPI_SUBTABLE_HEADER Header; + U16 IntiFlags; + U32 GlobalIrq; // Global system interrupt +} __attribute__((packed))ACPI_MADT_NMI_SOURCE; + +// 4: Local APIC NMI +typedef struct acpi_madt_local_apic_nmi { + ACPI_SUBTABLE_HEADER Header; + U8 ProcessorId; // ACPI processor id + U16 IntiFlags; + U8 Lint; // LINTn to which NMI is connected +} __attribute__((packed))ACPI_MADT_LOCAL_APIC_NMI; + +// 5: Address Override +typedef struct acpi_madt_local_apic_override { + ACPI_SUBTABLE_HEADER Header; + U16 Reserved; // Reserved, must be zero + U64 Address; // APIC physical address +} __attribute__((packed))ACPI_MADT_LOCAL_APIC_OVERRIDE; + +// 6: I/O Sapic +typedef struct acpi_madt_io_sapic { + ACPI_SUBTABLE_HEADER Header; + U8 Id; // I/O SAPIC ID + U8 Reserved; // Reserved, must be zero + U32 GlobalIrqBase; // Global interrupt for SAPIC start + U64 Address; // SAPIC physical address +} __attribute__((packed))ACPI_MADT_IO_SAPIC; + +// 7: Local Sapic +typedef struct acpi_madt_local_sapic { + ACPI_SUBTABLE_HEADER Header; + U8 ProcessorId; // ACPI processor id + U8 Id; // SAPIC ID + U8 Eid; // SAPIC EID + U8 Reserved[3]; // Reserved, must be zero + U32 LapicFlags; + U32 Uid; // Numeric UID - ACPI 3.0 + char UidString[1]; // String UID - ACPI 3.0 +} __attribute__((packed))ACPI_MADT_LOCAL_SAPIC; + +// 8: Platform Interrupt Source +typedef struct acpi_madt_interrupt_source { + ACPI_SUBTABLE_HEADER Header; + U16 IntiFlags; + U8 Type; // 1=PMI, 2=INIT, 3=corrected + U8 Id; // Processor ID + U8 Eid; // Processor EID + U8 IoSapicVector; // Vector value for PMI interrupts + U32 GlobalIrq; // Global system interrupt + U32 Flags; // Interrupt Source Flags +} __attribute__((packed))ACPI_MADT_INTERRUPT_SOURCE; + +// 9: Processor X2APIC +typedef struct acpi_madt_x2apic { + ACPI_SUBTABLE_HEADER Header; + U16 Reserved; // Must be zero + U32 x2apicId; // Processor's X2APIC ID + U32 x2apicFlags; + U32 UID; +} __attribute__((packed))ACPI_MADT_X2APIC; + +// Common flags fields for MADT subtables + +// MADT Local APIC flags (LapicFlags) +#define ACPI_MADT_ENABLED (1) // 00: Processor is usable if set + +// MADT MPS INTI flags (IntiFlags) +#define ACPI_MADT_POLARITY_MASK (3) // 00-01: Polarity of APIC I/O input signals +#define ACPI_MADT_TRIGGER_MASK (3<<2) // 02-03: Trigger mode of APIC input signals + +// Values for MPS INTI flags +#define ACPI_MADT_POLARITY_CONFORMS 0 +#define ACPI_MADT_POLARITY_ACTIVE_HIGH 1 +#define ACPI_MADT_POLARITY_RESERVED 2 +#define ACPI_MADT_POLARITY_ACTIVE_LOW 3 + +#define ACPI_MADT_TRIGGER_CONFORMS (0) +#define ACPI_MADT_TRIGGER_EDGE (1<<2) +#define ACPI_MADT_TRIGGER_RESERVED (2<<2) +#define ACPI_MADT_TRIGGER_LEVEL (3<<2) + +#define ACPI_COORD_TYPE_SW_ALL 0xFC +#define ACPI_COORD_TYPE_SW_ANY 0xFD +#define ACPI_COORD_TYPE_HW_ALL 0xFE + +typedef struct packageLength { + U8 packageLength0; + U8 packageLength1; +} __attribute__((packed))ACPI_PACKAGE_LENGTH; + +typedef struct acpi_scope { + U8 scopeOpcode; + ACPI_PACKAGE_LENGTH pkgLength; + U8 rootChar; +} __attribute__((packed))ACPI_SCOPE; + +typedef struct dual_name_path { + U8 prefix; + U32 nameseg[2]; +} __attribute__((packed))DUAL_NAME_PATH; + +typedef struct multi_name_path { + U8 prefix; + U8 segCount; + U32 nameseg[MAX_SUPPORTED_CPU_NAMESEGS]; +} __attribute__((packed))MULTI_NAME_PATH; + +typedef struct generic_register { + U8 genericRegisterField; + ACPI_PACKAGE_LENGTH pkgLength; + ACPI_GENERIC_ADDRESS gas; +} __attribute__((packed))ACPI_GENERIC_REGISTER; + +typedef struct package { + U8 packageOpcode; + ACPI_PACKAGE_LENGTH pkgLength; + U8 numElements; +} __attribute__((packed))ACPI_PACKAGE; + +typedef struct small_package { + U8 packageOpcode; + U8 packageLength; + U8 numElements; +} __attribute__((packed))ACPI_SMALL_PACKAGE; + +typedef struct small_buffer { + U8 bufferOpcode; + U8 packageLength; +} __attribute__((packed))ACPI_SMALL_BUFFER; + +typedef struct end_tag { + U8 endTagField; + U8 checksum; +} __attribute__((packed))ACPI_END_TAG; + +typedef struct return_name_seg { + U8 returnOpcode; + U32 name; +} __attribute__((packed))ACPI_RETURN_NAME_SEG; + +typedef struct return_package { + U8 returnOpcode; + ACPI_PACKAGE package; +} __attribute__((packed))ACPI_RETURN_PACKAGE; + +typedef struct return_zero { + U8 returnOpcode; + U8 zeroOpcode; +} __attribute__((packed))ACPI_RETURN_ZERO; + +typedef struct return_opcode { + U8 returnOpcode; + U8 opcodeToReturn; +} __attribute__((packed))ACPI_RETURN_OPCODE; + +typedef struct byteConst { + U8 byteOpcode; + U8 byteData; +} __attribute__((packed))ACPI_BYTE_CONST; + +typedef struct wordConst { + U8 wordOpcode; + U16 wordData; +} __attribute__((packed))ACPI_WORD_CONST; + +typedef struct dwordConst { + U8 dwordOpcode; + U32 dwordData; +} __attribute__((packed))ACPI_DWORD_CONST; + +typedef struct small_method { + U8 methodOpcode; + U8 packageLength; + U32 name; + U8 methodFlags; +} __attribute__((packed))ACPI_SMALL_METHOD; + +typedef struct method { + U8 methodOpcode; + ACPI_PACKAGE_LENGTH pkgLength; + U32 name; + U8 methodFlags; +} __attribute__((packed))ACPI_METHOD; + +typedef struct namePath { + U8 nameOpcode; + U32 name; +} __attribute__((packed))ACPI_NAME_PATH; + +typedef struct named_dword { + ACPI_NAME_PATH namePath; + ACPI_DWORD_CONST dword; +} __attribute__((packed))ACPI_NAMED_DWORD; + +typedef struct rootNamePath { + U8 nameOpcode; + U8 rootPrefix; + U32 name; +} ACPI_ROOT_NAME_PATH; + +typedef struct root_named_dword { + ACPI_ROOT_NAME_PATH rootNamePath; + ACPI_DWORD_CONST dword; +} __attribute__((packed))ACPI_ROOT_NAMED_DWORD; + +typedef struct named_object { + ACPI_NAME_PATH namePath; + ACPI_PACKAGE package; +} __attribute__((packed))ACPI_NAMED_OBJECT; + +typedef struct small_named_object { + ACPI_NAME_PATH namePath; + ACPI_SMALL_PACKAGE package; +} __attribute__((packed))ACPI_SMALL_NAMED_OBJECT; + +typedef struct create_dword_field { + ACPI_NAME_PATH namePath; + ACPI_SMALL_PACKAGE package; +} __attribute__((packed))ACPI_CREATE_DWORD_FIELD; + +typedef struct tstate_package { + ACPI_SMALL_PACKAGE package; + ACPI_DWORD_CONST FreqPercent; + ACPI_DWORD_CONST Power; + ACPI_DWORD_CONST TransLatency; + ACPI_DWORD_CONST Control; + ACPI_DWORD_CONST Status; +} __attribute__((packed))ACPI_TSTATE_PACKAGE; + +typedef struct pstate_package { + ACPI_SMALL_PACKAGE package; + ACPI_DWORD_CONST CoreFreq; + ACPI_DWORD_CONST Power; + ACPI_DWORD_CONST TransLatency; + ACPI_DWORD_CONST BMLatency; + ACPI_DWORD_CONST Control; + ACPI_DWORD_CONST Status; +} __attribute__((packed))ACPI_PSTATE_PACKAGE; + +typedef struct psd_package { + ACPI_SMALL_PACKAGE package; + ACPI_BYTE_CONST NumberOfEntries; + ACPI_BYTE_CONST Revision; + ACPI_DWORD_CONST Domain; + ACPI_DWORD_CONST CoordType; + ACPI_DWORD_CONST NumProcessors; +} __attribute__((packed))ACPI_PSD_PACKAGE; + +typedef struct csd_package { + ACPI_SMALL_PACKAGE package; + ACPI_BYTE_CONST NumberOfEntries; + ACPI_BYTE_CONST Revision; + ACPI_DWORD_CONST Domain; + ACPI_DWORD_CONST CoordType; + ACPI_DWORD_CONST NumProcessors; + ACPI_DWORD_CONST Index; +} __attribute__((packed))ACPI_CSD_PACKAGE; + +typedef struct tsd_package { + ACPI_SMALL_PACKAGE package; + ACPI_BYTE_CONST NumberOfEntries; + ACPI_BYTE_CONST Revision; + ACPI_DWORD_CONST Domain; + ACPI_DWORD_CONST CoordType; + ACPI_DWORD_CONST NumProcessors; +} __attribute__((packed))ACPI_TSD_PACKAGE; + +typedef struct processor { + U8 processorOpCode; + U8 packageLength; + U8 numElements; + ACPI_BYTE_CONST ProcID; + ACPI_DWORD_CONST PblkAddr; + ACPI_BYTE_CONST PblkLen; +} __attribute__((packed))ACPI_PROCESSOR; + +//#pragma pack() + +#endif /* !__LIBSAIO_INTEL_ACPI_H */ Property changes on: trunk/i386/modules/Sata/include/include/intel_acpi.h ___________________________________________________________________ Added: svn:executable + * Index: trunk/i386/modules/Sata/include/Cconfig =================================================================== --- trunk/i386/modules/Sata/include/Cconfig (revision 0) +++ trunk/i386/modules/Sata/include/Cconfig (revision 2031) @@ -0,0 +1,10 @@ +# +# Chameleon Modules +# + +config ACPICODEC_MODULE + tristate "ACPICodec Module" + default m + ---help--- + Say Y here if you want to enable the use of this module. + Index: trunk/i386/modules/Sata/include/acpicode.c =================================================================== --- trunk/i386/modules/Sata/include/acpicode.c (revision 0) +++ trunk/i386/modules/Sata/include/acpicode.c (revision 2031) @@ -0,0 +1,638 @@ +/* +Copyright (c) 2010, Intel Corporation +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + * Neither the name of Intel Corporation nor the names of its contributors + may be used to endorse or promote products derived from this software + without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR +ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON +ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + +#include "datatype.h" +#include "acpi.h" +#include "ppm.h" +#include "acpicode.h" + +static void setPackage(ACPI_PACKAGE * package, U8 numElements); +static void setNamePath(ACPI_NAME_PATH * namePath, U32 name); + +void SetChecksum(struct acpi_table_header *header) +{ + header->Checksum = 0; + header->Checksum = 0 - GetChecksum(header, header->Length); +} + +void setRsdpchecksum(ACPI_TABLE_RSDP *rsdp) +{ + rsdp->Checksum = 0; + rsdp->Checksum = 0 - GetChecksum(rsdp, ACPI_RSDP_REV0_SIZE); +} + +void setRsdpXchecksum(ACPI_TABLE_RSDP *rsdp) +{ + rsdp->ExtendedChecksum = 0; + rsdp->ExtendedChecksum = 0 - GetChecksum(rsdp, rsdp->Length); +} + +U32 update_rsdp_with_xsdt(ACPI_TABLE_RSDP *rsdp, ACPI_TABLE_XSDT *xsdt) +{ + // 1. Update the XSDT pointer in the RSDP + // 2. Update the Xchecksum of the RSDP + + { + // 1. Update the XSDT pointer in the RSDP + rsdp->XsdtPhysicalAddress = ((U64)((U32)xsdt)); + } + + { + // 2. Update the Xchecksum of the RSDP + setRsdpXchecksum(rsdp); + } + + return (1); +} + +U32 update_rsdp_with_rsdt(ACPI_TABLE_RSDP *rsdp, ACPI_TABLE_RSDT *rsdt) +{ + // 1. Update the RSDT pointer in the RSDP + // 2. Update the checksum of the RSDP + + { + // 1. Update the RSDT pointer in the RSDP + rsdp->RsdtPhysicalAddress = (U32)rsdt; + } + + { + // 2. Update the checksum of the RSDP + setRsdpchecksum(rsdp); + } + + return (1); +} + + +//----------------------------------------------------------------------------- +U32 ProcessMadtInfo(ACPI_TABLE_MADT * madt, MADT_INFO * madt_info) +{ + void *current; + void *end; + + // Quick sanity check for a valid MADT + if (madt == 0ul) + return (0ul); + + madt_info->lapic_count = 0; + + // Search MADT for Sub-tables with needed data + current = madt + 1; + end = (U8 *) madt + madt->Header.Length; + + while (current < end) + { + ACPI_SUBTABLE_HEADER *subtable = current; + + switch (subtable->Type) + { + + case ACPI_MADT_TYPE_LOCAL_APIC: + { + // Process sub-tables with Type as 0: Processor Local APIC + ACPI_MADT_LOCAL_APIC *lapic = current; + current = lapic + 1; + + if (!(lapic->LapicFlags & ACPI_MADT_ENABLED)) + continue; + + { + LAPIC_INFO *lapic_info = &madt_info->lapic[madt_info->lapic_count]; + + lapic_info->processorId = lapic->ProcessorId; + lapic_info->apicId = lapic->Id; + lapic_info->madt_type = ACPI_MADT_TYPE_LOCAL_APIC; + } + + madt_info->lapic_count++; + + // Sanity check to verify compile time limit for max logical CPU is not exceeded + if (madt_info->lapic_count > MAX_LOGICAL_CPU) + return (0); + + break; + } + + case ACPI_MADT_TYPE_X2APIC: + { + // Process sub-tables with Type as 9: Processor X2APIC + ACPI_MADT_X2APIC *x2apic = current; + current = x2apic + 1; + + if (!(x2apic->x2apicFlags & ACPI_MADT_ENABLED)) + continue; + + { + LAPIC_INFO *lapic_info = &madt_info->lapic[madt_info->lapic_count]; + + lapic_info->uid = x2apic->UID; + lapic_info->apicId = x2apic->x2apicId; + lapic_info->madt_type = ACPI_MADT_TYPE_X2APIC; + } + + madt_info->lapic_count++; + + // Sanity check to verify compile time limit for max logical CPU is not exceeded + if (madt_info->lapic_count > MAX_LOGICAL_CPU) + return (0); + + break; + } + + default: + { + // Process all other sub-tables + current = (U8 *) subtable + subtable->Length; + break; + } + } // switch + + } // while + + return (1); +} + +//------------------------------------------------------------------------------- +U32 ProcessDsdt(ACPI_TABLE_DSDT * DsdtPointer, U8 * PCIUIDPointer, U8 uid) +{ + // 1. Sanity check + // 2. Replace UID value with the new value + // 3. Update the checksum of the DSDT + + { + // 1. Sanity check + if ((memcmp(&uid, PCIUIDPointer, sizeof(U8)) == 0) || (PCIUIDPointer == (U8*)0) || (DsdtPointer == (void*)0ul)) + return (0); + } + + { + // 2. Replace UID value with the new value + buildOpCode((void*)PCIUIDPointer, uid); + } + + { + // 3. Update the checksum of the DSDT + SetChecksum(&DsdtPointer->Header); + } + + return (1); +} + +//------------------------------------------------------------------------------- +void MoveRsdtInsertSsdt(ACPI_TABLE_RSDP * RsdPointer, ACPI_TABLE_RSDT * OldRsdtPointer, ACPI_TABLE_RSDT * NewRsdtPointer, ACPI_TABLE_SSDT * SsdtPointer) +{ + // 1. Move the RSDT in memory to the new location + // 2. Add new pointer for the SSDT into the RSDT + // 3. Update the size of the RSDT + // 4. Update the checksum of the RSDT + // 5. Update the RSDT pointer in the RSDP + // 6. Update the checksum of the RSDP + + { + // 1. Move the RSDT in memory to the new location + memcpy(NewRsdtPointer, OldRsdtPointer, OldRsdtPointer->Header.Length); + } + + { + // 2. Add new pointer for the SSDT into the RSDT + // 3. Update the size of the RSDT + // 4. Update the checksum of the RSDT + InsertSsdt(NewRsdtPointer, SsdtPointer); + } + + { + // 5. Update the RSDT pointer in the RSDP + RsdPointer->RsdtPhysicalAddress = (U32) NewRsdtPointer; + } + + { + // 6. Update the checksum of the RSDP + setRsdpchecksum(RsdPointer); + } +} + +//------------------------------------------------------------------------------- +void InsertSsdt(ACPI_TABLE_RSDT * RsdtPointer, ACPI_TABLE_SSDT * SsdtPointer) +{ + // 1. Add new pointer for the SSDT into the RSDT + // 2. Update the size of the RSDT + // 3. Update the checksum of the RSDT + + { + // 1. Add new pointer for the SSDT into the RSDT + U32 index = get_num_tables(RsdtPointer); + RsdtPointer->TableOffsetEntry[index] = (U32) SsdtPointer; + } + + { + // 2. Update the size of the RSDT + RsdtPointer->Header.Length = RsdtPointer->Header.Length + sizeof(ACPI_TABLE_SSDT *); + } + + { + // 3. Update the checksum of the RSDT + SetChecksum(&RsdtPointer->Header); + } +} + +//------------------------------------------------------------------------------- +void InsertSsdt64(ACPI_TABLE_XSDT * XsdtPointer, ACPI_TABLE_SSDT * SsdtPointer) +{ + { + void *null = 0ul; + if (XsdtPointer == null) + return; + } + + // 1. Add new pointer for the SSDT into the XSDT + // 2. Update the size of the XSDT + // 3. Update the checksum of the XSDT + + { + // 1. Add new pointer for the SSDT into the XSDT + U32 index = get_num_tables64(XsdtPointer); + XsdtPointer->TableOffsetEntry[index] = (U64) ((U32) SsdtPointer); + } + + { + // 2. Update the size of the XSDT + XsdtPointer->Header.Length = XsdtPointer->Header.Length + sizeof(U64); + } + + { + // 3. Update the checksum of the XSDT + SetChecksum(&XsdtPointer->Header); + } +} + +//----------------------------------------------------------------------------- +void *buildNameSeg(void *current, U32 name) +{ + U32 *nameSeg = current; + current = nameSeg + 1; + + *nameSeg = name; + + return (current); +} + +//----------------------------------------------------------------------------- +void *buildOpCode(void *current, U8 opCode) +{ + U8 *op = current; + current = op + 1; + + *op = opCode; + + return (current); +} + +//----------------------------------------------------------------------------- +void *buildReturnPackage(void *current, U8 numElements) +{ + ACPI_RETURN_PACKAGE *returnPackage = current; + current = returnPackage + 1; + + returnPackage->returnOpcode = AML_RETURN_OP; + setPackage(&returnPackage->package, numElements); + + return (current); +} + +//----------------------------------------------------------------------------- +void *buildReturnZero(void *current) +{ + ACPI_RETURN_ZERO *returnZero = current; + current = returnZero + 1; + + returnZero->returnOpcode = AML_RETURN_OP; + returnZero->zeroOpcode = AML_ZERO_OP; + + return (current); +} + +//----------------------------------------------------------------------------- +void *buildReturnOpcode(void *current, U8 opcodeToReturn) +{ + ACPI_RETURN_OPCODE *returnOpcode = current; + current = returnOpcode + 1; + + returnOpcode->returnOpcode = AML_RETURN_OP; + returnOpcode->opcodeToReturn = opcodeToReturn; + + return (current); +} + +//----------------------------------------------------------------------------- +void *buildMethod(void *current, U32 name, U8 methodFlags) +{ + ACPI_METHOD *method = current; + current = method + 1; + + method->methodOpcode = AML_METHOD_OP; + method->name = name; + method->methodFlags = methodFlags; + + return (current); +} + +//----------------------------------------------------------------------------- +void *buildSmallMethod(void *current, U32 name, U8 methodFlags) +{ + ACPI_SMALL_METHOD *method = current; + current = method + 1; + + method->methodOpcode = AML_METHOD_OP; + method->name = name; + method->methodFlags = methodFlags; + + return (current); +} + +//----------------------------------------------------------------------------- +void *buildNamedDword(void *current, U32 name, U32 dword) +{ + ACPI_NAMED_DWORD *namedDword = current; + current = namedDword + 1; + + setNamePath(&namedDword->namePath, name); + setDwordConst(&namedDword->dword, dword); + + return (current); +} + +//----------------------------------------------------------------------------- +void *buildGenericRegister(void *current, const ACPI_GENERIC_ADDRESS * gas) +{ + ACPI_GENERIC_REGISTER *genReg = current; + current = genReg + 1; + + genReg->genericRegisterField = AML_GEN_REG_FIELD; + genReg->pkgLength.packageLength0 = 0x0c; + genReg->pkgLength.packageLength1 = 0; + + genReg->gas.SpaceId = gas->SpaceId; + genReg->gas.BitWidth = gas->BitWidth; + genReg->gas.BitOffset = gas->BitOffset; + genReg->gas.AccessWidth = gas->AccessWidth; + genReg->gas.Address = gas->Address; + + return (current); +} + +//----------------------------------------------------------------------------- +void *buildSmallBuffer(void *current) +{ + ACPI_SMALL_BUFFER *buffer = current; + current = buffer + 1; + + buffer->bufferOpcode = AML_BUFFER_OP; + + return (current); +} + +//----------------------------------------------------------------------------- +void *buildEndTag(void *current) +{ + ACPI_END_TAG *endTag = current; + current = endTag + 1; + + endTag->endTagField = AML_END_TAG_OP; + endTag->checksum = 0; + + return (current); +} + +//----------------------------------------------------------------------------- +void setSmallPackage(ACPI_SMALL_PACKAGE * package, U8 numElements) +{ + package->packageOpcode = AML_PACKAGE_OP; + package->numElements = numElements; +} + +//----------------------------------------------------------------------------- +void *buildSmallPackage(void *current, U8 numElements) +{ + ACPI_SMALL_PACKAGE *package = current; + current = package + 1; + setSmallPackage(package, numElements); + return (current); +} + +//----------------------------------------------------------------------------- +static void setPackage(ACPI_PACKAGE * package, U8 numElements) +{ + package->packageOpcode = AML_PACKAGE_OP; + package->numElements = numElements; +} + +//----------------------------------------------------------------------------- +void setPackageLength(ACPI_PACKAGE_LENGTH * packageLength, U32 length) +{ + packageLength->packageLength0 = 0x40 + (U8) (length & 0xf); + packageLength->packageLength1 = (U8) (length >> 4); +} + +//----------------------------------------------------------------------------- +void *buildPackageLength(void *current, U32 length) +{ + ACPI_PACKAGE_LENGTH *packageLength = current; + current = packageLength + 1; + setPackageLength(packageLength, length); + return (current); +} + +//----------------------------------------------------------------------------- +static void setNamePath(ACPI_NAME_PATH * namePath, U32 name) +{ + namePath->nameOpcode = AML_NAME_OP; + namePath->name = name; +} + +//----------------------------------------------------------------------------- +void *buildNamePath(void *current, U32 name) +{ + ACPI_NAME_PATH *namePath = current; + current = namePath + 1; + setNamePath(namePath, name); + return (current); +} + +//----------------------------------------------------------------------------- +static void setTableHeader(ACPI_TABLE_HEADER * tableHeader, U32 signature, U64 oemTableId) +{ + *(U32 *) &tableHeader->Signature = signature; + tableHeader->Length = 0; + tableHeader->Revision = 1; + tableHeader->Checksum = 0; + memcpy(&tableHeader->OemId[0], "INTEL ", 6); + *(U64 *) (tableHeader->OemTableId) = oemTableId; + tableHeader->OemRevision = 0x80000001; + *(U32 *) tableHeader->AslCompilerId = NAMESEG("INTL"); // ASCII ASL compiler vendor ID + tableHeader->AslCompilerRevision = 0x20061109; // ASL compiler version +} + +//----------------------------------------------------------------------------- +void *buildTableHeader(void *current, U32 signature, U64 oemTableId) +{ + ACPI_TABLE_HEADER *tableHeader = current; + current = tableHeader + 1; + setTableHeader(tableHeader, signature, oemTableId); + return (current); +} + +//----------------------------------------------------------------------------- +void setByteConst(ACPI_BYTE_CONST * byteConst, U8 byteData) +{ + byteConst->byteOpcode = AML_BYTE_OP; + byteConst->byteData = byteData; +} + +//----------------------------------------------------------------------------- +void *buildByteConst(void *current, U8 byteData) +{ + ACPI_BYTE_CONST *byteConst = current; + current = byteConst + 1; + setByteConst(byteConst, byteData); + return (current); +} + +//----------------------------------------------------------------------------- +void setWordConst(ACPI_WORD_CONST * wordConst, U16 wordData) +{ + wordConst->wordOpcode = AML_WORD_OP; + wordConst->wordData = wordData; +} + +//----------------------------------------------------------------------------- +void *buildWordConst(void *current, U16 wordData) +{ + ACPI_WORD_CONST *wordConst = current; + current = wordConst + 1; + setWordConst(wordConst, wordData); + return (current); +} + +//----------------------------------------------------------------------------- +void setDwordConst(ACPI_DWORD_CONST * dwordConst, U32 dwordData) +{ + dwordConst->dwordOpcode = AML_DWORD_OP; + dwordConst->dwordData = dwordData; +} + +//----------------------------------------------------------------------------- +void *buildDwordConst(void *current, U32 dwordData) +{ + ACPI_DWORD_CONST *dwordConst = current; + current = dwordConst + 1; + setDwordConst(dwordConst, dwordData); + return (current); +} + +//------------------------------------------------------------------------------- +U32 ProcessFadt(ACPI_TABLE_FADT * FadtPointer, U32 pmbase) +{ + { + // Update fields in FADT + + // Update ACPI 1.0 fields first + + FadtPointer->Pm1aEventBlock = pmbase; + FadtPointer->Pm1aControlBlock = pmbase + 4; + FadtPointer->Pm2ControlBlock = pmbase + 0x50; + FadtPointer->PmTimerBlock = pmbase + 8; + FadtPointer->Pm1EventLength = 4; + FadtPointer->Pm1ControlLength = 2; + FadtPointer->Pm2ControlLength = 1; + FadtPointer->PmTimerLength = 4; + + // No legacy C2 + FadtPointer->C2Latency = 101; + + // No legacy C3 + FadtPointer->C3Latency = 1001; + + // C1 power state is supported on all processors + FadtPointer->BootFlags |= 1UL << 2; + + // No legacy C2 on MP systems + FadtPointer->BootFlags &= ~(1UL << 3); + + // Update ACPI 2.0+ fields if supported + if (FadtPointer->Header.Revision >= 3) { + // Address space where struct or register exists - System IO + FadtPointer->XPm1aEventBlock.SpaceId = 1; + // Size in bits of given register + FadtPointer->XPm1aEventBlock.BitWidth = 0x20; + // Bit offset within the register + FadtPointer->XPm1aEventBlock.BitOffset = 0; + // Minimum Access size (ACPI 3.0) + FadtPointer->XPm1aEventBlock.AccessWidth = 0; + // 64-bit address of struct or register + FadtPointer->XPm1aEventBlock.Address = pmbase; + + // Address space where struct or register exists - System IO + FadtPointer->XPm1aControlBlock.SpaceId = 1; + // Size in bits of given register + FadtPointer->XPm1aControlBlock.BitWidth = 0x10; + // Bit offset within the register + FadtPointer->XPm1aControlBlock.BitOffset = 0; + // Minimum Access size (ACPI 3.0) + FadtPointer->XPm1aControlBlock.AccessWidth = 0; + // 64-bit address of struct or register + FadtPointer->XPm1aControlBlock.Address = pmbase + 4; + + // Address space where struct or register exists - System IO + FadtPointer->XPm2ControlBlock.SpaceId = 1; + // Size in bits of given register + FadtPointer->XPm2ControlBlock.BitWidth = 0x08; + // Bit offset within the register + FadtPointer->XPm2ControlBlock.BitOffset = 0; + // Minimum Access size (ACPI 3.0) + FadtPointer->XPm2ControlBlock.AccessWidth = 0; + // 64-bit address of struct or register + FadtPointer->XPm2ControlBlock.Address = pmbase + 0x50; + + // Address space where struct or register exists - System IO + FadtPointer->XPmTimerBlock.SpaceId = 1; + // Size in bits of given register + FadtPointer->XPmTimerBlock.BitWidth = 0x20; + // Bit offset within the register + FadtPointer->XPmTimerBlock.BitOffset = 0; + // Minimum Access size (ACPI 3.0) + FadtPointer->XPmTimerBlock.AccessWidth = 0; + // 64-bit address of struct or register + FadtPointer->XPmTimerBlock.Address = pmbase + 8; + } + } + + // Update checksum in FADT + SetChecksum(&FadtPointer->Header); + + return (1); +} Index: trunk/i386/modules/Sata/include/acpi_codec.c =================================================================== --- trunk/i386/modules/Sata/include/acpi_codec.c (revision 0) +++ trunk/i386/modules/Sata/include/acpi_codec.c (revision 2031) @@ -0,0 +1,5176 @@ +/* + * Copyright 2008 mackerintel + */ + +/* + Copyright (c) 2010, Intel Corporation + All rights reserved. + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + * Neither the name of Intel Corporation nor the names of its contributors + may be used to endorse or promote products derived from this software + without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND + ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR + ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +/* + * Copyright (c) 2011,2012 cparm . All rights reserved. + * + */ + +#include "libsaio.h" +#include "bootstruct.h" +#include "acpi.h" +#include "acpidecode.h" +#include "acpicode.h" +#include "efi_tables.h" +#include "fake_efi.h" +#include "acpi_codec.h" +#include "platform.h" +#include "cpu.h" +#include "xml.h" +#include "sl.h" +#include "convert.h" +#include "modules.h" +#include "pci.h" +#include "pci_root.h" + +U64 rsd_p; +ACPI_TABLES acpi_tables; +U32 uuid32; +U32 Model32; +bool checkOem = false; + +extern EFI_STATUS addConfigurationTable(); + +extern EFI_GUID gEfiAcpiTableGuid; +extern EFI_GUID gEfiAcpi20TableGuid; + +#ifndef DEBUG_ACPI +#define DEBUG_ACPI 0 +#endif + +#if DEBUG_ACPI==2 +#define DBG(x...) {printf(x); sleep(1);} +#elif DEBUG_ACPI==1 +#define DBG(x...) printf(x) +#else +#define DBG(x...) +#endif + +#define OLD_SSDT 0 +#define BETA 0 +#define BUILD_ACPI_TSS 0 +#define pstate_power_support 1 + +#if BETA +#ifdef pstate_power_support +#undef pstate_power_support +#endif +#define pstate_power_support 1 +#endif + +#if DEBUG_ACPI +static void print_nameseg(U32 i); +#endif + +static ACPI_TABLE_HEADER * get_new_table_in_list(U32 *new_table_list, U32 Signature, U8 *retIndex ); +static U8 get_number_of_tables_in_list(U32 *new_table_list, U32 Signature ); +static U8 get_0ul_index_in_list(U32 *new_table_list, bool reserved ); +static void sanitize_new_table_list(U32 *new_table_list ); +static void move_table_list_to_kmem(U32 *new_table_list ); +static ACPI_TABLE_RSDP * gen_alloc_rsdp_v2_from_v1(ACPI_TABLE_RSDP *rsdp ); +static ACPI_TABLE_RSDT * gen_alloc_rsdt_from_xsdt(ACPI_TABLE_XSDT *xsdt); +static ACPI_TABLE_XSDT * gen_alloc_xsdt_from_rsdt(ACPI_TABLE_RSDT *rsdt); +#if 0 +static void MakeAcpiSgn(void); +#endif +static void *loadACPITable(U32 *new_table_list, char *dirspec, const char *filename ); +static int generate_cpu_map_from_acpi(ACPI_TABLE_DSDT * DsdtPointer); +static ACPI_GENERIC_ADDRESS FillGASStruct(U32 Address, U8 Length); +static U32 process_xsdt (ACPI_TABLE_RSDP *rsdp_mod , U32 *new_table_list); +static U32 process_rsdt(ACPI_TABLE_RSDP *rsdp_mod , bool gen_xsdt, U32 *new_table_list); +static ACPI_TABLE_FADT * patch_fadt(ACPI_TABLE_FADT *fadt, ACPI_TABLE_DSDT *new_dsdt, bool UpdateFADT); + + +#define IA32_MISC_ENABLES 0x01A0 +#define MSR_TURBO_POWER_CURRENT_LIMIT 0x1AC +#define MSR_PKG_CST_CONFIG_CONTROL 0x00E2 +#define MSR_RAPL_POWER_UNIT 0x606 +#define MSR_PKG_RAPL_POWER_LIMIT 0x610 +static U32 turbo_enabled = 0; +static U32 ProcessMadt(ACPI_TABLE_MADT * madt, MADT_INFO * madt_info, void * buffer, U32 bufferSize, U32 NB_CPU); +static U32 buildMADT(U32 * new_table_list, ACPI_TABLE_DSDT *dsdt, MADT_INFO * madt_info); +static U32 BuildSsdt(MADT_INFO * madt_info, ACPI_TABLE_DSDT *dsdt, void * buffer, U32 bufferSize, bool enable_cstates, bool enable_pstates, bool enable_tstates); +static bool is_sandybridge(void); +static bool is_jaketown(void); +static U32 encode_pstate(U32 ratio); +static void collect_cpu_info(CPU_DETAILS * cpu); +#ifndef BETA +//static U32 BuildCoreIPstateInfo(CPU_DETAILS * cpu); +#endif +static U32 BuildCstateInfo(CPU_DETAILS * cpu, U32 pmbase); +static U32 BuildPstateInfo(CPU_DETAILS * cpu); +static U32 ProcessSsdt(U32 * new_table_list, ACPI_TABLE_DSDT *dsdt, MADT_INFO * madt_info, bool enable_cstates, bool enable_pstates, bool enable_tstates ); +static void * buildCpuScope (void * current, U32 cpu_namespace, PROCESSOR_NUMBER_TO_NAMESEG * aslCpuNamePath); +static void * buildPDC(void * current); +static void * buildOSC(void * current); +static void * buildPSS(void * current, PKG_PSTATES * pkg_pstates); +static void * buildPSD(void * current, U32 domain, U32 cpusInDomain, U32 pstate_coordination); +static void * buildPPC(void * current); +static void * buildPCT(void * current); +static void * buildCstate(void * current, ACPI_GENERIC_ADDRESS * gas, CSTATE * cstate); +static void * buildReturnPackageCST(void * current, PKG_CSTATES * pkg_cstates); +static void * buildCST(void * current, PKG_CSTATES * mwait_pkg_cstates, PKG_CSTATES * io_pkg_cstates); +#if BUILD_ACPI_CSD +static void * buildCSD(void * current, U32 domain, U32 cpusInDomain, PKG_CSTATES * pkg_cstates); +#endif +#if BUILD_ACPI_TSS +static U32 BuildTstateInfo(CPU_DETAILS * cpu); +static void * buildTPC(void * current); +static void * buildPTC(void * current); +static void * buildTSS(void * current, PKG_TSTATES * pkg_tstates); +static void * buildTSD(void * current, U32 domain, U32 cpusInDomain); +#endif +#if pstate_power_support +static U64 mulU64byU64(U64 a, U64 b, U64 * high); +static U32 compute_pstate_power(CPU_DETAILS * cpu, U32 ratio, U32 TDP); +#endif +#if BUILD_ACPI_TSS || pstate_power_support +static U64 divU64byU64(U64 n, U64 d, U64 * rem); +static U32 compute_tdp(CPU_DETAILS * cpu); +#endif +static bool is_sandybridge(void); +static bool is_jaketown(void); +static U32 get_bclk(void); +static void GetMaxRatio(U32 * max_non_turbo_ratio); +//static U32 computePstateRatio(const U32 max, const U32 min, const U32 turboEnabled, const U32 numStates, const U32 pstate); +//static U32 computeNumPstates(const U32 max, const U32 min, const U32 turboEnabled, const U32 pssLimit); + +#if UNUSED +static ACPI_TABLE_FACS* generate_facs(bool updatefacs ); +#endif + +#define MAX_NON_SSDT_TABLE 15 +#define MAX_SSDT_TABLE 15 // 15 additional SSDT tables +#define MAX_ACPI_TABLE MAX_NON_SSDT_TABLE + MAX_SSDT_TABLE + +// Security space for SSDT , FACP & MADT table generation, +// the size can be increased +// note: the table will not placed in the reserved space if the 'normal' space is not full +#define RESERVED_AERA 3 + +#define ACPI_TABLE_LIST_FULL MAX_ACPI_TABLE + RESERVED_AERA + 1 + +#define ACPI_TABLE_LIST_FULL_NON_RESERVED MAX_ACPI_TABLE + 1 + +#ifndef ULONG_MAX_32 +#define ULONG_MAX_32 4294967295UL +#endif + +#define __RES(s, u) \ +static inline unsigned u \ +resolve_##s(unsigned u defaultentry, char *str, int base) \ +{ \ +unsigned u entry = defaultentry; \ +if (str && (strcmp(str,"Default") != 0)) { \ +entry = strtoul((const char *)str, NULL,base); \ +} \ +return entry; \ +} + +__RES(pss, long) +__RES(cst, int) + +static ACPI_TABLE_HEADER * get_new_table_in_list(U32 *new_table_list, U32 Signature, U8 *retIndex ) +{ + ACPI_TABLE_HEADER **table_array = (ACPI_TABLE_HEADER **) new_table_list; + U8 index ; + *retIndex = 0; + + for (index = 0; index < (MAX_ACPI_TABLE + RESERVED_AERA); index++) + { + if (*(U32 *) (table_array[index]->Signature) == Signature) + { + *retIndex = index; + return table_array[index] ; + } + } + return (void*)0ul; +} + +static U8 get_number_of_tables_in_list(U32 *new_table_list, U32 Signature ) +{ + ACPI_TABLE_HEADER **table_array = (ACPI_TABLE_HEADER **) new_table_list; + U8 index ; + U8 InstalledTables = 0; + + for (index = 0; index < (MAX_ACPI_TABLE + RESERVED_AERA); index++) + { + if (*(U32 *) (table_array[index]->Signature) == Signature) + { + InstalledTables++ ; + } + } + return InstalledTables; +} + +static U8 get_0ul_index_in_list(U32 *new_table_list, bool reserved ) +{ + U8 index ; + + U8 maximum = (reserved == true) ? MAX_ACPI_TABLE + RESERVED_AERA : MAX_ACPI_TABLE; + + for (index = 0; index < maximum; index++) + { + if (new_table_list[index] == 0ul) + { + return index ; + } + } + return (reserved == true)? ACPI_TABLE_LIST_FULL : ACPI_TABLE_LIST_FULL_NON_RESERVED; +} + +/* cparm : This time we check it by the acpi signature */ +static void sanitize_new_table_list(U32 *new_table_list ) +{ + ACPI_TABLE_HEADER **table_array = (ACPI_TABLE_HEADER **) new_table_list; + U8 index ; + + for (index = 0; index < MAX_ACPI_TABLE; index++) + { + U32 current_sig = *(U32 *) (table_array[index]->Signature); + + if ((current_sig == NAMESEG(ACPI_SIG_FACS) /* not supported */ ) + || (current_sig == NAMESEG(ACPI_SIG_XSDT)) + || (current_sig == NAMESEG(ACPI_SIG_RSDT)) || (*(volatile U64 *)table_array[index] == NAMESEG64(ACPI_SIG_RSDP)) ) + { + + void *buf = (void*)new_table_list[index]; + free(buf); + new_table_list[index] = 0ul ; + } + } +} + +/* cparm : move all tables to kernel memory */ +static void move_table_list_to_kmem(U32 *new_table_list ) +{ + ACPI_TABLE_HEADER **table_array = (ACPI_TABLE_HEADER **) new_table_list; + U8 index ; + + for (index = 0; index < MAX_ACPI_TABLE; index++) + { + if (new_table_list[index] != 0ul) + { + + U32 current_sig = *(U32 *) (table_array[index]->Signature); + if ((current_sig != NAMESEG(ACPI_SIG_FACS) /* not supported */ ) + && (current_sig != NAMESEG(ACPI_SIG_XSDT)) + && (current_sig != NAMESEG(ACPI_SIG_RSDT)) && (*(volatile U64 *)table_array[index] != NAMESEG64(ACPI_SIG_RSDP)) + && (GetChecksum(table_array[index], table_array[index]->Length) == 0)) + { + + void *tableAddr=(void*)AllocateKernelMemory(table_array[index]->Length); + if (!tableAddr) { + printf("Unable to allocate kernel memory for aml file "); + + void *buf = (void*)new_table_list[index]; + free(buf); + new_table_list[index] = 0ul ; + continue; + } + bcopy(table_array[index], tableAddr, table_array[index]->Length); + new_table_list[index] = 0ul ; + new_table_list[index] = (U32)tableAddr ; + + } + else + { + + void *buf = (void*)new_table_list[index]; + free(buf); + new_table_list[index] = 0ul ; + } + } + } +} + +static ACPI_TABLE_RSDP * gen_alloc_rsdp_v2_from_v1(ACPI_TABLE_RSDP *rsdp ) +{ + + ACPI_TABLE_RSDP * rsdp_conv = (ACPI_TABLE_RSDP *)AllocateKernelMemory(sizeof(ACPI_TABLE_RSDP)); + + if (rsdp_conv) { + bzero(rsdp_conv, sizeof(ACPI_TABLE_RSDP)); + memcpy(rsdp_conv, rsdp, ACPI_RSDP_REV0_SIZE); + + /* Add/change fields */ + rsdp_conv->Revision = 2; /* ACPI version 3 */ + rsdp_conv->Length = sizeof(ACPI_TABLE_RSDP); + + /* Correct checksums */ + setRsdpchecksum(rsdp_conv); + setRsdpXchecksum(rsdp_conv); + } + + return (rsdp_conv) ? rsdp_conv : (void*)0ul ; +} + +static ACPI_TABLE_RSDT * gen_alloc_rsdt_from_xsdt(ACPI_TABLE_XSDT *xsdt) +{ + U32 index; + U32 num_tables; + + DBG("Attempting to generate RSDT from XSDT \n"); + + num_tables= get_num_tables64(xsdt); + + ACPI_TABLE_RSDT * rsdt_conv=(ACPI_TABLE_RSDT *)AllocateKernelMemory(sizeof(ACPI_TABLE_HEADER)+(num_tables * 4)); + if (!rsdt_conv) + { + printf("Unable to allocate kernel memory for rsdt conv\n"); + return (void*)0ul; + } + + + bzero(rsdt_conv, sizeof(ACPI_TABLE_HEADER)+(num_tables * 4)); + memcpy(&rsdt_conv->Header, &xsdt->Header, sizeof(ACPI_TABLE_HEADER)); + + rsdt_conv->Header.Signature[0] = 'R'; + rsdt_conv->Header.Signature[1] = 'S'; + rsdt_conv->Header.Signature[2] = 'D'; + rsdt_conv->Header.Signature[3] = 'T'; + rsdt_conv->Header.Length = sizeof(ACPI_TABLE_HEADER)+(num_tables * 4); + + for (index=0;indexTableOffsetEntry[index]; + + { + if (ptr > ULONG_MAX) + { +#if DEBUG_ACPI + printf("Warning xsdt->TableOffsetEntry[%d]: Beyond addressable memory in this CPU mode, ignored !!!\n",index); +#endif + continue; + } +#if DEBUG_ACPI + printf("* Processing : "); + print_nameseg(*(U32 *) ((ACPI_TABLE_HEADER *) (unsigned long)ptr)->Signature); + printf("\n"); +#endif + int method = 0; + getIntForKey(kAcpiMethod, &method, &bootInfo->chameleonConfig); + + + if (method != 0x2) + { + if (GetChecksum(((ACPI_TABLE_HEADER *) (unsigned long)ptr), + ((ACPI_TABLE_HEADER *) (unsigned long)ptr)->Length) != 0) + { +#if DEBUG_ACPI + printf("Warning : Invalide checksum, ignored !!!\n",index); +#endif + continue; + } + } + + } + + { + if (*(U32 *) ((ACPI_TABLE_HEADER *) (unsigned long)ptr)->Signature == NAMESEG(ACPI_SIG_FADT)) + { + ACPI_TABLE_FADT *fadt=(ACPI_TABLE_FADT *)((U32)ptr); + + ACPI_TABLE_FADT *fadt_conv = (void*)0ul; + + if (fadt->Header.Revision > 1) + { + U8 buffer[0x74]; + DBG("Downgrading ACPI V%d FADT to ACPI V1 FADT \n", fadt->Header.Revision); + fadt_conv=(ACPI_TABLE_FADT *)buffer; + memcpy(fadt_conv, fadt, 0x74); + fadt_conv->Header.Length = 0x74; + fadt_conv->Header.Revision = 0x01; + SetChecksum(&fadt_conv->Header); + } + else + { + fadt_conv = fadt; + } + + ACPI_TABLE_FADT *fadt_mod = patch_fadt(fadt_conv, ((ACPI_TABLE_DSDT*)((U32)fadt->XDsdt)), false); + if (fadt_mod == (void*)0ul) + { + printf("Error: Failed to patch FADT Table, trying wiht the original fadt pointer\n"); + fadt_mod = fadt; + } + + rsdt_conv->TableOffsetEntry[index] = ((U32)fadt_mod); +#if DEBUG_ACPI + print_nameseg(*(U32 *) ((ACPI_TABLE_HEADER *) (unsigned long)ptr)->Signature); + printf(" table converted and added succesfully\n"); +#endif + continue; + } + } + + { + rsdt_conv->TableOffsetEntry[index] = (U32)ptr; +#if DEBUG_ACPI + print_nameseg(*(U32 *) ((ACPI_TABLE_HEADER *) (unsigned long)ptr)->Signature); + printf(" table converted and added succesfully\n"); +#endif + } + + } + DBG("RSDT_CONV : Original checksum %d\n", rsdt_conv->Header.Checksum); + SetChecksum(&rsdt_conv->Header); + DBG("New checksum %d\n", rsdt_conv->Header.Checksum); + + return rsdt_conv; +} + +static ACPI_TABLE_XSDT * gen_alloc_xsdt_from_rsdt(ACPI_TABLE_RSDT *rsdt) +{ + U32 index; + U32 num_tables; + + DBG("Attempting to generate XSDT from RSDT \n"); + + num_tables= get_num_tables(rsdt); + + ACPI_TABLE_XSDT * xsdt_conv=(ACPI_TABLE_XSDT *)AllocateKernelMemory(sizeof(ACPI_TABLE_HEADER)+(num_tables * 8)); + + if (!xsdt_conv) { + printf("Unable to allocate kernel memory for xsdt conv\n"); + return (void*)0ul; + } + + bzero(xsdt_conv, sizeof(ACPI_TABLE_HEADER)+(num_tables * 8)); + memcpy(&xsdt_conv->Header, &rsdt->Header, sizeof(ACPI_TABLE_HEADER)); + + xsdt_conv->Header.Signature[0] = 'X'; + xsdt_conv->Header.Signature[1] = 'S'; + xsdt_conv->Header.Signature[2] = 'D'; + xsdt_conv->Header.Signature[3] = 'T'; + xsdt_conv->Header.Length = sizeof(ACPI_TABLE_HEADER)+(num_tables * 8); + + ACPI_TABLE_HEADER **table_array = (ACPI_TABLE_HEADER **) rsdt->TableOffsetEntry; + + for (index=0;indexSignature)); + printf("\n"); +#endif + int method = 0; + getIntForKey(kAcpiMethod, &method, &bootInfo->chameleonConfig); + + + if (method != 0x2) + { + if (GetChecksum(table_array[index], table_array[index]->Length) != 0) + { +#if DEBUG_ACPI + printf("Warning : Invalide checksum, ignored !!!\n",index); +#endif + continue; + } + } + + } + + { + if (*(U32 *) (table_array[index]->Signature) == NAMESEG(ACPI_SIG_FADT)) + { + ACPI_TABLE_FADT *FacpPointer = ((ACPI_TABLE_FADT*)table_array[index]); + ACPI_TABLE_FADT *fadt_mod = (ACPI_TABLE_FADT *)patch_fadt(FacpPointer,((ACPI_TABLE_DSDT*)FacpPointer->Dsdt),true); + if (fadt_mod == (void*)0ul) + { + printf("Error: Failed to patch (& update) FADT Table, fallback to original fadt pointer\n"); + fadt_mod = FacpPointer; + } + xsdt_conv->TableOffsetEntry[index] = ((U64)((U32)fadt_mod)); + + continue; + } + } + + xsdt_conv->TableOffsetEntry[index] = ((U64)((U32)table_array[index])); + } + DBG("XSDT_CONV : Original checksum %d\n", xsdt_conv->Header.Checksum); + SetChecksum(&xsdt_conv->Header); + DBG("New checksum %d\n", xsdt_conv->Header.Checksum); + + return xsdt_conv; +} + +#if ACPISGN +static void MakeAcpiSgn(void) +{ + + char * DefaultplatformName = NULL; + Model32 = 0; + + if ((DefaultplatformName = readDefaultPlatformName())) + { + Model32 = OSSwapHostToBigInt32(adler32( (unsigned char *) DefaultplatformName, strlen(DefaultplatformName))); + } + + uuid32 = 0; + + const char *uuidStr = getStringFromUUID((int8_t*)(uint32_t)get_env(envSysId)); + + if (strlen(uuidStr)) + { + uuid32 = OSSwapHostToBigInt32(adler32( (unsigned char *) uuidStr, UUID_STR_LEN )); + } + +} +#endif + +static void *loadACPITable(U32 *new_table_list, char *dirspec, const char *filename ) +{ + int fd = -1; + char acpi_file[512]; + + DBG("Searching for %s file ...\n", filename); + // Check booting partition + + sprintf(acpi_file, "%s%s",dirspec, filename); + + fd=open(acpi_file,0); + + if (fd<0) + { + DBG("Couldn't open ACPI Table: %s\n", acpi_file); + return (void *)0ul ; + } + + void *tableAddr=(void*)malloc(file_size (fd)); + + if (tableAddr) + { + if (read (fd, tableAddr, file_size (fd))!=file_size (fd)) + { + printf("Couldn't read table %s\n",acpi_file); + free (tableAddr); + close (fd); + return (void *)0ul ; + } + + close (fd); + + ACPI_TABLE_HEADER * header = (ACPI_TABLE_HEADER *)tableAddr; + + if (*(U32*)(header->Signature) != NAMESEG("SSDT")) + { + U8 dummy = 0; + if (get_new_table_in_list(new_table_list, *(U32*)(header->Signature), &dummy)) + { +#if DEBUG_ACPI + printf("Warning: A "); + print_nameseg(*(U32*) (header->Signature)); + printf(" Aml file is already loaded and registred, file skipped !!\n"); +#endif + free(tableAddr); + return (void*)0ul; + } + } + else + { + if (get_number_of_tables_in_list(new_table_list, NAMESEG("SSDT")) >= MAX_SSDT_TABLE) + { + DBG("Warning: Max number of SSDT aml files reached, file skipped !!\n"); + free(tableAddr); + return (void*)0ul; + } + } + + + if (checkOem == true) + { + if (header->OemRevision == Model32) + { + goto continue_loading; + } + + if (header->OemRevision == uuid32) + { + goto continue_loading; + } + + DBG("Bad signature aka Oem Revision (0x%08lx) for Aml file (%s), file skipped !!\n", header->OemRevision, acpi_file); + DBG("uuid32 (0x%08lx) , model32 (0x%08lx)\n", uuid32, Model32); + + free(tableAddr); + return (void*)0ul; + } + + continue_loading: + + if (GetChecksum(header, header->Length) == 0) + { + DBG("Found valid AML file : %s ", filename); + verbose("[ %s ] read and stored at: %x", acpi_file, tableAddr); + printf("\n"); + return tableAddr; + } + else + { + printf("Warning : Incorrect cheksum for the file : %s,", acpi_file); + printf(" this file will be dropped.\n"); + free(tableAddr); + return (void*)0ul; + } + } + else + { + printf("Couldn't allocate memory for table %s\n", acpi_file); + close (fd); + } + + return (void *)0ul ; +} + +static U32 pmbase; +static short cpuNamespace; +PROCESSOR_NUMBER_TO_NAMESEG cpu_map[CPU_MAP_LIMIT]; +unsigned int cpu_map_count; +int cpu_map_error; + +#if DEBUG_ACPI +static void print_nameseg(U32 i) +{ + printf("%c%c%c%c", + (int)(i & 0x000000ff), + (int)((i & 0x0000ff00) >> 8), + (int)((i & 0x00ff0000) >> 16), + (int)(i >> 24)); +} +#endif + +static int generate_cpu_map_from_acpi(ACPI_TABLE_DSDT * DsdtPointer) +{ + PROCESSOR_NUMBER_TO_NAMESEG *map = cpu_map; + U32 processor_namespace = 0; + U32 cpu; + U8 *current, *end; + ACPI_TABLE_HEADER *header; + struct acpi_namespace ns; + + if ((cpu_map_error == 1) || (DsdtPointer == (void*)0ul)) + return 1; + else if (cpu_map_count > 0) + return 0; + + DBG("Attempting to autodetect CPU map from ACPI DSDT; wish me luck\n"); + + current = (U8 *) DsdtPointer; + current = decodeTableHeader(current, &header); + end = current - sizeof(*header) + header->Length; + ns.depth = 0; + acpi_processor_count = 0; + //DBG("* DSDT debug start\n"); + parse_acpi_termlist(&ns, current, end); + //DBG("* DSDT debug end\n"); + + if (acpi_processor_count > CPU_MAP_LIMIT) + { + verbose("Too many processors: found %u processors\n", acpi_processor_count); + return (cpu_map_error = 1); + } + if (acpi_processor_count == 0) + { + verbose( "Found no processors in ACPI\n"); + return (cpu_map_error = 1); + } + for (cpu = 0; cpu < acpi_processor_count; cpu++) + { + U32 nameseg; + if (acpi_processors[cpu].pmbase) + { + U32 cpu_pmbase = acpi_processors[cpu].pmbase - 0x10; + if (pmbase && cpu_pmbase != pmbase) + { + verbose("Found inconsistent pmbase addresses in ACPI: 0x%x and 0x%x\n", pmbase, cpu_pmbase); + return (cpu_map_error = 1); + } + pmbase = cpu_pmbase; + } + if (acpi_processors[cpu].ns.depth > MAX_SUPPORTED_CPU_NAMESEGS + 1) + { + verbose("Processor path too deep: depth %u\n", acpi_processors[cpu].ns.depth); + return (cpu_map_error = 1); + } + if (processor_namespace && acpi_processors[cpu].ns.nameseg[0] != processor_namespace) + { + verbose("Processor namespaces inconsistent\n"); + return (cpu_map_error = 1); + } + processor_namespace = acpi_processors[cpu].ns.nameseg[0]; + map->acpi_processor_number = acpi_processors[cpu].id; + map->seg_count = acpi_processors[cpu].ns.depth - 1; + for (nameseg = 0; nameseg < map->seg_count; nameseg++) + map->nameseg[nameseg] = acpi_processors[cpu].ns.nameseg[nameseg + 1]; + map++; + } + if (!pmbase) + { + verbose("No pmbase found in ACPI\n"); + return (cpu_map_error = 1); + } + if (processor_namespace == NAMESEG("_PR_")) + cpuNamespace = CPU_NAMESPACE_PR; + else if (processor_namespace == NAMESEG("_SB_")) + cpuNamespace = CPU_NAMESPACE_SB; + else + { + verbose("Found processors in invalid namespace; not _PR_ or _SB_\n"); + return (cpu_map_error = 1); + } + cpu_map_count = map - cpu_map; + +#if DEBUG_ACPI + verbose("Found %d processors in ACPI, pmbase : 0x%x, cpu_map_count : %d, namespace : ",acpi_processor_count, pmbase, cpu_map_count ); + print_nameseg(processor_namespace); + verbose("\n"); + U32 i; + verbose("Found processors name : \n" ); + for ( i = 0; i> 63; + q <<= 1; + if (r >= d) { + r -= d; + q |= 1; + } + } + if (rem) + *rem = r; + return q; +} + +static U32 compute_tdp(CPU_DETAILS * cpu) +{ + { + if (is_jaketown() || is_sandybridge()) + { + U64 power_limit_1 = cpu->package_power_limit & ((1ULL << 15) - 1); + U64 power_unit = cpu->package_power_sku_unit & ((1ULL << 4) - 1); + U64 tdp = divU64byU64(power_limit_1, 1 << power_unit, NULL); + return (U32)tdp; + } + else + { + // tdp = (TURBO_POWER_CURRENT_LIMIT MSR 1ACh bit [14:0] / 8) Watts + return cpu->tdp_limit / 8; + } + } + return (0); +} +#endif // BUILD_ACPI_TSS || pstate_power_support + +#if pstate_power_support +static U64 mulU64byU64(U64 a, U64 b, U64 * high) +{ + U64 b_high = 0; + U64 r_high = 0, r_low = 0; + U64 bit; + + for (bit = 1; bit; bit <<= 1) { + if (a & bit) { + if (r_low + b < r_low) + r_high++; + r_low += b; + r_high += b_high; + } + b_high <<= 1; + b_high |= (b & (1ULL << 63)) >> 63; + b <<= 1; + } + + if (high) + *high = r_high; + return r_low; +} + +static U32 compute_pstate_power(CPU_DETAILS * cpu, U32 ratio, U32 TDP) +{ + if (is_jaketown() || is_sandybridge()) + { + U32 P1_Ratio = cpu->max_ratio_as_mfg; + U64 M, pstate_power; + + // M = ((1.1 - ((P1_ratio - ratio) * 0.00625)) / 1.1) ^2 + // To prevent loss of precision compute M * 10^5 (preserves 5 decimal places) + M = (P1_Ratio - ratio) * 625; + M = (110000 - M); + M = divU64byU64(M, 11, NULL); + M = divU64byU64(mulU64byU64(M, M, NULL), 1000, NULL); + + // pstate_power = ((ratio/p1_ratio) * M * TDP) + // Divide the final answer by 10^5 to remove the precision factor + pstate_power = mulU64byU64(ratio, M, NULL); + pstate_power = mulU64byU64(pstate_power, TDP, NULL); + pstate_power = divU64byU64(pstate_power, P1_Ratio, NULL); + pstate_power = divU64byU64(pstate_power, 100000, NULL); + return (U32)pstate_power; // in Watts + } + else + { + // pstate_power[ratio] = (ratio/P1_ratio)^3 * Core_TDP + Uncore_TDP + + // Core_TDP = (TURBO_POWER_CURRENT_LIMIT MSR 1ACh bit [30:16] / 8) Watts + U32 Core_TDP = cpu->tdc_limit / 8; + + // Uncore_TDP = TDP - Core_TDP + U32 Uncore_TDP = TDP - Core_TDP; + + // max_ratio_as_mfg = P1_Ratio derived from Brand String returned by CPUID instruction + U32 P1_Ratio = cpu->max_ratio_as_mfg; + +#define PRECISION_FACTOR (U32) 30 +#define PRECISION_FACTOR_CUBED (U32) (PRECISION_FACTOR * PRECISION_FACTOR * PRECISION_FACTOR) + + U32 ratio_factor = (ratio * PRECISION_FACTOR)/P1_Ratio; + return ((ratio_factor * ratio_factor * ratio_factor * Core_TDP) / PRECISION_FACTOR_CUBED) + Uncore_TDP; + } + return (0); +} +#endif // pstate_power_support + +static U32 encode_pstate(U32 ratio) +{ + if (is_jaketown() || is_sandybridge()) + return ratio << 8; + return ratio; +} + +//----------------------------------------------------------------------------- +static void GetMaxRatio(U32 * max_non_turbo_ratio) +{ + U32 index; + U32 max_ratio=0; + U32 frequency=0; + U32 multiplier = 0; + char *BrandString; + // Verify CPUID brand string function is supported + if (Platform.CPU.CPUID[CPUID_80][0] < 80000004) + { + *max_non_turbo_ratio = max_ratio; + return; + } + BrandString = (char *)Platform.CPU.BrandString; + // -2 to prevent buffer overrun because looking for y in yHz, so z is +2 from y + for (index=0; index<48-2; index++) { + // format is either “x.xxyHz” or “xxxxyHz”, where y=M,G,T and x is digits + // Search brand string for “yHz” where y is M, G, or T + // Set multiplier so frequency is in MHz + if ( BrandString[index+1] == 'H' && BrandString[index+2] == 'z') + { + if (BrandString[index] == 'M') + multiplier = 1; + else if (BrandString[index] == 'G') + multiplier = 1000; + else if (BrandString[index] == 'T') + multiplier = 1000000; + } + if (multiplier > 0 && index >= 4 /* who can i call that, buffer underflow :-) ??*/) + { + // Copy 7 characters (length of “x.xxyHz”) + // index is at position of y in “x.xxyHz” + + // Compute frequency (in MHz) from brand string + if (BrandString[index-3] == '.') + { // If format is “x.xx” + if (isdigit(BrandString[index-4]) && isdigit(BrandString[index-2]) && + isdigit(BrandString[index-1])) + { + frequency = (U32)(BrandString[index-4] - '0') * multiplier; + frequency += (U32)(BrandString[index-2] - '0') * (multiplier / 10); + frequency += (U32)(BrandString[index-1] - '0') * (multiplier / 100); + } + } + else + { // If format is xxxx + if (isdigit(BrandString[index-4]) && isdigit(BrandString[index-3]) && + isdigit(BrandString[index-2]) && isdigit(BrandString[index-1])) + { + frequency = (U32)(BrandString[index-4] - '0') * 1000; + frequency += (U32)(BrandString[index-3] - '0') * 100; + frequency += (U32)(BrandString[index-2] - '0') * 10; + frequency += (U32)(BrandString[index-1] - '0'); + frequency *= multiplier; + } + + } + + max_ratio = frequency / get_bclk(); + break; + } + } + + // Return non-zero Max Non-Turbo Ratio obtained from CPUID brand string + // or return 0 indicating Max Non-Turbo Ratio not available + *max_non_turbo_ratio = max_ratio; +} + +//----------------------------------------------------------------------------- +static void collect_cpu_info(CPU_DETAILS * cpu) +{ + boolean_t dynamic_acceleration = 0; + U32 sub_Cstates = 0; + U32 extensions = 0; + boolean_t invariant_APIC_timer = 0; + boolean_t fine_grain_clock_mod = 0; + +#if BUILD_ACPI_TSS || pstate_power_support + if (Platform.CPU.CPUID[CPUID_0][0] >= 0x5) { + /* + * Extract the Monitor/Mwait Leaf info: + */ + sub_Cstates = Platform.CPU.CPUID[CPUID_5][3]; + extensions = Platform.CPU.CPUID[CPUID_5][2]; + } + + if (Platform.CPU.CPUID[CPUID_0][0] >= 6) { + dynamic_acceleration = bitfield(Platform.CPU.CPUID[CPUID_6][0], 1, 1); // "Dynamic Acceleration Technology (Turbo Mode)" + invariant_APIC_timer = bitfield(Platform.CPU.CPUID[CPUID_6][0], 2, 2); // "Invariant APIC Timer" + fine_grain_clock_mod = bitfield(Platform.CPU.CPUID[CPUID_6][0], 4, 4); + } + cpu->turbo_available = (U32)dynamic_acceleration; + + { + U32 temp32 = 0; + U64 temp64= 0; + int tdp; + if (getIntForKey("TDP", &tdp, &bootInfo->chameleonConfig)) + { + temp32 = (U32) (tdp*8) ; + + int tdc; + if (getIntForKey("TDC", &tdc, &bootInfo->chameleonConfig)) + { + temp32 = (U32) (temp32) | tdc<<16 ; + + } + else if (tdp) + { + temp32 = (U32) (temp32) | ((tdp)*8)<<16 ; + } + + } + else if (!is_sandybridge() && !is_jaketown()) + { + if (turbo_enabled && cpu->turbo_available) + { + temp64 = rdmsr64(MSR_TURBO_POWER_CURRENT_LIMIT); + temp32 = (U32)temp64; + } + else + { + // Unfortunately, Intel don't provide a better method for non turbo processors + // and it will give a TDP of 95w (for ex. mine is 65w) , to fix this issue, + // you can set this value by simply adding the option TDP = XX (XX is an integer) + // in your boot.plist + temp32 = (U32)0x02a802f8; + } + + } + if (temp32) { + cpu->tdp_limit = ( temp32 & 0x7fff ); + cpu->tdc_limit = ( (temp32 >> 16) & 0x7fff ); + } + } + +#endif + + switch (Platform.CPU.Family) + { + case 0x06: + { + switch (Platform.CPU.Model) + { + case CPU_MODEL_DOTHAN: + case CPU_MODEL_YONAH: // Yonah + case CPU_MODEL_MEROM: // Merom + case CPU_MODEL_PENRYN: // Penryn + case CPU_MODEL_ATOM: // Intel Atom (45nm) + { + + cpu->core_c1_supported = ((sub_Cstates >> 4) & 0xf) ? 1 : 0; + cpu->core_c4_supported = ((sub_Cstates >> 16) & 0xf) ? 1 : 0; + + if (Platform.CPU.Model == CPU_MODEL_ATOM) + { + cpu->core_c2_supported = cpu->core_c3_supported = ((sub_Cstates >> 8) & 0xf) ? 1 : 0; + cpu->core_c6_supported = ((sub_Cstates >> 12) & 0xf) ? 1 : 0; + + } + else + { + cpu->core_c3_supported = ((sub_Cstates >> 12) & 0xf) ? 1 : 0; + cpu->core_c2_supported = ((sub_Cstates >> 8) & 0xf) ? 1 : 0; + cpu->core_c6_supported = 0; + + } + + cpu->core_c7_supported = 0; + +#if BETA + GetMaxRatio(&cpu->max_ratio_as_mfg); + U64 msr = rdmsr64(MSR_IA32_PERF_STATUS); + U16 idlo = (msr >> 48) & 0xffff; + U16 idhi = (msr >> 32) & 0xffff; + cpu->min_ratio = (U32) (idlo >> 8) & 0xff; + cpu->max_ratio_as_cfg = (U32) (idhi >> 8) & 0xff; + +#else + if (Platform.CPU.MaxCoef) + { + if (Platform.CPU.MaxDiv) + { + cpu->max_ratio_as_cfg = cpu->max_ratio_as_mfg = (U32) (Platform.CPU.MaxCoef * 10) + 5; + } + else + { + cpu->max_ratio_as_cfg = cpu->max_ratio_as_mfg = (U32) Platform.CPU.MaxCoef * 10; + } + } +#endif + + break; + } + case CPU_MODEL_FIELDS: + case CPU_MODEL_DALES: + case CPU_MODEL_DALES_32NM: + case CPU_MODEL_NEHALEM: + case CPU_MODEL_NEHALEM_EX: + case CPU_MODEL_WESTMERE: + case CPU_MODEL_WESTMERE_EX: + case CPU_MODEL_SANDYBRIDGE: + case CPU_MODEL_JAKETOWN: + { + + cpu->core_c1_supported = ((sub_Cstates >> 4) & 0xf) ? 1 : 0; + cpu->core_c3_supported = ((sub_Cstates >> 8) & 0xf) ? 1 : 0; + cpu->core_c6_supported = ((sub_Cstates >> 12) & 0xf) ? 1 : 0; + cpu->core_c7_supported = ((sub_Cstates >> 16) & 0xf) ? 1 : 0; + cpu->core_c2_supported = 0; + cpu->core_c4_supported = 0; + + GetMaxRatio(&cpu->max_ratio_as_mfg); + U64 platform_info = rdmsr64(MSR_PLATFORM_INFO); + cpu->max_ratio_as_cfg = (U32) ((U32)platform_info >> 8) & 0xff; + cpu->min_ratio = (U32) ((platform_info >> 40) & 0xff); + + cpu->tdc_tdp_limits_for_turbo_flag = (platform_info & (1ULL << 29)) ? 1 : 0; + cpu->ratio_limits_for_turbo_flag = (platform_info & (1ULL << 28)) ? 1 : 0; + cpu->xe_available = cpu->tdc_tdp_limits_for_turbo_flag | cpu->ratio_limits_for_turbo_flag; + + + + if (is_sandybridge() || is_jaketown()) + { + cpu->package_power_limit = rdmsr64(MSR_PKG_RAPL_POWER_LIMIT); + cpu->package_power_sku_unit = rdmsr64(MSR_RAPL_POWER_UNIT); + } + break; + } + default: + verbose ("Unsupported CPU\n"); + return /*(0)*/; + break; + } + } + default: + break; + } + + cpu->mwait_supported = (extensions & (1UL << 0)) ? 1 : 0; + + cpu->invariant_apic_timer_flag = (U32)invariant_APIC_timer; + +#if DEBUG_ACPI + printf("CPU INFO : \n"); +#if BETA + printf("min_ratio : %d\n", cpu->min_ratio); +#endif + printf("max_ratio_as_cfg : %d\n", cpu->max_ratio_as_cfg); + printf("max_ratio_as_mfg : %d\n", cpu->max_ratio_as_mfg); + + printf("turbo_available : %d\n",cpu->turbo_available); + + printf("core_c1_supported : %d\n",cpu->core_c1_supported); + printf("core_c2_supported : %d\n",cpu->core_c1_supported); + printf("core_c3_supported : %d\n",cpu->core_c3_supported); + printf("core_c6_supported : %d\n",cpu->core_c6_supported); + printf("core_c7_supported : %d\n",cpu->core_c7_supported); + printf("mwait_supported : %d\n",cpu->mwait_supported); + +#if BUILD_ACPI_TSS || pstate_power_support + if (is_sandybridge() || is_jaketown()) + { + + printf("package_power_limit : %d\n",cpu->package_power_limit); + printf("package_power_sku_unit : %d\n",cpu->package_power_sku_unit); + + } +#endif + + DBG("invariant_apic_timer_flag : %d\n",cpu->invariant_apic_timer_flag); + + +#endif +} + +#if BETA +//----------------------------------------------------------------------------- +static U32 BuildPstateInfo(CPU_DETAILS * cpu) +{ + // Build P-state table info based on verified options + + // Compute the number of p-states based on the ratio range + cpu->pkg_pstates.num_pstates = computeNumPstates(cpu->max_ratio_as_cfg, cpu->min_ratio, cpu->turbo_available, MAX_PSTATES); + + if (!cpu->pkg_pstates.num_pstates) + { + return (0); + } + + // Compute pstate data + { + U32 TDP = compute_tdp(cpu); + + U32 index; + for (index=0; index < cpu->pkg_pstates.num_pstates; index ++) + { + PSTATE * pstate = &cpu->pkg_pstates.pstate[index]; + + // Set ratio + pstate->ratio = computePstateRatio(cpu->max_ratio_as_cfg, cpu->min_ratio, cpu->turbo_available, cpu->pkg_pstates.num_pstates, index); + + // Compute frequency based on ratio + if ((index != 0) || (cpu->turbo_available == 0)) + pstate->frequency = pstate->ratio * get_bclk(); + else + pstate->frequency = ((pstate->ratio - 1) * get_bclk()) + 1; + + // Compute power based on ratio and other data + if (pstate->ratio >= cpu->max_ratio_as_mfg) + // Use max power in mW + pstate->power = TDP * 1000; + else + { + pstate->power = compute_pstate_power(cpu, pstate->ratio, TDP); + + // Convert to mW + pstate->power*= 1000; + } + } + } + + return (1); +} +#else +/* + //----------------------------------------------------------------------------- + static U32 BuildCoreIPstateInfo(CPU_DETAILS * cpu) + { + // Build P-state table info based on verified options + + // Compute the number of p-states based on the ratio range + cpu->pkg_pstates.num_pstates = computeNumPstates(cpu->max_ratio_as_cfg, cpu->min_ratio, cpu->turbo_available, MAX_PSTATES); + + if (!cpu->pkg_pstates.num_pstates) + { + return (0); + } + + // Compute pstate data + { + #ifdef pstate_power_support + U32 TDP = compute_tdp(cpu); + #endif + + U32 index; + for (index=0; index < cpu->pkg_pstates.num_pstates; index ++) + { + PSTATE * pstate = &cpu->pkg_pstates.pstate[index]; + + // Set ratio + pstate->ratio = computePstateRatio(cpu->max_ratio_as_cfg, cpu->min_ratio, cpu->turbo_available, cpu->pkg_pstates.num_pstates, index); + + // Compute frequency based on ratio + if ((index != 0) || (cpu->turbo_available == 0)) + pstate->frequency = pstate->ratio * get_bclk(); + else + pstate->frequency = ((pstate->ratio - 1) * get_bclk()) + 1; + + #ifdef pstate_power_support + // Compute power based on ratio and other data + if (pstate->ratio >= cpu->max_ratio_as_mfg) + // Use max power in mW + pstate->power = TDP * 1000; + else + { + pstate->power = compute_pstate_power(cpu, pstate->ratio, TDP); + + // Convert to mW + pstate->power*= 1000; + } + #else + pstate->power = 0; + #endif + } + } + + return (1); + } + */ +//----------------------------------------------------------------------------- +static U32 BuildPstateInfo(CPU_DETAILS * cpu) +{ + + struct p_state p_states[32]; + U8 p_states_count = 0; + + if (!cpu) + { + return (0); + } + + { +#if UNUSED + struct p_state initial; +#endif + struct p_state maximum, minimum; + // Retrieving P-States, ported from code by superhai (c) + switch (Platform.CPU.Family) + { + case 0x06: + { + switch (Platform.CPU.Model) + { + case CPU_MODEL_DOTHAN: + case CPU_MODEL_YONAH: // Yonah + case CPU_MODEL_MEROM: // Merom + case CPU_MODEL_PENRYN: // Penryn + case CPU_MODEL_ATOM: // Intel Atom (45nm) + { + bool cpu_dynamic_fsb = false; + + if (rdmsr64(MSR_IA32_EXT_CONFIG) & (1 << 27)) + { + wrmsr64(MSR_IA32_EXT_CONFIG, (rdmsr64(MSR_IA32_EXT_CONFIG) | (1 << 28))); + delay(1); + cpu_dynamic_fsb = rdmsr64(MSR_IA32_EXT_CONFIG) & (1 << 28); + } + + bool cpu_noninteger_bus_ratio = (rdmsr64(MSR_IA32_PERF_STATUS) & (1ULL << 46)); +#if UNUSED + //initial.Control = rdmsr64(MSR_IA32_PERF_STATUS); +#endif + maximum.Control = ((rdmsr64(MSR_IA32_PERF_STATUS) >> 32) & 0x1F3F) | (0x4000 * cpu_noninteger_bus_ratio); + maximum.CID = ((maximum.FID & 0x1F) << 1) | cpu_noninteger_bus_ratio; + + minimum.FID = ((rdmsr64(MSR_IA32_PERF_STATUS) >> 24) & 0x1F) | (0x80 * cpu_dynamic_fsb); + minimum.VID = ((rdmsr64(MSR_IA32_PERF_STATUS) >> 48) & 0x3F); + + if (minimum.FID == 0) + { + U64 msr; + U8 i; + // Probe for lowest fid + for (i = maximum.FID; i >= 0x6; i--) + { + msr = rdmsr64(MSR_IA32_PERF_CONTROL); + wrmsr64(MSR_IA32_PERF_CONTROL, (msr & 0xFFFFFFFFFFFF0000ULL) | (i << 8) | minimum.VID); + intel_waitforsts(); + minimum.FID = (rdmsr64(MSR_IA32_PERF_STATUS) >> 8) & 0x1F; + delay(1); + } + + msr = rdmsr64(MSR_IA32_PERF_CONTROL); + wrmsr64(MSR_IA32_PERF_CONTROL, (msr & 0xFFFFFFFFFFFF0000ULL) | (maximum.FID << 8) | maximum.VID); + intel_waitforsts(); + } + + if (minimum.VID == maximum.VID) + { + U64 msr; + U8 i; + // Probe for lowest vid + for (i = maximum.VID; i > 0xA; i--) + { + msr = rdmsr64(MSR_IA32_PERF_CONTROL); + wrmsr64(MSR_IA32_PERF_CONTROL, (msr & 0xFFFFFFFFFFFF0000ULL) | (minimum.FID << 8) | i); + intel_waitforsts(); + minimum.VID = rdmsr64(MSR_IA32_PERF_STATUS) & 0x3F; + delay(1); + } + + msr = rdmsr64(MSR_IA32_PERF_CONTROL); + wrmsr64(MSR_IA32_PERF_CONTROL, (msr & 0xFFFFFFFFFFFF0000ULL) | (maximum.FID << 8) | maximum.VID); + intel_waitforsts(); + } + + minimum.CID = ((minimum.FID & 0x1F) << 1) >> cpu_dynamic_fsb; + + // Sanity check + if (maximum.CID < minimum.CID) + { + DBG("Insane FID values!"); + p_states_count = 0; + } + else + { + // Finalize P-States + // Find how many P-States machine supports + p_states_count = maximum.CID - minimum.CID + 1; + + if (p_states_count > MAX_PSTATES) // was 32 + p_states_count = MAX_PSTATES; // was 32 + + U8 vidstep; + U8 i = 0, u, invalid = 0; + + vidstep = ((maximum.VID << 2) - (minimum.VID << 2)) / (p_states_count - 1); + + U32 fsb = (U32)divU64byU64(Platform.CPU.FSBFrequency , 1000000 , NULL); + + for (u = 0; u < p_states_count; u++) + { + i = u - invalid; + + p_states[i].CID = maximum.CID - u; + p_states[i].FID = (p_states[i].CID >> 1); + + if (p_states[i].FID < 0x6) + { + if (cpu_dynamic_fsb) + p_states[i].FID = (p_states[i].FID << 1) | 0x80; + } + else if (cpu_noninteger_bus_ratio) + { + p_states[i].FID = p_states[i].FID | (0x40 * (p_states[i].CID & 0x1)); + } + + if (i && p_states[i].FID == p_states[i-1].FID) + invalid++; + + p_states[i].VID = ((maximum.VID << 2) - (vidstep * u)) >> 2; + + U32 multiplier = p_states[i].FID & 0x1f; // = 0x08 + bool half = p_states[i].FID & 0x40; // = 0x01 + bool dfsb = p_states[i].FID & 0x80; // = 0x00 + //U32 fsb = (U32)get_env(envFSBFreq) / 1000000; // = 400 + U32 halffsb = (fsb + 1) >> 1; // = 200 + U32 frequency = (multiplier * fsb); // = 3200 + + p_states[i].Frequency = (frequency + (half * halffsb)) >> dfsb; // = 3200 + 200 = 3400 + } + + p_states_count -= invalid; + } + break; + } + case CPU_MODEL_FIELDS: + case CPU_MODEL_DALES: + case CPU_MODEL_DALES_32NM: + case CPU_MODEL_NEHALEM: + case CPU_MODEL_NEHALEM_EX: + case CPU_MODEL_WESTMERE: + case CPU_MODEL_WESTMERE_EX: + case CPU_MODEL_SANDYBRIDGE: + case CPU_MODEL_JAKETOWN: + { + + maximum.Control = rdmsr64(MSR_IA32_PERF_STATUS) & 0xff; // Seems it always contains maximum multiplier value (with turbo, that's we need)... + minimum.Control = (rdmsr64(MSR_PLATFORM_INFO) >> 40) & 0xff; + + DBG("P-States: min 0x%x, max 0x%x\n", minimum.Control, maximum.Control); + + // Sanity check + if (maximum.Control < minimum.Control) + { + DBG("Insane control values!"); + p_states_count = 0; + } + else + { + U8 i; + p_states_count = 0; + U32 fsb = (U32)divU64byU64(Platform.CPU.FSBFrequency , 1000000, NULL) ; + for (i = maximum.Control; i >= minimum.Control; i--) + { + p_states[p_states_count].Control = i; + p_states[p_states_count].CID = p_states[p_states_count].Control << 1; + p_states[p_states_count].Frequency = (U32)fsb * i; + p_states_count++; + if (p_states_count >= MAX_PSTATES) { // was 32 + + if (p_states_count > MAX_PSTATES) // was 32 + p_states_count = MAX_PSTATES; // was 32 + + break; + } + } + } + + /* + U32 sta = BuildCoreIPstateInfo(cpu); + if (sta) + { + DBG("_PSS PGK generated successfully\n"); + return (1); + + } + else + { + verbose("CoreI _PSS Generation failed !!\n"); + return (0); + } + */ + break; + } + default: + verbose ("Unsupported CPU: P-States will not be generated !!!\n"); + return (0); + break; + } + } + default: + break; + } + } + + // Generating Pstate PKG + if (p_states_count > 0) + { + U32 fsb = (U32)Platform.CPU.FSBFrequency; + U8 minPSratio = divU64byU64(p_states[p_states_count-1].Frequency , divU64byU64(fsb , 10000000 , NULL ) , NULL); + U8 maxPSratio = divU64byU64(p_states[0].Frequency , divU64byU64(fsb , 10000000 , NULL ) , NULL); + U8 cpu_ratio = 0; + + { + U8 cpu_div = (U8)Platform.CPU.CurrDiv; + U8 cpu_coef = (U8)Platform.CPU.CurrCoef; + + if (cpu_div) + cpu_ratio = (cpu_coef * 10) + 5; + else + cpu_ratio = cpu_coef * 10; + } + + + { + int user_max_ratio = 0; + getIntForKey(kMaxRatio, &user_max_ratio, &bootInfo->chameleonConfig); + if (user_max_ratio >= minPSratio && maxPSratio >= user_max_ratio) + { + + U8 maxcurrdiv = 0, maxcurrcoef = (int)divU64byU64(user_max_ratio , 10, NULL); + + U8 maxdiv = user_max_ratio - (maxcurrcoef * 10); + if (maxdiv > 0) + maxcurrdiv = 1; + + if (maxcurrdiv) + cpu_ratio = (maxcurrcoef * 10) + 5; + else + cpu_ratio = maxcurrcoef * 10; + } + } + + { + int user_min_ratio = 0; + getIntForKey(kMinRatio, &user_min_ratio, &bootInfo->chameleonConfig); + if (user_min_ratio >= minPSratio && cpu_ratio >= user_min_ratio) + { + + U8 mincurrdiv = 0, mincurrcoef = (int)divU64byU64(user_min_ratio , 10 , NULL); + + U8 mindiv = user_min_ratio - (mincurrcoef * 10); + + if (mindiv > 0) + mincurrdiv = 1; + + if (mincurrdiv) + minPSratio = (mincurrcoef * 10) + 5; + else + minPSratio = mincurrcoef * 10; + + } + } + + + if (maxPSratio >= cpu_ratio && cpu_ratio >= minPSratio) maxPSratio = cpu_ratio; + + { + int base = 16; + U8 expert = 0; /* Default: 0 , mean mixed mode + * expert mode : 1 , mean add only p-states found in boot.plist + */ + + TagPtr PstateTag; + U32 pstate_tag_count = 0; + + { + + + if (bootInfo->chameleonConfig.dictionary) + { + PstateTag = XMLCastDict(XMLGetProperty(bootInfo->chameleonConfig.dictionary, (const char*)"P-States")); + if (PstateTag) pstate_tag_count = XMLTagCount(PstateTag) ; + } + + if (!pstate_tag_count) + if ((PstateTag = XMLCastDict(XMLGetProperty(bootInfo->chameleonConfig.dictionary, (const char*)"P-States")))) pstate_tag_count = XMLTagCount(PstateTag); + + + if ((pstate_tag_count > 0) && PstateTag) + { + char *tmpstr = XMLCastString(XMLGetProperty(PstateTag, (const char*)"Mode")); + + if (strcmp(tmpstr,"Expert") == 0) + { + p_states_count = pstate_tag_count - 1 ; // - 1 = - ("Mode" tag) + expert = 1; + } + + + if ((tmpstr = XMLCastString(XMLGetProperty(PstateTag, (const char*)"Base")))) + { + + if (expert) p_states_count--; // -= ("Base" tag) + + int mybase = strtol(tmpstr, NULL, 10); + + if (mybase == 8 || mybase == 10 || mybase == 16 ) + base = mybase; + } + } + + } + + { + U32 dropPSS = 0, Pstatus = 0; + char MatchStat[5]; +#ifdef pstate_power_support + U32 TDP = compute_tdp(cpu); +#endif + U32 i; + U32 fsb = (U32)Platform.CPU.FSBFrequency; + for (i = 0; i < p_states_count; i++) + { + char *Lat1 = NULL, *clk = NULL, *Pw = NULL, *Lat2 = NULL, *Ctrl = NULL ; + + if ((pstate_tag_count > 0) && PstateTag) + { + sprintf(MatchStat, "%d",i); + TagPtr match_Status = XMLGetProperty(PstateTag, (const char*)MatchStat); + + if (match_Status && (XMLTagCount(match_Status) > 0)) + { + + clk = XMLCastString(XMLGetProperty(match_Status, (const char*)"CoreFreq")); + Pw = XMLCastString(XMLGetProperty(match_Status, (const char*)"Power")); + Lat1 = XMLCastString(XMLGetProperty(match_Status, (const char*)"Transition Latency")); + Lat2 = XMLCastString(XMLGetProperty(match_Status, (const char*)"Bus Master Latency")); + Ctrl = XMLCastString(XMLGetProperty(match_Status, (const char*)"Control")); + + + } else if (expert) + continue; + } + + unsigned long Frequency = 0x00000000; + + if (!expert || !pstate_tag_count) Frequency = p_states[i].Frequency; + + if (clk) + Frequency = strtoul((const char *)clk, NULL,base); + + if (!Frequency || Frequency > p_states[0].Frequency ) continue; + + U8 curr_ratio = (U8)divU64byU64(Frequency , divU64byU64(fsb , 10000000, NULL ), NULL); + + + { + U8 fixed_ratio = (U8)divU64byU64(Frequency , divU64byU64(fsb , 1000000 , NULL ) , NULL) * 10; + U8 diff = curr_ratio - fixed_ratio ; + + if (diff) + { + if (diff < 5) + { + curr_ratio = fixed_ratio; + } + else + { + curr_ratio = fixed_ratio + 5; + } + } + + } + + if (curr_ratio > maxPSratio || minPSratio > curr_ratio) + goto dropPstate; + + { + PSTATE * pstate = &cpu->pkg_pstates.pstate[Pstatus]; + + pstate->ratio = curr_ratio; + + pstate->frequency = Frequency; // CoreFreq (in MHz). + + U32 power = 0x00000000; +#ifdef pstate_power_support + // Compute power based on ratio and other data + if (pstate->ratio >= cpu->max_ratio_as_mfg) + // Use max power in mW + power = TDP * 1000; + else + { + power = compute_pstate_power(cpu, pstate->ratio, TDP); + + // Convert to mW + power*= 1000; + } +#endif + pstate->power = resolve_pss(power, Pw, base); // Power (in milliWatts) + pstate->translatency = resolve_pss(0x0000000A, Lat1, base); // Transition Latency (in microseconds). + pstate->bmlatency = resolve_pss(0x0000000A, Lat2, base); // Bus Master Latency (in microseconds). + + { + U32 Control = 0 /*encode_pstate(curr_ratio)*/ ; + if (!expert || !pstate_tag_count) Control = p_states[i].Control; + pstate->control = resolve_pss(Control, Ctrl, base); // Control + } + + pstate->status = Pstatus+1; // Status + + DBG("state :: frequency :%d power: %d translatency: %d bmlatency: %d control: %d status: %d ratio :%d :: registred !! \n",pstate->frequency,pstate->power, + pstate->translatency,pstate->bmlatency,pstate->control,pstate->status,pstate->ratio ); + } + + + Pstatus++; + continue; + + dropPstate: + DBG("state with cpu frequency :%d and ratio :%d will be dropped\n",p_states[i].Frequency,curr_ratio); + dropPSS++; + + + } + + if (Pstatus == 0) + { + verbose("No suitable P-states found, P-States will not be generated !!!\n"); + return (0); + } + cpu->pkg_pstates.num_pstates = Pstatus; + } + } + } + else + { + verbose("ACPI CPUs not found: P-States will not be generated !!!\n"); + return (0); + } + + DBG("_PSS PGK generated successfully\n"); + return (1); +} +#endif // BETA + +//----------------------------------------------------------------------------- +static U32 BuildCstateInfo(CPU_DETAILS * cpu, U32 pmbase) +{ + { + + TagPtr CstateTag; + U32 entry_count = 0; + + if (bootInfo->chameleonConfig.dictionary) + { + CstateTag = XMLCastDict(XMLGetProperty(bootInfo->chameleonConfig.dictionary, (const char*)"C-States")); + } + + if (CstateTag) + { + int base = 16; + + entry_count = XMLTagCount(CstateTag); + + if (entry_count > 0) + { + { + char *tmpstr; + + if ((tmpstr = XMLCastString(XMLGetProperty(CstateTag, (const char*)"Base")))) + { + + entry_count--; // -= ("Base" tag) + + int mybase = strtol(tmpstr, NULL, 10); + + if (mybase == 8 || mybase == 10 || mybase == 16 ) + base = mybase; + } + } + + cpu->pkg_io_cstates.num_cstates = 0; + cpu->pkg_mwait_cstates.num_cstates = 0; + U32 num_cstates = 0; + + { + U32 i; + char MatchStat[5]; + + for (i = 0; i < 32 ; i++) + { + char *Lat = NULL, *Pw = NULL, *BWidth= NULL, *BOffset= NULL, *Address= NULL, *AccessSize= NULL, *index= NULL; + + sprintf(MatchStat, "C%d",i); + TagPtr match_Status = XMLGetProperty(CstateTag, (const char*)MatchStat); + if (match_Status) + { + Pw = XMLCastString(XMLGetProperty(match_Status, (const char*)"Power")); + Lat = XMLCastString(XMLGetProperty(match_Status, (const char*)"Latency")); + BWidth= XMLCastString(XMLGetProperty(match_Status, (const char*)"BitWidth")); + + BOffset = XMLCastString(XMLGetProperty(match_Status, (const char*)"BitOffset")); + Address = XMLCastString(XMLGetProperty(match_Status, (const char*)"Latency")); + AccessSize = XMLCastString(XMLGetProperty(match_Status, (const char*)"AccessSize")); + index = XMLCastString(XMLGetProperty(match_Status, (const char*)"index")); + + if (Pw && Lat && BWidth && BOffset && Address && AccessSize && index) + { + U32 bw = strtoul((const char *)BWidth, NULL,base); + U32 boff = strtoul((const char *)BOffset, NULL,base); + U32 acs = strtoul((const char *)AccessSize, NULL,base); + U32 addr = strtoul((const char *)Address, NULL,base); + U32 idx = strtoul((const char *)index, NULL,base); + U32 lat = strtoul((const char *)Lat, NULL,base); + U32 pw = strtoul((const char *)Pw, NULL,base); + + ACPI_GENERIC_ADDRESS mwait_gas = {GAS_TYPE_FFH,bw,boff,acs,addr}; + ACPI_GENERIC_ADDRESS io_gas = {(i == 1) ? GAS_TYPE_FFH : GAS_TYPE_SYSTEM_IO,bw,boff,acs,addr}; + + CSTATE mwait_cstate = {idx,lat,pw}; + CSTATE io_cstate = {idx,lat,pw}; + + { + cpu->pkg_mwait_cstates.cstate[cpu->pkg_mwait_cstates.num_cstates] = mwait_cstate; + cpu->pkg_mwait_cstates.gas[cpu->pkg_mwait_cstates.num_cstates] = mwait_gas; + cpu->pkg_mwait_cstates.num_cstates++; + } + + { + cpu->pkg_io_cstates.cstate[cpu->pkg_io_cstates.num_cstates] = io_cstate; + cpu->pkg_io_cstates.gas[cpu->pkg_io_cstates.num_cstates] = io_gas; + cpu->pkg_io_cstates.num_cstates++; + } + num_cstates++; + + if (num_cstates >= MAX_CSTATES) + { + break; + } + } + } + } + } + + if (num_cstates) + { + return (1); + } + } + } + } + + { + static const ACPI_GENERIC_ADDRESS mwait_gas[] = { + {GAS_TYPE_FFH,1,2,1,0x00}, // processor C1 + {GAS_TYPE_FFH,1,2,1,0x10}, // processor C3 as ACPI C2 + {GAS_TYPE_FFH,1,2,1,0x10}, // processor C3 as ACPI C3 + {GAS_TYPE_FFH,1,2,1,0x10}, // processor C3 as ACPI C4 + {GAS_TYPE_FFH,1,2,1,0x20}, // processor C6 + {GAS_TYPE_FFH,1,2,1,0x30}, // processor C7 + }; + + static const ACPI_GENERIC_ADDRESS io_gas[] = { + {GAS_TYPE_FFH, 0,0,0,0x00}, // processor C1 + {GAS_TYPE_SYSTEM_IO,8,0,0,0x14}, // processor C3 as ACPI C2 or processor C2 + {GAS_TYPE_SYSTEM_IO,8,0,0,0x14}, // processor C3 as ACPI C3 + {GAS_TYPE_SYSTEM_IO,8,0,0,0x15}, // processor C4 as ACPI C4 + {GAS_TYPE_SYSTEM_IO,8,0,0,0x15}, // processor C6 + {GAS_TYPE_SYSTEM_IO,8,0,0,0x16}, // processor C7 + }; + + static const CSTATE mwait_cstate [] = { + {1,0x01,0x3e8}, // processor C1 + {2,0x40,0x1f4}, // processor C3 as ACPI C2 or processor C2 + {3,0x40,0x1f4}, // processor C3 as ACPI C3 + {4,0x40,0x1f4}, // processor C4 + {6/*was 3*/,0x60,0x15e}, // processor C6 + {7/*was 3*/,0x60,0x0c8}, // processor C7 + }; + + static const CSTATE io_cstate [] = { + {1,0x01,0x3e8}, // processor C1 + {2,0x40,0x1f4}, // processor C3 as ACPI C2 or processor C2 + {3,0x40,0x1f4}, // processor C3 as ACPI C3 + {4,0x40,0x1f4}, // processor C4 + {6/*was 3*/,0x60,0x15e}, // processor C6 + {7/*was 3*/,0x60,0x0c8}, // processor C7 + }; + + static const U32 cstate_2_index [] = {0,0,0,1,2,3,4,5}; + + // Build C-state table info based on verified options + + // Desired state for the processor core C3 state included in the _CST as an + // ACPI C2 state. + // 1= processor core C3 can be used as an ACPI C2 state + // 0= processor core C3 cannot be used as an ACPI C2 state + int c2_enabled = 0; + + // Desired state for the processor core C3 state included in the _CST + // 0= processor core C3 cannot be used as an ACPI C state + // 2= processor core C3 can be used as an ACPI C2 state + // 3= processor core C3 can be used as an ACPI C3 state + // 4= processor core C3 can be used as an ACPI C2 state + // if Invariant APIC Timer detected, else not used as ACPI C state + // 5= processor core C3 can be used as an ACPI C2 state + // if Invariant APIC Timer detected, else APIC C3 state + // 6= processor core C3 can be used as an ACPI C4 state + int c3_enabled = 3; + + // Desired state for the processor core C3 state included in the _CST as an + // ACPI C4 state. + // 1= processor core C3 can be used as an ACPI C4 state + // 0= processor core C3 cannot be used as an ACPI C4 state + int c4_enabled = 0; + + // Desired state for the processor core C6 state included in the _CST as an + // ACPI C3 state. + // 1= processor core C6 can be used as an ACPI C3 state + // 0= processor core C6 cannot be used as an ACPI C3 state + int c6_enabled = 0; + + // Desired state for the processor core C7 state included in the _CST as an + // ACPI C3 state. + // 1= processor core C7 can be used as an ACPI C7 state + // 0= processor core C7 cannot be used as an ACPI C7 state + int c7_enabled = 0; + + { + bool tmpval; + + + if (getBoolForKey(kEnableC2State, &tmpval, &bootInfo->chameleonConfig)) + { + c2_enabled = tmpval; + } + + if (!getIntForKey("C3StateOption", &c3_enabled, &bootInfo->chameleonConfig)) + { + c3_enabled = (getBoolForKey(kEnableC3State, &tmpval, &bootInfo->chameleonConfig)&&tmpval) ? 3 : 0; + } + if (c3_enabled == 6) + { + c4_enabled = 1; + } + else + { + c4_enabled = (getBoolForKey(kEnableC4State, &tmpval, &bootInfo->chameleonConfig)&&tmpval) ? 1 : 0; + } + c6_enabled = (getBoolForKey(kEnableC6State, &tmpval, &bootInfo->chameleonConfig)&&tmpval) ? 1 : 0; + c7_enabled = (getBoolForKey(kEnableC7State, &tmpval, &bootInfo->chameleonConfig)&&tmpval) ? 1 : 0; + } + + cpu->pkg_mwait_cstates.num_cstates = 0; + { + { + cpu->pkg_mwait_cstates.cstate[cpu->pkg_mwait_cstates.num_cstates] = mwait_cstate[cstate_2_index[CPU_C1]]; + cpu->pkg_mwait_cstates.gas[cpu->pkg_mwait_cstates.num_cstates] = mwait_gas[cstate_2_index[CPU_C1]]; + cpu->pkg_mwait_cstates.num_cstates++; + } + if (((cpu->core_c3_supported || cpu->core_c2_supported) && (c2_enabled)) && ((c3_enabled == 2) || + ((c3_enabled == 4) && cpu->invariant_apic_timer_flag))) + { + cpu->pkg_mwait_cstates.cstate[cpu->pkg_mwait_cstates.num_cstates] = mwait_cstate[cstate_2_index[CPU_C3_ACPI_C2]]; + cpu->pkg_mwait_cstates.gas[cpu->pkg_mwait_cstates.num_cstates] = mwait_gas[cstate_2_index[CPU_C3_ACPI_C2]]; + cpu->pkg_mwait_cstates.num_cstates++; + } + if (cpu->core_c4_supported && c4_enabled) + { + + cpu->pkg_mwait_cstates.cstate[cpu->pkg_mwait_cstates.num_cstates] = mwait_cstate[cstate_2_index[CPU_C4]]; + cpu->pkg_mwait_cstates.gas[cpu->pkg_mwait_cstates.num_cstates] = mwait_gas[cstate_2_index[CPU_C4]]; + cpu->pkg_mwait_cstates.num_cstates++; + + } + else + { + + if (cpu->core_c3_supported && ((c3_enabled == 3) || + ((c3_enabled == 4) && !cpu->invariant_apic_timer_flag))) + { + cpu->pkg_mwait_cstates.cstate[cpu->pkg_mwait_cstates.num_cstates] = mwait_cstate[cstate_2_index[CPU_C3_ACPI_C3]]; + cpu->pkg_mwait_cstates.gas[cpu->pkg_mwait_cstates.num_cstates] = mwait_gas[cstate_2_index[CPU_C3_ACPI_C3]]; + cpu->pkg_mwait_cstates.num_cstates++; + } + } + + + if (cpu->core_c6_supported && c6_enabled) + { + cpu->pkg_mwait_cstates.cstate[cpu->pkg_mwait_cstates.num_cstates] = mwait_cstate[cstate_2_index[CPU_C6]]; + cpu->pkg_mwait_cstates.gas[cpu->pkg_mwait_cstates.num_cstates] = mwait_gas[cstate_2_index[CPU_C6]]; + cpu->pkg_mwait_cstates.num_cstates++; + } + if (cpu->core_c7_supported && c7_enabled) + { + cpu->pkg_mwait_cstates.cstate[cpu->pkg_mwait_cstates.num_cstates] = mwait_cstate[cstate_2_index[CPU_C7]]; + cpu->pkg_mwait_cstates.gas[cpu->pkg_mwait_cstates.num_cstates] = mwait_gas[cstate_2_index[CPU_C7]]; + cpu->pkg_mwait_cstates.num_cstates++; + } + } + + cpu->pkg_io_cstates.num_cstates = 0; + { + { + cpu->pkg_io_cstates.cstate[cpu->pkg_io_cstates.num_cstates] = io_cstate[cstate_2_index[CPU_C1]]; + cpu->pkg_io_cstates.gas[cpu->pkg_io_cstates.num_cstates] = io_gas[cstate_2_index[CPU_C1]]; + cpu->pkg_io_cstates.num_cstates++; + } + if ((cpu->core_c3_supported || cpu->core_c2_supported) && (c2_enabled || (c3_enabled == 2) || + ((c3_enabled == 4) && cpu->invariant_apic_timer_flag))) + { + cpu->pkg_io_cstates.cstate[cpu->pkg_io_cstates.num_cstates] = io_cstate[cstate_2_index[CPU_C3_ACPI_C2]]; + cpu->pkg_io_cstates.gas[cpu->pkg_io_cstates.num_cstates] = io_gas[cstate_2_index[CPU_C3_ACPI_C2]]; + cpu->pkg_io_cstates.gas[cpu->pkg_io_cstates.num_cstates].Address += pmbase; + cpu->pkg_io_cstates.num_cstates++; + } + if (cpu->core_c4_supported && c4_enabled) + { + + cpu->pkg_io_cstates.cstate[cpu->pkg_io_cstates.num_cstates] = io_cstate[cstate_2_index[CPU_C4]]; + cpu->pkg_io_cstates.gas[cpu->pkg_io_cstates.num_cstates] = io_gas[cstate_2_index[CPU_C4]]; + cpu->pkg_io_cstates.gas[cpu->pkg_io_cstates.num_cstates].Address += pmbase; + cpu->pkg_io_cstates.num_cstates++; + + } + else + { + + if (cpu->core_c3_supported && ((c3_enabled == 3) || + ((c3_enabled == 4) && !cpu->invariant_apic_timer_flag))) + { + cpu->pkg_io_cstates.cstate[cpu->pkg_io_cstates.num_cstates] = io_cstate[cstate_2_index[CPU_C3_ACPI_C3]]; + cpu->pkg_io_cstates.gas[cpu->pkg_io_cstates.num_cstates] = io_gas[cstate_2_index[CPU_C3_ACPI_C3]]; + cpu->pkg_io_cstates.gas[cpu->pkg_io_cstates.num_cstates].Address += pmbase; + cpu->pkg_io_cstates.num_cstates++; + } + } + + if (cpu->core_c6_supported && c6_enabled) + { + cpu->pkg_io_cstates.cstate[cpu->pkg_io_cstates.num_cstates] = io_cstate[cstate_2_index[CPU_C6]]; + cpu->pkg_io_cstates.gas[cpu->pkg_io_cstates.num_cstates] = io_gas[cstate_2_index[CPU_C6]]; + cpu->pkg_io_cstates.gas[cpu->pkg_io_cstates.num_cstates].Address += pmbase; + cpu->pkg_io_cstates.num_cstates++; + } + if (cpu->core_c7_supported && c7_enabled) + { + cpu->pkg_io_cstates.cstate[cpu->pkg_io_cstates.num_cstates] = io_cstate[cstate_2_index[CPU_C7]]; + cpu->pkg_io_cstates.gas[cpu->pkg_io_cstates.num_cstates] = io_gas[cstate_2_index[CPU_C7]]; + cpu->pkg_io_cstates.gas[cpu->pkg_io_cstates.num_cstates].Address += pmbase; + cpu->pkg_io_cstates.num_cstates++; + } + } + } + + return (1); +} + +#if BUILD_ACPI_TSS +//----------------------------------------------------------------------------- +static U32 BuildTstateInfo(CPU_DETAILS * cpu) +{ + // Coarse grained clock modulation is available if cpuid.6.eax[5] = 0 + // Max of 8 T-states using 12.5% increments + static const TSTATE tstate_coarse_grain [] = { + {100,0,0,0x00,0}, + { 88,0,0,0x1e,0}, + { 75,0,0,0x1c,0}, + { 63,0,0,0x1a,0}, + { 50,0,0,0x18,0}, + { 38,0,0,0x16,0}, + { 25,0,0,0x14,0}, + { 13,0,0,0x12,0}, + }; + + // Fine grained clock modulation is available if cpuid.6.eax[5] = 1 + // Max of 15 T-states using 6.25% increments + static const TSTATE tstate_fine_grain [] = { + {100,0,0,0x00,0}, + { 94,0,0,0x1f,0}, + { 88,0,0,0x1e,0}, + { 81,0,0,0x1d,0}, + { 75,0,0,0x1c,0}, + { 69,0,0,0x1b,0}, + { 63,0,0,0x1a,0}, + { 56,0,0,0x19,0}, + { 50,0,0,0x18,0}, + { 44,0,0,0x17,0}, + { 38,0,0,0x16,0}, + { 31,0,0,0x15,0}, + { 25,0,0,0x14,0}, + { 19,0,0,0x13,0}, + { 13,0,0,0x12,0}, + }; + + // Build T-state table info based on verified options + U32 num_cpu; + const TSTATE * tstate; + U32 num_tstates; + + for (num_cpu = 0; num_cpu < cpu_map_count; num_cpu ++) + { + // Check if fine or coarse grained clock modulation is available + if (get_env(envFineGrainClockMod)) + { + // Fine grain thermal throttling is available + num_tstates = 15; + tstate = tstate_fine_grain; + } + else + { + // Coarse grain thermal throttling is available + num_tstates = 8; + tstate = tstate_coarse_grain; + } + + cpu->pkg_tstates.num_tstates = num_tstates; + { + U32 index; + for (index = 0; index < num_tstates; index++) + { + cpu->pkg_tstates.tstate[index] = tstate[index]; + cpu->pkg_tstates.tstate[index].power = 1000 * (compute_tdp(cpu) * (num_tstates - index)) / num_tstates; + } + } + + + } + return (1); +} +#endif // BUILD_ACPI_TSS + +//----------------------------------------------------------------------------- +U32 ProcessMadt(ACPI_TABLE_MADT * madt, MADT_INFO * madt_info, void * buffer, U32 bufferSize, U32 nb_cpu) +{ + void *current; + void *currentOut; + void *end; + void * endOut; + + U32 LOCAL_APIC_NMI_CNT = 0, LOCAL_SAPIC_CNT = 0, INT_SRC_CNT = 0, Length = 0; + + // Quick sanity check for a valid MADT + if (madt == 0ul || !nb_cpu) + return (0); + + // Confirm a valid MADT buffer was provided + if (!buffer) + { + printf("Error: Invalid Buffer Address for MADT\n"); + return(0); + } + + // Confirm a valid MADT buffer length was provided + if (!bufferSize) + { + printf("Error: Invalid Buffer Length for MADT\n"); + return(0); + } + + madt_info->lapic_count = 0; + + memcpy(buffer, madt, sizeof(ACPI_TABLE_MADT)); + + // Search MADT for Sub-tables with needed data + current = madt + 1; + currentOut = buffer + sizeof(ACPI_TABLE_MADT) ; + + end = (U8 *) madt + madt->Header.Length; + endOut = (U8 *)buffer + bufferSize; + + // Check to confirm no MADT buffer overflow + if ( (U8 *)currentOut > (U8 *)endOut ) + { + printf("Error: MADT Buffer Length exceeded available space \n"); + return(0); + } + + Length += sizeof(ACPI_TABLE_MADT); + + while (current < end) + { + ACPI_SUBTABLE_HEADER *subtable = current; + ACPI_SUBTABLE_HEADER *subtableOut = currentOut; + + + switch (subtable->Type) + { + + case ACPI_MADT_TYPE_LOCAL_APIC: + { + + // Process sub-tables with Type as 0: Processor Local APIC + ACPI_MADT_LOCAL_APIC *lapic = current; + current = lapic + 1; + + if (!(lapic->LapicFlags & ACPI_MADT_ENABLED)) + continue; + + if (madt_info->lapic_count >= nb_cpu) + continue; + + // copy subtable + { + + memcpy(currentOut, lapic, lapic->Header.Length); + + currentOut = currentOut + lapic->Header.Length; + + // Check to confirm no MADT buffer overflow + if ( (U8 *)currentOut > (U8 *)endOut ) + { + printf("Error: MADT Buffer Length exceeded available space \n"); + return(0); + } + } + + { + LAPIC_INFO *lapic_info = &madt_info->lapic[madt_info->lapic_count]; + + lapic_info->processorId = lapic->ProcessorId; + lapic_info->apicId = lapic->Id; + lapic_info->madt_type = ACPI_MADT_TYPE_LOCAL_APIC; + } + + madt_info->lapic_count++; + + Length += lapic->Header.Length; + + // Sanity check to verify compile time limit for max logical CPU is not exceeded + if (madt_info->lapic_count > MAX_LOGICAL_CPU) + return (0); + + break; + } + + case ACPI_MADT_TYPE_X2APIC: + { + + // Process sub-tables with Type as 9: Processor X2APIC + ACPI_MADT_X2APIC *x2apic = current; + current = x2apic + 1; + + if (!(x2apic->x2apicFlags & ACPI_MADT_ENABLED)) + continue; + + if (madt_info->lapic_count >= nb_cpu) + continue; + + // copy subtable + { + memcpy(currentOut, x2apic, x2apic->Header.Length); + + currentOut = currentOut + x2apic->Header.Length; + + // Check to confirm no MADT buffer overflow + if ( (U8 *)currentOut > (U8 *)endOut ) + { + printf("Error: MADT Buffer Length exceeded available space \n"); + return(0); + } + + } + + { + LAPIC_INFO *lapic_info = &madt_info->lapic[madt_info->lapic_count]; + + lapic_info->uid = x2apic->UID; + lapic_info->apicId = x2apic->x2apicId; + lapic_info->madt_type = ACPI_MADT_TYPE_X2APIC; + } + + madt_info->lapic_count++; + + Length += x2apic->Header.Length; + + // Sanity check to verify compile time limit for max logical CPU is not exceeded + if (madt_info->lapic_count > MAX_LOGICAL_CPU) + return (0); + + break; + } + + case ACPI_MADT_TYPE_LOCAL_APIC_NMI: + { + // Process sub-tables with Type as 4: Local APIC NMI + ACPI_MADT_LOCAL_APIC_NMI *nmi = current; + current = nmi + 1; + /* + if (!(nmi->IntiFlags & ACPI_MADT_ENABLED)) + continue; + */ + if (LOCAL_APIC_NMI_CNT >= nb_cpu) + continue; + + memcpy(currentOut, nmi, nmi->Header.Length); + + currentOut = currentOut + nmi->Header.Length; + + // Check to confirm no MADT buffer overflow + if ( (U8 *)currentOut > (U8 *)endOut ) + { + printf("Error: MADT Buffer Length exceeded available space \n"); + return(0); + } + + + LOCAL_APIC_NMI_CNT++; + + Length += nmi->Header.Length; + + // Sanity check to verify compile time limit for max logical CPU is not exceeded + if (LOCAL_APIC_NMI_CNT > MAX_LOGICAL_CPU) + return (0); + + break; + } + + case ACPI_MADT_TYPE_LOCAL_SAPIC: + { + // Process sub-tables with Type as 7: Local Sapic + ACPI_MADT_LOCAL_SAPIC *sapic = current; + current = sapic + 1; + /* + if (!(sapic->LapicFlags & ACPI_MADT_ENABLED)) + continue; + */ + if (LOCAL_SAPIC_CNT >= nb_cpu) + continue; + + memcpy(currentOut, sapic, sapic->Header.Length); + + currentOut = currentOut + sapic->Header.Length; + + // Check to confirm no MADT buffer overflow + if ( (U8 *)currentOut > (U8 *)endOut ) + { + printf("Error: MADT Buffer Length exceeded available space \n"); + return(0); + } + + + LOCAL_SAPIC_CNT++; + + Length += sapic->Header.Length; + + // Sanity check to verify compile time limit for max logical CPU is not exceeded + if (LOCAL_SAPIC_CNT > MAX_LOGICAL_CPU) + return (0); + + break; + } + + case ACPI_MADT_TYPE_INTERRUPT_SOURCE: + { + // Process sub-tables with Type as 8: Platform Interrupt Source + ACPI_MADT_INTERRUPT_SOURCE *intsrc = current; + current = intsrc + 1; + /* + if (!(intsrc->IntiFlags & ACPI_MADT_ENABLED)) + continue; + */ + if (INT_SRC_CNT >= nb_cpu) + continue; + + memcpy(currentOut, intsrc, intsrc->Header.Length); + + currentOut = currentOut + intsrc->Header.Length; + + // Check to confirm no MADT buffer overflow + if ( (U8 *)currentOut > (U8 *)endOut ) + { + printf("Error: MADT Buffer Length exceeded available space \n"); + return(0); + } + + + INT_SRC_CNT++; + + Length += intsrc->Header.Length; + + // Sanity check to verify compile time limit for max logical CPU is not exceeded + if (INT_SRC_CNT > MAX_LOGICAL_CPU) + return (0); + + break; + } + + default: + { + + // Process all other sub-tables + current = (U8 *) subtable + subtable->Length; + currentOut = (U8 *) subtableOut + subtable->Length; + + memcpy(subtableOut, subtable, subtable->Length); + + // Check to confirm no MADT buffer overflow + if ( (U8 *)currentOut > (U8 *)endOut ) + { + printf("Error: MADT Buffer Length exceeded available space \n"); + return(0); + } + + Length += subtable->Length; + + break; + } + } // switch + + } // while + + { + ACPI_TABLE_MADT * new_madt = (ACPI_TABLE_MADT * )buffer; + + // Update the Lenght of the new MADT table + new_madt->Header.Length = Length; + + // Update the checksum of the new MADT table + SetChecksum(&new_madt->Header); + } + + return (1); +} + +static U32 buildMADT(U32 * new_table_list, ACPI_TABLE_DSDT *dsdt, MADT_INFO * madt_info) +{ + DBG("Build MADT\n"); + + ACPI_TABLE_MADT * madt_file = (void*)0ul; + ACPI_TABLE_MADT * MadtPointer = (void*)0ul; + bool oem_apic=false; + U8 new_table_index = 0; + + // Check that we have a valid cpu_map (if it's not already done, it will try to generate it) + if (generate_cpu_map_from_acpi(dsdt) != 0) + { + return(0); + } + + { + bool tmpval; + oem_apic=getBoolForKey(kOEMAPIC, &tmpval, &bootInfo->chameleonConfig)&&tmpval; + } + + if (oem_apic == true) + { + return(0); + } + + if ((madt_file = (ACPI_TABLE_MADT *)get_new_table_in_list(new_table_list, NAMESEG("APIC"), &new_table_index)) != (void *)0ul) + { + MadtPointer = (ACPI_TABLE_MADT *)madt_file; + + new_table_list[new_table_index] = 0ul; // This way, the non-patched table will not be added in our new rsdt/xsdt table list + } + else + { + MadtPointer = (acpi_tables.MadtPointer64 != (void*)0ul) ? (ACPI_TABLE_MADT *)acpi_tables.MadtPointer64 : (ACPI_TABLE_MADT *)acpi_tables.MadtPointer; + + new_table_index = get_0ul_index_in_list(new_table_list, true); + + // Check to confirm space is available + if (new_table_index == ACPI_TABLE_LIST_FULL) + { + printf("Error: not enought reserved space in the new acpi list for the MADT table,\n "); + printf(" please increase the RESERVED_AERA\n"); + return(0); + } + } + + // Create buffer for MADT + //U8 memory_for_madt[2 * 1024]; // seems to bug with xcode4, need to found out what is going on (not enough memory in the stack ?) + U8 *memory_for_madt = (U8*)AllocateKernelMemory(2 * 1024); + + // Build the new MADT + if ( (ProcessMadt(MadtPointer, madt_info, memory_for_madt, 2 * 1024, cpu_map_count))== 0) + { + printf("Error: Failed to build MADT table\n"); + return (0); + } + + // insert MADT in the new_table_list + { + // Create pointer to MADT just built in the stack buffer + ACPI_TABLE_MADT * old_madt = (ACPI_TABLE_MADT *)memory_for_madt; + + // Reserved kernel memory for the madt table + ACPI_TABLE_MADT *new_madt = (ACPI_TABLE_MADT *)AllocateKernelMemory(old_madt->Header.Length); + + if (!new_madt) + { + printf("Unable to allocate kernel memory for MADT "); + return (0); + } + // Move the old stack buffer to kernel memory + memcpy(new_madt, old_madt, old_madt->Header.Length); + + // Add the new madt into an empty space of the new_table_list + new_table_list[new_table_index] = (U32)new_madt; + } + + verbose ("MADT table successfully patched\n"); + return(1); +} + +static U32 ProcessSsdt(U32 * new_table_list, ACPI_TABLE_DSDT *dsdt, MADT_INFO * madt_info, bool enable_cstates, bool enable_pstates, bool enable_tstates ) +{ + DBG("Processing SSDT\n"); + + // Check we are on an intel platform + if (Platform.CPU.Vendor != CPUID_VENDOR_INTEL) { + verbose ("Not an Intel platform: SSDT will not be generated !!!\n"); + return(0); + } + + // Check for the msr feature flag + if (!(Platform.CPU.Features & CPU_FEATURE_MSR)) { + verbose ("Unsupported CPU: SSDT will not be generated !!!\n"); + return(0); + } + + if (dsdt == (void *)0ul) { + verbose ("DSDT not found: SSDT will not be generated !!!\n"); + return (0); + } + + // Get an empty space in the new_talbe_list (true = allow reserved space) + U8 empty = get_0ul_index_in_list(new_table_list, true); + + // Check to confirm space is available + if (empty == ACPI_TABLE_LIST_FULL) + { + printf("Error: not enought reserved space in the new acpi list for the SSDT table,\n "); + printf(" please increase the RESERVED_AERA\n"); + return(0); + } + + // Create buffer for SSDT + //U8 memory_for_ssdt[20 * 1024]; // seems to bug with xcode4, need to found out what is going on (not enough memory in the stack ?) + U8 *memory_for_ssdt =(U8*)AllocateKernelMemory(20 * 1024); + + // Build the SSDT + if ( (BuildSsdt(madt_info, dsdt, memory_for_ssdt, 20 * 1024 /*sizeof(memory_for_ssdt)*/, enable_cstates, enable_pstates, enable_tstates)) == 0) + { + printf("Error: Failed to build SSDT table\n"); + return (0); + } + + // insert SSDT in the new_table_list + { + // Create pointer to SSDT just built in the stack buffer + ACPI_TABLE_SSDT * old_ssdt = (ACPI_TABLE_SSDT *)memory_for_ssdt; + + // Reserved kernel memory for the ssdt table + ACPI_TABLE_SSDT *new_ssdt = (ACPI_TABLE_SSDT *)AllocateKernelMemory(old_ssdt->Header.Length); + + if (!new_ssdt) + { + printf("Unable to allocate kernel memory for SSDT "); + return (0); + } + // Move the old stack buffer to kernel memory + memcpy(new_ssdt, old_ssdt, old_ssdt->Header.Length); + + // Add the new ssdt into an empty space of the new_table_list + new_table_list[empty] = (U32)new_ssdt; + } + + verbose ("SSDT table generated successfully\n"); + return(1); +} + +//----------------------------------------------------------------------------- +static void * buildCpuScope (void * current, U32 cpu_namespace, PROCESSOR_NUMBER_TO_NAMESEG * aslCpuNamePath) +{ + ACPI_SCOPE * scope = current; + current = scope + 1; + + scope->scopeOpcode = AML_SCOPE_OP; + scope->rootChar = AML_ROOT_PREFIX; + + if (aslCpuNamePath->seg_count == 1) + { + DUAL_NAME_PATH * dualNamePath = current; + current = dualNamePath + 1; + dualNamePath->prefix = AML_DUAL_NAME_PREFIX; + dualNamePath->nameseg[0] = cpu_namespace; + dualNamePath->nameseg[1] = aslCpuNamePath->nameseg[0]; + } + else + { + MULTI_NAME_PATH * multiNamePath = current; + current = multiNamePath + 1; + multiNamePath->prefix = AML_MULTI_NAME_PREFIX; + // the nameseg count includes the root prefix and all other namesegs + multiNamePath->segCount = (U8) aslCpuNamePath->seg_count+1; + multiNamePath->nameseg[0] = cpu_namespace; + { + U32 i; + for (i=0; iseg_count; i++) + multiNamePath->nameseg[i+1] = aslCpuNamePath->nameseg[i]; + } + } + return (current); +} +//----------------------------------------------------------------------------- +static void * buildPDC(void * current) +{ + ACPI_METHOD * pdc = current; + current = buildMethod(current, NAMESEG("_PDC"), 1); + + // CreateDWordField (Arg0, 0x08, CAPA) + current = buildOpCode(current, AML_CREATE_DWORD_FIELD_OP); + current = buildOpCode(current, AML_ARG0_OP); + current = buildByteConst(current, 0x08); + current = buildNameSeg(current, NAMESEG("CAPA")); + + // Store (CAPA, TYPE) + current = buildOpCode(current, AML_STORE_OP); + current = buildNameSeg(current, NAMESEG("CAPA")); + current = buildNameSeg(current, NAMESEG("TYPE")); + + // CreateDWordField (Arg0, 0x00, REVS) + current = buildOpCode(current, AML_CREATE_DWORD_FIELD_OP); + current = buildOpCode(current, AML_ARG0_OP); + current = buildByteConst(current, 0x00); + current = buildNameSeg(current, NAMESEG("REVS")); + + // CreateDWordField (Arg0, 0x04, SIZE) + current = buildOpCode(current, AML_CREATE_DWORD_FIELD_OP); + current = buildOpCode(current, AML_ARG0_OP); + current = buildByteConst(current, 0x04); + current = buildNameSeg(current, NAMESEG("SIZE")); + + // Store(SizeOf(Arg0), Local0) + current = buildOpCode(current, AML_STORE_OP); + current = buildOpCode(current, AML_SIZEOF_OP); + current = buildOpCode(current, AML_ARG0_OP); + current = buildOpCode(current, AML_LOCAL0_OP); + + // Store(Subtract(Local0, 0x08),Local1) + current = buildOpCode(current, AML_STORE_OP); + current = buildOpCode(current, AML_SUBTRACT_OP); + current = buildOpCode(current, AML_LOCAL0_OP); + current = buildByteConst(current, 0x08); + current = buildOpCode(current, AML_ZERO_OP); + current = buildOpCode(current, AML_LOCAL1_OP); + + // CreateField (Arg0, 0x40, Multiply (Local1, 0x08), TEMP) + current = buildOpCode(current, AML_EXT_OP_PREFIX); + current = buildOpCode(current, AML_CREATE_FIELD_OP); + current = buildOpCode(current, AML_ARG0_OP); + current = buildByteConst(current, 0x40); + current = buildOpCode(current, AML_MULTIPLY_OP); + current = buildOpCode(current, AML_LOCAL1_OP); + current = buildByteConst(current, 0x08); + current = buildOpCode(current, AML_ZERO_OP); + current = buildNameSeg(current, NAMESEG("TEMP")); + + // Name (STS0, Buffer (0x04) {0x00, 0x00, 0x00, 0x00}) + // Create STS0 as named buffer + current = buildNamePath(current, NAMESEG("STS0")); + { + ACPI_SMALL_BUFFER * buff = current; + current = buildSmallBuffer(current); + + // count of buffer elements + current = buildByteConst(current, 4); + + current = buildOpCode(current, AML_ZERO_OP); + current = buildOpCode(current, AML_ZERO_OP); + current = buildOpCode(current, AML_ZERO_OP); + current = buildOpCode(current, AML_ZERO_OP); + { + U32 length = (U8 *)current - (U8 *)buff; + buff->packageLength = (U8)length - 1; + } + } + + //Concatenate (STS0, TEMP, Local2) + current = buildOpCode(current, AML_CONCAT_OP); + current = buildNameSeg(current, NAMESEG("STS0")); + current = buildNameSeg(current, NAMESEG("TEMP")); + current = buildOpCode(current, AML_LOCAL2_OP); + + //_OSC (Buffer (0x10) + // { + // /* 0000 */ 0x16, 0xA6, 0x77, 0x40, 0x0C, 0x29, 0xBE, 0x47, + // /* 0008 */ 0x9E, 0xBD, 0xD8, 0x70, 0x58, 0x71, 0x39, 0x53 + // }, REVS, SIZE, Local2) + current = buildNameSeg(current, NAMESEG("_OSC")); + { + ACPI_SMALL_BUFFER * buff = current; + current = buildSmallBuffer(current); + + // count of buffer elements + current = buildByteConst(current, 0x10); + + current = buildOpCode(current, 0x16); + current = buildOpCode(current, 0xa6); + current = buildOpCode(current, 0x77); + current = buildOpCode(current, 0x40); + current = buildOpCode(current, 0x0c); + current = buildOpCode(current, 0x29); + current = buildOpCode(current, 0xbe); + current = buildOpCode(current, 0x47); + current = buildOpCode(current, 0x9e); + current = buildOpCode(current, 0xbd); + current = buildOpCode(current, 0xd8); + current = buildOpCode(current, 0x70); + current = buildOpCode(current, 0x58); + current = buildOpCode(current, 0x71); + current = buildOpCode(current, 0x39); + current = buildOpCode(current, 0x53); + { + U32 length = (U8 *)current - (U8 *)buff; + buff->packageLength = (U8)length - 1; + } + } + current = buildNameSeg(current, NAMESEG("REVS")); + current = buildNameSeg(current, NAMESEG("SIZE")); + current = buildOpCode(current, AML_LOCAL2_OP); + + // Update package length in PDC object + //pdc->packageLength = (U8)((U8 *)current - (U8 *)&pdc->packageLength); + setPackageLength(&pdc->pkgLength, (U8 *)current - (U8 *)&pdc->pkgLength); + + return(current); +} + +//----------------------------------------------------------------------------- +static void * buildOSC(void * current) +{ + // + // + ACPI_METHOD * osc = current; + current = buildMethod(current, NAMESEG("_OSC"), 4); + + // CreateDWordField (Arg3, 0x04, CAPA) + current = buildOpCode(current, AML_CREATE_DWORD_FIELD_OP); + current = buildOpCode(current, AML_ARG3_OP); + current = buildByteConst(current, 0x04); + current = buildNameSeg(current, NAMESEG("CAPA")); + + // Store (CAPA, TYPE) + current = buildOpCode(current, AML_STORE_OP); + current = buildNameSeg(current, NAMESEG("CAPA")); + current = buildNameSeg(current, NAMESEG("TYPE")); + + // CreateDWordField (Arg3, 0x00, STS0) + current = buildOpCode(current, AML_CREATE_DWORD_FIELD_OP); + current = buildOpCode(current, AML_ARG3_OP); + current = buildByteConst(current, 0x00); + current = buildNameSeg(current, NAMESEG("STS0")); + + // CreateDWordField (Arg3, 0x04, CAP0) + current = buildOpCode(current, AML_CREATE_DWORD_FIELD_OP); + current = buildOpCode(current, AML_ARG3_OP); + current = buildByteConst(current, 0x04); + current = buildNameSeg(current, NAMESEG("CAP0")); + + // CreateDWordField (Arg0, 0x00, IID0) + current = buildOpCode(current, AML_CREATE_DWORD_FIELD_OP); + current = buildOpCode(current, AML_ARG0_OP); + current = buildByteConst(current, 0x00); + current = buildNameSeg(current, NAMESEG("IID0")); + + // CreateDWordField (Arg0, 0x04, IID1) + current = buildOpCode(current, AML_CREATE_DWORD_FIELD_OP); + current = buildOpCode(current, AML_ARG0_OP); + current = buildByteConst(current, 0x04); + current = buildNameSeg(current, NAMESEG("IID1")); + + // CreateDWordField (Arg0, 0x08, IID2) + current = buildOpCode(current, AML_CREATE_DWORD_FIELD_OP); + current = buildOpCode(current, AML_ARG0_OP); + current = buildByteConst(current, 0x08); + current = buildNameSeg(current, NAMESEG("IID2")); + + // CreateDWordField (Arg0, 0x0C, IID3) + current = buildOpCode(current, AML_CREATE_DWORD_FIELD_OP); + current = buildOpCode(current, AML_ARG0_OP); + current = buildByteConst(current, 0x0C); + current = buildNameSeg(current, NAMESEG("IID3")); + + // Name (UID0, Buffer (0x10) + // { + // 0x16, 0xA6, 0x77, 0x40, 0x0C, 0x29, 0xBE, 0x47, + // 0x9E, 0xBD, 0xD8, 0x70, 0x58, 0x71, 0x39, 0x53 + // }) + current = buildNamePath(current, NAMESEG("UID0")); + { + ACPI_SMALL_BUFFER * buff = current; + current = buildSmallBuffer(current); + + // count of buffer elements + current = buildByteConst(current, 0x10); + + current = buildOpCode(current, 0x16); + current = buildOpCode(current, 0xa6); + current = buildOpCode(current, 0x77); + current = buildOpCode(current, 0x40); + current = buildOpCode(current, 0x0c); + current = buildOpCode(current, 0x29); + current = buildOpCode(current, 0xbe); + current = buildOpCode(current, 0x47); + current = buildOpCode(current, 0x9e); + current = buildOpCode(current, 0xbd); + current = buildOpCode(current, 0xd8); + current = buildOpCode(current, 0x70); + current = buildOpCode(current, 0x58); + current = buildOpCode(current, 0x71); + current = buildOpCode(current, 0x39); + current = buildOpCode(current, 0x53); + + { + U32 length = (U8 *)current - (U8 *)buff; + buff->packageLength = (U8)length - 1; + } + } + + // CreateDWordField (UID0, 0x00, EID0) + current = buildOpCode(current, AML_CREATE_DWORD_FIELD_OP); + current = buildOpCode(current, AML_ARG0_OP); + current = buildByteConst(current, 0x00); + current = buildNameSeg(current, NAMESEG("EID0")); + + // CreateDWordField (UID0, 0x04, EID1) + current = buildOpCode(current, AML_CREATE_DWORD_FIELD_OP); + current = buildOpCode(current, AML_ARG0_OP); + current = buildByteConst(current, 0x04); + current = buildNameSeg(current, NAMESEG("EID1")); + + // CreateDWordField (UID0, 0x08, EID2) + current = buildOpCode(current, AML_CREATE_DWORD_FIELD_OP); + current = buildOpCode(current, AML_ARG0_OP); + current = buildByteConst(current, 0x08); + current = buildNameSeg(current, NAMESEG("EID2")); + + // CreateDWordField (UID0, 0x0C, EID3) + current = buildOpCode(current, AML_CREATE_DWORD_FIELD_OP); + current = buildOpCode(current, AML_ARG0_OP); + current = buildByteConst(current, 0x0C); + current = buildNameSeg(current, NAMESEG("EID3")); + + // If (LNot (LAnd (LAnd (LEqual (IID0, EID0), LEqual (IID1, EID1)), + // LAnd (LEqual (IID2, EID2), LEqual (IID3, EID3))))) + // { + // Store (0x06, Index (STS0, 0x00)) + // Return (Arg3) + // } + { + current = buildOpCode(current, AML_IF_OP); + { + ACPI_PACKAGE_LENGTH * packageLength = current; + current = buildPackageLength(current, 0); + + current = buildOpCode(current, AML_LNOT_OP); + current = buildOpCode(current, AML_LAND_OP); + current = buildOpCode(current, AML_LAND_OP); + current = buildOpCode(current, AML_LEQUAL_OP); + current = buildNameSeg(current, NAMESEG("IID0")); + current = buildNameSeg(current, NAMESEG("EID0")); + + current = buildOpCode(current, AML_LEQUAL_OP); + current = buildNameSeg(current, NAMESEG("IID1")); + current = buildNameSeg(current, NAMESEG("EID1")); + + current = buildOpCode(current, AML_LAND_OP); + current = buildOpCode(current, AML_LEQUAL_OP); + current = buildNameSeg(current, NAMESEG("IID2")); + current = buildNameSeg(current, NAMESEG("EID2")); + + current = buildOpCode(current, AML_LEQUAL_OP); + current = buildNameSeg(current, NAMESEG("IID3")); + current = buildNameSeg(current, NAMESEG("EID3")); + + // Store (0x06, Index (STS0, 0x00)) + current = buildOpCode(current, AML_STORE_OP); + current = buildByteConst(current, 0x06); + current = buildOpCode(current, AML_INDEX_OP); + current = buildNameSeg(current, NAMESEG("STS0")); + current = buildByteConst(current, 0x00); + current = buildOpCode(current, AML_ZERO_OP); + + // Return (Arg3) + current = buildReturnOpcode(current, AML_ARG3_OP); + + setPackageLength(packageLength, + (U8 *)current - (U8 *)packageLength); + } + } + + // If (LNotEqual (Arg1, 0x01)) + // { + // Store (0x0A, Index (STS0, 0x00)) + // Return (Arg3) + // } + { + current = buildOpCode(current, AML_IF_OP); + { + ACPI_PACKAGE_LENGTH * packageLength = current; + current = buildPackageLength(current, 0); + + // If ("LNotEqual (Arg1, 0x01)") + current = buildOpCode(current, AML_LNOT_OP); + current = buildOpCode(current, AML_LEQUAL_OP); + current = buildOpCode(current, AML_ARG1_OP); + current = buildByteConst(current, 0x01); + + // Store (0x0A, Index (STS0, 0x00)) + current = buildOpCode(current, AML_STORE_OP); + current = buildByteConst(current, 0x0A); + current = buildOpCode(current, AML_INDEX_OP); + current = buildNameSeg(current, NAMESEG("STS0")); + current = buildByteConst(current, 0x00); + current = buildOpCode(current, AML_ZERO_OP); + + // Return (Arg3) + current = buildReturnOpcode(current, AML_ARG3_OP); + + setPackageLength(packageLength, + (U8 *)current - (U8 *)packageLength); + } + } + + // If (And (STS0, 0x01)) + // { + // And (CAP0, 0x0BFF, CAP0) + // Return (Arg3) + // } + { + current = buildOpCode(current, AML_IF_OP); + { + ACPI_PACKAGE_LENGTH * packageLength = current; + current = buildPackageLength(current, 0); + + // If ("And (STS0, 0x01)") + current = buildOpCode(current, AML_AND_OP); + current = buildNameSeg(current, NAMESEG("STS0")); + current = buildByteConst(current, 0x01); + current = buildOpCode(current, AML_ZERO_OP); + + // And (CAP0, 0x0BFF, CAP0) + current = buildOpCode(current, AML_AND_OP); + current = buildNameSeg(current, NAMESEG("CAP0")); + current = buildWordConst(current, 0x0BFF); + current = buildNameSeg(current, NAMESEG("CAP0")); + + // Return (Arg3) + current = buildReturnOpcode(current, AML_ARG3_OP); + + setPackageLength(packageLength, + (U8 *)current - (U8 *)packageLength); + } + } + + // And (CAP0, 0x0BFF, CAP0) + current = buildOpCode(current, AML_AND_OP); + current = buildNameSeg(current, NAMESEG("CAP0")); + current = buildWordConst(current, 0x0BFF); + current = buildNameSeg(current, NAMESEG("CAP0")); + + // Store (CAP0, TYPE) + current = buildOpCode(current, AML_STORE_OP); + current = buildNameSeg(current, NAMESEG("CAP0")); + current = buildNameSeg(current, NAMESEG("TYPE")); + + // Return (Arg3) + current = buildReturnOpcode(current, AML_ARG3_OP); + + // Set package length for the OSC object + setPackageLength(&osc->pkgLength, (U8 *)current - (U8 *)&osc->pkgLength); + + return(current); +} + +//----------------------------------------------------------------------------- +static void * buildPSS(void * current, PKG_PSTATES * pkg_pstates) +{ + // + // IF (PSEN) + // { + // Return (Package of Pstate Packages) + // } + // Return(Zero) + // + ACPI_METHOD * pss = current; + current = buildMethod(current, NAMESEG("_PSS"), 0); + + { + // "IF" (PSEN) -- IF Opcode + current = buildOpCode(current, AML_IF_OP); + { + ACPI_PACKAGE_LENGTH * packageLength = current; + current = buildPackageLength(current, 0); + + // IF "(PSEN)" -- IF Predicate + current = buildNameSeg(current, NAMESEG("PSEN")); + + { + ACPI_RETURN_PACKAGE * returnPkg = current; + current = buildReturnPackage(current, (U8)pkg_pstates->num_pstates); + + // (3.3.3) For each P-state + { + U32 pstateIndex = 0; + for (pstateIndex=0; pstateIndex < pkg_pstates->num_pstates; pstateIndex++) + { + // (3.3.3.1) Create P-state package + ACPI_PSTATE_PACKAGE * pstate = current; + current = pstate + 1; + + setSmallPackage(&pstate->package, 6); + pstate->package.packageLength = (U8)(sizeof(ACPI_PSTATE_PACKAGE) - 1); + + setDwordConst(&pstate->CoreFreq, pkg_pstates->pstate[pstateIndex].frequency);// CoreFreq (in MHz). + setDwordConst(&pstate->Power, pkg_pstates->pstate[pstateIndex].power);// Power (in milliWatts). + setDwordConst(&pstate->TransLatency, pkg_pstates->pstate[pstateIndex].translatency);// Transition Latency (in microseconds). + setDwordConst(&pstate->BMLatency, pkg_pstates->pstate[pstateIndex].bmlatency);// Bus Master Latency (in microseconds). + setDwordConst(&pstate->Control, pkg_pstates->pstate[pstateIndex].control); // Control. + + setDwordConst(&pstate->Status, encode_pstate(pkg_pstates->pstate[pstateIndex].ratio));// Status. + } // for + } // for block + + // (3.3.4) Update package length in return package + setPackageLength(&returnPkg->package.pkgLength, (U8 *)current - (U8 *)&returnPkg->package.pkgLength); + } + + // "IF (PSEN) and its body" -- Set package length + setPackageLength(packageLength, + (U8 *)current - (U8 *)packageLength); + } + // "Return (ZERO)" + current = buildReturnZero(current); + } + // Set package length for the _PSS object + setPackageLength(&pss->pkgLength, (U8 *)current - (U8 *)&pss->pkgLength); + + return(current); +} + +//----------------------------------------------------------------------------- +static void * buildPSD(void * current, U32 domain, U32 cpusInDomain, U32 pstate_coordination) +{ + // If (And(TYPE, 0x0820)) + // { + // Return (PSD Package) + // } + // Return(Zero) + + ACPI_METHOD * psdMethod = current; + current = buildMethod(current, NAMESEG("_PSD"), 0); + { + // "IF" (And(TYPE, 0x0820)) -- IF Opcode + current = buildOpCode(current, AML_IF_OP); + { + ACPI_PACKAGE_LENGTH * packageLength = current; + current = buildPackageLength(current, 0); + + // IF ("And"(TYPE, 0x820)) -- AND Opcode + current = buildOpCode(current, AML_AND_OP); + + // IF (And("TYPE", 0x820)) -- TYPE Term + current = buildNameSeg(current, NAMESEG("TYPE")); + + // IF (And(TYPE, "0x0820")) -- DWORD Value Term + current = buildDwordConst(current, 0x820); + + // IF ("And(TYPE, 0x200)") -- Target for And term (unused) + current = buildOpCode(current, AML_ZERO_OP); + + // Build return package containing PSD package + { + ACPI_RETURN_PACKAGE * returnPkg = current; + current = buildReturnPackage(current, 1); + + { + // Create PSD package + ACPI_PSD_PACKAGE * psd = current; + current = psd + 1; + + setSmallPackage(&psd->package, 5); + psd->package.packageLength = (U8)(sizeof(ACPI_PSD_PACKAGE) - 1); + + setByteConst(&psd->NumberOfEntries, 5); + setByteConst(&psd->Revision, 0); + setDwordConst(&psd->Domain, domain); + setDwordConst(&psd->CoordType, pstate_coordination); + setDwordConst(&psd->NumProcessors, cpusInDomain); + + } // PSD package + + setPackageLength(&returnPkg->package.pkgLength, + (U8 *)current - (U8 *)&returnPkg->package.pkgLength); + } + setPackageLength(packageLength, (U8 *)current - (U8 *)packageLength); + } + // "Return (ZERO)" + current = buildReturnZero(current); + } + // Update length in _PSD method + setPackageLength(&psdMethod->pkgLength, (U8 *)current - (U8 *)&psdMethod->pkgLength); + + return(current); +} + +//----------------------------------------------------------------------------- +static void * buildPPC(void * current/*, U8 valueToReturn*/) +{ + ACPI_SMALL_METHOD * ppc = current; + current = buildSmallMethod(current, NAMESEG("_PPC"), 0); + + current = buildReturnZero(current); + + //current = buildReturnOpcode(current, valueToReturn); + + // Update package length in PPC object + ppc->packageLength = (U8) ( (U8 *)current - (U8 *)&ppc->packageLength ); + + return(current); +} + +#if UNUSED +//----------------------------------------------------------------------------- +static void * buildPDL(void * current, U8 valueToReturn) +{ + ACPI_SMALL_METHOD * pdl = current; + current = buildSmallMethod(current, NAMESEG("_PDL"), 0); + + current = buildReturnOpcode(current, valueToReturn); + + // Update package length in PDL object + pdl->packageLength = (U8) ( (U8 *)current - (U8 *)&pdl->packageLength ); + + return(current); +} +#endif + +//----------------------------------------------------------------------------- +static void * buildPCT(void * current) +{ + static const ACPI_GENERIC_ADDRESS pct_gas[] = { + {0x7f,0x40,0,0,0x199}, + {0x7f,0x10,0,0,0x198}, + }; + + ACPI_SMALL_METHOD * pct = current; + current = buildSmallMethod(current, NAMESEG("_PCT"), 0); + + { + ACPI_RETURN_PACKAGE * returnPkg = current; + current = buildReturnPackage(current, 2); + + { + ACPI_SMALL_BUFFER * buff = current; + current = buildSmallBuffer(current); + + current = buildByteConst(current, sizeof(ACPI_GENERIC_REGISTER) + sizeof(ACPI_END_TAG) ); + current = buildGenericRegister(current, &pct_gas[0]); + current = buildEndTag(current); + + { + U32 length = (U8 *)current - (U8 *)buff; + buff->packageLength = (U8)length - 1; + } + } + { + ACPI_SMALL_BUFFER * buff = current; + current = buildSmallBuffer(current); + + current = buildByteConst(current, sizeof(ACPI_GENERIC_REGISTER) + sizeof(ACPI_END_TAG) ); + current = buildGenericRegister(current, &pct_gas[1]); + current = buildEndTag(current); + + { + U32 length = (U8 *)current - (U8 *)buff; + buff->packageLength = (U8)length - 1; + } + + } + + setPackageLength(&returnPkg->package.pkgLength, + (U8 *)current - (U8 *)&returnPkg->package.pkgLength); + } + + // Update package length in PCT object + pct->packageLength = (U8)((U8 *)current - (U8 *)&pct->packageLength); + + return(current); +} + +//----------------------------------------------------------------------------- +static void * buildCstate(void * current, ACPI_GENERIC_ADDRESS * gas, CSTATE * cstate) +{ + // + // Build a C-state + // + ACPI_SMALL_PACKAGE * pkg1 = current; + current = buildSmallPackage(current, 4); + + { + { + ACPI_SMALL_BUFFER * buffer = current; + current = buildSmallBuffer(current); + + { + // Buffer length + current = buildByteConst(current, sizeof(ACPI_GENERIC_REGISTER) + sizeof(ACPI_END_TAG) ); + current = buildGenericRegister(current, gas); + current = buildEndTag(current); + } + { + U32 length = (U8 *)current - (U8 *)buffer; + buffer->packageLength = (U8)length - 1; + } + } + + { + current = buildByteConst(current, cstate->type); + current = buildWordConst(current, cstate->latency); + current = buildDwordConst(current, cstate->power); + } + } + pkg1->packageLength = (U8)((U8 *)current - (U8 *)&pkg1->packageLength); + + return(current); +} + +//----------------------------------------------------------------------------- +static void * buildReturnPackageCST(void * current, PKG_CSTATES * pkg_cstates) +{ + // Create package returning C-states + ACPI_RETURN_PACKAGE * returnPkg = current; + current = buildReturnPackage(current, (U8)pkg_cstates->num_cstates + 1); + + { + // Include number of C-states + current = buildByteConst(current, (U8)pkg_cstates->num_cstates); + + { + U32 cstateIndex = 0; + for (cstateIndex=0; cstateIndex < pkg_cstates->num_cstates; cstateIndex++) + // Build C-state + current = buildCstate(current, &pkg_cstates->gas[cstateIndex], &pkg_cstates->cstate[cstateIndex]); + } + } + + // Update package length in return package + setPackageLength(&returnPkg->package.pkgLength, + (U8 *)current - (U8 *)&returnPkg->package.pkgLength); + + return(current); +} + +//----------------------------------------------------------------------------- +static void * buildCST(void * current, PKG_CSTATES * mwait_pkg_cstates, PKG_CSTATES * io_pkg_cstates) +{ + // + // IF (CSEN) + // { + // IF (LAnd(MWOS, And(TYPE, 0x200))) + // { + // Return package containing MWAIT C-states + // } + // Return package containing IO C-states + // } + // Return(Zero) + // + ACPI_METHOD * cst = current; + current = buildMethod(current, NAMESEG("_CST"), 0); + { + // "IF" CSEN -- IF Opcode + current = buildOpCode(current, AML_IF_OP); + { + ACPI_PACKAGE_LENGTH * packageLength1 = current; + current = buildPackageLength(current, 0); + + // IF "(CSEN)" -- IF Predicate + current = buildNameSeg(current, NAMESEG("CSEN")); + + // "IF" (LAnd(MWOS, And(TYPE, 0x200))) -- IF Opcode + current = buildOpCode(current, AML_IF_OP); + { + ACPI_PACKAGE_LENGTH * packageLength2 = current; + current = buildPackageLength(current, 0); + + // IF ("LAnd"(MWOS, And(TYPE, 0x200))) -- LAND Opcode + current = buildOpCode(current, AML_LAND_OP); + + // IF (LAnd("MWOS", And(TYPE, 0x200))) -- MWOS Term + current = buildNameSeg(current, NAMESEG("MWOS")); + + // IF (LAnd(MWOS, "And"(TYPE, 0x200))) -- AND Opcode + current = buildOpCode(current, AML_AND_OP); + + // IF (LAnd(MWOS, And("TYPE", 0x200))) -- TYPE Term + current = buildNameSeg(current, NAMESEG("TYPE")); + + // IF (LAnd(MWOS, And(TYPE, "0x200"))) -- DWORD Value Term + current = buildWordConst(current, 0x200); + + // IF (LAnd(MWOS, "And(TYPE, 0x200)")) -- Target for And term (unused) + current = buildOpCode(current, AML_ZERO_OP); + + // Build return package for mwait c-states + current = buildReturnPackageCST(current, mwait_pkg_cstates); + + setPackageLength(packageLength2, + (U8 *)current - (U8 *)packageLength2); + } + + // Build return package for io c-states + current = buildReturnPackageCST(current, io_pkg_cstates); + + setPackageLength(packageLength1, + (U8 *)current - (U8 *)packageLength1); + } + // "Return (ZERO)" + current = buildReturnZero(current); + } + // Update length in _CST method + setPackageLength(&cst->pkgLength, (U8 *)current - (U8 *)&cst->pkgLength); + + return(current); +} + +#if BUILD_ACPI_CSD +//----------------------------------------------------------------------------- +static void * buildCSD(void * current, U32 domain, U32 cpusInDomain, PKG_CSTATES * pkg_cstates) +{ + // If (And(TYPE, 0x0040)) + // { + // Return (CSD Package) + // } + // Return(Zero) + + ACPI_METHOD * csdMethod = current; + current = buildMethod(current, NAMESEG("_CSD"), 0); + { + // "IF" (And(TYPE, 0x0040)) -- IF Opcode + current = buildOpCode(current, AML_IF_OP); + { + ACPI_PACKAGE_LENGTH * packageLength = current; + current = buildPackageLength(current, 0); + + // IF ("And"(TYPE, 0x0040)) -- AND Opcode + current = buildOpCode(current, AML_AND_OP); + + // IF (And("TYPE", 0x0040)) -- TYPE Term + current = buildNameSeg(current, NAMESEG("TYPE")); + + // IF (And(TYPE, "0x0040")) -- DWORD Value Term + current = buildDwordConst(current, 0x0040); + + // IF ("And(TYPE, 0x0040)") -- Target for And term (unused) + current = buildOpCode(current, AML_ZERO_OP); + + // Build return package containing CSD package(s) + { + ACPI_RETURN_PACKAGE * returnPkg = current; + current = buildReturnPackage(current, (U8)pkg_cstates->num_cstates - 1); + + { + U32 cstateIndex; + for (cstateIndex=1; cstateIndex < pkg_cstates->num_cstates; cstateIndex++) + { + // Build CSD for this C-state + + // Create CSD package + ACPI_CSD_PACKAGE * csd = current; + current = csd + 1; + + setSmallPackage(&csd->package, 6); + csd->package.packageLength = (U8)(sizeof(ACPI_CSD_PACKAGE) - 1); + + setByteConst(&csd->NumberOfEntries, 6); + setByteConst(&csd->Revision, 0); + setDwordConst(&csd->Domain, domain); + setDwordConst(&csd->CoordType, ACPI_COORD_TYPE_HW_ALL); + setDwordConst(&csd->NumProcessors, cpusInDomain); + setDwordConst(&csd->Index, cstateIndex); + } + } + + setPackageLength(&returnPkg->package.pkgLength, + (U8 *)current - (U8 *)&returnPkg->package.pkgLength); + } + + setPackageLength(packageLength, (U8 *)current - (U8 *)packageLength); + } + // "Return (ZERO)" + current = buildReturnZero(current); + } + // Update length in _CSD method + setPackageLength(&csdMethod->pkgLength, (U8 *)current - (U8 *)&csdMethod->pkgLength); + + return(current); +} +#endif // BUILD_ACPI_CSD + +#if BUILD_ACPI_TSS +//----------------------------------------------------------------------------- +static void * buildTPC(void * current) +{ + ACPI_SMALL_METHOD * tpc = current; + current = buildSmallMethod(current, NAMESEG("_TPC"), 0); + + current = buildReturnZero(current); + + // Update package length in PPC object + tpc->packageLength = (U8) ( (U8 *)current - (U8 *)&tpc->packageLength ); + + return(current); +} + +//----------------------------------------------------------------------------- +static void * buildPTC(void * current) +{ + static const ACPI_GENERIC_ADDRESS ptc_gas[] = { + {0x7f,0x00,0,0,0}, + {0x7f,0x00,0,0,0}, + }; + + ACPI_SMALL_METHOD * ptc = current; + current = buildSmallMethod(current, NAMESEG("_PTC"), 0); + + { + ACPI_RETURN_PACKAGE * returnPkg = current; + current = buildReturnPackage(current, 2); + + { + ACPI_SMALL_BUFFER * buff = current; + current = buildSmallBuffer(current); + + current = buildByteConst(current, sizeof(ACPI_GENERIC_REGISTER) + sizeof(ACPI_END_TAG) ); + current = buildGenericRegister(current, &ptc_gas[0]); + current = buildEndTag(current); + + { + U32 length = (U8 *)current - (U8 *)buff; + buff->packageLength = (U8)length - 1; + } + } + { + ACPI_SMALL_BUFFER * buff = current; + current = buildSmallBuffer(current); + + current = buildByteConst(current, sizeof(ACPI_GENERIC_REGISTER) + sizeof(ACPI_END_TAG) ); + current = buildGenericRegister(current, &ptc_gas[1]); + current = buildEndTag(current); + + { + U32 length = (U8 *)current - (U8 *)buff; + buff->packageLength = (U8)length - 1; + } + } + + setPackageLength(&returnPkg->package.pkgLength, + (U8 *)current - (U8 *)&returnPkg->package.pkgLength); + } + + // Update package length in PTC object + ptc->packageLength = (U8)((U8 *)current - (U8 *)&ptc->packageLength); + + return(current); +} + +//----------------------------------------------------------------------------- +static void * buildTSS(void * current, PKG_TSTATES * pkg_tstates) +{ + // + // IF (LAnd(TSEN, And(TYPE,4))) + // { + // Return (Package of Tstate Packages) + // } + // Return(Zero) + // + ACPI_METHOD * tss = current; + current = buildMethod(current, NAMESEG("_TSS"), 0); + + { + // "IF" (LAnd(TSEN, And(TYPE,4))) -- IF Opcode + current = buildOpCode(current, AML_IF_OP); + { + ACPI_PACKAGE_LENGTH * packageLength = current; + current = buildPackageLength(current, 0); + + // IF ("LAnd"(TSEN, And(TYPE, 4))) -- LAND Opcode + current = buildOpCode(current, AML_LAND_OP); + + // IF (LAnd("TSEN", And(TYPE, 4))) -- TSEN Term + current = buildNameSeg(current, NAMESEG("TSEN")); + + // IF (LAnd(TSEN, "And"(TYPE, 4))) -- AND Opcode + current = buildOpCode(current, AML_AND_OP); + + // IF (LAnd(TSEN, And("TYPE", 4))) -- TYPE Term + current = buildNameSeg(current, NAMESEG("TYPE")); + + // IF (LAnd(TSEN, And(TYPE, "4"))) -- DWORD Value Term + current = buildWordConst(current, 4); + + // IF (LAnd(MWOS, "And(TYPE, 4)")) -- Target for And term (unused) + current = buildOpCode(current, AML_ZERO_OP); + + // Return (Package of Tstate Packages) + { + ACPI_RETURN_PACKAGE * returnPkg = current; + current = buildReturnPackage(current, (U8)pkg_tstates->num_tstates); + + // (3.3.3) For each T-state + { + U32 tstateIndex = 0; + for (tstateIndex=0; tstateIndex < pkg_tstates->num_tstates; tstateIndex++) + { + // (3.3.3.1) Create T-state package + ACPI_TSTATE_PACKAGE * tstate = current; + current = tstate + 1; + + setSmallPackage(&tstate->package, 5); + tstate->package.packageLength = (U8)(sizeof(ACPI_TSTATE_PACKAGE) - 1); + + setDwordConst(&tstate->FreqPercent, pkg_tstates->tstate[tstateIndex].freqpercent); + setDwordConst(&tstate->Power, pkg_tstates->tstate[tstateIndex].power); + setDwordConst(&tstate->TransLatency, pkg_tstates->tstate[tstateIndex].latency); + setDwordConst(&tstate->Control, pkg_tstates->tstate[tstateIndex].control); + setDwordConst(&tstate->Status, pkg_tstates->tstate[tstateIndex].status); + } // for + } // for block + + // (3.3.4) Update package length in return package + setPackageLength(&returnPkg->package.pkgLength, (U8 *)current - (U8 *)&returnPkg->package.pkgLength); + } + + // "IF (LAnd(TSEN, And(TYPE,4))) and its body" -- Set package length + setPackageLength(packageLength, (U8 *)current - (U8 *)packageLength); + } + // "Return (ZERO)" + current = buildReturnZero(current); + } + // Set package length for the _TSS object + setPackageLength(&tss->pkgLength, (U8 *)current - (U8 *)&tss->pkgLength); + + return(current); +} + +//----------------------------------------------------------------------------- +static void * buildTSD(void * current, U32 domain, U32 cpusInDomain) +{ + // If (And(TYPE, 0x0080)) + // { + // Return (Package containing TSD package) + // } + // Return(Zero) + + ACPI_METHOD * tsdMethod = current; + current = buildMethod(current, NAMESEG("_TSD"), 0); + { + // "IF" (And(TYPE, 0x0080)) -- IF Opcode + current = buildOpCode(current, AML_IF_OP); + { + ACPI_PACKAGE_LENGTH * packageLength = current; + current = buildPackageLength(current, 0); + + // IF ("And"(TYPE, 0x0080)) -- AND Opcode + current = buildOpCode(current, AML_AND_OP); + + // IF (And("TYPE", 0x0080)) -- TYPE Term + current = buildNameSeg(current, NAMESEG("TYPE")); + + // IF (And(TYPE, "0x0080")) -- DWORD Value Term + current = buildDwordConst(current, 0x0080); + + // IF ("And(TYPE, 0x0080)") -- Target for And term (unused) + current = buildOpCode(current, AML_ZERO_OP); + + // Build package containing TSD package + { + ACPI_RETURN_PACKAGE * returnPkg = current; + current = buildReturnPackage(current, 1); + + { + // Create PSD package + ACPI_TSD_PACKAGE * tsd = current; + current = tsd + 1; + + setSmallPackage(&tsd->package, 5); + tsd->package.packageLength = (U8)(sizeof(ACPI_TSD_PACKAGE) - 1); + + setByteConst(&tsd->NumberOfEntries, 5); + setByteConst(&tsd->Revision, 0); + setDwordConst(&tsd->Domain, domain); + setDwordConst(&tsd->CoordType, ACPI_COORD_TYPE_SW_ANY); + setDwordConst(&tsd->NumProcessors, cpusInDomain); + + } // TSD package + + setPackageLength(&returnPkg->package.pkgLength, + (U8 *)current - (U8 *)&returnPkg->package.pkgLength); + } + + setPackageLength(packageLength, (U8 *)current - (U8 *)packageLength); + } + // "Return (ZERO)" + current = buildReturnZero(current); + } + // Update length in _TSD method + setPackageLength(&tsdMethod->pkgLength, (U8 *)current - (U8 *)&tsdMethod->pkgLength); + + return(current); +} +#endif // BUILD_ACPI_TSS + +//----------------------------------------------------------------------------- +static U32 BuildSsdt(MADT_INFO * madt_info, ACPI_TABLE_DSDT *dsdt, void * buffer, U32 bufferSize, bool enable_cstates, bool enable_pstates, bool enable_tstates) +{ + // Build SSDT + { + // (1) Setup pointers to SSDT memory location + // (2) Create SSDT Definition Block + // (2.1) Save pointer to SSDT package length and checksum fields + // (2.2) Create variables in SSDT scope + // (3) For each logical processor CPUn + // (3.1) Create scope for CPUn + // (3.2) Create variables in CPU scope + // (3.3) Create _OSC and/or _PDC Methods + // (3.4) Create P-state related structures + // (3.4.1) Create _PSS Method + // (3.4.2) Create _PCT Object + // (3.4.3) Create _PPC Method + // (3.4.4) Create _PSD Object + // (3.5) Create C-state related structures + // (3.5.1) Create _CST Method + // (3.5.2) Create _CSD Method + // (3.6) Create T-state related structures (Optional) + // (3.6.1) Create _TPC Method + // (3.6.2) Create _PTC Method + // (3.6.3) Create _TSS Method + // (3.6.4) Create _TSD Method + // (3.7) Update length in CPUn Scope + // (4) Update length and checksum in SSDT Definition Block + DBG("Attempting to build SSDT\n"); + + U32 pstates_enabled = 0; + U32 cstates_enabled = 0; + CPU_DETAILS cpu; + cpu.max_ratio_as_mfg = 0; + cpu.package_power_limit = 0; + + U8 ACPI_COORD_TYPE = ACPI_COORD_TYPE_SW_ANY; // default + ACPI_TABLE_SSDT *SsdtPointer = (void*)0ul; + + // Desired state for providing alternate ACPI _CST structure using MWAIT + // extensions + // 1= Alternate _CST using MWAIT extension is enabled for OSPM use + // 0= Alternate _CST using MWAIT extension is disabled for OSPM use + bool enable_mwait = 1; + + // (1) Setup pointers to SSDT memory location + void * current = buffer; + void * end = (U8 *)buffer + bufferSize; + + // Confirm a valid SSDT buffer was provided + if (!buffer) + { + printf("Error: Invalid Buffer Address for SSDT\n"); + return(0); + } + + // Confirm a valid SSDT buffer length was provided + if (!bufferSize) + { + printf("Error: Invalid Buffer Length for SSDT\n"); + return(0); + } + + if (madt_info == (void*) 0ul) + { + return(0); + } + + if (dsdt == (void*) 0ul) + { + return(0); + } + + // Check that we have a valid cpu_map (if it's not already done, it will try to generate it) + if (generate_cpu_map_from_acpi(dsdt) != 0) + { + return(0); + } + + collect_cpu_info(&cpu); + + if (enable_cstates && pmbase) + { + DBG("Building Cstate Info\n"); + + cstates_enabled = BuildCstateInfo(&cpu, pmbase); + if (cstates_enabled) + { + getBoolForKey(KEnableMwait, &enable_mwait, &bootInfo->chameleonConfig); + } + } + + if (enable_pstates) + { + DBG("Building Pstate Info\n"); + + pstates_enabled = BuildPstateInfo(&cpu); + if (pstates_enabled) + { + const char *str = getStringForKey(KAcpiCoordType, &bootInfo->chameleonConfig); + U8 tmp = (U8)strtoul(str, NULL,16); + if ((tmp == ACPI_COORD_TYPE_SW_ALL) || (tmp == ACPI_COORD_TYPE_SW_ANY) || (tmp == ACPI_COORD_TYPE_HW_ALL) ) + { + ACPI_COORD_TYPE = tmp; + } + } + } +#if BUILD_ACPI_TSS + U32 tstates_enabled = 0; + if (enable_tstates) + { + DBG("Building Pstate Info\n"); + + tstates_enabled = BuildTstateInfo(&cpu); + } +#endif + + SsdtPointer = (ACPI_TABLE_SSDT *)buffer; + + // (2) Create SSDT Definition Block + // (2.1) Save pointer to SSDT package length and checksum fields + current = buildTableHeader(current, NAMESEG("SSDT"), NAMESEG64("PPM RCM ")); + + // Check to confirm no SSDT buffer overflow + if ( (U8 *)current > (U8 *)end ) + { + printf("Error: SSDT Buffer Length exceeded available space \n"); + return(0); + } + + // (3) For each logical processor CPUn + // We will use the dsdt datas in place of madt,for the cpu(s) detection. + // 'Cause most users use the dsdt table to change the numbers of cpu(s) that the OS and the bootloader should use, + // Note also that due to chameleon limit we use the same package per each cpu(s) for all objects and methods + // (package detection for each cpu(s) is still in progress) + { + U32 lapic_index; + for (lapic_index=0; lapic_index < cpu_map_count; lapic_index++) + { + // (3.1) Create scope for CPUn + ACPI_SCOPE * scope = current; + + { + DBG("Building CPU Scope\n"); + U32 cpu_namespace = (cpuNamespace == CPU_NAMESPACE_SB) ? NAMESEG("_SB_") : NAMESEG("_PR_"); + PROCESSOR_NUMBER_TO_NAMESEG * namepath = &cpu_map[lapic_index]; + current = buildCpuScope (current, cpu_namespace, namepath ); + } + + // Check to confirm no SSDT buffer overflow + if ( (U8 *)current > (U8 *)end ) + { + printf("Error: SSDT Buffer Length exceeded available space \n"); + return(0); + } + + // (3.2) Create variables in CPU scope + DBG("Creating variables in CPU scope\n"); // Build Type variable used to store PDC capabilities + current = buildNamedDword(current, NAMESEG("TYPE"), 0); + + // Build PSEN variable used to store state of P-State Enable setup option + current = buildNamedDword(current, NAMESEG("PSEN"), pstates_enabled); + + // Build CSEN variable used to store state of C-State Enable setup option + current = buildNamedDword(current, NAMESEG("CSEN"), cstates_enabled); + + // Build MWOS variable used to store state of MWAIT OS setup option + current = buildNamedDword(current, NAMESEG("MWOS"), (U32)(enable_mwait&&cpu.mwait_supported)); + + // (3.3) Create _OSC and/or _PDC Methods + { + // Build _PDC method + DBG("Building PDC method\n"); + current = buildPDC(current); + + // Check to confirm no SSDT buffer overflow + if ( (U8 *)current > (U8 *)end ) + { + printf("Error: SSDT Buffer Length exceeded available space \n"); + return(0); + } + + // Build _OSC method + DBG("Building _OSC method\n"); + current = buildOSC(current); + + // Check to confirm no SSDT buffer overflow + if ( (U8 *)current > (U8 *)end ) + { + printf("Error: SSDT Buffer Length exceeded available space \n"); + return(0); + } + } + + // (3.4) Create P-state related structures + if (pstates_enabled == 1) + { + // (3.4.1) Create _PSS Method + { + DBG("Building _PSS method\n"); + PKG_PSTATES * pkg_pstates = &cpu.pkg_pstates; + current = buildPSS(current, pkg_pstates); + } + + // Check to confirm no SSDT buffer overflow + if ( (U8 *)(current) > (U8 *)end ) + { + printf("Error: SSDT Buffer Length exceeded available space \n"); + return(0); + } + + // (3.4.2) Create _PCT Object + DBG("Building _PCT Object\n"); + current = buildPCT(current); + + // Check to confirm no SSDT buffer overflow + if ( (U8 *)(current) > (U8 *)end ) + { + printf("Error: SSDT Buffer Length exceeded available space \n"); + return(0); + } + + // (3.4.3) Create _PPC Method + DBG("Building _PPC Method\n"); + current = buildPPC(current); + + // Check to confirm no SSDT buffer overflow + if ( (U8 *)(current) > (U8 *)end ) + { + printf("Error: SSDT Buffer Length exceeded available space \n"); + return(0); + } + + // (3.4.4) Create PSD with hardware coordination + { + DBG("Building _PSD Method\n"); + U32 domain = madt_info->lapic[lapic_index].pkg_index; + + // In this (bad?) implementation we use the nb of cpu found in the dsdt + U32 cpusInDomain = cpu_map_count; + current = buildPSD(current, domain, cpusInDomain, ACPI_COORD_TYPE); + } + + // Check to confirm no SSDT buffer overflow + if ( (U8 *)(current) > (U8 *)end ) + { + printf("Error: SSDT Buffer Length exceeded available space \n"); + return(0); + } + } + + // (3.5) Create C-state related structures + if (cstates_enabled == 1) + { + { + PKG_CSTATES * mwait_pkg_cstates = &cpu.pkg_mwait_cstates; + PKG_CSTATES * io_pkg_cstates = &cpu.pkg_io_cstates; + + // Build CST + DBG("Building _CST Method\n"); + current = buildCST(current, mwait_pkg_cstates, io_pkg_cstates); + } + +#if BUILD_ACPI_CSD + { + // Use core_apic_id as domain + U32 domain = lapic->core_apic_id; + + // In this (bad?) implementation we use the nb of cpu found in the dsdt + U32 cpusInDomain = cpu_map_count; + + // Create CSD + current = buildCSD(current, domain, cpusInDomain, io_pkg_cstates); + } +#endif + + // Check to confirm no SSDT buffer overflow + if ( (U8 *)(current) > (U8 *)end ) + { + printf("Error: SSDT Buffer Length exceeded available space \n"); + return(0); + } + } +#if BUILD_ACPI_TSS + // (3.6) Create T-state related structures + if (tstates_enabled == 1) + { + // (3.6.1) Create _TPC Method + current = buildTPC(current); + + // (3.6.2) Create _PTC Method + current = buildPTC(current); + + // (3.6.3) Create _TSS Method + { + PKG_TSTATES * pkg_tstates = &cpu.pkg_tstates; + current = buildTSS(current, pkg_tstates); + } + + // (3.6.4) Create _TSD Method + { + LAPIC_INFO * lapic = &madt_info.lapic[lapic_index]; + + // Use core_apic_id as domain + U32 domain = lapic->core_apic_id; + + // In this (bad?) implementation we use the nb of cpu found in the dsdt + U32 cpusInDomain = cpu_map_count; + + current = buildTSD(current, domain, cpusInDomain); + } + } +#endif + // (3.7) Update length in CPUn Scope + setPackageLength(&scope->pkgLength, (U8 *)current - (U8 *)&scope->pkgLength); + + } // End for + + // (4) Update length and checksum in SSDT Definition Block + { + DBG("Updating length and checksum in SSDT Definition Block\n"); + + SsdtPointer->Header.Length = (U8 *)current - (U8 *)SsdtPointer; + SetChecksum(&SsdtPointer->Header); + } + + // Check to confirm no SSDT buffer overflow + if ( (U8 *)current > (U8 *)end ) + { + printf("Error: SSDT Buffer Length exceeded available space \n"); + return(0); + } + + } // End build SSDT + + } // SSDT + + return(1); +} + +#if UNUSED +static ACPI_TABLE_FACS* generate_facs(bool updatefacs ) +{ + ACPI_TABLE_FACS* facs_mod=(ACPI_TABLE_FACS *)AllocateKernelMemory(sizeof(ACPI_TABLE_FACS)); + if (!facs_mod) + { + printf("Unable to allocate kernel memory for facs mod\n"); + return (void*)0ul; + } + bzero(facs_mod, sizeof(ACPI_TABLE_FACS)); + + ACPI_TABLE_FACS * FacsPointer =(acpi_tables.FacsPointer64 != (void *)0ul) ? + (ACPI_TABLE_FACS *)acpi_tables.FacsPointer64 : (ACPI_TABLE_FACS *)acpi_tables.FacsPointer; + + memcpy(facs_mod, FacsPointer , FacsPointer->Length); + facs_mod->Length = sizeof(ACPI_TABLE_FACS); + + if (FacsPointer->Length < sizeof(ACPI_TABLE_FACS)) + { + facs_mod->FirmwareWakingVector = 0; + facs_mod->GlobalLock = 0; + facs_mod->Flags = 0; + } + + if (updatefacs && FacsPointer->Version < 2) + { + if (FacsPointer->Version > 0) + { + facs_mod->XFirmwareWakingVector = FacsPointer->XFirmwareWakingVector; + } + else + { + facs_mod->XFirmwareWakingVector = (U64)facs_mod->FirmwareWakingVector; + } + + facs_mod->Version = 2; /* ACPI 1.0: 0, ACPI 2.0/3.0: 1, ACPI 4.0: 2 */ + + } + + return facs_mod; +} +#endif + +static ACPI_GENERIC_ADDRESS FillGASStruct(U32 Address, U8 Length) +{ + ACPI_GENERIC_ADDRESS TmpGAS; + + TmpGAS.SpaceId = 1; /* I/O Address */ + + if (Address == 0) + { + TmpGAS.BitWidth = 0; + } + else + { + TmpGAS.BitWidth = Length * 8; + } + + TmpGAS.BitOffset = 0; + TmpGAS.AccessWidth = 0; /* Not set for Legacy reasons... */ + TmpGAS.Address = (U64)Address; + + return (TmpGAS); +} + +static ACPI_TABLE_FADT * +patch_fadt(ACPI_TABLE_FADT *fadt, ACPI_TABLE_DSDT *new_dsdt, bool UpdateFADT) +{ + ACPI_TABLE_FADT *fadt_mod = (void*)0; + bool fadt_rev2_needed = false; + bool fix_restart = false; + const char * value; + + // Restart Fix + if (Platform.CPU.Vendor == CPUID_VENDOR_INTEL) + { + fix_restart = true; + getBoolForKey(kRestartFix, &fix_restart, &bootInfo->chameleonConfig); + + } else { + verbose ("Not an Intel platform: Restart Fix disabled !!!\n"); + } + + if (fix_restart) + fadt_rev2_needed = true; + + // Allocate new fadt table + if (UpdateFADT) + { + if (fadt->Header.Length < 0xF4) + { + fadt_mod=(ACPI_TABLE_FADT *)AllocateKernelMemory(0xF4); + if (!fadt_mod) + { + printf("Unable to allocate kernel memory for fadt mod\n"); + return (void*)0ul; + } + bzero(fadt_mod, 0xF4); + memcpy(fadt_mod, fadt, fadt->Header.Length); + fadt_mod->Header.Length = 0xF4; + + } + else + { + fadt_mod=(ACPI_TABLE_FADT *)AllocateKernelMemory(fadt->Header.Length); + if (!fadt_mod) + { + printf("Unable to allocate kernel memory for fadt mod\n"); + return (void*)0ul; + } + memcpy(fadt_mod, fadt, fadt->Header.Length); + } + + + //fadt_mod->Header.Revision = 0x04; // FADT rev 4 + fadt_mod->ResetRegister = FillGASStruct(0, 0); + fadt_mod->ResetValue = 0; + fadt_mod->Reserved4[0] = 0; + fadt_mod->Reserved4[1] = 0; + fadt_mod->Reserved4[2] = 0; + + fadt_mod->XPm1aEventBlock = FillGASStruct(fadt_mod->Pm1aEventBlock, fadt_mod->Pm1EventLength); + fadt_mod->XPm1bEventBlock = FillGASStruct(fadt_mod->Pm1bEventBlock, fadt_mod->Pm1EventLength); + fadt_mod->XPm1aControlBlock = FillGASStruct(fadt_mod->Pm1aControlBlock, fadt_mod->Pm1ControlLength); + fadt_mod->XPm1bControlBlock = FillGASStruct(fadt_mod->Pm1bControlBlock, fadt_mod->Pm1ControlLength); + fadt_mod->XPm2ControlBlock = FillGASStruct(fadt_mod->Pm2ControlBlock, fadt_mod->Pm2ControlLength); + fadt_mod->XPmTimerBlock = FillGASStruct(fadt_mod->PmTimerBlock, fadt_mod->PmTimerLength); + fadt_mod->XGpe0Block = FillGASStruct(fadt_mod->Gpe0Block, fadt_mod->Gpe0BlockLength); + fadt_mod->XGpe1Block = FillGASStruct(fadt_mod->Gpe1Block, fadt_mod->Gpe1BlockLength); + if (fadt->Header.Revision < 4) + { + fadt_mod->Header.Revision = 0x04; // FADT rev 4 + verbose("Converted ACPI V%d FADT to ACPI V4 FADT\n", fadt->Header.Revision); + + } + } + else + { + + if (fadt_rev2_needed) + { + if (fadt->Header.Length < 0x84 ) + { + fadt_mod=(ACPI_TABLE_FADT *)AllocateKernelMemory(0x84); + if (!fadt_mod) + { + printf("Unable to allocate kernel memory for fadt mod\n"); + return (void*)0ul; + } + bzero(fadt_mod, 0x84); + memcpy(fadt_mod, fadt, fadt->Header.Length); + fadt_mod->Header.Length = 0x84; + } + else + { + fadt_mod=(ACPI_TABLE_FADT *)AllocateKernelMemory(fadt->Header.Length); + if (!fadt_mod) + { + printf("Unable to allocate kernel memory for fadt mod\n"); + return (void*)0ul; + } + memcpy(fadt_mod, fadt, fadt->Header.Length); + } + + if (fadt->Header.Revision < 2) + { + fadt_mod->Header.Revision = 0x02; // FADT rev 2 (ACPI 1.0B MS extensions) + verbose("Converted ACPI V%d FADT to ACPI V2 FADT\n", fadt->Header.Revision ); + } + } + else + { + if (fadt->Header.Length < 0x74 ) + { + fadt_mod=(ACPI_TABLE_FADT *)AllocateKernelMemory(0x74); + if (!fadt_mod) + { + printf("Unable to allocate kernel memory for fadt mod\n"); + return (void*)0ul; + } + bzero(fadt_mod, 0x74); + memcpy(fadt_mod, fadt, fadt->Header.Length); + fadt_mod->Header.Length = 0x74; + fadt_mod->Header.Revision = 0x01; + verbose("Warning: ACPI FADT length was < 0x74 which is the minimum for the ACPI FADT V1 specification, \n", fadt->Header.Revision ); + verbose(" trying to convert it to Version 1. \n"); + + } + else + { + fadt_mod=(ACPI_TABLE_FADT *)AllocateKernelMemory(fadt->Header.Length); + if (!fadt_mod) + { + printf("Unable to allocate kernel memory for fadt mod\n"); + return (void*)0ul; + } + memcpy(fadt_mod, fadt, fadt->Header.Length); + } + } + } + bool intelfadtspec = true; + U8 Type = PMProfileError; + // Determine system type / PM_Model + + // Fix System-type if needed (should never happen) + if (Platform.Type > MaxSupportedPMProfile) + { + if(fadt_mod->PreferredProfile <= MaxSupportedPMProfile) + Platform.Type = fadt_mod->PreferredProfile;// get the fadt if correct + else + Platform.Type = 1; /* Set a fixed value (Desktop) */ + } + + // If needed, set System-type from PM_Profile (if valid) else set PM_Profile with a fixed the System-type + // Give prior to the FADT pm profile, allow to also control this value with a patched FADT table + if (fadt_mod->PreferredProfile != Platform.Type) + { + bool val = false; + getBoolForKey("PreferInternalProfileDetect", &val, &bootInfo->chameleonConfig); // if true Give prior to the profile resolved trought the CPU model + + //val = get_env(envIsServer) ; + + if (fadt_mod->PreferredProfile <= MaxSupportedPMProfile && !val) + { + Platform.Type = fadt_mod->PreferredProfile; + } + else + { + fadt_mod->PreferredProfile = (U8)Platform.Type; + } + + } + + // Set PM_Profile and System-type if user wanted this value to be forced + if ( (value=getStringForKey("SystemType", &bootInfo->chameleonConfig))!=NULL) + { + if ((Type = (unsigned char) strtoul(value, NULL, 10) ) <= MaxSupportedPMProfile) + { + if (fadt_mod->PreferredProfile != Type) + { + verbose("FADT: changing Preferred_PM_Profile from %d to %d\n", fadt->PreferredProfile, Type); + + Platform.Type = (fadt_mod->PreferredProfile = Type); + } + else + { + DBG("FADT: Preferred_PM_Profile was already set to %d, no need to be changed\n",Type); + } + + } else printf("Error: system-type must be 0..6. Defaulting to %d !\n", (U8)Platform.Type); + } + + getBoolForKey(KIntelFADT, &intelfadtspec, &bootInfo->chameleonConfig); + if ((pmbase == 0) && (cpu_map_error == 0) && (intelfadtspec == true)) + { + ACPI_TABLE_DSDT *DsdtPointer ; + if (new_dsdt != (void*)0ul) + DsdtPointer = new_dsdt; + else if ((fadt_mod->Header.Revision >= 3) && (fadt_mod->XDsdt != 0ul)) + DsdtPointer = (ACPI_TABLE_DSDT *)((U32)fadt_mod->XDsdt); + else + DsdtPointer = (ACPI_TABLE_DSDT *)fadt_mod->Dsdt; + + generate_cpu_map_from_acpi(DsdtPointer); + } + + // Patch DSDT Address if we have loaded a DSDT table + if(new_dsdt != (void*)0ul) + fadt_mod->Dsdt=(U32)new_dsdt; + + fadt_mod->Facs= fadt->Facs; + //fadt_mod->Facs=(U32)generate_facs(false); + + // Patch FADT to fix restart + if (fadt_mod->Header.Revision >= 2 && fix_restart) + { + fadt_mod->Flags|= 0x400; + + int type = PCI_RESET_TYPE; + getIntForKey(KResetType, &type, &bootInfo->chameleonConfig); + if (type == KEYBOARD_RESET_TYPE) + { + //Azi: keyboard reset; http://forum.voodooprojects.org/index.php/topic,1056.msg9802.html#msg9802 + fadt_mod->ResetRegister = FillGASStruct(0x64, 1); + fadt_mod->ResetValue = 0xfe; + } + else + { + fadt_mod->ResetRegister = FillGASStruct(0x0cf9, 1); + fadt_mod->ResetValue = 0x06; + } + verbose("FADT: Restart Fix applied (Type : %s) !\n", (type == 0) ? "PCI": "KEYBOARD"); + } + + if (fadt_mod->Header.Revision >= 3) + { + + + if (UpdateFADT) + { + + //fadt_mod->XFacs= (U64)((U32)generate_facs(true)); + fadt_mod->XFacs=(U64)fadt->Facs; + + } + else + { + fadt_mod->XFacs=(U64)fadt->XFacs; + } + + + if(new_dsdt != (void*)0ul) + fadt_mod->XDsdt=((U64)(U32)new_dsdt); + else if (UpdateFADT) + fadt_mod->XDsdt=(U64)fadt_mod->Dsdt; + + + //safe_set_env(envHardwareSignature,((ACPI_TABLE_FACS *)((U32)fadt_mod->XFacs))->HardwareSignature); + + + } +#if 0 + else + { + + safe_set_env(envHardwareSignature,((ACPI_TABLE_FACS *)fadt_mod->Facs)->HardwareSignature); + + } + + + DBG("setting hardware_signature to %x \n",(U32)get_env(envHardwareSignature)); +#endif + + + + if (pmbase && (intelfadtspec == true)) + ProcessFadt(fadt_mod, pmbase); // The checksum correction will be done by ProcessFadt + else + SetChecksum(&fadt_mod->Header); // Correct the checksum + + return fadt_mod; +} + +static U32 process_xsdt (ACPI_TABLE_RSDP *rsdp_mod , U32 *new_table_list) +{ + TagPtr DropTables_p = 0; + int DropTables_tag_count = 0; + + if (bootInfo->chameleonConfig.dictionary) + { + DropTables_p = XMLCastDict(XMLGetProperty(bootInfo->chameleonConfig.dictionary, (const char*)"ACPIDropTables")); + if (DropTables_p) DropTables_tag_count = XMLTagCount(DropTables_p) ; + } + + U32 new_table = 0ul; + U8 new_table_index = 0, table_added = 0; + ACPI_TABLE_XSDT *xsdt = (void*)0ul, *xsdt_mod = (void*)0ul; + ACPI_TABLE_RSDT *rsdt_conv = (void *)0ul; + + // FIXME: handle 64-bit address correctly + + xsdt=(ACPI_TABLE_XSDT *)acpi_tables.XsdtPointer; + + verbose("* Processing XSDT: \n"); + + DBG(" XSDT @%x, Length=%d\n", (U32)xsdt, + xsdt->Header.Length); + + if (xsdt != (void *)0ul) + { + U32 dropoffset=0, index; + table_added = 0; + + xsdt_mod=(ACPI_TABLE_XSDT *)AllocateKernelMemory(xsdt->Header.Length); + if (!xsdt_mod) + { + printf("Unable to allocate kernel memory for xsdt mod\n"); + return (0); + } + bzero(xsdt_mod, xsdt->Header.Length); + memcpy(&xsdt_mod->Header, &xsdt->Header, sizeof(ACPI_TABLE_HEADER)); + + U32 num_tables=get_num_tables64(xsdt); + + for (index = 0; index < num_tables; index++) + { + + U64 ptr = xsdt->TableOffsetEntry[index]; + + { + if (ptr > ULONG_MAX) + { +#if DEBUG_ACPI + printf("Warning xsdt->TableOffsetEntry[%d]: Beyond addressable memory in this CPU mode, ignored !!!\n",index); +#endif + continue; + } + + int method = 0; + getIntForKey(kAcpiMethod, &method, &bootInfo->chameleonConfig); + + + if (method != 0x2) + { + if (GetChecksum(((ACPI_TABLE_HEADER *) (unsigned long)ptr), + ((ACPI_TABLE_HEADER *) (unsigned long)ptr)->Length) != 0) + { +#if DEBUG_ACPI + printf("Warning xsdt->TableOffsetEntry[%d]: Invalide checksum, ignored !!!\n",index); +#endif + continue; + } + } + + } + + xsdt_mod->TableOffsetEntry[index-dropoffset]=ptr; + + char tableSig[5]; + strlcpy(tableSig, (char*)((U32)ptr), sizeof(tableSig)); + + DBG("** Processing %s,", tableSig ); + + DBG(" @%x, Length=%d\n", (U32)ptr, + ((ACPI_TABLE_HEADER *) (unsigned long)ptr)->Length); + + { + bool oem = false; + char oemOption[OEMOPT_SIZE]; + sprintf(oemOption, "oem%s",tableSig ); + if (getBoolForKey(oemOption, &oem, &bootInfo->chameleonConfig) && oem) // This method don't work for DSDT and FACS + { + + DBG(" %s required\n", oemOption); + + if (get_new_table_in_list(new_table_list,(*(U32 *) ((ACPI_TABLE_HEADER *) (unsigned long)ptr)->Signature), &new_table_index) != (void*)0ul) + new_table_list[new_table_index] = 0ul; // This way new table will not be added to the new rsdt list !! + + continue; + } + } + + if ((DropTables_tag_count > 0) && DropTables_p) + { + TagPtr match_drop = XMLGetProperty(DropTables_p, (const char*)tableSig); + if ( match_drop ) + { + char *tmp = XMLCastString(match_drop); + if (tmp && (strcmp(tmp,"No") != 0)) + { + dropoffset++; + DBG(" %s table dropped\n",tableSig); + continue; + } + } + } + + { + if ((new_table = (U32)get_new_table_in_list(new_table_list,(*(U32 *) ((ACPI_TABLE_HEADER *) (unsigned long)ptr)->Signature), &new_table_index)) != 0ul) + { + DBG(" Found replacement for table %s\n",tableSig); + xsdt_mod->TableOffsetEntry[index-dropoffset]=(U64)new_table; + new_table_list[new_table_index] = 0ul; // table replaced !! + continue; + } + } + + } + + + { + U8 i; + for (i = 0; i< (MAX_ACPI_TABLE + RESERVED_AERA); i++) + { + if (new_table_list[i] != 0ul) + { +#if DEBUG_ACPI + ACPI_TABLE_HEADER **table_array = (ACPI_TABLE_HEADER **) new_table_list; + printf("Adding table : "); + print_nameseg(*(U32 *) (table_array[i]->Signature)); + printf("\n"); +#endif + xsdt_mod->TableOffsetEntry[index-dropoffset]=(U64)new_table_list[i]; + table_added++; + index++; + } + } + } + + // Correct the checksum of XSDT + xsdt_mod->Header.Length-=8*dropoffset; + xsdt_mod->Header.Length+=8*table_added; + + SetChecksum(&xsdt_mod->Header); + + update_rsdp_with_xsdt(rsdp_mod, xsdt_mod); + + verbose("* Creating new RSDT from XSDT table\n"); + + rsdt_conv = (ACPI_TABLE_RSDT *)gen_alloc_rsdt_from_xsdt(xsdt_mod); + + if (rsdt_conv != (void*)0ul) + { +#if DEBUG_ACPI + DBG("Attempting to update RSDP with RSDT \n"); + { + U32 ret = update_rsdp_with_rsdt(rsdp_mod, rsdt_conv); + if (ret) + DBG("RSDP update with RSDT successfully !!! \n"); + } +#else + update_rsdp_with_rsdt(rsdp_mod, rsdt_conv); +#endif + } + + } + else + { + DBG("About to drop XSDT\n"); + + /*FIXME: Now we just hope that if MacOS doesn't find XSDT it reverts to RSDT. + * A Better strategy would be to generate + */ + + rsdp_mod->XsdtPhysicalAddress=0xffffffffffffffffLL; + verbose("XSDT not found or XSDT incorrect\n"); + } + return (1); + +} + +static U32 process_rsdt(ACPI_TABLE_RSDP *rsdp_mod , bool gen_xsdt, U32 *new_table_list) +{ + TagPtr DropTables_p = 0; + int DropTables_tag_count = 0; + + if (bootInfo->chameleonConfig.dictionary) + { + DropTables_p = XMLCastDict(XMLGetProperty(bootInfo->chameleonConfig.dictionary, (const char*)"ACPIDropTables")); + if (DropTables_p) DropTables_tag_count = XMLTagCount(DropTables_p) ; + } + + U32 new_table = 0ul; + U8 new_table_index = 0, table_added = 0; + U32 dropoffset=0, index; + ACPI_TABLE_RSDT *rsdt = (void *)0ul, *rsdt_mod = (void *)0ul; + ACPI_TABLE_XSDT *xsdt_conv = (void *)0ul; + + rsdt=(ACPI_TABLE_RSDT *)acpi_tables.RsdtPointer; + + rsdt_mod=(ACPI_TABLE_RSDT *)AllocateKernelMemory(rsdt->Header.Length); + + if (!rsdt_mod) + { + printf("Unable to allocate kernel memory for rsdt mod\n"); + return (0); + } + + bzero(rsdt_mod, rsdt->Header.Length); + memcpy (&rsdt_mod->Header, &rsdt->Header, sizeof(ACPI_TABLE_HEADER)); + + // Compute number of table pointers included in RSDT + U32 num_tables = get_num_tables(rsdt); + + verbose("* Processing RSDT: \n"); + + DBG(" RSDT @%x, Length %d\n",rsdt, rsdt->Header.Length); + + ACPI_TABLE_HEADER **table_array = (ACPI_TABLE_HEADER **) rsdt->TableOffsetEntry; + + for (index = 0; index < num_tables; index++) + { + + { + + int method = 0; + getIntForKey(kAcpiMethod, &method, &bootInfo->chameleonConfig); + + + if (method != 0x2) + { + if (GetChecksum(table_array[index], table_array[index]->Length) != 0) + { +#if DEBUG_ACPI + printf("Warning rsdt->TableOffsetEntry[%d]: Invalide checksum, ignored !!!\n",index); +#endif + continue; + } + } + + } + + rsdt_mod->TableOffsetEntry[index-dropoffset]=rsdt->TableOffsetEntry[index]; + + char tableSig[5]; + strlcpy(tableSig, (char*)(rsdt->TableOffsetEntry[index]), sizeof(tableSig)); + + DBG("** Processing %s,", tableSig ); + + DBG(" @%x, Length=%d\n", (U32)table_array[index], + table_array[index]->Length); + + { + bool oem = false; + char oemOption[OEMOPT_SIZE]; + sprintf(oemOption, "oem%s",tableSig ); + if (getBoolForKey(oemOption, &oem, &bootInfo->chameleonConfig) && oem) // This method don't work for DSDT and FACS + { + DBG(" %s required\n", oemOption); + + if (get_new_table_in_list(new_table_list,(*(U32 *) (table_array[index]->Signature)), &new_table_index) != (void*)0ul ) + new_table_list[new_table_index] = 0ul; // This way new table will not be added to the new rsdt list !! + + continue; + } + } + + if ((DropTables_tag_count > 0) && DropTables_p) + { + TagPtr match_drop = XMLGetProperty(DropTables_p, (const char*)tableSig); + if ( match_drop ) + { + char *tmp = XMLCastString(match_drop); + if (strcmp(tmp,"No") != 0) + { + dropoffset++; + DBG(" %s table dropped\n",tableSig); + continue; + } + } + } + + { + if ((new_table = (U32)get_new_table_in_list(new_table_list,(*(U32 *) (table_array[index]->Signature)), &new_table_index)) != 0ul) + { + DBG(" Found replacement for table %s\n",tableSig); + + rsdt_mod->TableOffsetEntry[index-dropoffset]=new_table; + new_table_list[new_table_index] = 0ul; // table replaced !! + continue; + } + } + + } + DBG("\n"); + + { + U8 i; + for (i = 0; i< (MAX_ACPI_TABLE + RESERVED_AERA); i++) + { + if (new_table_list[i] != 0ul) + { +#if DEBUG_ACPI + ACPI_TABLE_HEADER **table_array = (ACPI_TABLE_HEADER **) new_table_list; + printf("Adding table : "); + print_nameseg(*(U32 *) (table_array[i]->Signature)); + printf("\n"); +#endif + rsdt_mod->TableOffsetEntry[index-dropoffset]=new_table_list[i]; + table_added++; + index++; + } + } + } + + // Correct the checksum of RSDT + rsdt_mod->Header.Length-=4*dropoffset; + rsdt_mod->Header.Length+=4*table_added; + + DBG("RSDT: Original checksum %d\n", rsdt_mod->Header.Checksum); + + SetChecksum(&rsdt_mod->Header); + + DBG("New checksum %d at %x\n", rsdt_mod->Header.Checksum,rsdt_mod); + + update_rsdp_with_rsdt(rsdp_mod, rsdt_mod); + + if (gen_xsdt) + { + verbose("* Creating new XSDT from RSDT table\n"); + xsdt_conv = (ACPI_TABLE_XSDT *)gen_alloc_xsdt_from_rsdt(rsdt_mod); + + if (xsdt_conv != (void *)0ul ) + { +#if DEBUG_ACPI + DBG("Attempting to update RSDP with XSDT \n"); + { + U32 ret = update_rsdp_with_xsdt(rsdp_mod, xsdt_conv); + if (ret) + DBG("RSDP update with XSDT successfully !!! \n"); + } +#else + update_rsdp_with_xsdt(rsdp_mod, xsdt_conv); +#endif + + } + + } + return (1); +} + +EFI_STATUS setup_Acpi(void) +{ + U8 Revision = 0; + + cpu_map_error = 0; + cpu_map_count = 0; + pmbase = 0; + + EFI_STATUS Status = EFI_ABORTED; + + U32 new_table_list[MAX_ACPI_TABLE + RESERVED_AERA]; //max table + reserved aera + U8 new_table_index = 0; + + ACPI_TABLE_DSDT* DsdtPtr = (void *)0ul; // a Pointer to the dsdt table present in fadt_mod + + ACPI_TABLE_DSDT *new_dsdt = (void *)0ul; // a Pointer to the dsdt file + ACPI_TABLE_FADT *fadt_mod = (void *)0ul; // a Pointer to the patched FACP table + ACPI_TABLE_FADT *fadt_file = (void *)0ul; // a Pointer to the (non-patched) fadt file + ACPI_TABLE_FADT *FacpPointer = (void *)0ul; // a Pointer to the non-patched FACP table, it can be a file or the FACP table found in the RSDT/XSDT + ACPI_TABLE_RSDP *rsdp_mod = (void *)0ul, *rsdp_conv = (void *)0ul; + + U32 rsdplength; + + bool update_acpi=false, gen_xsdt=false; + + bool gen_csta=false, gen_psta=false, speed_step=false; + bool gen_ssdt=false; // will force to generate ssdt even if gen_csta and gen_psta = false + bool gen_tsta=false; + bool oem_dsdt=false, oem_fadt=false; + + // Find original rsdp + if (!FindAcpiTables(&acpi_tables)) + { + printf("Error: AcpiCodec Failed to detect ACPI tables.\n"); + getchar(); + return EFI_NOT_FOUND; + } + + { + U8 i; + + for (i=0; i<(MAX_ACPI_TABLE + RESERVED_AERA); i++) + { + new_table_list[i] = 0ul; + } + bool tmpval; + + oem_dsdt=getBoolForKey(kOEMDSDT, &tmpval, &bootInfo->chameleonConfig)&&tmpval; + oem_fadt=getBoolForKey(kOEMFADT, &tmpval, &bootInfo->chameleonConfig)&&tmpval; + + gen_csta=getBoolForKey(kGenerateCStates, &tmpval, &bootInfo->chameleonConfig)&&tmpval; + gen_psta=getBoolForKey(kGeneratePStates, &tmpval, &bootInfo->chameleonConfig)&&tmpval; + gen_ssdt=getBoolForKey(KForceSSDT, &tmpval, &bootInfo->chameleonConfig)&&tmpval; + update_acpi=getBoolForKey(kUpdateACPI, &tmpval, &bootInfo->chameleonConfig)&&tmpval; + + speed_step=getBoolForKey(kSpeedstep, &tmpval, &bootInfo->chameleonConfig)&&tmpval; + turbo_enabled=(U32)getBoolForKey(kCoreTurbo, &tmpval, &bootInfo->chameleonConfig)&&tmpval; +#if BUILD_ACPI_TSS + gen_tsta=(U32)getBoolForKey(kGenerateTStates, &tmpval, &bootInfo->chameleonConfig)&&tmpval; +#endif + checkOem=getBoolForKey(kOnlySignedAml, &tmpval, &bootInfo->chameleonConfig)&&tmpval; + } + + { + long ret, length, flags, time; + long long index = 0; + const char * name; + + U8 i = 0; + char dirspec[512]; + bool acpidir_found = false; + + ret = GetFileInfo("rd(0,0)/Extra/", "Acpi", &flags, &time); + if ((ret == 0) && ((flags & kFileTypeMask) == kFileTypeDirectory)) + { + sprintf(dirspec, "rd(0,0)/Extra/Acpi/"); + acpidir_found = true; + + } + else + { + + ret = GetFileInfo("/Extra/", "Acpi", &flags, &time); + if ((ret == 0) && ((flags & kFileTypeMask) == kFileTypeDirectory)) + { + sprintf(dirspec, "/Extra/Acpi/"); + acpidir_found = true; + + } + else + { + ret = GetFileInfo("bt(0,0)/Extra/", "Acpi", &flags, &time); + if ((ret == 0) && ((flags & kFileTypeMask) == kFileTypeDirectory)) + { + sprintf(dirspec, "bt(0,0)/Extra/Acpi/"); + acpidir_found = true; + + } + } + } + + if (acpidir_found == true) + { +#if ACPISGN + if (checkOem == true) + { + MakeAcpiSgn(); + } +#endif + + while (1) { + ret = GetDirEntry(dirspec, &index, &name, &flags, &time); + if (ret == -1) break; +#if DEBUG_ACPI + printf("testing %s\n", name); +#endif + // Make sure this is a directory. + if ((flags & kFileTypeMask) == kFileTypeDirectory) continue; + + // Make sure this is a kext. + length = strlen(name); + if (strcmp(name + length - 4, ".aml")) + { +#if DEBUG_ACPI + printf("Ignoring %s\n", name); +#endif + continue; + } + + // Some simple verifications to save time in case of those tables simply named as follow: + if ((strncmp(name, "RSDT", 4) == 0) || (strncmp(name, "rsdt", 4) == 0) || + (strncmp(name, "XSDT", 4) == 0) || (strncmp(name, "xsdt", 4) == 0) || + (strncmp(name, "RSDP", 4) == 0) || (strncmp(name, "rsdp", 4) == 0)) + { +#if DEBUG_ACPI + printf("Ignoring %s\n", name); +#endif + continue; + } + + if ((strncmp(name, "FACS", 4) == 0) || (strncmp(name, "facs", 4) == 0)) // FACS is not supported + { +#if DEBUG_ACPI + printf("Ignoring %s\n", name); +#endif + continue; + } + + DBG("* Attempting to load acpi table: %s\n", name); + if ( (new_table_list[i]=(U32)loadACPITable(new_table_list,dirspec,name))) + { + if (i < MAX_ACPI_TABLE) + { + i++; + } + else + { + DBG("Max nb of allowed aml files reached, exiting ."); + break; + } + } + } + + if (i) + { + //sanitize the new tables list + sanitize_new_table_list(new_table_list); + + //move to kernel memory + move_table_list_to_kmem(new_table_list); + + DBG("New ACPI tables Loaded in memory\n"); + } + + + } + + } +#if HARDCODED_DSDT + do { +#include "dsdt_PRLSACPI.h" + + U8 index = 0; + + if ((get_new_table_in_list(new_table_list, NAMESEG("DSDT"), &new_table_index)) != (void*)0ul ) + { + index = new_table_index; + } + else + { + U8 empty = get_0ul_index_in_list(new_table_list, false); + if (empty != ACPI_TABLE_LIST_FULL_NON_RESERVED) + { + index = empty; + } + else + { + printf("Error: not enought reserved space in the new acpi list for the Harcoded DSDT table,\n "); + printf(" please increase the RESERVED_AERA\n"); + + break; + } + } + + if (index) + { + + ACPI_TABLE_DSDT *tmp = (ACPI_TABLE_DSDT *)DsdtAmlCode; + ACPI_TABLE_DSDT *hardcoded_dsdt = (void *)0ul; + + hardcoded_dsdt = (ACPI_TABLE_DSDT *)AllocateKernelMemory(tmp->Header.Length); + memcpy(hardcoded_dsdt, tmp, tmp->Header.Length); + new_table_list[index] = (U32)hardcoded_dsdt; // add the patched table to the list + } + else + { + printf("Error: not enought reserved space in the new acpi list for the Harcoded DSDT table,\n "); + printf(" please increase the RESERVED_AERA\n"); + + break; + } + } while (0); +#endif + if (speed_step) + { + gen_psta= true; + gen_csta= true; + } + + + ACPI_TABLE_RSDP *rsdp=(ACPI_TABLE_RSDP *)acpi_tables.RsdPointer; + + if (rsdp == (void*)0ul || (GetChecksum(rsdp, (rsdp->Revision == 0) ? ACPI_RSDP_REV0_SIZE:sizeof(ACPI_TABLE_RSDP)) != 0) ) + { + printf("Error : ACPI RSD PTR Revision %d checksum is incorrect or table not found \n",rsdp->Revision ); + return EFI_UNSUPPORTED; + } + + if ((update_acpi) && (rsdp->Revision == 0)) + { + + rsdp_conv = (ACPI_TABLE_RSDP *)gen_alloc_rsdp_v2_from_v1(rsdp); + if (rsdp_conv != (void *)0ul) + { + gen_xsdt = true; + rsdp = rsdp_conv; + verbose("Converted ACPI RSD PTR Revision 0 to Revision 2\n"); + } + + } + + Revision = rsdp->Revision ; + rsdplength=(Revision == 2)?rsdp->Length:ACPI_RSDP_REV0_SIZE; + + DBG("RSDP Revision %d found @%x. Length=%d\n",Revision,rsdp,rsdplength); + + if (gen_xsdt) + { + rsdp_mod=rsdp_conv; + } + else + { + rsdp_mod=(ACPI_TABLE_RSDP *) AllocateKernelMemory(rsdplength); + + if (!rsdp_mod) return EFI_OUT_OF_RESOURCES; + + memcpy(rsdp_mod, rsdp, rsdplength); + } + + + if ((fadt_file = (ACPI_TABLE_FADT *)get_new_table_in_list(new_table_list, NAMESEG("FACP"), &new_table_index)) != (void *)0ul) + { + + if (oem_fadt == false) + FacpPointer = (ACPI_TABLE_FADT *)fadt_file; + + new_table_list[new_table_index] = 0ul; // This way, the non-patched table will not be added in our new rsdt/xsdt table list + + } else + FacpPointer = (acpi_tables.FacpPointer64 != (void *)0ul) ? + (ACPI_TABLE_FADT *)acpi_tables.FacpPointer64 : (ACPI_TABLE_FADT *)acpi_tables.FacpPointer; + +#if DEBUG_ACPI + if ((FacpPointer != (void *)0ul) || (oem_fadt == false)) + { + printf("FADT found @%x, Length %d\n",FacpPointer, FacpPointer->Header.Length); + printf("Attempting to patch FADT entry of %s\n",(acpi_tables.FacpPointer64 != (void *)0ul) ? ACPI_SIG_XSDT : ACPI_SIG_RSDT); + } + else if (oem_fadt == true) + { + ACPI_TABLE_FADT * FacpPtr = (acpi_tables.FacpPointer64 != (void *)0ul) ? + (ACPI_TABLE_FADT *)acpi_tables.FacpPointer64 : (ACPI_TABLE_FADT *)acpi_tables.FacpPointer; + + printf("FADT found @%x ( Length %d ) in %s \n",FacpPtr, FacpPtr->Header.Length, (acpi_tables.FacpPointer64 != (void *)0ul) ? ACPI_SIG_XSDT : ACPI_SIG_RSDT); + } +#endif + + if ((new_dsdt = (ACPI_TABLE_DSDT *)get_new_table_in_list(new_table_list, NAMESEG("DSDT"), &new_table_index)) != (void*)0ul ) + { + new_table_list[new_table_index] = 0ul; // This way, the DSDT file will not be added in our new rsdt/xsdt table list, and it shouldn't be anyway + } + + if (oem_fadt == false) + { + + fadt_mod = patch_fadt(FacpPointer, (oem_dsdt == false) ? new_dsdt : (void*)0ul , (acpi_tables.FacpPointer64 != (void *)0ul )); + + if (fadt_mod != (void*)0ul) + { + DsdtPtr = ((fadt_mod->Header.Revision >= 3) && (fadt_mod->XDsdt != 0)) ? (ACPI_TABLE_DSDT*)((U32)fadt_mod->XDsdt):(ACPI_TABLE_DSDT*)fadt_mod->Dsdt; + + U8 empty = get_0ul_index_in_list(new_table_list,true); + if (empty != ACPI_TABLE_LIST_FULL) + { + new_table_list[empty] = (U32)fadt_mod; // add the patched table to the list + } + else + { + printf("Error: not enought reserved space in the new acpi list for the Patched FACP table,\n "); + printf(" please increase the RESERVED_AERA\n"); + } + + } + else + { + printf("Error: Failed to patch the FADT Table, trying fallback to the FADT original pointer\n"); + fadt_mod = (acpi_tables.FacpPointer64 != (void *)0ul) ? + (ACPI_TABLE_FADT *)acpi_tables.FacpPointer64 : (ACPI_TABLE_FADT *)acpi_tables.FacpPointer; + + DsdtPtr = ((fadt_mod->Header.Revision >= 3) && (fadt_mod->XDsdt != 0)) ? (ACPI_TABLE_DSDT*)((U32)fadt_mod->XDsdt):(ACPI_TABLE_DSDT*)fadt_mod->Dsdt; + + U8 empty = get_0ul_index_in_list(new_table_list,true); + if (empty != ACPI_TABLE_LIST_FULL) + { + new_table_list[empty] = (U32)fadt_mod; + } + else + { + printf("Error: not enought reserved space in the new acpi list for the FACP table,\n "); + printf(" please increase the RESERVED_AERA\n"); + } + } + + if (oem_dsdt == false) + { + if (generate_cpu_map_from_acpi(DsdtPtr) == 0) + { + U8 new_uid = (U8)getPciRootUID(); + + /* WARNING: THIS METHOD WORK PERFECTLY BUT IT CAN RESULT TO AN INCORRECT CHECKSUM */ + + if (ProcessDsdt(DsdtPtr, UIDPointer, new_uid)) + { + printf("PCI0 _UID patched to %d in the DSDT table\n", new_uid); + } + + } + } + + + } + else + { + + // here we use the variable fadt_mod only for SSDT Generation + + fadt_mod = (acpi_tables.FacpPointer64 != (void *)0ul) ? + (ACPI_TABLE_FADT *)acpi_tables.FacpPointer64 : (ACPI_TABLE_FADT *)acpi_tables.FacpPointer; + + DsdtPtr = ((fadt_mod->Header.Revision >= 3) && (fadt_mod->XDsdt != 0)) ? (ACPI_TABLE_DSDT*)((U32)fadt_mod->XDsdt) + :(ACPI_TABLE_DSDT*)fadt_mod->Dsdt; + } + + { + MADT_INFO madt_info; + bool strip_madt = true; + + getBoolForKey(kSTRIPAPIC, &strip_madt, &bootInfo->chameleonConfig); + + if ((strip_madt == false) || (!buildMADT(new_table_list, DsdtPtr, &madt_info ))) + { + + ACPI_TABLE_MADT * madt_file = (void*)0ul; + ACPI_TABLE_MADT * MadtPointer = (void*)0ul; + bool oem_apic=false; + + { + bool tmpval; + oem_apic=getBoolForKey(kOEMAPIC, &tmpval, &bootInfo->chameleonConfig)&&tmpval; + } + + if ((madt_file = (ACPI_TABLE_MADT *)get_new_table_in_list(new_table_list, NAMESEG("APIC"), &new_table_index)) != (void *)0ul) + { + if (oem_apic == false) + { + MadtPointer = (ACPI_TABLE_MADT *)madt_file; + } + + } else + MadtPointer = (acpi_tables.MadtPointer64 != (void*)0ul) ? (ACPI_TABLE_MADT *)acpi_tables.MadtPointer64 : (ACPI_TABLE_MADT *)acpi_tables.MadtPointer; + + ProcessMadtInfo(MadtPointer, &madt_info); + + } + + if (gen_ssdt || gen_csta || gen_psta || gen_tsta) + { + ProcessSsdt(new_table_list, DsdtPtr, &madt_info, gen_csta, gen_psta, gen_tsta ); + } + } + + if ((rsdp_mod != (void *)0ul) && (rsdp_mod->Length >= ACPI_RSDP_REV0_SIZE) ) + { + if ((rsdp_mod->Revision == 0) || (gen_xsdt == true)) + { + process_rsdt(rsdp_mod, gen_xsdt, new_table_list); + goto out; + } + + } + else + { + printf("Error: Incorect ACPI RSD PTR or not found \n"); + return EFI_UNSUPPORTED; + } + + if ((GetChecksum(rsdp_mod, sizeof(ACPI_TABLE_RSDP)) == 0) && + (Revision == 2) && + (rsdplength == sizeof(ACPI_TABLE_RSDP))) + { + process_xsdt(rsdp_mod, new_table_list); + + } + else + { + printf("Warning : ACPI RSD PTR Revision 2 is incorrect, \n"); + printf(" trying to fallback to Revision 1\n"); + if ((rsdp_mod != (void *)0ul) && (rsdp_mod->Length >= ACPI_RSDP_REV0_SIZE) ) + { + process_rsdt(rsdp_mod, false, new_table_list); + + } + else + { + printf("Error: Incorect ACPI RSD PTR or not found \n"); + return EFI_UNSUPPORTED; + } + } + +out: + // Correct the checksum of RSDP + + DBG("RSDP: Original checksum %d\n", rsdp_mod->Checksum); + + setRsdpchecksum(rsdp_mod); + + DBG("New checksum %d\n", rsdp_mod->Checksum); + + if (Revision == 2) + { + DBG("RSDP: Original extended checksum %d\n", rsdp_mod->ExtendedChecksum); + + setRsdpXchecksum(rsdp_mod); + + DBG("New extended checksum %d\n", rsdp_mod->ExtendedChecksum); + + } + + verbose("ACPI Revision %d successfully patched\n", Revision); + + if (Revision == 2) + { + /* XXX aserebln why uint32 cast if pointer is uint64 ? */ + rsd_p = (U32)rsdp_mod; + addConfigurationTable(&gEfiAcpi20TableGuid, &rsd_p, "ACPI_20"); + } + else + { + /* XXX aserebln why uint32 cast if pointer is uint64 ? */ + rsd_p = (U32)rsdp_mod; + addConfigurationTable(&gEfiAcpiTableGuid, &rsd_p, "ACPI"); + } + + +#if DEBUG_ACPI==2 + printf("Press a key to continue... (DEBUG_ACPI)\n"); + getc(); +#endif + return Status; +} + +int AcpiSetup(void) +{ + EFI_STATUS status = setup_Acpi(); + + return (status == EFI_SUCCESS); +} Property changes on: trunk/i386/modules/Sata/include/acpi_codec.c ___________________________________________________________________ Added: svn:executable + * Index: trunk/i386/modules/Sata/include/ACPICodec.c =================================================================== --- trunk/i386/modules/Sata/include/ACPICodec.c (revision 0) +++ trunk/i386/modules/Sata/include/ACPICodec.c (revision 2031) @@ -0,0 +1,15 @@ +/* + * Copyright (c) 2010,2012 cparm . All rights reserved. + * + */ + +#include "libsaio.h" +#include "modules.h" +#include "bootstruct.h" +#include "acpi_codec.h" + +void ACPICodec_start(void); +void ACPICodec_start(void) +{ + replace_function("_setupAcpi",&AcpiSetup); +} \ No newline at end of file Property changes on: trunk/i386/modules/Sata/include/ACPICodec.c ___________________________________________________________________ Added: svn:executable + * Index: trunk/i386/modules/Sata/include/Readme.txt =================================================================== --- trunk/i386/modules/Sata/include/Readme.txt (revision 0) +++ trunk/i386/modules/Sata/include/Readme.txt (revision 2031) @@ -0,0 +1,130 @@ +Module: ACPICodec +Description: This module provides a remplacement for the internal acpi patcher +Dependencies: none + +Help: + +AcpiCodec module: (Warning: acpi signature not implemented) +------------------ + IMPORTANT NOTE: 1- with AcpiCodec all aml files must be placed in /Extra/Acpi/, alternate or overridden path is no longer supported + + 2- the name of the aml file(s) is not important anymore but it must contain the extention .aml, for example let suppose that you have 3 aml files: dsdt.aml, ssdt-0.aml and ssdt-1.aml + you can rename your dsdt file into blablabr.aml, and rename your ssdt files into blablablaen.aml and blablablablada.aml, acpicodec will auto-magically detect those files as 2 ssdt and one dsdt + + RestartFix=Yes|No Enable/Disable internal restart fix patch (Enabled by default, only available for intel platform). + + ResetType=0|1 0 : PCI reset (Default) + 1 : keyboard reset + + EnableSpeedStep=Yes|No Enable/Disable GenerateCStates & GeneratePStates (Disabled by default). + + GeneratePStates=Yes|No Enable/Disable Generate P-states SSDT table (Disabled by default). + GenerateCStates=Yes|No Enable/Disable Generate C-states SSDT table (Disabled by default). + EnableC4State=Yes|No Enable C4 state in C-states SSDT table, GenerateCStates=Yes is needed (Disabled by default). + + StripAPICTable=Yes|No Enable/Disable Generate a stripped MADT (APIC) table (Enabled by default). + + IntelFADTSpec=Yes|No Enable/Disable Intel recommendations for the FADT table (Enabled by default). + Warning : When enabled, this setting disable the C2 and C3 C-states, but be aware that these are the Intel's recommendations for the newest CPU, + if you really need those c-states please disable IntelFADTSpec. + + P-States= P-States fine tuning method, see usage below(GeneratePStates=Yes is needed). + ACPIDropTables= drop acpi table(s) method (can drop any unwanted tables), see usage below. + C-States= C-States fine tuning method, see usage below(GenerateCStates=Yes is needed). + + + UpdateACPI=Yes|No Enable/Disable ACPI version update(Disabled by default). + + MaxBusRatio= (was BusRatio) Set the current Bus Ratio to n, + n must be a multiple of 10, + (eg. if you want to set a bus ratio to 8.5, n will be + 8.5*10=85), + if n = 0, MaxBusRatio = Disable, + if set, Acpipatcher will drop every P-states with + a bus ratio higher than n. + + MinBusRatio= Set the Minimum Bus Ratio to n, + n must be a multiple of 10, + (eg. if you want to set the bus ratio to 8.5, n will be + 8.5*10=85), if set Acpipatcher will drop every + P-states with a bus ratio lower than n, + if n = 0, MinBusRatio = Disable. + + P-States usage e.g: (by default all numbers must be expressed in base 16, + except the pss statue key and base key itself) + + P-States + + 0 // the pss status (must be expressed in Base 10) + + Bus Master Latency + 10 + Control + 18719 + CoreFreq + 3164 + Transition Latency + 10 + + 1 // the pss status (must be expressed in Base 10) + . + . + . + + 2 // the pss status (must be expressed in Base 10) + . + . + . + + X // the pss status (must be expressed in Base 10) + . + . + . + + Base + 10 // must always be expressed in Base 10 + Mode + Default + + + + C-States usage e.g: (by default all numbers must be expressed in base 16, + except the base key itself) + + C-states + + C1 + + Latency + THE LATENCY FOR THIS STATE + Power + THE POWER FOR THIS STATE + + . + . + C4 + + Latency + THE LATENCY FOR THIS STATE + Power + THE POWER FOR THIS STATE + + + + ACPIDropTables usage e.g: + + ACPIDropTables + + SSDT + // drop SSDT table(s) + TAMG + Yes //drop TAMG table + ECDT + ANY_VALUE_EXCEPT_NO //drop ECDT table + XXXX + //drop XXXX table (if exist) + YYYY + No //do not drop YYYY table (if exist) + + + Index: trunk/i386/modules/Sata/include/Makefile =================================================================== --- trunk/i386/modules/Sata/include/Makefile (revision 0) +++ trunk/i386/modules/Sata/include/Makefile (revision 2031) @@ -0,0 +1,13 @@ +MODULE_NAME = ACPICodec +MODULE_DESCRIPTION = This module provides a remplacement for the internal acpi patcher +MODULE_AUTHOR = "Cparm" +MODULE_VERSION = "1.0.0" +MODULE_COMPAT_VERSION = "1.0.0" +MODULE_START = $(MODULE_NAME)_start +MODULE_DEPENDENCIES = + +DIR = ACPICodec + +MODULE_OBJS = ACPICodec.o acpi_tools.o acpi_codec.o acpidecode.o acpicode.o + +include ../MakeInc.dir \ No newline at end of file Property changes on: trunk/i386/modules/Sata/include/Makefile ___________________________________________________________________ Added: svn:executable + * Index: trunk/i386/modules/Sata/include/acpi_tools.c =================================================================== --- trunk/i386/modules/Sata/include/acpi_tools.c (revision 0) +++ trunk/i386/modules/Sata/include/acpi_tools.c (revision 2031) @@ -0,0 +1,328 @@ +/* + Copyright (c) 2010, Intel Corporation + All rights reserved. + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + * Neither the name of Intel Corporation nor the names of its contributors + may be used to endorse or promote products derived from this software + without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND + ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR + ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +#include "libsaio.h" +#include "bootstruct.h" +#include "datatype.h" +#include "intel_acpi.h" +#include "ppm.h" +#include "acpi.h" + +static U32 GetRsdtPointer(void *mem_addr, U32 mem_size, ACPI_TABLES * acpi_tables); +static U32 GetXsdtPointer(ACPI_TABLES * acpi_tables); +static ACPI_TABLE_HEADER *GetTablePtr(ACPI_TABLE_RSDT * rsdt, U32 signature); +static ACPI_TABLE_HEADER *GetTablePtr64(ACPI_TABLE_XSDT * xsdt, U32 signature); + +//------------------------------------------------------------------------------- +// +// Procedure: FindAcpiTables - Collects addresses for RSDP, RSDT, FADT, & DSDT. +// +// Description: Finds the differentiated system description table pointer +// by scanning and checking ACPI tables. This function will +// get and store the following ACPI Table Pointers: +// 1) RSD Pointer in RsdPointer Variable +// 2) RSDT Pointer in RsdtPointer Variable (RSDP->RSDT) +// 3) XSDT Pointer in XsdtPointer Variable (RSDP->XSDT) +// 4) FACP Pointer in FacpPointer Variable (RSDP->RSDT->FACP) +// 5) FACP(64) Pointer in FacpPointer64 Variable (RSDP->XSDT->FACP) +// 6) DSDT Pointer in DsdtPointer Variable (RSDP->RSDT->FACP->DSDT) +// 7) DSDT(64) Pointer in DsdtPointer64 Variable (RSDP->XSDT->FACP->XDSDT) +// 8) FACS Pointer in FacsPointer Variable (RSDP->RSDT->FACP->FACS) +// 9) FACS(64) Pointer in FacsPointer64 Variable (RSDP->XSDT->FACP->XFACS) +// A) MADT Pointer in FacsPointer Variable (RSDP->RSDT->APIC) +// B) MADT(64) Pointer in MadtPointer64 Variable (RSDP->XSDT->APIC) +// +//------------------------------------------------------------------------------- +U32 FindAcpiTables(ACPI_TABLES * acpi_tables) +{ + U32 success = 0ul; + + // Perform init of ACPI table pointers + { + void *null = 0ul; + acpi_tables->DsdtPointer = null; + acpi_tables->DsdtPointer64 = null; + acpi_tables->FacpPointer = null; + acpi_tables->FacsPointer = null; + acpi_tables->FacsPointer64 = null; + acpi_tables->RsdPointer = null; + acpi_tables->RsdtPointer = null; + acpi_tables->MadtPointer = null; + acpi_tables->MadtPointer64 = null; + acpi_tables->XsdtPointer = null; + acpi_tables->FacpPointer64 = null; + } + + // Find the RSDT pointer by scanning EBDA/E000/F000 segments. + + // Init memory address as EBDA and scan 1KB region + success = GetRsdtPointer((void *)(((U32) * (U16 *) 0x40E) << 4), 0x400, acpi_tables); + + // Init memory address as E000 segment and scan 64KB region + if (!success) + success = GetRsdtPointer((void *)0x0E0000, 0x10000, acpi_tables); + + // Init memory address as F000 segment and scan 64KB region + if (!success) + success = GetRsdtPointer((void *)0x0F0000, 0x10000, acpi_tables); + + if (!success || (acpi_tables->RsdtPointer == 0ul)) + return (0ul); + + success = GetXsdtPointer(acpi_tables); + + // Find FACP table pointer which is one of table pointers in the RDST + acpi_tables->FacpPointer = (ACPI_TABLE_FADT *) + GetTablePtr(acpi_tables->RsdtPointer, NAMESEG("FACP")); + if (acpi_tables->FacpPointer == 0ul) + return (0ul); + + // Find the DSDT which is included in the FACP table + acpi_tables->DsdtPointer = (ACPI_TABLE_DSDT *) acpi_tables->FacpPointer->Dsdt; + if ((acpi_tables->DsdtPointer == 0ul) || (*(U32 *) (acpi_tables->DsdtPointer->Header.Signature) != NAMESEG("DSDT")) || + (GetChecksum(acpi_tables->DsdtPointer, acpi_tables->DsdtPointer->Header.Length) != 0)) + return (0ul); + + // Find the FACS which is included in the FACP table + acpi_tables->FacsPointer = (ACPI_TABLE_FACS *) acpi_tables->FacpPointer->Facs; + if ((acpi_tables->FacsPointer == 0ul) || (*(U32 *) (acpi_tables->FacsPointer->Signature) != NAMESEG("FACS"))) + return (0ul); + + // Find the MADT table which is one of the table pointers in the RSDT + acpi_tables->MadtPointer = (ACPI_TABLE_MADT *) GetTablePtr(acpi_tables->RsdtPointer, NAMESEG("APIC")); + if (acpi_tables->MadtPointer == 0ul) + return (0ul); + + do { + + if (!success || (acpi_tables->XsdtPointer == 0ul)) + break; + + // Find FACP(64) table pointer which is one of table pointers in the XDST + acpi_tables->FacpPointer64 = (ACPI_TABLE_FADT *) + GetTablePtr64(acpi_tables->XsdtPointer, NAMESEG("FACP")); + + if (acpi_tables->FacpPointer64 == 0ul) + break; + + // Find the XDSDT which is included in the FACP(64) table + ACPI_TABLE_DSDT *DsdtPointer64 = (ACPI_TABLE_DSDT *)((U32)acpi_tables->FacpPointer64->XDsdt); + + if (DsdtPointer64 == 0ul) + break; + + if ((*(U32*) (DsdtPointer64->Header.Signature) == NAMESEG("DSDT")) && + (GetChecksum(DsdtPointer64, DsdtPointer64->Header.Length) == 0)) + acpi_tables->DsdtPointer64 = (ACPI_TABLE_DSDT *) DsdtPointer64; + + // Find the XFACS which is included in the FACP(64) table + ACPI_TABLE_FACS *FacsPointer64 = (ACPI_TABLE_FACS *)((U32)acpi_tables->FacpPointer64->XFacs); + + if (FacsPointer64 == 0ul) + break; + + if (*(U32*) (FacsPointer64->Signature) == NAMESEG("FACS")) + acpi_tables->FacsPointer64 = (ACPI_TABLE_FACS *) FacsPointer64; + + + // Find the MADT(64) table which is one of the table pointers in the XSDT + acpi_tables->MadtPointer64 = (ACPI_TABLE_MADT *) GetTablePtr64(acpi_tables->XsdtPointer, NAMESEG("APIC")); + + } while (0); + + + return (1ul); +} + +//----------------------------------------------------------------------------- +U32 get_num_tables(ACPI_TABLE_RSDT * rsdt) +{ + // Compute number of table pointers included in RSDT + return ((rsdt->Header.Length - sizeof(ACPI_TABLE_HEADER)) + / sizeof(ACPI_TABLE_HEADER *)); +} + +//----------------------------------------------------------------------------- +U32 get_num_tables64(ACPI_TABLE_XSDT * xsdt) +{ + { + void *null = 0ul; + if (xsdt == null) + return 0ul; + } + + // Compute number of table pointers included in XSDT + return ((xsdt->Header.Length - sizeof(ACPI_TABLE_HEADER)) + / sizeof(U64)); +} + +//------------------------------------------------------------------------------- +// +// Procedure: GetTablePtr - Find ACPI table in RSDT with input signature. +// +//------------------------------------------------------------------------------- +static ACPI_TABLE_HEADER *GetTablePtr(ACPI_TABLE_RSDT * rsdt, U32 signature) +{ + U32 index; + U32 num_tables; + ACPI_TABLE_HEADER **table_array = (ACPI_TABLE_HEADER **) rsdt->TableOffsetEntry; + + // Compute number of table pointers included in RSDT + num_tables = get_num_tables(rsdt); + + for (index = 0; index < num_tables; index++) { + if ((*(U32 *) (table_array[index]->Signature) == signature) && + (GetChecksum(table_array[index], table_array[index]->Length) == 0)) { + return (table_array[index]); + } + } + return (0); +} + +//------------------------------------------------------------------------------- +// +// Procedure: GetTablePtr64 - Find ACPI table in XSDT with input signature. +// +//------------------------------------------------------------------------------- +static ACPI_TABLE_HEADER *GetTablePtr64(ACPI_TABLE_XSDT * xsdt, U32 signature) +{ + U32 index; + U32 num_tables; + + int method; + + // Compute number of table pointers included in XSDT + num_tables = get_num_tables64(xsdt); + + getIntForKey(kAcpiMethod, &method, &bootInfo->chameleonConfig); + switch (method) { + case 0x2: + { + for (index = 0; index < num_tables; index++) { + U64 ptr = xsdt->TableOffsetEntry[index]; + + if ((*(U32 *) ((ACPI_TABLE_HEADER *) (unsigned long)ptr)->Signature == signature) && + (GetChecksum(((ACPI_TABLE_HEADER *) (unsigned long)ptr), ((ACPI_TABLE_HEADER *) (unsigned long)ptr)->Length) == 0)) { + return (((ACPI_TABLE_HEADER *) (unsigned long)ptr)); + } + } + break; + } + case 0x1: + default: + { + ACPI_TABLE_HEADER *table = (ACPI_TABLE_HEADER *) xsdt->TableOffsetEntry; + + for (index = 0; index < num_tables; index++) { + if (((U32) (table->Signature) == signature) && + (GetChecksum(table, table->Length) == 0)) { + return (table); + } + // Move array pointer to next 64-bit pointer + table = (ACPI_TABLE_HEADER *) ((U32) table + sizeof(U64)); + } + break; + } + } + + return (0); +} + +//------------------------------------------------------------------------------- +// +// Procedure: GetChecksum - Performs byte checksum +// +//------------------------------------------------------------------------------- +U8 GetChecksum(void *mem_addr, U32 mem_size) +{ + U8 *current = mem_addr; + U8 *end = current + mem_size; + U8 checksum = 0; + + for (; current < end; current++) + checksum = checksum + *current; + + return (checksum); +} + +/*========================================================================== + * Function to map 32 bit physical address to 64 bit virtual address + */ + + +//------------------------------------------------------------------------------- +// +// Procedure: GetRsdtPointer - Scans given segment for RSDT pointer +// +// Description: Scans for root system description table pointer signature +// ('RSD PTR ') , verifies checksum, and returns pointer to +// RSDT table if found. +// +//------------------------------------------------------------------------------- +static U32 GetRsdtPointer(void *mem_addr, U32 mem_size, ACPI_TABLES * acpi_tables) +{ + U8 *current = mem_addr; + U8 *end = current + mem_size; + + // Quick sanity check for a valid start address + if (current == 0ul) + return (0ul); + + for (; current < end; current += 16) { + if (*(volatile U64 *)current == NAMESEG64("RSD PTR ")) { + if (GetChecksum(current, ACPI_RSDP_REV0_SIZE) == 0) { + // RSD pointer structure checksum okay, lookup the RSDT pointer. + acpi_tables->RsdPointer = (ACPI_TABLE_RSDP *)current; + acpi_tables->RsdtPointer = (ACPI_TABLE_RSDT *) acpi_tables->RsdPointer->RsdtPhysicalAddress; + if ((acpi_tables->RsdPointer != (void*)0ul) && (acpi_tables->RsdtPointer != (void*)0ul)) + return (1ul); + else + return (0ul); + } + } + } + + return (0); +} + +//------------------------------------------------------------------------------- +// +// Procedure: GetXsdtPointer +// +//------------------------------------------------------------------------------- +static U32 GetXsdtPointer(ACPI_TABLES * acpi_tables) +{ + if ((GetChecksum(acpi_tables->RsdPointer, sizeof(ACPI_TABLE_RSDP)) == 0) && + (acpi_tables->RsdPointer->Revision == 2) && + (acpi_tables->RsdPointer->Length == sizeof(ACPI_TABLE_RSDP))) { + // RSD pointer structure checksum okay, lookup the XSDT pointer. + acpi_tables->XsdtPointer = (ACPI_TABLE_XSDT *) (U32) acpi_tables->RsdPointer->XsdtPhysicalAddress; + return (1ul); + } + + return (0ul); +} Property changes on: trunk/i386/modules/Sata/include/acpi_tools.c ___________________________________________________________________ Added: svn:executable + * Index: trunk/i386/modules/Makefile =================================================================== --- trunk/i386/modules/Makefile (revision 2030) +++ trunk/i386/modules/Makefile (revision 2031) @@ -37,6 +37,10 @@ SUBDIRS += sata endif +ifdef CONFIG_ACPICODEC_MODULE +SUBDIRS += ACPICodec +endif + CFLAGS= -O3 $(MORECPP) -arch i386 -g -static DEFINES= CONFIG = hd