Index: trunk/i386/modules/Sata/include/acpidecode.c =================================================================== --- trunk/i386/modules/Sata/include/acpidecode.c (revision 2031) +++ trunk/i386/modules/Sata/include/acpidecode.c (revision 2032) @@ -1,918 +0,0 @@ -/* - 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; - } - } - } -} Index: trunk/i386/modules/Sata/include/Cconfig =================================================================== --- trunk/i386/modules/Sata/include/Cconfig (revision 2031) +++ trunk/i386/modules/Sata/include/Cconfig (revision 2032) @@ -1,10 +0,0 @@ -# -# 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 2031) +++ trunk/i386/modules/Sata/include/acpicode.c (revision 2032) @@ -1,638 +0,0 @@ -/* -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 2031) +++ trunk/i386/modules/Sata/include/acpi_codec.c (revision 2032) @@ -1,5176 +0,0 @@ -/* - * 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); -} Index: trunk/i386/modules/Sata/include/ACPICodec.c =================================================================== --- trunk/i386/modules/Sata/include/ACPICodec.c (revision 2031) +++ trunk/i386/modules/Sata/include/ACPICodec.c (revision 2032) @@ -1,15 +0,0 @@ -/* - * 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 Index: trunk/i386/modules/Sata/include/Readme.txt =================================================================== --- trunk/i386/modules/Sata/include/Readme.txt (revision 2031) +++ trunk/i386/modules/Sata/include/Readme.txt (revision 2032) @@ -1,130 +0,0 @@ -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 2031) +++ trunk/i386/modules/Sata/include/Makefile (revision 2032) @@ -1,13 +0,0 @@ -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 Index: trunk/i386/modules/Sata/include/acpi_tools.c =================================================================== --- trunk/i386/modules/Sata/include/acpi_tools.c (revision 2031) +++ trunk/i386/modules/Sata/include/acpi_tools.c (revision 2032) @@ -1,328 +0,0 @@ -/* - 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); -} Index: trunk/i386/modules/AcpiCodec/acpidecode.c =================================================================== --- trunk/i386/modules/AcpiCodec/acpidecode.c (revision 0) +++ trunk/i386/modules/AcpiCodec/acpidecode.c (revision 2032) @@ -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/AcpiCodec/acpidecode.c ___________________________________________________________________ Added: svn:executable + * Index: trunk/i386/modules/AcpiCodec/include/acpi_codec.h =================================================================== --- trunk/i386/modules/AcpiCodec/include/acpi_codec.h (revision 0) +++ trunk/i386/modules/AcpiCodec/include/acpi_codec.h (revision 2032) @@ -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/AcpiCodec/include/acpi_codec.h ___________________________________________________________________ Added: svn:executable + * Index: trunk/i386/modules/AcpiCodec/include/datatype.h =================================================================== --- trunk/i386/modules/AcpiCodec/include/datatype.h (revision 0) +++ trunk/i386/modules/AcpiCodec/include/datatype.h (revision 2032) @@ -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/AcpiCodec/include/datatype.h ___________________________________________________________________ Added: svn:executable + * Index: trunk/i386/modules/AcpiCodec/include/acpi.h =================================================================== --- trunk/i386/modules/AcpiCodec/include/acpi.h (revision 0) +++ trunk/i386/modules/AcpiCodec/include/acpi.h (revision 2032) @@ -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/AcpiCodec/include/acpi_tools.h =================================================================== --- trunk/i386/modules/AcpiCodec/include/acpi_tools.h (revision 0) +++ trunk/i386/modules/AcpiCodec/include/acpi_tools.h (revision 2032) @@ -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/AcpiCodec/include/acpi_tools.h ___________________________________________________________________ Added: svn:executable + * Index: trunk/i386/modules/AcpiCodec/include/ppm.h =================================================================== --- trunk/i386/modules/AcpiCodec/include/ppm.h (revision 0) +++ trunk/i386/modules/AcpiCodec/include/ppm.h (revision 2032) @@ -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/AcpiCodec/include/ppm.h ___________________________________________________________________ Added: svn:executable + * Index: trunk/i386/modules/AcpiCodec/include/ppmsetup.h =================================================================== --- trunk/i386/modules/AcpiCodec/include/ppmsetup.h (revision 0) +++ trunk/i386/modules/AcpiCodec/include/ppmsetup.h (revision 2032) @@ -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/AcpiCodec/include/ppmsetup.h ___________________________________________________________________ Added: svn:executable + * Index: trunk/i386/modules/AcpiCodec/include/acpidecode.h =================================================================== --- trunk/i386/modules/AcpiCodec/include/acpidecode.h (revision 0) +++ trunk/i386/modules/AcpiCodec/include/acpidecode.h (revision 2032) @@ -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/AcpiCodec/include/acpidecode.h ___________________________________________________________________ Added: svn:executable + * Index: trunk/i386/modules/AcpiCodec/include/acpicode.h =================================================================== --- trunk/i386/modules/AcpiCodec/include/acpicode.h (revision 0) +++ trunk/i386/modules/AcpiCodec/include/acpicode.h (revision 2032) @@ -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/AcpiCodec/include/intel_acpi.h =================================================================== --- trunk/i386/modules/AcpiCodec/include/intel_acpi.h (revision 0) +++ trunk/i386/modules/AcpiCodec/include/intel_acpi.h (revision 2032) @@ -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/AcpiCodec/include/intel_acpi.h ___________________________________________________________________ Added: svn:executable + * Index: trunk/i386/modules/AcpiCodec/Cconfig =================================================================== --- trunk/i386/modules/AcpiCodec/Cconfig (revision 0) +++ trunk/i386/modules/AcpiCodec/Cconfig (revision 2032) @@ -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/AcpiCodec/acpicode.c =================================================================== --- trunk/i386/modules/AcpiCodec/acpicode.c (revision 0) +++ trunk/i386/modules/AcpiCodec/acpicode.c (revision 2032) @@ -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/AcpiCodec/acpi_codec.c =================================================================== --- trunk/i386/modules/AcpiCodec/acpi_codec.c (revision 0) +++ trunk/i386/modules/AcpiCodec/acpi_codec.c (revision 2032) @@ -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/AcpiCodec/acpi_codec.c ___________________________________________________________________ Added: svn:executable + * Index: trunk/i386/modules/AcpiCodec/ACPICodec.c =================================================================== --- trunk/i386/modules/AcpiCodec/ACPICodec.c (revision 0) +++ trunk/i386/modules/AcpiCodec/ACPICodec.c (revision 2032) @@ -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/AcpiCodec/ACPICodec.c ___________________________________________________________________ Added: svn:executable + * Index: trunk/i386/modules/AcpiCodec/Readme.txt =================================================================== --- trunk/i386/modules/AcpiCodec/Readme.txt (revision 0) +++ trunk/i386/modules/AcpiCodec/Readme.txt (revision 2032) @@ -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/AcpiCodec/Makefile =================================================================== --- trunk/i386/modules/AcpiCodec/Makefile (revision 0) +++ trunk/i386/modules/AcpiCodec/Makefile (revision 2032) @@ -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/AcpiCodec/Makefile ___________________________________________________________________ Added: svn:executable + * Index: trunk/i386/modules/AcpiCodec/acpi_tools.c =================================================================== --- trunk/i386/modules/AcpiCodec/acpi_tools.c (revision 0) +++ trunk/i386/modules/AcpiCodec/acpi_tools.c (revision 2032) @@ -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/AcpiCodec/acpi_tools.c ___________________________________________________________________ Added: svn:executable + *