]> git.sur5r.net Git - u-boot/blob - arch/x86/lib/acpi_table.c
x86: acpi: Various changes to acpi_table.h
[u-boot] / arch / x86 / lib / acpi_table.c
1 /*
2  * Based on acpi.c from coreboot
3  *
4  * Copyright (C) 2015, Saket Sinha <saket.sinha89@gmail.com>
5  *
6  * SPDX-License-Identifier: GPL-2.0+
7  */
8
9 #include <common.h>
10 #include <cpu.h>
11 #include <dm.h>
12 #include <dm/uclass-internal.h>
13 #include <dm/lists.h>
14 #include <asm/acpi_table.h>
15 #include <asm/cpu.h>
16 #include <asm/ioapic.h>
17 #include <asm/lapic.h>
18 #include <asm/tables.h>
19 #include <asm/pci.h>
20
21 /*
22  * IASL compiles the dsdt entries and
23  * writes the hex values to AmlCode array.
24  * CamelCase cannot be handled here.
25  */
26 extern const unsigned char AmlCode[];
27
28 /**
29 * Add an ACPI table to the RSDT (and XSDT) structure, recalculate length
30 * and checksum.
31 */
32 static void acpi_add_table(struct acpi_rsdp *rsdp, void *table)
33 {
34         int i, entries_num;
35         struct acpi_rsdt *rsdt;
36         struct acpi_xsdt *xsdt = NULL;
37
38         /* The RSDT is mandatory while the XSDT is not */
39         rsdt = (struct acpi_rsdt *)rsdp->rsdt_address;
40
41         if (rsdp->xsdt_address)
42                 xsdt = (struct acpi_xsdt *)((u32)rsdp->xsdt_address);
43
44         /* This should always be MAX_ACPI_TABLES */
45         entries_num = ARRAY_SIZE(rsdt->entry);
46
47         for (i = 0; i < entries_num; i++) {
48                 if (rsdt->entry[i] == 0)
49                         break;
50         }
51
52         if (i >= entries_num) {
53                 debug("ACPI: Error: too many tables\n");
54                 return;
55         }
56
57         /* Add table to the RSDT */
58         rsdt->entry[i] = (u32)table;
59
60         /* Fix RSDT length or the kernel will assume invalid entries */
61         rsdt->header.length = sizeof(struct acpi_table_header) +
62                               (sizeof(u32) * (i + 1));
63
64         /* Re-calculate checksum */
65         rsdt->header.checksum = 0;
66         rsdt->header.checksum = table_compute_checksum((u8 *)rsdt,
67                                                        rsdt->header.length);
68
69         /*
70          * And now the same thing for the XSDT. We use the same index as for
71          * now we want the XSDT and RSDT to always be in sync in U-Boot
72          */
73         if (xsdt) {
74                 /* Add table to the XSDT */
75                 xsdt->entry[i] = (u64)(u32)table;
76
77                 /* Fix XSDT length */
78                 xsdt->header.length = sizeof(struct acpi_table_header) +
79                          (sizeof(u64) * (i + 1));
80
81                 /* Re-calculate checksum */
82                 xsdt->header.checksum = 0;
83                 xsdt->header.checksum = table_compute_checksum((u8 *)xsdt,
84                                 xsdt->header.length);
85         }
86 }
87
88 static int acpi_create_madt_lapic(struct acpi_madt_lapic *lapic,
89                          u8 cpu, u8 apic)
90 {
91         lapic->type = ACPI_APIC_LAPIC; /* Local APIC structure */
92         lapic->length = sizeof(struct acpi_madt_lapic);
93         lapic->flags = LOCAL_APIC_FLAG_ENABLED; /* Processor/LAPIC enabled */
94         lapic->processor_id = cpu;
95         lapic->apic_id = apic;
96
97         return lapic->length;
98 }
99
100 unsigned long acpi_create_madt_lapics(unsigned long current)
101 {
102         struct udevice *dev;
103
104         for (uclass_find_first_device(UCLASS_CPU, &dev);
105              dev;
106              uclass_find_next_device(&dev)) {
107                 struct cpu_platdata *plat = dev_get_parent_platdata(dev);
108
109                 current += acpi_create_madt_lapic(
110                         (struct acpi_madt_lapic *)current,
111                         plat->cpu_id, plat->cpu_id);
112                 }
113                 return current;
114 }
115
116 int acpi_create_madt_ioapic(struct acpi_madt_ioapic *ioapic, u8 id, u32 addr,
117                          u32 gsi_base)
118 {
119         ioapic->type = ACPI_APIC_IOAPIC;
120         ioapic->length = sizeof(struct acpi_madt_ioapic);
121         ioapic->reserved = 0x00;
122         ioapic->gsi_base = gsi_base;
123         ioapic->ioapic_id = id;
124         ioapic->ioapic_addr = addr;
125
126         return ioapic->length;
127 }
128
129 int acpi_create_madt_irqoverride(struct acpi_madt_irqoverride *irqoverride,
130                          u8 bus, u8 source, u32 gsirq, u16 flags)
131 {
132         irqoverride->type = ACPI_APIC_IRQ_SRC_OVERRIDE;
133         irqoverride->length = sizeof(struct acpi_madt_irqoverride);
134         irqoverride->bus = bus;
135         irqoverride->source = source;
136         irqoverride->gsirq = gsirq;
137         irqoverride->flags = flags;
138
139         return irqoverride->length;
140 }
141
142 int acpi_create_madt_lapic_nmi(struct acpi_madt_lapic_nmi *lapic_nmi,
143                          u8 cpu, u16 flags, u8 lint)
144 {
145         lapic_nmi->type = ACPI_APIC_LAPIC_NMI;
146         lapic_nmi->length = sizeof(struct acpi_madt_lapic_nmi);
147         lapic_nmi->flags = flags;
148         lapic_nmi->processor_id = cpu;
149         lapic_nmi->lint = lint;
150
151         return lapic_nmi->length;
152 }
153
154 static void fill_header(struct acpi_table_header *header, char *signature,
155                         int length)
156 {
157         memcpy(header->signature, signature, length);
158         memcpy(header->oem_id, OEM_ID, 6);
159         memcpy(header->oem_table_id, OEM_TABLE_ID, 8);
160         memcpy(header->aslc_id, ASLC_ID, 4);
161 }
162
163 static void acpi_create_madt(struct acpi_madt *madt)
164 {
165         struct acpi_table_header *header = &(madt->header);
166         unsigned long current = (unsigned long)madt + sizeof(struct acpi_madt);
167
168         memset((void *)madt, 0, sizeof(struct acpi_madt));
169
170         /* Fill out header fields */
171         fill_header(header, "APIC", 4);
172         header->length = sizeof(struct acpi_madt);
173
174         /* ACPI 1.0/2.0: 1, ACPI 3.0: 2, ACPI 4.0: 3 */
175         header->revision = ACPI_REV_ACPI_2_0;
176
177         madt->lapic_addr = LAPIC_DEFAULT_BASE;
178         madt->flags = ACPI_MADT_PCAT_COMPAT;
179
180         current = acpi_fill_madt(current);
181
182         /* (Re)calculate length and checksum */
183         header->length = current - (unsigned long)madt;
184
185         header->checksum = table_compute_checksum((void *)madt, header->length);
186 }
187
188 static int acpi_create_mcfg_mmconfig(struct acpi_mcfg_mmconfig *mmconfig,
189                          u32 base, u16 seg_nr, u8 start, u8 end)
190 {
191         memset(mmconfig, 0, sizeof(*mmconfig));
192         mmconfig->base_address_l = base;
193         mmconfig->base_address_h = 0;
194         mmconfig->pci_segment_group_number = seg_nr;
195         mmconfig->start_bus_number = start;
196         mmconfig->end_bus_number = end;
197
198         return sizeof(struct acpi_mcfg_mmconfig);
199 }
200
201 static unsigned long acpi_fill_mcfg(unsigned long current)
202 {
203         current += acpi_create_mcfg_mmconfig
204                 ((struct acpi_mcfg_mmconfig *)current,
205                  CONFIG_PCIE_ECAM_BASE, 0x0, 0x0, 255);
206
207         return current;
208 }
209
210 /* MCFG is defined in the PCI Firmware Specification 3.0 */
211 static void acpi_create_mcfg(struct acpi_mcfg *mcfg)
212 {
213         struct acpi_table_header *header = &(mcfg->header);
214         unsigned long current = (unsigned long)mcfg + sizeof(struct acpi_mcfg);
215
216         memset((void *)mcfg, 0, sizeof(struct acpi_mcfg));
217
218         /* Fill out header fields */
219         fill_header(header, "MCFG", 4);
220         header->length = sizeof(struct acpi_mcfg);
221
222         /* ACPI 1.0/2.0: 1, ACPI 3.0: 2, ACPI 4.0: 3 */
223         header->revision = ACPI_REV_ACPI_2_0;
224
225         current = acpi_fill_mcfg(current);
226
227         /* (Re)calculate length and checksum */
228         header->length = current - (unsigned long)mcfg;
229         header->checksum = table_compute_checksum((void *)mcfg, header->length);
230 }
231
232 static void acpi_create_facs(struct acpi_facs *facs)
233 {
234         memset((void *)facs, 0, sizeof(struct acpi_facs));
235
236         memcpy(facs->signature, "FACS", 4);
237         facs->length = sizeof(struct acpi_facs);
238         facs->hardware_signature = 0;
239         facs->firmware_waking_vector = 0;
240         facs->global_lock = 0;
241         facs->flags = 0;
242         facs->x_firmware_waking_vector_l = 0;
243         facs->x_firmware_waking_vector_h = 0;
244         facs->version = 1; /* ACPI 1.0: 0, ACPI 2.0/3.0: 1, ACPI 4.0: 2 */
245 }
246
247 static void acpi_write_rsdt(struct acpi_rsdt *rsdt)
248 {
249         struct acpi_table_header *header = &(rsdt->header);
250
251         /* Fill out header fields */
252         fill_header(header, "RSDT", 4);
253         header->length = sizeof(struct acpi_rsdt);
254
255         /* ACPI 1.0/2.0: 1, ACPI 3.0: 2, ACPI 4.0: 3 */
256         header->revision = ACPI_REV_ACPI_2_0;
257
258         /* Entries are filled in later, we come with an empty set */
259
260         /* Fix checksum */
261         header->checksum = table_compute_checksum((void *)rsdt,
262                         sizeof(struct acpi_rsdt));
263 }
264
265 static void acpi_write_xsdt(struct acpi_xsdt *xsdt)
266 {
267         struct acpi_table_header *header = &(xsdt->header);
268
269         /* Fill out header fields */
270         fill_header(header, "XSDT", 4);
271         header->length = sizeof(struct acpi_xsdt);
272
273         /* ACPI 1.0/2.0: 1, ACPI 3.0: 2, ACPI 4.0: 3 */
274         header->revision = ACPI_REV_ACPI_2_0;
275
276         /* Entries are filled in later, we come with an empty set */
277
278         /* Fix checksum */
279         header->checksum = table_compute_checksum((void *)xsdt,
280                         sizeof(struct acpi_xsdt));
281 }
282
283 static void acpi_write_rsdp(struct acpi_rsdp *rsdp, struct acpi_rsdt *rsdt,
284                          struct acpi_xsdt *xsdt)
285 {
286         memset(rsdp, 0, sizeof(struct acpi_rsdp));
287
288         memcpy(rsdp->signature, RSDP_SIG, 8);
289         memcpy(rsdp->oem_id, OEM_ID, 6);
290
291         rsdp->length = sizeof(struct acpi_rsdp);
292         rsdp->rsdt_address = (u32)rsdt;
293
294         /*
295         * Revision: ACPI 1.0: 0, ACPI 2.0/3.0/4.0: 2
296         *
297         * Some OSes expect an XSDT to be present for RSD PTR revisions >= 2.
298         * If we don't have an ACPI XSDT, force ACPI 1.0 (and thus RSD PTR
299         * revision 0)
300         */
301         if (xsdt == NULL) {
302                 rsdp->revision = ACPI_RSDP_REV_ACPI_1_0;
303         } else {
304                 rsdp->xsdt_address = (u64)(u32)xsdt;
305                 rsdp->revision = ACPI_RSDP_REV_ACPI_2_0;
306         }
307
308         /* Calculate checksums */
309         rsdp->checksum = table_compute_checksum((void *)rsdp, 20);
310         rsdp->ext_checksum = table_compute_checksum((void *)rsdp,
311                         sizeof(struct acpi_rsdp));
312 }
313
314 static void acpi_create_ssdt_generator(struct acpi_table_header *ssdt,
315                          const char *oem_table_id)
316 {
317         unsigned long current = (unsigned long)ssdt +
318                                 sizeof(struct acpi_table_header);
319
320         memset((void *)ssdt, 0, sizeof(struct acpi_table_header));
321
322         memcpy(&ssdt->signature, "SSDT", 4);
323         /* Access size in ACPI 2.0c/3.0/4.0/5.0 */
324         ssdt->revision = ACPI_REV_ACPI_3_0;
325         memcpy(&ssdt->oem_id, OEM_ID, 6);
326         memcpy(&ssdt->oem_table_id, oem_table_id, 8);
327         ssdt->oem_revision = OEM_REVISION;
328         memcpy(&ssdt->aslc_id, ASLC_ID, 4);
329         ssdt->aslc_revision = ASL_COMPILER_REVISION;
330         ssdt->length = sizeof(struct acpi_table_header);
331
332         /* (Re)calculate length and checksum */
333         ssdt->length = current - (unsigned long)ssdt;
334         ssdt->checksum = table_compute_checksum((void *)ssdt, ssdt->length);
335 }
336
337 /*
338  * QEMU's version of write_acpi_tables is defined in
339  * arch/x86/cpu/qemu/fw_cfg.c
340  */
341 u32 write_acpi_tables(u32 start)
342 {
343         u32 current;
344         struct acpi_rsdp *rsdp;
345         struct acpi_rsdt *rsdt;
346         struct acpi_xsdt *xsdt;
347         struct acpi_facs *facs;
348         struct acpi_table_header *dsdt;
349         struct acpi_fadt *fadt;
350         struct acpi_mcfg *mcfg;
351         struct acpi_madt *madt;
352         struct acpi_table_header *ssdt;
353
354         current = start;
355
356         /* Align ACPI tables to 16byte */
357         current = ALIGN(current, 16);
358
359         debug("ACPI: Writing ACPI tables at %x\n", start);
360
361         /* We need at least an RSDP and an RSDT Table */
362         rsdp = (struct acpi_rsdp *)current;
363         current += sizeof(struct acpi_rsdp);
364         current = ALIGN(current, 16);
365         rsdt = (struct acpi_rsdt *)current;
366         current += sizeof(struct acpi_rsdt);
367         current = ALIGN(current, 16);
368         xsdt = (struct acpi_xsdt *)current;
369         current += sizeof(struct acpi_xsdt);
370         current = ALIGN(current, 16);
371
372         /* clear all table memory */
373         memset((void *)start, 0, current - start);
374
375         acpi_write_rsdp(rsdp, rsdt, xsdt);
376         acpi_write_rsdt(rsdt);
377         acpi_write_xsdt(xsdt);
378
379         debug("ACPI:    * FACS\n");
380         facs = (struct acpi_facs *)current;
381         current += sizeof(struct acpi_facs);
382         current = ALIGN(current, 16);
383
384         acpi_create_facs(facs);
385
386         debug("ACPI:    * DSDT\n");
387         dsdt = (struct acpi_table_header *)current;
388         memcpy(dsdt, &AmlCode, sizeof(struct acpi_table_header));
389         if (dsdt->length >= sizeof(struct acpi_table_header)) {
390                 current += sizeof(struct acpi_table_header);
391                 memcpy((char *)current,
392                         (char *)&AmlCode + sizeof(struct acpi_table_header),
393                         dsdt->length - sizeof(struct acpi_table_header));
394                 current += dsdt->length - sizeof(struct acpi_table_header);
395
396                 /* (Re)calculate length and checksum */
397                 dsdt->length = current - (unsigned long)dsdt;
398                 dsdt->checksum = 0;
399                 dsdt->checksum = table_compute_checksum((void *)dsdt,
400                                 dsdt->length);
401         }
402         current = ALIGN(current, 16);
403
404         debug("ACPI:    * FADT\n");
405         fadt = (struct acpi_fadt *)current;
406         current += sizeof(struct acpi_fadt);
407         current = ALIGN(current, 16);
408         acpi_create_fadt(fadt, facs, dsdt);
409         acpi_add_table(rsdp, fadt);
410
411         debug("ACPI:    * MCFG\n");
412         mcfg = (struct acpi_mcfg *)current;
413         acpi_create_mcfg(mcfg);
414         if (mcfg->header.length > sizeof(struct acpi_mcfg)) {
415                 current += mcfg->header.length;
416                 current = ALIGN(current, 16);
417                 acpi_add_table(rsdp, mcfg);
418         }
419
420         debug("ACPI:    * MADT\n");
421         madt = (struct acpi_madt *)current;
422         acpi_create_madt(madt);
423         if (madt->header.length > sizeof(struct acpi_madt)) {
424                 current += madt->header.length;
425                 acpi_add_table(rsdp, madt);
426         }
427         current = ALIGN(current, 16);
428
429         debug("ACPI:    * SSDT\n");
430         ssdt = (struct acpi_table_header *)current;
431         acpi_create_ssdt_generator(ssdt, OEM_TABLE_ID);
432         if (ssdt->length > sizeof(struct acpi_table_header)) {
433                 current += ssdt->length;
434                 acpi_add_table(rsdp, ssdt);
435                 current = ALIGN(current, 16);
436         }
437
438         debug("current = %x\n", current);
439
440         debug("ACPI: done\n");
441
442         return current;
443 }