ia64/xen-unstable

view tools/firmware/hvmloader/acpi/build.c @ 17113:746fc8fe9d75

hvmloader/acpi: Simplify Processor Object definitions.

No need to generate the correct number dynamically since
present/not-present can be determined from the MADT. What *is*
required is that we have a Processor Object for every present
processor. We statically declare 16 Objects, which should be plenty
for now.

Signed-off-by: Keir Fraser <keir.fraser@citrix.com>
author Keir Fraser <keir.fraser@citrix.com>
date Mon Feb 25 10:56:23 2008 +0000 (2008-02-25)
parents 209512f6d89c
children cd5dc735bdf3
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"
24 #define align16(sz) (((sz) + 15) & ~15)
25 #define fixed_strcpy(d, s) strncpy((d), (s), sizeof(d))
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 static int uart_exists(uint16_t uart_base)
51 {
52 uint16_t ier = uart_base + 1;
53 uint8_t a, b, c;
55 a = inb(ier);
56 outb(ier, 0);
57 b = inb(ier);
58 outb(ier, 0xf);
59 c = inb(ier);
60 outb(ier, a);
62 return ((b == 0) && (c == 0xf));
63 }
65 static int hpet_exists(unsigned long hpet_base)
66 {
67 uint32_t hpet_id = *(uint32_t *)hpet_base;
68 return ((hpet_id >> 16) == 0x8086);
69 }
71 static int construct_bios_info_table(uint8_t *buf)
72 {
73 struct bios_info {
74 uint8_t com1_present:1;
75 uint8_t com2_present:1;
76 uint8_t hpet_present:1;
77 uint32_t pci_min, pci_len;
78 } *bios_info = (struct bios_info *)buf;
80 memset(bios_info, 0, sizeof(*bios_info));
82 bios_info->com1_present = uart_exists(0x3f8);
83 bios_info->com2_present = uart_exists(0x2f8);
85 bios_info->hpet_present = hpet_exists(ACPI_HPET_ADDRESS);
87 bios_info->pci_min = 0xf0000000;
88 bios_info->pci_len = 0x0c000000;
90 return align16(sizeof(*bios_info));
91 }
93 static int construct_madt(struct acpi_20_madt *madt)
94 {
95 struct acpi_20_madt_intsrcovr *intsrcovr;
96 struct acpi_20_madt_ioapic *io_apic;
97 struct acpi_20_madt_lapic *lapic;
98 int i, offset = 0;
100 memset(madt, 0, sizeof(*madt));
101 madt->header.signature = ACPI_2_0_MADT_SIGNATURE;
102 madt->header.revision = ACPI_2_0_MADT_REVISION;
103 fixed_strcpy(madt->header.oem_id, ACPI_OEM_ID);
104 fixed_strcpy(madt->header.oem_table_id, ACPI_OEM_TABLE_ID);
105 madt->header.oem_revision = ACPI_OEM_REVISION;
106 madt->header.creator_id = ACPI_CREATOR_ID;
107 madt->header.creator_revision = ACPI_CREATOR_REVISION;
108 madt->lapic_addr = LAPIC_BASE_ADDRESS;
109 madt->flags = ACPI_PCAT_COMPAT;
110 offset += sizeof(*madt);
112 intsrcovr = (struct acpi_20_madt_intsrcovr *)(madt + 1);
113 for ( i = 0; i < 16; i++ )
114 {
115 memset(intsrcovr, 0, sizeof(*intsrcovr));
116 intsrcovr->type = ACPI_INTERRUPT_SOURCE_OVERRIDE;
117 intsrcovr->length = sizeof(*intsrcovr);
118 intsrcovr->source = i;
120 if ( i == 0 )
121 {
122 /* ISA IRQ0 routed to IOAPIC GSI 2. */
123 intsrcovr->gsi = 2;
124 intsrcovr->flags = 0x0;
125 }
126 else if ( PCI_ISA_IRQ_MASK & (1U << i) )
127 {
128 /* PCI: active-low level-triggered. */
129 intsrcovr->gsi = i;
130 intsrcovr->flags = 0xf;
131 }
132 else
133 {
134 /* No need for a INT source override structure. */
135 continue;
136 }
138 offset += sizeof(*intsrcovr);
139 intsrcovr++;
140 }
142 io_apic = (struct acpi_20_madt_ioapic *)intsrcovr;
143 memset(io_apic, 0, sizeof(*io_apic));
144 io_apic->type = ACPI_IO_APIC;
145 io_apic->length = sizeof(*io_apic);
146 io_apic->ioapic_id = IOAPIC_ID;
147 io_apic->ioapic_addr = IOAPIC_BASE_ADDRESS;
148 offset += sizeof(*io_apic);
150 lapic = (struct acpi_20_madt_lapic *)(io_apic + 1);
151 for ( i = 0; i < get_vcpu_nr(); i++ )
152 {
153 memset(lapic, 0, sizeof(*lapic));
154 lapic->type = ACPI_PROCESSOR_LOCAL_APIC;
155 lapic->length = sizeof(*lapic);
156 /* Processor ID must match processor-object IDs in the DSDT. */
157 lapic->acpi_processor_id = i;
158 lapic->apic_id = LAPIC_ID(i);
159 lapic->flags = ACPI_LOCAL_APIC_ENABLED;
160 offset += sizeof(*lapic);
161 lapic++;
162 }
164 madt->header.length = offset;
165 set_checksum(madt, offsetof(struct acpi_header, checksum), offset);
167 return align16(offset);
168 }
170 static int construct_hpet(struct acpi_20_hpet *hpet)
171 {
172 int offset;
174 memset(hpet, 0, sizeof(*hpet));
175 hpet->header.signature = ACPI_2_0_HPET_SIGNATURE;
176 hpet->header.revision = ACPI_2_0_HPET_REVISION;
177 fixed_strcpy(hpet->header.oem_id, ACPI_OEM_ID);
178 fixed_strcpy(hpet->header.oem_table_id, ACPI_OEM_TABLE_ID);
179 hpet->header.oem_revision = ACPI_OEM_REVISION;
180 hpet->header.creator_id = ACPI_CREATOR_ID;
181 hpet->header.creator_revision = ACPI_CREATOR_REVISION;
182 hpet->timer_block_id = 0x8086a201;
183 hpet->addr.address = ACPI_HPET_ADDRESS;
184 offset = sizeof(*hpet);
186 hpet->header.length = offset;
187 set_checksum(hpet, offsetof(struct acpi_header, checksum), offset);
189 return offset;
190 }
192 static int construct_secondary_tables(uint8_t *buf, unsigned long *table_ptrs)
193 {
194 int offset = 0, nr_tables = 0;
195 struct acpi_20_madt *madt;
196 struct acpi_20_hpet *hpet;
197 struct acpi_20_tcpa *tcpa;
198 static const uint16_t tis_signature[] = {0x0001, 0x0001, 0x0001};
199 uint16_t *tis_hdr;
201 /* MADT. */
202 if ( (get_vcpu_nr() > 1) || get_apic_mode() )
203 {
204 madt = (struct acpi_20_madt *)&buf[offset];
205 offset += construct_madt(madt);
206 table_ptrs[nr_tables++] = (unsigned long)madt;
207 }
209 /* HPET. */
210 if ( hpet_exists(ACPI_HPET_ADDRESS) )
211 {
212 hpet = (struct acpi_20_hpet *)&buf[offset];
213 offset += construct_hpet(hpet);
214 table_ptrs[nr_tables++] = (unsigned long)hpet;
215 }
217 /* TPM TCPA and SSDT. */
218 tis_hdr = (uint16_t *)0xFED40F00;
219 if ( (tis_hdr[0] == tis_signature[0]) &&
220 (tis_hdr[1] == tis_signature[1]) &&
221 (tis_hdr[2] == tis_signature[2]) )
222 {
223 memcpy(&buf[offset], AmlCode_TPM, sizeof(AmlCode_TPM));
224 table_ptrs[nr_tables++] = (unsigned long)&buf[offset];
225 offset += align16(sizeof(AmlCode_TPM));
227 tcpa = (struct acpi_20_tcpa *)&buf[offset];
228 memset(tcpa, 0, sizeof(*tcpa));
229 offset += align16(sizeof(*tcpa));
230 table_ptrs[nr_tables++] = (unsigned long)tcpa;
232 tcpa->header.signature = ACPI_2_0_TCPA_SIGNATURE;
233 tcpa->header.length = sizeof(*tcpa);
234 tcpa->header.revision = ACPI_2_0_TCPA_REVISION;
235 fixed_strcpy(tcpa->header.oem_id, ACPI_OEM_ID);
236 fixed_strcpy(tcpa->header.oem_table_id, ACPI_OEM_TABLE_ID);
237 tcpa->header.oem_revision = ACPI_OEM_REVISION;
238 tcpa->header.creator_id = ACPI_CREATOR_ID;
239 tcpa->header.creator_revision = ACPI_CREATOR_REVISION;
240 tcpa->lasa = e820_malloc(ACPI_2_0_TCPA_LAML_SIZE);
241 if ( tcpa->lasa )
242 {
243 tcpa->laml = ACPI_2_0_TCPA_LAML_SIZE;
244 memset((char *)(unsigned long)tcpa->lasa, 0, tcpa->laml);
245 set_checksum(tcpa,
246 offsetof(struct acpi_header, checksum),
247 tcpa->header.length);
248 }
249 }
251 table_ptrs[nr_tables] = 0;
252 return align16(offset);
253 }
255 /* Copy all the ACPI table to buffer. */
256 int acpi_build_tables(uint8_t *buf)
257 {
258 struct acpi_20_rsdp *rsdp;
259 struct acpi_20_rsdt *rsdt;
260 struct acpi_20_xsdt *xsdt;
261 struct acpi_20_fadt *fadt;
262 struct acpi_10_fadt *fadt_10;
263 struct acpi_20_facs *facs;
264 unsigned char *dsdt;
265 unsigned long secondary_tables[16];
266 int offset = 0, i;
268 offset += construct_bios_info_table(&buf[offset]);
270 facs = (struct acpi_20_facs *)&buf[offset];
271 memcpy(facs, &Facs, sizeof(struct acpi_20_facs));
272 offset += align16(sizeof(struct acpi_20_facs));
274 dsdt = (unsigned char *)&buf[offset];
275 memcpy(dsdt, &AmlCode, DsdtLen);
276 offset += align16(DsdtLen);
278 /*
279 * N.B. ACPI 1.0 operating systems may not handle FADT with revision 2
280 * or above properly, notably Windows 2000, which tries to copy FADT
281 * into a 116 bytes buffer thus causing an overflow. The solution is to
282 * link the higher revision FADT with the XSDT only and introduce a
283 * compatible revision 1 FADT that is linked with the RSDT. Refer to:
284 * http://www.acpi.info/presentations/S01USMOBS169_OS%20new.ppt
285 */
286 fadt_10 = (struct acpi_10_fadt *)&buf[offset];
287 memcpy(fadt_10, &Fadt, sizeof(struct acpi_10_fadt));
288 offset += align16(sizeof(struct acpi_10_fadt));
289 fadt_10->header.length = sizeof(struct acpi_10_fadt);
290 fadt_10->header.revision = ACPI_1_0_FADT_REVISION;
291 fadt_10->dsdt = (unsigned long)dsdt;
292 fadt_10->firmware_ctrl = (unsigned long)facs;
293 set_checksum(fadt_10,
294 offsetof(struct acpi_header, checksum),
295 sizeof(struct acpi_10_fadt));
297 fadt = (struct acpi_20_fadt *)&buf[offset];
298 memcpy(fadt, &Fadt, sizeof(struct acpi_20_fadt));
299 offset += align16(sizeof(struct acpi_20_fadt));
300 fadt->dsdt = (unsigned long)dsdt;
301 fadt->x_dsdt = (unsigned long)dsdt;
302 fadt->firmware_ctrl = (unsigned long)facs;
303 fadt->x_firmware_ctrl = (unsigned long)facs;
304 set_checksum(fadt,
305 offsetof(struct acpi_header, checksum),
306 sizeof(struct acpi_20_fadt));
308 offset += construct_secondary_tables(&buf[offset], secondary_tables);
310 xsdt = (struct acpi_20_xsdt *)&buf[offset];
311 memcpy(xsdt, &Xsdt, sizeof(struct acpi_header));
312 xsdt->entry[0] = (unsigned long)fadt;
313 for ( i = 0; secondary_tables[i]; i++ )
314 xsdt->entry[i+1] = secondary_tables[i];
315 xsdt->header.length = sizeof(struct acpi_header) + (i+1)*sizeof(uint64_t);
316 offset += align16(xsdt->header.length);
317 set_checksum(xsdt,
318 offsetof(struct acpi_header, checksum),
319 xsdt->header.length);
321 rsdt = (struct acpi_20_rsdt *)&buf[offset];
322 memcpy(rsdt, &Rsdt, sizeof(struct acpi_header));
323 rsdt->entry[0] = (unsigned long)fadt_10;
324 for ( i = 0; secondary_tables[i]; i++ )
325 rsdt->entry[i+1] = secondary_tables[i];
326 rsdt->header.length = sizeof(struct acpi_header) + (i+1)*sizeof(uint32_t);
327 offset += align16(rsdt->header.length);
328 set_checksum(rsdt,
329 offsetof(struct acpi_header, checksum),
330 rsdt->header.length);
332 rsdp = (struct acpi_20_rsdp *)&buf[offset];
333 memcpy(rsdp, &Rsdp, sizeof(struct acpi_20_rsdp));
334 offset += align16(sizeof(struct acpi_20_rsdp));
335 rsdp->rsdt_address = (unsigned long)rsdt;
336 rsdp->xsdt_address = (unsigned long)xsdt;
337 set_checksum(rsdp,
338 offsetof(struct acpi_10_rsdp, checksum),
339 sizeof(struct acpi_10_rsdp));
340 set_checksum(rsdp,
341 offsetof(struct acpi_20_rsdp, extended_checksum),
342 sizeof(struct acpi_20_rsdp));
344 return offset;
345 }
347 /*
348 * Local variables:
349 * mode: C
350 * c-set-style: "BSD"
351 * c-basic-offset: 4
352 * tab-width: 4
353 * indent-tabs-mode: nil
354 * End:
355 */