ia64/xen-unstable

view tools/firmware/hvmloader/acpi/build.c @ 13989:2023386e38c4

hvm: Fix acpi processor id in MADT LAPIC entries.
Signed-off-by: Keir Fraser <keir@xensource.com>
author kfraser@localhost.localdomain
date Thu Feb 15 19:03:09 2007 +0000 (2007-02-15)
parents 4fc6ffff2ac5
children 0cf659332c3a
line source
1 /*
2 * Copyright (c) 2004, Intel Corporation.
3 * Copyright (c) 2006, Keir Fraser, XenSource Inc.
4 *
5 * This program is free software; you can redistribute it and/or modify it
6 * under the terms and conditions of the GNU General Public License, version
7 * 2, as published by the Free Software Foundation.
8 *
9 * This program is distributed in the hope it will be useful, but WITHOUT ANY
10 * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
11 * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
12 * details.
13 *
14 * You should have received a copy of the GNU General Public License along with
15 * this program; if not, write to the Free Software Foundation, Inc., 59 Temple
16 * Place - Suite 330, Boston, MA 02111-1307 USA.
17 */
19 #include "acpi2_0.h"
20 #include "ssdt_tpm.h"
21 #include "../config.h"
22 #include "../util.h"
23 #include <xen/hvm/e820.h>
25 #define align16(sz) (((sz) + 15) & ~15)
27 extern struct acpi_20_rsdp Rsdp;
28 extern struct acpi_20_rsdt Rsdt;
29 extern struct acpi_20_xsdt Xsdt;
30 extern struct acpi_20_fadt Fadt;
31 extern struct acpi_20_facs Facs;
32 extern unsigned char AmlCode[];
33 extern int DsdtLen;
35 static void set_checksum(
36 void *table, uint32_t checksum_offset, uint32_t length)
37 {
38 uint8_t *p, sum = 0;
40 p = table;
41 p[checksum_offset] = 0;
43 while ( length-- )
44 sum = sum + *p++;
46 p = table;
47 p[checksum_offset] = -sum;
48 }
50 int construct_madt(struct acpi_20_madt *madt)
51 {
52 struct acpi_20_madt_intsrcovr *intsrcovr;
53 struct acpi_20_madt_ioapic *io_apic;
54 struct acpi_20_madt_lapic *lapic;
55 int i, offset = 0;
57 memset(madt, 0, sizeof(*madt));
58 madt->header.signature = ACPI_2_0_MADT_SIGNATURE;
59 madt->header.revision = ACPI_2_0_MADT_REVISION;
60 strncpy(madt->header.oem_id, ACPI_OEM_ID, 6);
61 strncpy(madt->header.oem_table_id, ACPI_OEM_TABLE_ID, 8);
62 madt->header.oem_revision = ACPI_OEM_REVISION;
63 madt->header.creator_id = ACPI_CREATOR_ID;
64 madt->header.creator_revision = ACPI_CREATOR_REVISION;
65 madt->lapic_addr = LAPIC_BASE_ADDRESS;
66 madt->flags = ACPI_PCAT_COMPAT;
67 offset += sizeof(*madt);
69 intsrcovr = (struct acpi_20_madt_intsrcovr *)(madt + 1);
70 for ( i = 0; i < 16; i++ )
71 {
72 memset(intsrcovr, 0, sizeof(*intsrcovr));
73 intsrcovr->type = ACPI_INTERRUPT_SOURCE_OVERRIDE;
74 intsrcovr->length = sizeof(*intsrcovr);
75 intsrcovr->source = i;
77 if ( i == 0 )
78 {
79 /* ISA IRQ0 routed to IOAPIC GSI 2. */
80 intsrcovr->gsi = 2;
81 intsrcovr->flags = 0x0;
82 }
83 else if ( PCI_ISA_IRQ_MASK & (1U << i) )
84 {
85 /* PCI: active-low level-triggered. */
86 intsrcovr->gsi = i;
87 intsrcovr->flags = 0xf;
88 }
89 else
90 {
91 /* No need for a INT source override structure. */
92 continue;
93 }
95 offset += sizeof(*intsrcovr);
96 intsrcovr++;
97 }
99 io_apic = (struct acpi_20_madt_ioapic *)intsrcovr;
100 memset(io_apic, 0, sizeof(*io_apic));
101 io_apic->type = ACPI_IO_APIC;
102 io_apic->length = sizeof(*io_apic);
103 io_apic->ioapic_id = IOAPIC_ID;
104 io_apic->ioapic_addr = IOAPIC_BASE_ADDRESS;
105 offset += sizeof(*io_apic);
107 lapic = (struct acpi_20_madt_lapic *)(io_apic + 1);
108 for ( i = 0; i < get_vcpu_nr(); i++ )
109 {
110 memset(lapic, 0, sizeof(*lapic));
111 lapic->type = ACPI_PROCESSOR_LOCAL_APIC;
112 lapic->length = sizeof(*lapic);
113 /* Processor ID must match processor-object IDs in the DSDT. */
114 lapic->acpi_processor_id = i;
115 lapic->apic_id = LAPIC_ID(i);
116 lapic->flags = ACPI_LOCAL_APIC_ENABLED;
117 offset += sizeof(*lapic);
118 lapic++;
119 }
121 madt->header.length = offset;
122 set_checksum(madt, offsetof(struct acpi_header, checksum), offset);
124 return align16(offset);
125 }
127 int construct_hpet(struct acpi_20_hpet *hpet)
128 {
129 int offset;
131 memset(hpet, 0, sizeof(*hpet));
132 hpet->header.signature = ACPI_2_0_HPET_SIGNATURE;
133 hpet->header.revision = ACPI_2_0_HPET_REVISION;
134 strncpy(hpet->header.oem_id, ACPI_OEM_ID, 6);
135 strncpy(hpet->header.oem_table_id, ACPI_OEM_TABLE_ID, 8);
136 hpet->header.oem_revision = ACPI_OEM_REVISION;
137 hpet->header.creator_id = ACPI_CREATOR_ID;
138 hpet->header.creator_revision = ACPI_CREATOR_REVISION;
139 hpet->timer_block_id = 0x8086a201;
140 hpet->addr.address = ACPI_HPET_ADDRESS;
141 offset = sizeof(*hpet);
143 hpet->header.length = offset;
144 set_checksum(hpet, offsetof(struct acpi_header, checksum), offset);
146 return offset;
147 }
149 int construct_secondary_tables(uint8_t *buf, unsigned long *table_ptrs)
150 {
151 int offset = 0, nr_tables = 0;
152 struct acpi_20_madt *madt;
153 struct acpi_20_hpet *hpet;
154 struct acpi_20_tcpa *tcpa;
155 static const uint16_t tis_signature[] = {0x0001, 0x0001, 0x0001};
156 uint16_t *tis_hdr;
158 /* MADT. */
159 if ( (get_vcpu_nr() > 1) || get_apic_mode() )
160 {
161 madt = (struct acpi_20_madt *)&buf[offset];
162 offset += construct_madt(madt);
163 table_ptrs[nr_tables++] = (unsigned long)madt;
164 }
166 /* HPET. */
167 hpet = (struct acpi_20_hpet *)&buf[offset];
168 offset += construct_hpet(hpet);
169 table_ptrs[nr_tables++] = (unsigned long)hpet;
171 /* TPM TCPA and SSDT. */
172 tis_hdr = (uint16_t *)0xFED40F00;
173 if ( (tis_hdr[0] == tis_signature[0]) &&
174 (tis_hdr[1] == tis_signature[1]) &&
175 (tis_hdr[2] == tis_signature[2]) )
176 {
177 memcpy(&buf[offset], AmlCode_TPM, sizeof(AmlCode_TPM));
178 table_ptrs[nr_tables++] = (unsigned long)&buf[offset];
179 offset += align16(sizeof(AmlCode_TPM));
181 tcpa = (struct acpi_20_tcpa *)&buf[offset];
182 memset(tcpa, 0, sizeof(*tcpa));
183 offset += align16(sizeof(*tcpa));
184 table_ptrs[nr_tables++] = (unsigned long)tcpa;
186 tcpa->header.signature = ACPI_2_0_TCPA_SIGNATURE;
187 tcpa->header.length = sizeof(*tcpa);
188 tcpa->header.revision = ACPI_2_0_TCPA_REVISION;
189 strncpy(tcpa->header.oem_id, ACPI_OEM_ID, 6);
190 strncpy(tcpa->header.oem_table_id, ACPI_OEM_TABLE_ID, 8);
191 tcpa->header.oem_revision = ACPI_OEM_REVISION;
192 tcpa->header.creator_id = ACPI_CREATOR_ID;
193 tcpa->header.creator_revision = ACPI_CREATOR_REVISION;
194 tcpa->lasa = e820_malloc(
195 ACPI_2_0_TCPA_LAML_SIZE, E820_RESERVED, (uint32_t)~0);
196 if ( tcpa->lasa )
197 {
198 tcpa->laml = ACPI_2_0_TCPA_LAML_SIZE;
199 memset((char *)(unsigned long)tcpa->lasa, 0, tcpa->laml);
200 set_checksum(tcpa,
201 offsetof(struct acpi_header, checksum),
202 tcpa->header.length);
203 }
204 }
206 table_ptrs[nr_tables] = 0;
207 return align16(offset);
208 }
210 /* Copy all the ACPI table to buffer. */
211 int acpi_build_tables(uint8_t *buf)
212 {
213 struct acpi_20_rsdp *rsdp;
214 struct acpi_20_rsdt *rsdt;
215 struct acpi_20_xsdt *xsdt;
216 struct acpi_20_fadt *fadt;
217 struct acpi_20_facs *facs;
218 unsigned char *dsdt;
219 unsigned long secondary_tables[16];
220 int offset = 0, i;
222 facs = (struct acpi_20_facs *)&buf[offset];
223 memcpy(facs, &Facs, sizeof(struct acpi_20_facs));
224 offset += align16(sizeof(struct acpi_20_facs));
226 dsdt = (unsigned char *)&buf[offset];
227 memcpy(dsdt, &AmlCode, DsdtLen);
228 offset += align16(DsdtLen);
230 fadt = (struct acpi_20_fadt *)&buf[offset];
231 memcpy(fadt, &Fadt, sizeof(struct acpi_20_fadt));
232 offset += align16(sizeof(struct acpi_20_fadt));
233 fadt->dsdt = (unsigned long)dsdt;
234 fadt->x_dsdt = (unsigned long)dsdt;
235 fadt->firmware_ctrl = (unsigned long)facs;
236 fadt->x_firmware_ctrl = (unsigned long)facs;
237 set_checksum(fadt,
238 offsetof(struct acpi_header, checksum),
239 sizeof(struct acpi_20_fadt));
241 offset += construct_secondary_tables(&buf[offset], secondary_tables);
243 xsdt = (struct acpi_20_xsdt *)&buf[offset];
244 memcpy(xsdt, &Xsdt, sizeof(struct acpi_header));
245 xsdt->entry[0] = (unsigned long)fadt;
246 for ( i = 0; secondary_tables[i]; i++ )
247 xsdt->entry[i+1] = secondary_tables[i];
248 xsdt->header.length = sizeof(struct acpi_header) + (i+1)*sizeof(uint64_t);
249 offset += align16(xsdt->header.length);
250 set_checksum(xsdt,
251 offsetof(struct acpi_header, checksum),
252 xsdt->header.length);
254 rsdt = (struct acpi_20_rsdt *)&buf[offset];
255 memcpy(rsdt, &Rsdt, sizeof(struct acpi_header));
256 rsdt->entry[0] = (unsigned long)fadt;
257 for ( i = 0; secondary_tables[i]; i++ )
258 rsdt->entry[i+1] = secondary_tables[i];
259 rsdt->header.length = sizeof(struct acpi_header) + (i+1)*sizeof(uint32_t);
260 offset += align16(rsdt->header.length);
261 set_checksum(rsdt,
262 offsetof(struct acpi_header, checksum),
263 rsdt->header.length);
265 rsdp = (struct acpi_20_rsdp *)&buf[offset];
266 memcpy(rsdp, &Rsdp, sizeof(struct acpi_20_rsdp));
267 offset += align16(sizeof(struct acpi_20_rsdp));
268 rsdp->rsdt_address = (unsigned long)rsdt;
269 rsdp->xsdt_address = (unsigned long)xsdt;
270 set_checksum(rsdp,
271 offsetof(struct acpi_10_rsdp, checksum),
272 sizeof(struct acpi_10_rsdp));
273 set_checksum(rsdp,
274 offsetof(struct acpi_20_rsdp, extended_checksum),
275 sizeof(struct acpi_20_rsdp));
277 return offset;
278 }
280 /*
281 * Local variables:
282 * mode: C
283 * c-set-style: "BSD"
284 * c-basic-offset: 4
285 * tab-width: 4
286 * indent-tabs-mode: nil
287 * End:
288 */