VBoxAcpi.cpp revision 497a49aa22807122b7dd0bcab3bcdc43d3c479c2
616c4e73368513b3c835881ff9f2386083afad01vboxsync * VBoxAcpi - VirtualBox ACPI maniputation functionality.
7f8a04081173dbe3c72bddd0ffeb237e7f9070b0vboxsync * Copyright (C) 2009 Sun Microsystems, Inc.
7f8a04081173dbe3c72bddd0ffeb237e7f9070b0vboxsync * This file is part of VirtualBox Open Source Edition (OSE), as
7f8a04081173dbe3c72bddd0ffeb237e7f9070b0vboxsync * available from http://www.virtualbox.org. This file is free software;
7f8a04081173dbe3c72bddd0ffeb237e7f9070b0vboxsync * you can redistribute it and/or modify it under the terms of the GNU
7f8a04081173dbe3c72bddd0ffeb237e7f9070b0vboxsync * General Public License (GPL) as published by the Free Software
7f8a04081173dbe3c72bddd0ffeb237e7f9070b0vboxsync * Foundation, in version 2 as it comes in the "COPYING" file of the
7f8a04081173dbe3c72bddd0ffeb237e7f9070b0vboxsync * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
7f8a04081173dbe3c72bddd0ffeb237e7f9070b0vboxsync * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
7f8a04081173dbe3c72bddd0ffeb237e7f9070b0vboxsync * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa
7f8a04081173dbe3c72bddd0ffeb237e7f9070b0vboxsync * Clara, CA 95054 USA or visit http://www.sun.com if you need
7f8a04081173dbe3c72bddd0ffeb237e7f9070b0vboxsync * additional information or have any questions.
7f8a04081173dbe3c72bddd0ffeb237e7f9070b0vboxsync#if !defined(IN_RING3)
7f8a04081173dbe3c72bddd0ffeb237e7f9070b0vboxsync/* vbox.dsl - input to generate proper DSDT on the fly */
7f8a04081173dbe3c72bddd0ffeb237e7f9070b0vboxsync/* Statically compiled AML */
ecb074924ed761fe89e91113482db5b7374441b0vboxsyncstatic int patchAml(PPDMDEVINS pDevIns, uint8_t* pAml, size_t uAmlLen)
928e1d6581a40f26932a8b35526773805bc69e47vboxsync rc = CFGMR3QueryU16Def(pDevIns->pCfg, "NumCPUs", &cNumCpus, 1);
a2779f5bd9cc55216a2911d7714ede6a77cac3b2vboxsync /* Clear CPU objects at all, if needed */
928e1d6581a40f26932a8b35526773805bc69e47vboxsync rc = CFGMR3QueryBoolDef(pDevIns->pCfg, "ShowCpu", &fShowCpu, false);
ecb074924ed761fe89e91113482db5b7374441b0vboxsync * Now search AML for:
ecb074924ed761fe89e91113482db5b7374441b0vboxsync * AML_PROCESSOR_OP (UINT16) 0x5b83
ecb074924ed761fe89e91113482db5b7374441b0vboxsync * and replace whole block with
616c4e73368513b3c835881ff9f2386083afad01vboxsync * AML_NOOP_OP (UINT16) 0xa3
ecb074924ed761fe89e91113482db5b7374441b0vboxsync * for VCPU not configured
616c4e73368513b3c835881ff9f2386083afad01vboxsync * AML_PROCESSOR_OP
616c4e73368513b3c835881ff9f2386083afad01vboxsync * DefProcessor := ProcessorOp PkgLength NameString ProcID
ecb074924ed761fe89e91113482db5b7374441b0vboxsync PblkAddr PblkLen ObjectList
ecb074924ed761fe89e91113482db5b7374441b0vboxsync * ProcessorOp := ExtOpPrefix 0x83
ecb074924ed761fe89e91113482db5b7374441b0vboxsync * ProcID := ByteData
ecb074924ed761fe89e91113482db5b7374441b0vboxsync * PblkAddr := DwordData
ecb074924ed761fe89e91113482db5b7374441b0vboxsync * PblkLen := ByteData
ecb074924ed761fe89e91113482db5b7374441b0vboxsync /* false alarm, not named starting CP */
3854599844436d009da0f32760d657fc7690a5a8vboxsync /* Processor ID */
ecb074924ed761fe89e91113482db5b7374441b0vboxsync /* Will fill unwanted CPU block with NOOPs */
616c4e73368513b3c835881ff9f2386083afad01vboxsync * See 18.2.4 Package Length Encoding in ACPI spec
616c4e73368513b3c835881ff9f2386083afad01vboxsync * for full format
ecb074924ed761fe89e91113482db5b7374441b0vboxsync ("So far, we only understand simple package length"));
ecb074924ed761fe89e91113482db5b7374441b0vboxsync /* including AML_PROCESSOR_OP itself */
ecb074924ed761fe89e91113482db5b7374441b0vboxsync /* Can increase i by cBytes + 1, but not really worth it */
ecb074924ed761fe89e91113482db5b7374441b0vboxsync /* now recompute checksum, whole file byte sum must be 0 */
497a49aa22807122b7dd0bcab3bcdc43d3c479c2vboxsync * Loads an AML file if present in CFGM
497a49aa22807122b7dd0bcab3bcdc43d3c479c2vboxsync * @returns VBox status code
497a49aa22807122b7dd0bcab3bcdc43d3c479c2vboxsync * @param pDevIns The device instance
497a49aa22807122b7dd0bcab3bcdc43d3c479c2vboxsync * @param pcszCfgName The configuration key holding the file path
497a49aa22807122b7dd0bcab3bcdc43d3c479c2vboxsync * @param pcszSignature The signature to check for
497a49aa22807122b7dd0bcab3bcdc43d3c479c2vboxsync * @param ppbAmlCode Where to store the pointer to the AML code on success.
497a49aa22807122b7dd0bcab3bcdc43d3c479c2vboxsync * @param pcbAmlCode Where to store the number of bytes of the AML code on success.
497a49aa22807122b7dd0bcab3bcdc43d3c479c2vboxsyncstatic int acpiAmlLoadExternal(PPDMDEVINS pDevIns, const char *pcszCfgName, const char *pcszSignature, uint8_t **ppbAmlCode, size_t *pcbAmlCode)
497a49aa22807122b7dd0bcab3bcdc43d3c479c2vboxsync int rc = CFGMR3QueryStringAlloc(pDevIns->pCfg, pcszCfgName, &pszAmlFilePath);
70e70d246c1b592db31d93071c48bb43ea61100evboxsync /* Load from file. */
70e70d246c1b592db31d93071c48bb43ea61100evboxsync rc = RTFileOpen(&FileAml, pszAmlFilePath, RTFILE_O_OPEN | RTFILE_O_READ | RTFILE_O_DENY_NONE);
70e70d246c1b592db31d93071c48bb43ea61100evboxsync * An AML file contains the raw DSDT thus the size of the file
70e70d246c1b592db31d93071c48bb43ea61100evboxsync * is equal to the size of the DSDT.
70e70d246c1b592db31d93071c48bb43ea61100evboxsync /* Don't use AML files over 4GB ;) */
70e70d246c1b592db31d93071c48bb43ea61100evboxsync rc = RTFileReadAt(FileAml, 0, pbAmlCode, cbAmlCode, NULL);
70e70d246c1b592db31d93071c48bb43ea61100evboxsync * We fail if reading failed or the identifier at the
70e70d246c1b592db31d93071c48bb43ea61100evboxsync * beginning is wrong.
ec7708c74d7fc8feb18fbe1f84b320ec86fb11efvboxsync || strncmp((const char *)pbAmlCode, pcszSignature, 4))
70e70d246c1b592db31d93071c48bb43ea61100evboxsync /* Return error if file header check failed */
ec7708c74d7fc8feb18fbe1f84b320ec86fb11efvboxsync/* Two only public functions */
ec7708c74d7fc8feb18fbe1f84b320ec86fb11efvboxsyncint acpiPrepareDsdt(PPDMDEVINS pDevIns, void * *ppPtr, size_t *puDsdtLen)
ec7708c74d7fc8feb18fbe1f84b320ec86fb11efvboxsync return prepareDynamicDsdt(pDevIns, ppPtr, puDsdtLen);
ec7708c74d7fc8feb18fbe1f84b320ec86fb11efvboxsync int rc = acpiAmlLoadExternal(pDevIns, "DsdtFilePath", "DSDT", &pbAmlCodeDsdt, &cbAmlCodeDsdt);
70e70d246c1b592db31d93071c48bb43ea61100evboxsync /* Use the compiled in AML code */
ec7708c74d7fc8feb18fbe1f84b320ec86fb11efvboxsync pbAmlCodeDsdt = (uint8_t *)RTMemAllocZ(cbAmlCodeDsdt);
ec7708c74d7fc8feb18fbe1f84b320ec86fb11efvboxsync N_("Configuration error: Failed to read \"DsdtFilePath\""));
7f8a04081173dbe3c72bddd0ffeb237e7f9070b0vboxsyncint acpiCleanupDsdt(PPDMDEVINS pDevIns, void * pPtr)
ec7708c74d7fc8feb18fbe1f84b320ec86fb11efvboxsyncint acpiPrepareSsdt(PPDMDEVINS pDevIns, void* *ppPtr, size_t *puSsdtLen)
ec7708c74d7fc8feb18fbe1f84b320ec86fb11efvboxsync int rc = acpiAmlLoadExternal(pDevIns, "SsdtFilePath", "SSDT", &pbAmlCodeSsdt, &cbAmlCodeSsdt);
ec7708c74d7fc8feb18fbe1f84b320ec86fb11efvboxsync bool fCpuHotPlug = false;
497a49aa22807122b7dd0bcab3bcdc43d3c479c2vboxsync rc = CFGMR3QueryBoolDef(pDevIns->pCfg, "CpuHotPlug", &fCpuHotPlug, false);
ec7708c74d7fc8feb18fbe1f84b320ec86fb11efvboxsync pbAmlCodeSsdt = (uint8_t *)RTMemAllocZ(cbAmlCodeSsdt);
ec7708c74d7fc8feb18fbe1f84b320ec86fb11efvboxsync N_("Configuration error: Failed to read \"SsdtFilePath\""));