2 * This file is part of the coreboot project.
4 * coreboot ACPI Table support
5 * written by Stefan Reinauer <stepan@openbios.org>
7 * Copyright (C) 2004 SUSE LINUX AG
8 * Copyright (C) 2005-2009 coresystems GmbH
10 * ACPI FADT, FACS, and DSDT table support added by
11 * Nick Barker <nick.barker9@btinternet.com>, and those portions
12 * Copyright (C) 2004 Nick Barker
14 * Copyright (C) 2005 ADVANCED MICRO DEVICES, INC. All Rights Reserved.
15 * 2005.9 yhlu add SRAT table generation
19 * Each system port implementing ACPI has to provide two functions:
24 * See Kontron 986LCD-M port for a good example of an ACPI implementation
28 #include <console/console.h>
30 #include <arch/acpi.h>
31 #include <arch/acpigen.h>
32 #include <device/pci.h>
34 #include <cpu/x86/lapic_def.h>
37 #include <timestamp.h>
38 #include <romstage_handoff.h>
40 /* FIXME: Kconfig doesn't support overridable defaults :-( */
41 #ifndef CONFIG_HPET_MIN_TICKS
42 #define CONFIG_HPET_MIN_TICKS 0x1000
45 u8
acpi_checksum(u8
*table
, u32 length
)
56 * Add an ACPI table to the RSDT (and XSDT) structure, recalculate length
59 void acpi_add_table(acpi_rsdp_t
*rsdp
, void *table
)
63 acpi_xsdt_t
*xsdt
= NULL
;
65 /* The RSDT is mandatory... */
66 rsdt
= (acpi_rsdt_t
*)(uintptr_t)rsdp
->rsdt_address
;
68 /* ...while the XSDT is not. */
69 if (rsdp
->xsdt_address
)
70 xsdt
= (acpi_xsdt_t
*)((uintptr_t)rsdp
->xsdt_address
);
72 /* This should always be MAX_ACPI_TABLES. */
73 entries_num
= ARRAY_SIZE(rsdt
->entry
);
75 for (i
= 0; i
< entries_num
; i
++) {
76 if (rsdt
->entry
[i
] == 0)
80 if (i
>= entries_num
) {
81 printk(BIOS_ERR
, "ACPI: Error: Could not add ACPI table, "
82 "too many tables.\n");
86 /* Add table to the RSDT. */
87 rsdt
->entry
[i
] = (uintptr_t)table
;
89 /* Fix RSDT length or the kernel will assume invalid entries. */
90 rsdt
->header
.length
= sizeof(acpi_header_t
) + (sizeof(u32
) * (i
+ 1));
92 /* Re-calculate checksum. */
93 rsdt
->header
.checksum
= 0; /* Hope this won't get optimized away */
94 rsdt
->header
.checksum
= acpi_checksum((u8
*)rsdt
, rsdt
->header
.length
);
97 * And now the same thing for the XSDT. We use the same index as for
98 * now we want the XSDT and RSDT to always be in sync in coreboot.
101 /* Add table to the XSDT. */
102 xsdt
->entry
[i
] = (u64
)(uintptr_t)table
;
104 /* Fix XSDT length. */
105 xsdt
->header
.length
= sizeof(acpi_header_t
) +
106 (sizeof(u64
) * (i
+ 1));
108 /* Re-calculate checksum. */
109 xsdt
->header
.checksum
= 0;
110 xsdt
->header
.checksum
= acpi_checksum((u8
*)xsdt
,
111 xsdt
->header
.length
);
114 printk(BIOS_DEBUG
, "ACPI: added table %d/%d, length now %d\n",
115 i
+ 1, entries_num
, rsdt
->header
.length
);
118 int acpi_create_mcfg_mmconfig(acpi_mcfg_mmconfig_t
*mmconfig
, u32 base
,
119 u16 seg_nr
, u8 start
, u8 end
)
121 memset(mmconfig
, 0, sizeof(*mmconfig
));
122 mmconfig
->base_address
= base
;
123 mmconfig
->base_reserved
= 0;
124 mmconfig
->pci_segment_group_number
= seg_nr
;
125 mmconfig
->start_bus_number
= start
;
126 mmconfig
->end_bus_number
= end
;
128 return sizeof(acpi_mcfg_mmconfig_t
);
131 int acpi_create_madt_lapic(acpi_madt_lapic_t
*lapic
, u8 cpu
, u8 apic
)
133 lapic
->type
= 0; /* Local APIC structure */
134 lapic
->length
= sizeof(acpi_madt_lapic_t
);
135 lapic
->flags
= (1 << 0); /* Processor/LAPIC enabled */
136 lapic
->processor_id
= cpu
;
137 lapic
->apic_id
= apic
;
139 return lapic
->length
;
142 unsigned long acpi_create_madt_lapics(unsigned long current
)
147 for (cpu
= all_devices
; cpu
; cpu
= cpu
->next
) {
148 if ((cpu
->path
.type
!= DEVICE_PATH_APIC
) ||
149 (cpu
->bus
->dev
->path
.type
!= DEVICE_PATH_CPU_CLUSTER
)) {
154 current
+= acpi_create_madt_lapic((acpi_madt_lapic_t
*)current
,
155 index
, cpu
->path
.apic
.apic_id
);
162 int acpi_create_madt_ioapic(acpi_madt_ioapic_t
*ioapic
, u8 id
, u32 addr
,
165 ioapic
->type
= 1; /* I/O APIC structure */
166 ioapic
->length
= sizeof(acpi_madt_ioapic_t
);
167 ioapic
->reserved
= 0x00;
168 ioapic
->gsi_base
= gsi_base
;
169 ioapic
->ioapic_id
= id
;
170 ioapic
->ioapic_addr
= addr
;
172 return ioapic
->length
;
175 int acpi_create_madt_irqoverride(acpi_madt_irqoverride_t
*irqoverride
,
176 u8 bus
, u8 source
, u32 gsirq
, u16 flags
)
178 irqoverride
->type
= 2; /* Interrupt source override */
179 irqoverride
->length
= sizeof(acpi_madt_irqoverride_t
);
180 irqoverride
->bus
= bus
;
181 irqoverride
->source
= source
;
182 irqoverride
->gsirq
= gsirq
;
183 irqoverride
->flags
= flags
;
185 return irqoverride
->length
;
188 int acpi_create_madt_lapic_nmi(acpi_madt_lapic_nmi_t
*lapic_nmi
, u8 cpu
,
191 lapic_nmi
->type
= 4; /* Local APIC NMI structure */
192 lapic_nmi
->length
= sizeof(acpi_madt_lapic_nmi_t
);
193 lapic_nmi
->flags
= flags
;
194 lapic_nmi
->processor_id
= cpu
;
195 lapic_nmi
->lint
= lint
;
197 return lapic_nmi
->length
;
200 void acpi_create_madt(acpi_madt_t
*madt
)
202 acpi_header_t
*header
= &(madt
->header
);
203 unsigned long current
= (unsigned long)madt
+ sizeof(acpi_madt_t
);
205 memset((void *)madt
, 0, sizeof(acpi_madt_t
));
207 /* Fill out header fields. */
208 memcpy(header
->signature
, "APIC", 4);
209 memcpy(header
->oem_id
, OEM_ID
, 6);
210 memcpy(header
->oem_table_id
, ACPI_TABLE_CREATOR
, 8);
211 memcpy(header
->asl_compiler_id
, ASLC
, 4);
213 header
->length
= sizeof(acpi_madt_t
);
214 header
->revision
= 1; /* ACPI 1.0/2.0: 1, ACPI 3.0: 2, ACPI 4.0: 3 */
216 madt
->lapic_addr
= LOCAL_APIC_ADDR
;
217 madt
->flags
= 0x1; /* PCAT_COMPAT */
219 current
= acpi_fill_madt(current
);
221 /* (Re)calculate length and checksum. */
222 header
->length
= current
- (unsigned long)madt
;
224 header
->checksum
= acpi_checksum((void *)madt
, header
->length
);
227 /* MCFG is defined in the PCI Firmware Specification 3.0. */
228 void acpi_create_mcfg(acpi_mcfg_t
*mcfg
)
230 acpi_header_t
*header
= &(mcfg
->header
);
231 unsigned long current
= (unsigned long)mcfg
+ sizeof(acpi_mcfg_t
);
233 memset((void *)mcfg
, 0, sizeof(acpi_mcfg_t
));
235 /* Fill out header fields. */
236 memcpy(header
->signature
, "MCFG", 4);
237 memcpy(header
->oem_id
, OEM_ID
, 6);
238 memcpy(header
->oem_table_id
, ACPI_TABLE_CREATOR
, 8);
239 memcpy(header
->asl_compiler_id
, ASLC
, 4);
241 header
->length
= sizeof(acpi_mcfg_t
);
242 header
->revision
= 1;
244 current
= acpi_fill_mcfg(current
);
246 /* (Re)calculate length and checksum. */
247 header
->length
= current
- (unsigned long)mcfg
;
248 header
->checksum
= acpi_checksum((void *)mcfg
, header
->length
);
251 static void *get_tcpa_log(u32
*size
)
253 const struct cbmem_entry
*ce
;
254 const u32 tcpa_default_log_len
= 0x10000;
256 ce
= cbmem_entry_find(CBMEM_ID_TCPA_LOG
);
258 lasa
= cbmem_entry_start(ce
);
259 *size
= cbmem_entry_size(ce
);
260 printk(BIOS_DEBUG
, "TCPA log found at %p\n", lasa
);
263 lasa
= cbmem_add(CBMEM_ID_TCPA_LOG
, tcpa_default_log_len
);
265 printk(BIOS_ERR
, "TCPA log creation failed\n");
269 printk(BIOS_DEBUG
, "TCPA log created at %p\n", lasa
);
270 memset (lasa
, 0, tcpa_default_log_len
);
272 *size
= tcpa_default_log_len
;
276 static void acpi_create_tcpa(acpi_tcpa_t
*tcpa
)
278 acpi_header_t
*header
= &(tcpa
->header
);
282 memset((void *)tcpa
, 0, sizeof(acpi_tcpa_t
));
284 lasa
= get_tcpa_log(&tcpa_log_len
);
289 /* Fill out header fields. */
290 memcpy(header
->signature
, "TCPA", 4);
291 memcpy(header
->oem_id
, OEM_ID
, 6);
292 memcpy(header
->oem_table_id
, ACPI_TABLE_CREATOR
, 8);
293 memcpy(header
->asl_compiler_id
, ASLC
, 4);
295 header
->length
= sizeof(acpi_tcpa_t
);
296 header
->revision
= 2;
298 tcpa
->platform_class
= 0;
299 tcpa
->laml
= tcpa_log_len
;
300 tcpa
->lasa
= (uintptr_t) lasa
;
302 /* Calculate checksum. */
303 header
->checksum
= acpi_checksum((void *)tcpa
, header
->length
);
306 void acpi_create_ssdt_generator(acpi_header_t
*ssdt
, const char *oem_table_id
)
308 unsigned long current
= (unsigned long)ssdt
+ sizeof(acpi_header_t
);
310 memset((void *)ssdt
, 0, sizeof(acpi_header_t
));
312 memcpy(&ssdt
->signature
, "SSDT", 4);
313 ssdt
->revision
= 2; /* ACPI 1.0/2.0: ?, ACPI 3.0/4.0: 2 */
314 memcpy(&ssdt
->oem_id
, OEM_ID
, 6);
315 memcpy(&ssdt
->oem_table_id
, oem_table_id
, 8);
316 ssdt
->oem_revision
= 42;
317 memcpy(&ssdt
->asl_compiler_id
, ASLC
, 4);
318 ssdt
->asl_compiler_revision
= 42;
319 ssdt
->length
= sizeof(acpi_header_t
);
321 acpigen_set_current((char *) current
);
324 for (dev
= all_devices
; dev
; dev
= dev
->next
)
325 if (dev
->ops
&& dev
->ops
->acpi_fill_ssdt_generator
) {
326 dev
->ops
->acpi_fill_ssdt_generator(dev
);
328 current
= (unsigned long) acpigen_get_current();
331 /* (Re)calculate length and checksum. */
332 ssdt
->length
= current
- (unsigned long)ssdt
;
333 ssdt
->checksum
= acpi_checksum((void *)ssdt
, ssdt
->length
);
336 int acpi_create_srat_lapic(acpi_srat_lapic_t
*lapic
, u8 node
, u8 apic
)
338 memset((void *)lapic
, 0, sizeof(acpi_srat_lapic_t
));
340 lapic
->type
= 0; /* Processor local APIC/SAPIC affinity structure */
341 lapic
->length
= sizeof(acpi_srat_lapic_t
);
342 lapic
->flags
= (1 << 0); /* Enabled (the use of this structure). */
343 lapic
->proximity_domain_7_0
= node
;
344 /* TODO: proximity_domain_31_8, local SAPIC EID, clock domain. */
345 lapic
->apic_id
= apic
;
347 return lapic
->length
;
350 int acpi_create_srat_mem(acpi_srat_mem_t
*mem
, u8 node
, u32 basek
, u32 sizek
,
353 mem
->type
= 1; /* Memory affinity structure */
354 mem
->length
= sizeof(acpi_srat_mem_t
);
355 mem
->base_address_low
= (basek
<< 10);
356 mem
->base_address_high
= (basek
>> (32 - 10));
357 mem
->length_low
= (sizek
<< 10);
358 mem
->length_high
= (sizek
>> (32 - 10));
359 mem
->proximity_domain
= node
;
365 /* http://www.microsoft.com/whdc/system/sysinternals/sratdwn.mspx */
366 void acpi_create_srat(acpi_srat_t
*srat
,
367 unsigned long (*acpi_fill_srat
)(unsigned long current
))
369 acpi_header_t
*header
= &(srat
->header
);
370 unsigned long current
= (unsigned long)srat
+ sizeof(acpi_srat_t
);
372 memset((void *)srat
, 0, sizeof(acpi_srat_t
));
374 /* Fill out header fields. */
375 memcpy(header
->signature
, "SRAT", 4);
376 memcpy(header
->oem_id
, OEM_ID
, 6);
377 memcpy(header
->oem_table_id
, ACPI_TABLE_CREATOR
, 8);
378 memcpy(header
->asl_compiler_id
, ASLC
, 4);
380 header
->length
= sizeof(acpi_srat_t
);
381 header
->revision
= 1; /* ACPI 1.0: N/A, 2.0: 1, 3.0: 2, 4.0: 3 */
383 srat
->resv
= 1; /* Spec: Reserved to 1 for backwards compatibility. */
385 current
= acpi_fill_srat(current
);
387 /* (Re)calculate length and checksum. */
388 header
->length
= current
- (unsigned long)srat
;
389 header
->checksum
= acpi_checksum((void *)srat
, header
->length
);
392 void acpi_create_dmar(acpi_dmar_t
*dmar
, enum dmar_flags flags
,
393 unsigned long (*acpi_fill_dmar
) (unsigned long))
395 acpi_header_t
*header
= &(dmar
->header
);
396 unsigned long current
= (unsigned long)dmar
+ sizeof(acpi_dmar_t
);
398 memset((void *)dmar
, 0, sizeof(acpi_dmar_t
));
400 /* Fill out header fields. */
401 memcpy(header
->signature
, "DMAR", 4);
402 memcpy(header
->oem_id
, OEM_ID
, 6);
403 memcpy(header
->oem_table_id
, ACPI_TABLE_CREATOR
, 8);
404 memcpy(header
->asl_compiler_id
, ASLC
, 4);
406 header
->length
= sizeof(acpi_dmar_t
);
407 header
->revision
= 1;
409 dmar
->host_address_width
= 40 - 1; /* FIXME: == MTRR size? */
412 current
= acpi_fill_dmar(current
);
414 /* (Re)calculate length and checksum. */
415 header
->length
= current
- (unsigned long)dmar
;
416 header
->checksum
= acpi_checksum((void *)dmar
, header
->length
);
419 unsigned long acpi_create_dmar_drhd(unsigned long current
, u8 flags
,
420 u16 segment
, u32 bar
)
422 dmar_entry_t
*drhd
= (dmar_entry_t
*)current
;
423 memset(drhd
, 0, sizeof(*drhd
));
424 drhd
->type
= DMAR_DRHD
;
425 drhd
->length
= sizeof(*drhd
); /* will be fixed up later */
427 drhd
->segment
= segment
;
433 void acpi_dmar_drhd_fixup(unsigned long base
, unsigned long current
)
435 dmar_entry_t
*drhd
= (dmar_entry_t
*)base
;
436 drhd
->length
= current
- base
;
439 static unsigned long acpi_create_dmar_drhd_ds(unsigned long current
,
440 enum dev_scope_type type
, u8 enumeration_id
, u8 bus
, u8 dev
, u8 fn
)
442 /* we don't support longer paths yet */
443 const size_t dev_scope_length
= sizeof(dev_scope_t
) + 2;
445 dev_scope_t
*ds
= (dev_scope_t
*)current
;
446 memset(ds
, 0, dev_scope_length
);
448 ds
->length
= dev_scope_length
;
449 ds
->enumeration
= enumeration_id
;
451 ds
->path
[0].dev
= dev
;
457 unsigned long acpi_create_dmar_drhd_ds_pci(unsigned long current
, u8 bus
,
460 return acpi_create_dmar_drhd_ds(current
,
461 SCOPE_PCI_ENDPOINT
, 0, bus
, dev
, fn
);
464 unsigned long acpi_create_dmar_drhd_ds_ioapic(unsigned long current
,
465 u8 enumeration_id
, u8 bus
, u8 dev
, u8 fn
)
467 return acpi_create_dmar_drhd_ds(current
,
468 SCOPE_IOAPIC
, enumeration_id
, bus
, dev
, fn
);
471 unsigned long acpi_create_dmar_drhd_ds_msi_hpet(unsigned long current
,
472 u8 enumeration_id
, u8 bus
, u8 dev
, u8 fn
)
474 return acpi_create_dmar_drhd_ds(current
,
475 SCOPE_MSI_HPET
, enumeration_id
, bus
, dev
, fn
);
478 /* http://h21007.www2.hp.com/portal/download/files/unprot/Itanium/slit.pdf */
479 void acpi_create_slit(acpi_slit_t
*slit
,
480 unsigned long (*acpi_fill_slit
)(unsigned long current
))
482 acpi_header_t
*header
= &(slit
->header
);
483 unsigned long current
= (unsigned long)slit
+ sizeof(acpi_slit_t
);
485 memset((void *)slit
, 0, sizeof(acpi_slit_t
));
487 /* Fill out header fields. */
488 memcpy(header
->signature
, "SLIT", 4);
489 memcpy(header
->oem_id
, OEM_ID
, 6);
490 memcpy(header
->oem_table_id
, ACPI_TABLE_CREATOR
, 8);
491 memcpy(header
->asl_compiler_id
, ASLC
, 4);
493 header
->length
= sizeof(acpi_slit_t
);
494 header
->revision
= 1; /* ACPI 1.0: N/A, ACPI 2.0/3.0/4.0: 1 */
496 current
= acpi_fill_slit(current
);
498 /* (Re)calculate length and checksum. */
499 header
->length
= current
- (unsigned long)slit
;
500 header
->checksum
= acpi_checksum((void *)slit
, header
->length
);
503 /* http://www.intel.com/hardwaredesign/hpetspec_1.pdf */
504 void acpi_create_hpet(acpi_hpet_t
*hpet
)
506 acpi_header_t
*header
= &(hpet
->header
);
507 acpi_addr_t
*addr
= &(hpet
->addr
);
509 memset((void *)hpet
, 0, sizeof(acpi_hpet_t
));
511 /* Fill out header fields. */
512 memcpy(header
->signature
, "HPET", 4);
513 memcpy(header
->oem_id
, OEM_ID
, 6);
514 memcpy(header
->oem_table_id
, ACPI_TABLE_CREATOR
, 8);
515 memcpy(header
->asl_compiler_id
, ASLC
, 4);
517 header
->length
= sizeof(acpi_hpet_t
);
518 header
->revision
= 1; /* Currently 1. Table added in ACPI 2.0. */
520 /* Fill out HPET address. */
521 addr
->space_id
= 0; /* Memory */
522 addr
->bit_width
= 64;
523 addr
->bit_offset
= 0;
524 addr
->addrl
= CONFIG_HPET_ADDRESS
& 0xffffffff;
525 addr
->addrh
= ((unsigned long long)CONFIG_HPET_ADDRESS
) >> 32;
527 hpet
->id
= *(unsigned int*)CONFIG_HPET_ADDRESS
;
529 hpet
->min_tick
= CONFIG_HPET_MIN_TICKS
;
531 header
->checksum
= acpi_checksum((void *)hpet
, sizeof(acpi_hpet_t
));
534 unsigned long acpi_write_hpet(device_t device
, unsigned long current
, acpi_rsdp_t
*rsdp
)
539 * We explicitly add these tables later on:
541 printk(BIOS_DEBUG
, "ACPI: * HPET\n");
543 hpet
= (acpi_hpet_t
*) current
;
544 current
+= sizeof(acpi_hpet_t
);
545 current
= ALIGN(current
, 16);
546 acpi_create_hpet(hpet
);
547 acpi_add_table(rsdp
, hpet
);
552 void acpi_create_facs(acpi_facs_t
*facs
)
554 memset((void *)facs
, 0, sizeof(acpi_facs_t
));
556 memcpy(facs
->signature
, "FACS", 4);
557 facs
->length
= sizeof(acpi_facs_t
);
558 facs
->hardware_signature
= 0;
559 facs
->firmware_waking_vector
= 0;
560 facs
->global_lock
= 0;
562 facs
->x_firmware_waking_vector_l
= 0;
563 facs
->x_firmware_waking_vector_h
= 0;
564 facs
->version
= 1; /* ACPI 1.0: 0, ACPI 2.0/3.0: 1, ACPI 4.0: 2 */
567 static void acpi_write_rsdt(acpi_rsdt_t
*rsdt
, char *oem_id
, char *oem_table_id
)
569 acpi_header_t
*header
= &(rsdt
->header
);
571 /* Fill out header fields. */
572 memcpy(header
->signature
, "RSDT", 4);
573 memcpy(header
->oem_id
, oem_id
, 6);
574 memcpy(header
->oem_table_id
, oem_table_id
, 8);
575 memcpy(header
->asl_compiler_id
, ASLC
, 4);
577 header
->length
= sizeof(acpi_rsdt_t
);
578 header
->revision
= 1; /* ACPI 1.0/2.0/3.0/4.0: 1 */
580 /* Entries are filled in later, we come with an empty set. */
583 header
->checksum
= acpi_checksum((void *)rsdt
, sizeof(acpi_rsdt_t
));
586 static void acpi_write_xsdt(acpi_xsdt_t
*xsdt
, char *oem_id
, char *oem_table_id
)
588 acpi_header_t
*header
= &(xsdt
->header
);
590 /* Fill out header fields. */
591 memcpy(header
->signature
, "XSDT", 4);
592 memcpy(header
->oem_id
, oem_id
, 6);
593 memcpy(header
->oem_table_id
, oem_table_id
, 8);
594 memcpy(header
->asl_compiler_id
, ASLC
, 4);
596 header
->length
= sizeof(acpi_xsdt_t
);
597 header
->revision
= 1; /* ACPI 1.0: N/A, 2.0/3.0/4.0: 1 */
599 /* Entries are filled in later, we come with an empty set. */
602 header
->checksum
= acpi_checksum((void *)xsdt
, sizeof(acpi_xsdt_t
));
605 static void acpi_write_rsdp(acpi_rsdp_t
*rsdp
, acpi_rsdt_t
*rsdt
,
606 acpi_xsdt_t
*xsdt
, char *oem_id
)
608 memset(rsdp
, 0, sizeof(acpi_rsdp_t
));
610 memcpy(rsdp
->signature
, RSDP_SIG
, 8);
611 memcpy(rsdp
->oem_id
, oem_id
, 6);
613 rsdp
->length
= sizeof(acpi_rsdp_t
);
614 rsdp
->rsdt_address
= (uintptr_t)rsdt
;
617 * Revision: ACPI 1.0: 0, ACPI 2.0/3.0/4.0: 2.
619 * Some OSes expect an XSDT to be present for RSD PTR revisions >= 2.
620 * If we don't have an ACPI XSDT, force ACPI 1.0 (and thus RSD PTR
626 rsdp
->xsdt_address
= (u64
)(uintptr_t)xsdt
;
630 /* Calculate checksums. */
631 rsdp
->checksum
= acpi_checksum((void *)rsdp
, 20);
632 rsdp
->ext_checksum
= acpi_checksum((void *)rsdp
, sizeof(acpi_rsdp_t
));
635 unsigned long acpi_create_hest_error_source(acpi_hest_t
*hest
, acpi_hest_esd_t
*esd
, u16 type
, void *data
, u16 data_len
)
637 acpi_header_t
*header
= &(hest
->header
);
638 acpi_hest_hen_t
*hen
;
643 memset(pos
, 0, sizeof(acpi_hest_esd_t
));
645 esd
->type
= type
; /* MCE */
646 esd
->source_id
= hest
->error_source_count
;
647 esd
->flags
= 0; /* FIRMWARE_FIRST */
649 esd
->prealloc_erecords
= 1;
650 esd
->max_section_per_record
= 0x1;
652 len
+= sizeof(acpi_hest_esd_t
);
659 hen
= (acpi_hest_hen_t
*) (pos
);
660 memset(pos
, 0, sizeof(acpi_hest_hen_t
));
661 hen
->type
= 3; /* SCI? */
662 hen
->length
= sizeof(acpi_hest_hen_t
);
663 hen
->conf_we
= 0; /* Configuration Write Enable. */
664 hen
->poll_interval
= 0;
666 hen
->sw2poll_threshold_val
= 0;
667 hen
->sw2poll_threshold_win
= 0;
668 hen
->error_threshold_val
= 0;
669 hen
->error_threshold_win
= 0;
670 len
+= sizeof(acpi_hest_hen_t
);
674 case 6: /* AER Root Port */
675 case 7: /* AER Endpoint */
676 case 8: /* AER Bridge */
677 case 9: /* Generic Hardware Error Source. */
681 printk(BIOS_DEBUG
, "Invalid type of Error Source.");
684 hest
->error_source_count
++;
686 memcpy(pos
, data
, data_len
);
688 header
->length
+= len
;
694 void acpi_write_hest(acpi_hest_t
*hest
,
695 unsigned long (*acpi_fill_hest
)(acpi_hest_t
*hest
))
697 acpi_header_t
*header
= &(hest
->header
);
699 memset(hest
, 0, sizeof(acpi_hest_t
));
701 memcpy(header
->signature
, "HEST", 4);
702 memcpy(header
->oem_id
, OEM_ID
, 6);
703 memcpy(header
->oem_table_id
, ACPI_TABLE_CREATOR
, 8);
704 memcpy(header
->asl_compiler_id
, ASLC
, 4);
705 header
->length
+= sizeof(acpi_hest_t
);
706 header
->revision
= 1;
708 acpi_fill_hest(hest
);
710 /* Calculate checksums. */
711 header
->checksum
= acpi_checksum((void *)hest
, header
->length
);
714 #if IS_ENABLED(CONFIG_COMMON_FADT)
715 void acpi_create_fadt(acpi_fadt_t
*fadt
,acpi_facs_t
*facs
, void *dsdt
)
717 acpi_header_t
*header
= &(fadt
->header
);
719 memset((void *) fadt
, 0, sizeof(acpi_fadt_t
));
720 memcpy(header
->signature
, "FACP", 4);
721 header
->length
= sizeof(acpi_fadt_t
);
722 header
->revision
= 4;
723 memcpy(header
->oem_id
, OEM_ID
, 6);
724 memcpy(header
->oem_table_id
, ACPI_TABLE_CREATOR
, 8);
725 memcpy(header
->asl_compiler_id
, ASLC
, 4);
726 header
->asl_compiler_revision
= 0;
728 fadt
->firmware_ctrl
= (unsigned long) facs
;
729 fadt
->dsdt
= (unsigned long) dsdt
;
731 fadt
->x_firmware_ctl_l
= (unsigned long)facs
;
732 fadt
->x_firmware_ctl_h
= 0;
733 fadt
->x_dsdt_l
= (unsigned long)dsdt
;
736 if(IS_ENABLED(CONFIG_SYSTEM_TYPE_LAPTOP
)) {
737 fadt
->preferred_pm_profile
= PM_MOBILE
;
739 fadt
->preferred_pm_profile
= PM_DESKTOP
;
742 acpi_fill_fadt(fadt
);
745 acpi_checksum((void *) fadt
, header
->length
);
749 unsigned long __attribute__ ((weak
)) fw_cfg_acpi_tables(unsigned long start
)
754 #define ALIGN_CURRENT current = (ALIGN(current, 16))
755 unsigned long write_acpi_tables(unsigned long start
)
757 unsigned long current
;
763 acpi_header_t
*slic_file
, *slic
;
765 acpi_header_t
*dsdt_file
, *dsdt
;
771 size_t slic_size
, dsdt_size
;
772 char oem_id
[6], oem_table_id
[8];
776 /* Align ACPI tables to 16byte */
779 fw
= fw_cfg_acpi_tables(current
);
783 #if CONFIG_COMPILE_IN_DSDT
784 extern char _binary_dsdt_aml_start
;
785 extern char _binary_dsdt_aml_end
;
786 dsdt_file
= (acpi_header_t
*)&_binary_dsdt_aml_start
;
787 dsdt_size
= (size_t)(&_binary_dsdt_aml_end
- &_binary_dsdt_aml_start
);
789 dsdt_file
= cbfs_boot_map_with_leak(
790 CONFIG_CBFS_PREFIX
"/dsdt.aml",
791 CBFS_TYPE_RAW
, &dsdt_size
);
794 printk(BIOS_ERR
, "No DSDT file, skipping ACPI tables\n");
798 if (dsdt_file
->length
> dsdt_size
799 || dsdt_file
->length
< sizeof (acpi_header_t
)
800 || memcmp(dsdt_file
->signature
, "DSDT", 4) != 0) {
801 printk(BIOS_ERR
, "Invalid DSDT file, skipping ACPI tables\n");
805 slic_file
= cbfs_boot_map_with_leak(CONFIG_CBFS_PREFIX
"/slic",
806 CBFS_TYPE_RAW
, &slic_size
);
808 && (slic_file
->length
> slic_size
809 || slic_file
->length
< sizeof (acpi_header_t
)
810 || memcmp(slic_file
->signature
, "SLIC", 4) != 0)) {
815 memcpy(oem_id
, slic_file
->oem_id
, 6);
816 memcpy(oem_table_id
, slic_file
->oem_table_id
, 8);
818 memcpy(oem_id
, OEM_ID
, 6);
819 memcpy(oem_table_id
, ACPI_TABLE_CREATOR
, 8);
822 printk(BIOS_INFO
, "ACPI: Writing ACPI tables at %lx.\n", start
);
824 /* We need at least an RSDP and an RSDT Table */
825 rsdp
= (acpi_rsdp_t
*) current
;
826 current
+= sizeof(acpi_rsdp_t
);
828 rsdt
= (acpi_rsdt_t
*) current
;
829 current
+= sizeof(acpi_rsdt_t
);
831 xsdt
= (acpi_xsdt_t
*) current
;
832 current
+= sizeof(acpi_xsdt_t
);
835 /* clear all table memory */
836 memset((void *) start
, 0, current
- start
);
838 acpi_write_rsdp(rsdp
, rsdt
, xsdt
, oem_id
);
839 acpi_write_rsdt(rsdt
, oem_id
, oem_table_id
);
840 acpi_write_xsdt(xsdt
, oem_id
, oem_table_id
);
842 printk(BIOS_DEBUG
, "ACPI: * FACS\n");
843 current
= (ALIGN(current
, 64));
844 facs
= (acpi_facs_t
*) current
;
845 current
+= sizeof(acpi_facs_t
);
847 acpi_create_facs(facs
);
849 printk(BIOS_DEBUG
, "ACPI: * DSDT\n");
850 dsdt
= (acpi_header_t
*) current
;
851 memcpy(dsdt
, dsdt_file
, sizeof(acpi_header_t
));
852 if (dsdt
->length
>= sizeof(acpi_header_t
)) {
853 current
+= sizeof(acpi_header_t
);
855 acpigen_set_current((char *) current
);
856 for (dev
= all_devices
; dev
; dev
= dev
->next
)
857 if (dev
->ops
&& dev
->ops
->acpi_inject_dsdt_generator
) {
858 dev
->ops
->acpi_inject_dsdt_generator(dev
);
860 current
= (unsigned long) acpigen_get_current();
861 memcpy((char *)current
,
862 (char *)dsdt_file
+ sizeof(acpi_header_t
),
863 dsdt
->length
- sizeof(acpi_header_t
));
864 current
+= dsdt
->length
- sizeof(acpi_header_t
);
866 /* (Re)calculate length and checksum. */
867 dsdt
->length
= current
- (unsigned long)dsdt
;
869 dsdt
->checksum
= acpi_checksum((void *)dsdt
, dsdt
->length
);
874 printk(BIOS_DEBUG
, "ACPI: * FADT\n");
875 fadt
= (acpi_fadt_t
*) current
;
876 current
+= sizeof(acpi_fadt_t
);
879 acpi_create_fadt(fadt
, facs
, dsdt
);
880 acpi_add_table(rsdp
, fadt
);
883 printk(BIOS_DEBUG
, "ACPI: * SLIC\n");
884 slic
= (acpi_header_t
*)current
;
885 memcpy(slic
, slic_file
, slic_file
->length
);
886 current
+= slic_file
->length
;
888 acpi_add_table(rsdp
, slic
);
891 printk(BIOS_DEBUG
, "ACPI: * SSDT\n");
892 ssdt
= (acpi_header_t
*)current
;
893 acpi_create_ssdt_generator(ssdt
, ACPI_TABLE_CREATOR
);
894 if (ssdt
->length
> sizeof(acpi_header_t
)) {
895 current
+= ssdt
->length
;
896 acpi_add_table(rsdp
, ssdt
);
900 printk(BIOS_DEBUG
, "ACPI: * MCFG\n");
901 mcfg
= (acpi_mcfg_t
*) current
;
902 acpi_create_mcfg(mcfg
);
903 if (mcfg
->header
.length
> sizeof(acpi_mcfg_t
)) {
904 current
+= mcfg
->header
.length
;
906 acpi_add_table(rsdp
, mcfg
);
909 printk(BIOS_DEBUG
, "ACPI: * TCPA\n");
910 tcpa
= (acpi_tcpa_t
*) current
;
911 acpi_create_tcpa(tcpa
);
912 if (tcpa
->header
.length
>= sizeof(acpi_tcpa_t
)) {
913 current
+= tcpa
->header
.length
;
915 acpi_add_table(rsdp
, tcpa
);
918 printk(BIOS_DEBUG
, "ACPI: * MADT\n");
920 madt
= (acpi_madt_t
*) current
;
921 acpi_create_madt(madt
);
922 if (madt
->header
.length
> sizeof(acpi_madt_t
)) {
923 current
+=madt
->header
.length
;
924 acpi_add_table(rsdp
,madt
);
928 printk(BIOS_DEBUG
, "current = %lx\n", current
);
930 for (dev
= all_devices
; dev
; dev
= dev
->next
) {
931 if (dev
->ops
&& dev
->ops
->write_acpi_tables
) {
932 current
= dev
->ops
->write_acpi_tables(dev
, current
, rsdp
);
937 printk(BIOS_INFO
, "ACPI: done.\n");
941 #if CONFIG_HAVE_ACPI_RESUME
942 void __attribute__((weak
)) mainboard_suspend_resume(void)
946 void acpi_resume(void *wake_vec
)
948 #if CONFIG_HAVE_SMI_HANDLER
949 u32
*gnvs_address
= cbmem_find(CBMEM_ID_ACPI_GNVS_PTR
);
951 /* Restore GNVS pointer in SMM if found */
952 if (gnvs_address
&& *gnvs_address
) {
953 printk(BIOS_DEBUG
, "Restore GNVS pointer to 0x%08x\n",
955 smm_setup_structures((void *)*gnvs_address
, NULL
, NULL
);
959 /* Call mainboard resume handler first, if defined. */
960 mainboard_suspend_resume();
962 post_code(POST_OS_RESUME
);
963 acpi_jump_to_wakeup(wake_vec
);
966 /* This is filled with acpi_is_wakeup() call early in ramstage. */
967 int acpi_slp_type
= -1;
969 #if IS_ENABLED(CONFIG_EARLY_CBMEM_INIT)
970 int acpi_get_sleep_type(void)
972 struct romstage_handoff
*handoff
;
974 handoff
= cbmem_find(CBMEM_ID_ROMSTAGE_INFO
);
976 if (handoff
== NULL
) {
977 printk(BIOS_DEBUG
, "Unknown boot method, assuming normal.\n");
979 } else if (handoff
->s3_resume
) {
980 printk(BIOS_DEBUG
, "S3 Resume.\n");
983 printk(BIOS_DEBUG
, "Normal boot.\n");
989 static void acpi_handoff_wakeup(void)
991 if (acpi_slp_type
< 0)
992 acpi_slp_type
= acpi_get_sleep_type();
995 int acpi_is_wakeup(void)
997 acpi_handoff_wakeup();
998 /* Both resume from S2 and resume from S3 restart at CPU reset */
999 return (acpi_slp_type
== 3 || acpi_slp_type
== 2);
1002 int acpi_is_wakeup_s3(void)
1004 acpi_handoff_wakeup();
1005 return (acpi_slp_type
== 3);
1008 void acpi_fail_wakeup(void)
1010 if (acpi_slp_type
== 3 || acpi_slp_type
== 2)
1014 void acpi_prepare_resume_backup(void)
1016 if (!acpi_s3_resume_allowed())
1019 /* Let's prepare the ACPI S3 Resume area now already, so we can rely on
1020 * it being there during reboot time. We don't need the pointer, nor
1021 * the result right now. If it fails, ACPI resume will be disabled.
1024 if (HIGH_MEMORY_SAVE
)
1025 cbmem_add(CBMEM_ID_RESUME
, HIGH_MEMORY_SAVE
);
1028 static acpi_rsdp_t
*valid_rsdp(acpi_rsdp_t
*rsdp
)
1030 if (strncmp((char *)rsdp
, RSDP_SIG
, sizeof(RSDP_SIG
) - 1) != 0)
1033 printk(BIOS_DEBUG
, "Looking on %p for valid checksum\n", rsdp
);
1035 if (acpi_checksum((void *)rsdp
, 20) != 0)
1037 printk(BIOS_DEBUG
, "Checksum 1 passed\n");
1039 if ((rsdp
->revision
> 1) && (acpi_checksum((void *)rsdp
,
1040 rsdp
->length
) != 0))
1042 printk(BIOS_DEBUG
, "Checksum 2 passed all OK\n");
1047 static acpi_rsdp_t
*rsdp
;
1049 void *acpi_get_wakeup_rsdp(void)
1054 void *acpi_find_wakeup_vector(void)
1059 acpi_fadt_t
*fadt
= NULL
;
1065 if (!acpi_is_wakeup())
1068 printk(BIOS_DEBUG
, "Trying to find the wakeup vector...\n");
1071 for (p
= (char *)0xe0000; p
< (char *)0xfffff; p
+= 16) {
1072 if ((rsdp
= valid_rsdp((acpi_rsdp_t
*)p
)))
1079 printk(BIOS_DEBUG
, "RSDP found at %p\n", rsdp
);
1080 rsdt
= (acpi_rsdt_t
*)(uintptr_t)rsdp
->rsdt_address
;
1082 end
= (char *)rsdt
+ rsdt
->header
.length
;
1083 printk(BIOS_DEBUG
, "RSDT found at %p ends at %p\n", rsdt
, end
);
1085 for (i
= 0; ((char *)&rsdt
->entry
[i
]) < end
; i
++) {
1086 fadt
= (acpi_fadt_t
*)(uintptr_t)rsdt
->entry
[i
];
1087 if (strncmp((char *)fadt
, "FACP", 4) == 0)
1095 printk(BIOS_DEBUG
, "FADT found at %p\n", fadt
);
1096 facs
= (acpi_facs_t
*)(uintptr_t)fadt
->firmware_ctrl
;
1099 printk(BIOS_DEBUG
, "No FACS found, wake up from S3 not "
1104 printk(BIOS_DEBUG
, "FACS found at %p\n", facs
);
1105 wake_vec
= (void *)(uintptr_t)facs
->firmware_waking_vector
;
1106 printk(BIOS_DEBUG
, "OS waking vector is %p\n", wake_vec
);
1112 extern char *lowmem_backup
;
1113 extern char *lowmem_backup_ptr
;
1114 extern int lowmem_backup_size
;
1117 #define WAKEUP_BASE 0x600
1119 void (*acpi_do_wakeup
)(uintptr_t vector
, u32 backup_source
, u32 backup_target
,
1120 u32 backup_size
) asmlinkage
= (void *)WAKEUP_BASE
;
1122 extern unsigned char __wakeup
;
1123 extern unsigned int __wakeup_size
;
1125 void acpi_jump_to_wakeup(void *vector
)
1127 uintptr_t acpi_backup_memory
= 0;
1129 if (HIGH_MEMORY_SAVE
&& acpi_s3_resume_allowed()) {
1130 acpi_backup_memory
= (uintptr_t)cbmem_find(CBMEM_ID_RESUME
);
1132 if (!acpi_backup_memory
) {
1133 printk(BIOS_WARNING
, "ACPI: Backup memory missing. "
1140 // FIXME: This should go into the ACPI backup memory, too. No pork sausages.
1142 * Just restore the SMP trampoline and continue with wakeup on
1145 memcpy(lowmem_backup_ptr
, lowmem_backup
, lowmem_backup_size
);
1148 /* Copy wakeup trampoline in place. */
1149 memcpy((void *)WAKEUP_BASE
, &__wakeup
, __wakeup_size
);
1151 timestamp_add_now(TS_ACPI_WAKE_JUMP
);
1153 acpi_do_wakeup((uintptr_t)vector
, acpi_backup_memory
, CONFIG_RAMBASE
,
1158 void acpi_save_gnvs(u32 gnvs_address
)
1160 u32
*gnvs
= cbmem_add(CBMEM_ID_ACPI_GNVS_PTR
, sizeof(*gnvs
));
1162 *gnvs
= gnvs_address
;