VBoxAcpi.cpp revision f998395fdb2412040bc4d458e2b87e899c0cd3eb
96e08422d46465ebd7105bf48e475f77e60250d7wrowe/* $Id$ */
96e08422d46465ebd7105bf48e475f77e60250d7wrowe/** @file
96e08422d46465ebd7105bf48e475f77e60250d7wrowe * VBoxAcpi - VirtualBox ACPI maniputation functionality.
96e08422d46465ebd7105bf48e475f77e60250d7wrowe */
96e08422d46465ebd7105bf48e475f77e60250d7wrowe
96e08422d46465ebd7105bf48e475f77e60250d7wrowe/*
96e08422d46465ebd7105bf48e475f77e60250d7wrowe * Copyright (C) 2009 Sun Microsystems, Inc.
96e08422d46465ebd7105bf48e475f77e60250d7wrowe *
96e08422d46465ebd7105bf48e475f77e60250d7wrowe * This file is part of VirtualBox Open Source Edition (OSE), as
96e08422d46465ebd7105bf48e475f77e60250d7wrowe * available from http://www.virtualbox.org. This file is free software;
96e08422d46465ebd7105bf48e475f77e60250d7wrowe * you can redistribute it and/or modify it under the terms of the GNU
96e08422d46465ebd7105bf48e475f77e60250d7wrowe * General Public License (GPL) as published by the Free Software
0662ed52e814f8f08ef0e09956413a792584eddffuankg * Foundation, in version 2 as it comes in the "COPYING" file of the
96e08422d46465ebd7105bf48e475f77e60250d7wrowe * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
96e08422d46465ebd7105bf48e475f77e60250d7wrowe * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
96e08422d46465ebd7105bf48e475f77e60250d7wrowe *
96e08422d46465ebd7105bf48e475f77e60250d7wrowe * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa
96e08422d46465ebd7105bf48e475f77e60250d7wrowe * Clara, CA 95054 USA or visit http://www.sun.com if you need
96e08422d46465ebd7105bf48e475f77e60250d7wrowe * additional information or have any questions.
96e08422d46465ebd7105bf48e475f77e60250d7wrowe */
96e08422d46465ebd7105bf48e475f77e60250d7wrowe
96e08422d46465ebd7105bf48e475f77e60250d7wrowe#if !defined(IN_RING3)
96e08422d46465ebd7105bf48e475f77e60250d7wrowe#error Pure R3 code
96e08422d46465ebd7105bf48e475f77e60250d7wrowe#endif
96e08422d46465ebd7105bf48e475f77e60250d7wrowe
96e08422d46465ebd7105bf48e475f77e60250d7wrowe#define LOG_GROUP LOG_GROUP_DEV_ACPI
96e08422d46465ebd7105bf48e475f77e60250d7wrowe#include <VBox/pdmdev.h>
96e08422d46465ebd7105bf48e475f77e60250d7wrowe#include <VBox/pgm.h>
44f575c8cb19a7a5cd61664a7848be6bc197df02fuankg#include <VBox/log.h>
44f575c8cb19a7a5cd61664a7848be6bc197df02fuankg#include <VBox/param.h>
96e08422d46465ebd7105bf48e475f77e60250d7wrowe#include <iprt/assert.h>
96e08422d46465ebd7105bf48e475f77e60250d7wrowe#include <iprt/alloc.h>
96e08422d46465ebd7105bf48e475f77e60250d7wrowe#include <iprt/string.h>
96e08422d46465ebd7105bf48e475f77e60250d7wrowe
96e08422d46465ebd7105bf48e475f77e60250d7wrowe#ifdef VBOX_WITH_DYNAMIC_DSDT
96e08422d46465ebd7105bf48e475f77e60250d7wrowe/* vbox.dsl - input to generate proper DSDT on the fly */
96e08422d46465ebd7105bf48e475f77e60250d7wrowe# include <vboxdsl.hex>
96e08422d46465ebd7105bf48e475f77e60250d7wrowe#else
96e08422d46465ebd7105bf48e475f77e60250d7wrowe/* Statically compiled AML */
96e08422d46465ebd7105bf48e475f77e60250d7wrowe# include <vboxaml.hex>
96e08422d46465ebd7105bf48e475f77e60250d7wrowe#endif
96e08422d46465ebd7105bf48e475f77e60250d7wrowe
96e08422d46465ebd7105bf48e475f77e60250d7wrowe#ifdef VBOX_WITH_DYNAMIC_DSDT
96e08422d46465ebd7105bf48e475f77e60250d7wrowestatic int prepareDynamicDsdt(PPDMDEVINS pDevIns,
96e08422d46465ebd7105bf48e475f77e60250d7wrowe void* *ppPtr,
96e08422d46465ebd7105bf48e475f77e60250d7wrowe size_t *puDsdtLen)
96e08422d46465ebd7105bf48e475f77e60250d7wrowe{
96e08422d46465ebd7105bf48e475f77e60250d7wrowe *ppPtr = NULL;
96e08422d46465ebd7105bf48e475f77e60250d7wrowe *puDsdtLen = 0;
96e08422d46465ebd7105bf48e475f77e60250d7wrowe return 0;
96e08422d46465ebd7105bf48e475f77e60250d7wrowe}
96e08422d46465ebd7105bf48e475f77e60250d7wrowe
96e08422d46465ebd7105bf48e475f77e60250d7wrowestatic int cleanupDynamicDsdt(PPDMDEVINS pDevIns,
96e08422d46465ebd7105bf48e475f77e60250d7wrowe void* pPtr)
96e08422d46465ebd7105bf48e475f77e60250d7wrowe{
96e08422d46465ebd7105bf48e475f77e60250d7wrowe return 0;
96e08422d46465ebd7105bf48e475f77e60250d7wrowe}
96e08422d46465ebd7105bf48e475f77e60250d7wrowe
96e08422d46465ebd7105bf48e475f77e60250d7wrowe#else
96e08422d46465ebd7105bf48e475f77e60250d7wrowestatic int patchAml(PPDMDEVINS pDevIns, uint8_t* pAml, size_t uAmlLen)
96e08422d46465ebd7105bf48e475f77e60250d7wrowe{
96e08422d46465ebd7105bf48e475f77e60250d7wrowe uint16_t cNumCpus;
96e08422d46465ebd7105bf48e475f77e60250d7wrowe int rc;
96e08422d46465ebd7105bf48e475f77e60250d7wrowe
96e08422d46465ebd7105bf48e475f77e60250d7wrowe rc = CFGMR3QueryU16Def(pDevIns->pCfgHandle, "NumCPUs", &cNumCpus, 1);
96e08422d46465ebd7105bf48e475f77e60250d7wrowe
96e08422d46465ebd7105bf48e475f77e60250d7wrowe if (RT_FAILURE(rc))
96e08422d46465ebd7105bf48e475f77e60250d7wrowe return rc;
96e08422d46465ebd7105bf48e475f77e60250d7wrowe
96e08422d46465ebd7105bf48e475f77e60250d7wrowe /* Clear CPU objects at all, if needed */
96e08422d46465ebd7105bf48e475f77e60250d7wrowe bool fShowCpu;
96e08422d46465ebd7105bf48e475f77e60250d7wrowe rc = CFGMR3QueryBoolDef(pDevIns->pCfgHandle, "ShowCpu", &fShowCpu, false);
96e08422d46465ebd7105bf48e475f77e60250d7wrowe if (RT_FAILURE(rc))
96e08422d46465ebd7105bf48e475f77e60250d7wrowe return rc;
96e08422d46465ebd7105bf48e475f77e60250d7wrowe
96e08422d46465ebd7105bf48e475f77e60250d7wrowe if (!fShowCpu)
96e08422d46465ebd7105bf48e475f77e60250d7wrowe cNumCpus = 0;
96e08422d46465ebd7105bf48e475f77e60250d7wrowe
96e08422d46465ebd7105bf48e475f77e60250d7wrowe /**
96e08422d46465ebd7105bf48e475f77e60250d7wrowe * Now search AML for:
96e08422d46465ebd7105bf48e475f77e60250d7wrowe * AML_PROCESSOR_OP (UINT16) 0x5b83
96e08422d46465ebd7105bf48e475f77e60250d7wrowe * and replace whole block with
96e08422d46465ebd7105bf48e475f77e60250d7wrowe * AML_NOOP_OP (UINT16) 0xa3
96e08422d46465ebd7105bf48e475f77e60250d7wrowe * for VCPU not configured
96e08422d46465ebd7105bf48e475f77e60250d7wrowe */
96e08422d46465ebd7105bf48e475f77e60250d7wrowe for (uint32_t i = 0; i < uAmlLen - 7; i++)
96e08422d46465ebd7105bf48e475f77e60250d7wrowe {
96e08422d46465ebd7105bf48e475f77e60250d7wrowe /*
96e08422d46465ebd7105bf48e475f77e60250d7wrowe * AML_PROCESSOR_OP
96e08422d46465ebd7105bf48e475f77e60250d7wrowe *
96e08422d46465ebd7105bf48e475f77e60250d7wrowe * DefProcessor := ProcessorOp PkgLength NameString ProcID
96e08422d46465ebd7105bf48e475f77e60250d7wrowe PblkAddr PblkLen ObjectList
96e08422d46465ebd7105bf48e475f77e60250d7wrowe * ProcessorOp := ExtOpPrefix 0x83
96e08422d46465ebd7105bf48e475f77e60250d7wrowe * ProcID := ByteData
96e08422d46465ebd7105bf48e475f77e60250d7wrowe * PblkAddr := DwordData
96e08422d46465ebd7105bf48e475f77e60250d7wrowe * PblkLen := ByteData
96e08422d46465ebd7105bf48e475f77e60250d7wrowe */
96e08422d46465ebd7105bf48e475f77e60250d7wrowe if ((pAml[i] == 0x5b) && (pAml[i+1] == 0x83))
96e08422d46465ebd7105bf48e475f77e60250d7wrowe {
96e08422d46465ebd7105bf48e475f77e60250d7wrowe if ((pAml[i+3] != 'C') || (pAml[i+4] != 'P'))
96e08422d46465ebd7105bf48e475f77e60250d7wrowe /* false alarm, not named starting CP */
96e08422d46465ebd7105bf48e475f77e60250d7wrowe continue;
96e08422d46465ebd7105bf48e475f77e60250d7wrowe
96e08422d46465ebd7105bf48e475f77e60250d7wrowe /* Processor ID */
96e08422d46465ebd7105bf48e475f77e60250d7wrowe if (pAml[i+7] < cNumCpus)
96e08422d46465ebd7105bf48e475f77e60250d7wrowe continue;
96e08422d46465ebd7105bf48e475f77e60250d7wrowe
96e08422d46465ebd7105bf48e475f77e60250d7wrowe /* Will fill unwanted CPU block with NOOPs */
96e08422d46465ebd7105bf48e475f77e60250d7wrowe /*
96e08422d46465ebd7105bf48e475f77e60250d7wrowe * See 18.2.4 Package Length Encoding in ACPI spec
96e08422d46465ebd7105bf48e475f77e60250d7wrowe * for full format
96e08422d46465ebd7105bf48e475f77e60250d7wrowe */
96e08422d46465ebd7105bf48e475f77e60250d7wrowe uint32_t cBytes = pAml[i + 2];
96e08422d46465ebd7105bf48e475f77e60250d7wrowe AssertReleaseMsg((cBytes >> 6) == 0,
96e08422d46465ebd7105bf48e475f77e60250d7wrowe ("So far, we only understand simple package length"));
96e08422d46465ebd7105bf48e475f77e60250d7wrowe
96e08422d46465ebd7105bf48e475f77e60250d7wrowe /* including AML_PROCESSOR_OP itself */
96e08422d46465ebd7105bf48e475f77e60250d7wrowe for (uint32_t j = 0; j < cBytes + 2; j++)
0662ed52e814f8f08ef0e09956413a792584eddffuankg pAml[i+j] = 0xa3;
96e08422d46465ebd7105bf48e475f77e60250d7wrowe
96e08422d46465ebd7105bf48e475f77e60250d7wrowe /* Can increase i by cBytes + 1, but not really worth it */
96e08422d46465ebd7105bf48e475f77e60250d7wrowe }
96e08422d46465ebd7105bf48e475f77e60250d7wrowe }
96e08422d46465ebd7105bf48e475f77e60250d7wrowe
96e08422d46465ebd7105bf48e475f77e60250d7wrowe /* now recompute checksum, whole file byte sum must be 0 */
96e08422d46465ebd7105bf48e475f77e60250d7wrowe pAml[9] = 0;
96e08422d46465ebd7105bf48e475f77e60250d7wrowe uint8_t aSum = 0;
96e08422d46465ebd7105bf48e475f77e60250d7wrowe for (uint32_t i = 0; i < uAmlLen; i++)
96e08422d46465ebd7105bf48e475f77e60250d7wrowe aSum = aSum + (uint8_t)pAml[i];
96e08422d46465ebd7105bf48e475f77e60250d7wrowe pAml[9] = (uint8_t) (0 - aSum);
96e08422d46465ebd7105bf48e475f77e60250d7wrowe
0662ed52e814f8f08ef0e09956413a792584eddffuankg return 0;
96e08422d46465ebd7105bf48e475f77e60250d7wrowe}
96e08422d46465ebd7105bf48e475f77e60250d7wrowe#endif
96e08422d46465ebd7105bf48e475f77e60250d7wrowe
96e08422d46465ebd7105bf48e475f77e60250d7wrowe/* Two only public functions */
0662ed52e814f8f08ef0e09956413a792584eddffuankgint acpiPrepareDsdt(PPDMDEVINS pDevIns, void * *ppPtr, size_t *puDsdtLen)
96e08422d46465ebd7105bf48e475f77e60250d7wrowe{
96e08422d46465ebd7105bf48e475f77e60250d7wrowe#ifdef VBOX_WITH_DYNAMIC_DSDT
96e08422d46465ebd7105bf48e475f77e60250d7wrowe return prepareDynamicDsdt(pDevIns, ppPtr, puDsdtLen);
96e08422d46465ebd7105bf48e475f77e60250d7wrowe#else
96e08422d46465ebd7105bf48e475f77e60250d7wrowe patchAml(pDevIns, AmlCode, sizeof(AmlCode));
96e08422d46465ebd7105bf48e475f77e60250d7wrowe *ppPtr = AmlCode;
96e08422d46465ebd7105bf48e475f77e60250d7wrowe *puDsdtLen = sizeof(AmlCode);
96e08422d46465ebd7105bf48e475f77e60250d7wrowe return 0;
96e08422d46465ebd7105bf48e475f77e60250d7wrowe#endif
0662ed52e814f8f08ef0e09956413a792584eddffuankg}
96e08422d46465ebd7105bf48e475f77e60250d7wrowe
96e08422d46465ebd7105bf48e475f77e60250d7wroweint acpiCleanupDsdt(PPDMDEVINS pDevIns, void * pPtr)
96e08422d46465ebd7105bf48e475f77e60250d7wrowe{
96e08422d46465ebd7105bf48e475f77e60250d7wrowe#ifdef VBOX_WITH_DYNAMIC_DSDT
96e08422d46465ebd7105bf48e475f77e60250d7wrowe return cleanupDynamicDsdt(pDevIns, pPtr);
96e08422d46465ebd7105bf48e475f77e60250d7wrowe#else
96e08422d46465ebd7105bf48e475f77e60250d7wrowe /* Do nothing */
96e08422d46465ebd7105bf48e475f77e60250d7wrowe return 0;
96e08422d46465ebd7105bf48e475f77e60250d7wrowe#endif
96e08422d46465ebd7105bf48e475f77e60250d7wrowe}
96e08422d46465ebd7105bf48e475f77e60250d7wrowe
96e08422d46465ebd7105bf48e475f77e60250d7wrowe