VirtualBox

source: vbox/trunk/src/VBox/Devices/PC/ACPI/VBoxAcpi.cpp@ 20819

Last change on this file since 20819 was 20679, checked in by vboxsync, 16 years ago

ACPI: fix problem with certain Windows ACPI impls (such as XP) mistreating CPU objects - make them all of the same size and control behavior entirely by patching

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 4.2 KB
Line 
1/* $Id: VBoxAcpi.cpp 20679 2009-06-18 10:38:52Z vboxsync $ */
2/** @file
3 * VBoxAcpi - VirtualBox ACPI maniputation functionality.
4 */
5
6/*
7 * Copyright (C) 2009 Sun Microsystems, Inc.
8 *
9 * This file is part of VirtualBox Open Source Edition (OSE), as
10 * available from http://www.virtualbox.org. This file is free software;
11 * you can redistribute it and/or modify it under the terms of the GNU
12 * General Public License (GPL) as published by the Free Software
13 * Foundation, in version 2 as it comes in the "COPYING" file of the
14 * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
15 * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
16 *
17 * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa
18 * Clara, CA 95054 USA or visit http://www.sun.com if you need
19 * additional information or have any questions.
20 */
21
22#if !defined(IN_RING3)
23#error Pure R3 code
24#endif
25
26#define LOG_GROUP LOG_GROUP_DEV_ACPI
27#include <VBox/pdmdev.h>
28#include <VBox/pgm.h>
29#include <VBox/log.h>
30#include <VBox/param.h>
31#include <iprt/assert.h>
32#include <iprt/alloc.h>
33#include <iprt/string.h>
34
35#ifdef VBOX_WITH_DYNAMIC_DSDT
36/* vbox.dsl - input to generate proper DSDT on the fly */
37# include <vboxdsl.hex>
38#else
39/* Statically compiled AML */
40# include <vboxaml.hex>
41#endif
42
43#ifdef VBOX_WITH_DYNAMIC_DSDT
44static int prepareDynamicDsdt(PPDMDEVINS pDevIns,
45 void* *ppPtr,
46 size_t *puDsdtLen)
47{
48 *ppPtr = NULL;
49 *puDsdtLen = 0;
50 return 0;
51}
52
53static int cleanupDynamicDsdt(PPDMDEVINS pDevIns,
54 void* pPtr)
55{
56 return 0;
57}
58
59#else
60static int patchAml(PPDMDEVINS pDevIns, uint8_t* pAml, size_t uAmlLen)
61{
62 uint16_t cNumCpus;
63 int rc;
64
65 rc = CFGMR3QueryU16Def(pDevIns->pCfgHandle, "NumCPUs", &cNumCpus, 1);
66
67 if (RT_FAILURE(rc))
68 return rc;
69
70 /* Clear CPU objects at all, if needed */
71 bool fShowCpu;
72 rc = CFGMR3QueryBoolDef(pDevIns->pCfgHandle, "ShowCpu", &fShowCpu, false);
73 if (RT_FAILURE(rc))
74 return rc;
75
76 if (!fShowCpu)
77 cNumCpus = 0;
78
79 /**
80 * Now search AML for:
81 * AML_PROCESSOR_OP (UINT16) 0x5b83
82 * and replace whole block with
83 * AML_NOOP_OP (UINT16) 0xa3
84 * for VCPU not configured
85 */
86 for (uint32_t i = 0; i < uAmlLen - 7; i++)
87 {
88 /*
89 * AML_PROCESSOR_OP
90 *
91 * DefProcessor := ProcessorOp PkgLength NameString ProcID
92 PblkAddr PblkLen ObjectList
93 * ProcessorOp := ExtOpPrefix 0x83
94 * ProcID := ByteData
95 * PblkAddr := DwordData
96 * PblkLen := ByteData
97 */
98 if ((pAml[i] == 0x5b) && (pAml[i+1] == 0x83))
99 {
100 if ((pAml[i+3] != 'C') || (pAml[i+4] != 'P'))
101 /* false alarm, not named starting CP */
102 continue;
103
104 /* Processor ID */
105 if (pAml[i+7] < cNumCpus)
106 continue;
107
108 /* Will fill unwanted CPU block with NOOPs */
109 /*
110 * See 18.2.4 Package Length Encoding in ACPI spec
111 * for full format
112 */
113 uint32_t cBytes = pAml[i + 2];
114 AssertReleaseMsg((cBytes >> 6) == 0,
115 ("So far, we only understand simple package length"));
116
117 /* including AML_PROCESSOR_OP itself */
118 for (uint32_t j = 0; j < cBytes + 2; j++)
119 pAml[i+j] = 0xa3;
120
121 /* Can increase i by cBytes + 1, but not really worth it */
122 }
123 }
124
125 /* now recompute checksum, whole file byte sum must be 0 */
126 pAml[9] = 0;
127 uint8_t aSum = 0;
128 for (uint32_t i = 0; i < uAmlLen; i++)
129 aSum = aSum + (uint8_t)pAml[i];
130 pAml[9] = (uint8_t) (0 - aSum);
131
132 return 0;
133}
134#endif
135
136/* Two only public functions */
137int acpiPrepareDsdt(PPDMDEVINS pDevIns, void * *ppPtr, size_t *puDsdtLen)
138{
139#ifdef VBOX_WITH_DYNAMIC_DSDT
140 return prepareDynamicDsdt(pDevIns, ppPtr, puDsdtLen);
141#else
142 patchAml(pDevIns, AmlCode, sizeof(AmlCode));
143 *ppPtr = AmlCode;
144 *puDsdtLen = sizeof(AmlCode);
145 return 0;
146#endif
147}
148
149int acpiCleanupDsdt(PPDMDEVINS pDevIns, void * pPtr)
150{
151#ifdef VBOX_WITH_DYNAMIC_DSDT
152 return cleanupDynamicDsdt(pDevIns, pPtr);
153#else
154 /* Do nothing */
155 return 0;
156#endif
157}
158
Note: See TracBrowser for help on using the repository browser.

© 2024 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette