1 /* $OpenBSD: efiacpi.c,v 1.17 2024/06/23 15:37:31 kettenis Exp $ */
2
3 /*
4 * Copyright (c) 2018 Mark Kettenis <kettenis@openbsd.org>
5 *
6 * Permission to use, copy, modify, and distribute this software for any
7 * purpose with or without fee is hereby granted, provided that the above
8 * copyright notice and this permission notice appear in all copies.
9 *
10 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
11 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
12 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
13 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
14 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
15 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
16 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
17 */
18
19 #include <sys/param.h>
20
21 #include <efi.h>
22 #include <efiapi.h>
23
24 #include "fdt.h"
25 #include "libsa.h"
26
27 #define efi_guidcmp(_a, _b) memcmp((_a), (_b), sizeof(EFI_GUID))
28
29 #define fdt_node_add_string_property(n, p, s) \
30 fdt_node_add_property((n), (p), (s), strlen((s)) + 1)
31 #define fdt_node_set_string_property(n, p, s) \
32 fdt_node_set_property((n), (p), (s), strlen((s)) + 1)
33
34 extern EFI_SYSTEM_TABLE *ST;
35
36 /* ACPI tables */
37
38 struct acpi_rsdp1 {
39 uint8_t signature[8];
40 #define RSDP_SIG "RSD PTR "
41 #define rsdp_signature rsdp1.signature
42 uint8_t checksum; /* make sum == 0 */
43 #define rsdp_checksum rsdp1.checksum
44 uint8_t oemid[6];
45 #define rsdp_oemid rsdp1.oemid
46 uint8_t revision; /* 0 for 1, 2 for 2 */
47 #define rsdp_revision rsdp1.revision
48 uint32_t rsdt; /* physical */
49 #define rsdp_rsdt rsdp1.rsdt
50 } __packed;
51
52 struct acpi_rsdp {
53 struct acpi_rsdp1 rsdp1;
54 /*
55 * The following values are only valid
56 * when rsdp_revision == 2
57 */
58 uint32_t rsdp_length; /* length of rsdp */
59 uint64_t rsdp_xsdt; /* physical */
60 uint8_t rsdp_extchecksum; /* entire table */
61 uint8_t rsdp_reserved[3]; /* must be zero */
62 } __packed;
63
64 struct acpi_table_header {
65 uint8_t signature[4];
66 #define hdr_signature hdr.signature
67 uint32_t length;
68 #define hdr_length hdr.length
69 uint8_t revision;
70 #define hdr_revision hdr.revision
71 uint8_t checksum;
72 #define hdr_checksum hdr.checksum
73 uint8_t oemid[6];
74 #define hdr_oemid hdr.oemid
75 uint8_t oemtableid[8];
76 #define hdr_oemtableid hdr.oemtableid
77 uint32_t oemrevision;
78 #define hdr_oemrevision hdr.oemrevision
79 uint8_t aslcompilerid[4];
80 #define hdr_aslcompilerid hdr.aslcompilerid
81 uint32_t aslcompilerrevision;
82 #define hdr_aslcompilerrevision hdr.aslcompilerrevision
83 } __packed;
84
85 struct acpi_xsdt {
86 struct acpi_table_header hdr;
87 #define XSDT_SIG "XSDT"
88 uint64_t table_offsets[1];
89 } __packed;
90
91 struct acpi_gas {
92 uint8_t address_space_id;
93 #define GAS_SYSTEM_MEMORY 0
94 #define GAS_SYSTEM_IOSPACE 1
95 #define GAS_PCI_CFG_SPACE 2
96 #define GAS_EMBEDDED 3
97 #define GAS_SMBUS 4
98 #define GAS_FUNCTIONAL_FIXED 127
99 uint8_t register_bit_width;
100 uint8_t register_bit_offset;
101 uint8_t access_size;
102 #define GAS_ACCESS_UNDEFINED 0
103 #define GAS_ACCESS_BYTE 1
104 #define GAS_ACCESS_WORD 2
105 #define GAS_ACCESS_DWORD 3
106 #define GAS_ACCESS_QWORD 4
107 uint64_t address;
108 } __packed;
109
110 struct acpi_fadt {
111 struct acpi_table_header hdr;
112 #define FADT_SIG "FACP"
113 uint32_t firmware_ctl; /* phys addr FACS */
114 uint32_t dsdt; /* phys addr DSDT */
115 uint8_t int_model; /* interrupt model (hdr_revision < 3) */
116 #define FADT_INT_DUAL_PIC 0
117 #define FADT_INT_MULTI_APIC 1
118 uint8_t pm_profile; /* power mgmt profile */
119 #define FADT_PM_UNSPEC 0
120 #define FADT_PM_DESKTOP 1
121 #define FADT_PM_MOBILE 2
122 #define FADT_PM_WORKSTATION 3
123 #define FADT_PM_ENT_SERVER 4
124 #define FADT_PM_SOHO_SERVER 5
125 #define FADT_PM_APPLIANCE 6
126 #define FADT_PM_PERF_SERVER 7
127 uint16_t sci_int; /* SCI interrupt */
128 uint32_t smi_cmd; /* SMI command port */
129 uint8_t acpi_enable; /* value to enable */
130 uint8_t acpi_disable; /* value to disable */
131 uint8_t s4bios_req; /* value for S4 */
132 uint8_t pstate_cnt; /* value for performance (hdr_revision > 2) */
133 uint32_t pm1a_evt_blk; /* power management 1a */
134 uint32_t pm1b_evt_blk; /* power management 1b */
135 uint32_t pm1a_cnt_blk; /* pm control 1a */
136 uint32_t pm1b_cnt_blk; /* pm control 1b */
137 uint32_t pm2_cnt_blk; /* pm control 2 */
138 uint32_t pm_tmr_blk;
139 uint32_t gpe0_blk;
140 uint32_t gpe1_blk;
141 uint8_t pm1_evt_len;
142 uint8_t pm1_cnt_len;
143 uint8_t pm2_cnt_len;
144 uint8_t pm_tmr_len;
145 uint8_t gpe0_blk_len;
146 uint8_t gpe1_blk_len;
147 uint8_t gpe1_base;
148 uint8_t cst_cnt; /* (hdr_revision > 2) */
149 uint16_t p_lvl2_lat;
150 uint16_t p_lvl3_lat;
151 uint16_t flush_size;
152 uint16_t flush_stride;
153 uint8_t duty_offset;
154 uint8_t duty_width;
155 uint8_t day_alrm;
156 uint8_t mon_alrm;
157 uint8_t century;
158 uint16_t iapc_boot_arch; /* (hdr_revision > 2) */
159 #define FADT_LEGACY_DEVICES 0x0001 /* Legacy devices supported */
160 #define FADT_i8042 0x0002 /* Keyboard controller present */
161 #define FADT_NO_VGA 0x0004 /* Do not probe VGA */
162 uint8_t reserved1;
163 uint32_t flags;
164 #define FADT_WBINVD 0x00000001
165 #define FADT_WBINVD_FLUSH 0x00000002
166 #define FADT_PROC_C1 0x00000004
167 #define FADT_P_LVL2_UP 0x00000008
168 #define FADT_PWR_BUTTON 0x00000010
169 #define FADT_SLP_BUTTON 0x00000020
170 #define FADT_FIX_RTC 0x00000040
171 #define FADT_RTC_S4 0x00000080
172 #define FADT_TMR_VAL_EXT 0x00000100
173 #define FADT_DCK_CAP 0x00000200
174 #define FADT_RESET_REG_SUP 0x00000400
175 #define FADT_SEALED_CASE 0x00000800
176 #define FADT_HEADLESS 0x00001000
177 #define FADT_CPU_SW_SLP 0x00002000
178 #define FADT_PCI_EXP_WAK 0x00004000
179 #define FADT_USE_PLATFORM_CLOCK 0x00008000
180 #define FADT_S4_RTC_STS_VALID 0x00010000
181 #define FADT_REMOTE_POWER_ON_CAPABLE 0x00020000
182 #define FADT_FORCE_APIC_CLUSTER_MODEL 0x00040000
183 #define FADT_FORCE_APIC_PHYS_DEST_MODE 0x00080000
184 #define FADT_HW_REDUCED_ACPI 0x00100000
185 #define FADT_POWER_S0_IDLE_CAPABLE 0x00200000
186 /*
187 * Following values only exist when rev > 1
188 * If the extended addresses exists, they
189 * must be used in preference to the non-
190 * extended values above
191 */
192 struct acpi_gas reset_reg;
193 uint8_t reset_value;
194 uint16_t arm_boot_arch; /* (hdr_revision > 3) */
195 #define FADT_PSCI_COMPLIANT 0x0001 /* PSCI is implemented */
196 #define FADT_PSCI_USE_HVC 0x0002 /* HVC used as PSCI conduit */
197 uint8_t reserved2;
198 uint64_t x_firmware_ctl;
199 uint64_t x_dsdt;
200 struct acpi_gas x_pm1a_evt_blk;
201 struct acpi_gas x_pm1b_evt_blk;
202 struct acpi_gas x_pm1a_cnt_blk;
203 struct acpi_gas x_pm1b_cnt_blk;
204 struct acpi_gas x_pm2_cnt_blk;
205 struct acpi_gas x_pm_tmr_blk;
206 struct acpi_gas x_gpe0_blk;
207 struct acpi_gas x_gpe1_blk;
208 struct acpi_gas sleep_control_reg;
209 struct acpi_gas sleep_status_reg;
210 } __packed;
211
212 struct acpi_gtdt {
213 struct acpi_table_header hdr;
214 #define GTDT_SIG "GTDT"
215 uint64_t cnt_ctrl_base;
216 uint32_t reserved;
217 uint32_t sec_el1_interrupt;
218 uint32_t sec_el1_flags;
219 #define ACPI_GTDT_TIMER_TRIGGER_EDGE 0x1
220 #define ACPI_GTDT_TIMER_POLARITY_LOW 0x2
221 #define ACPI_GTDT_TIMER_ALWAYS_ON 0x4
222 uint32_t nonsec_el1_interrupt;
223 uint32_t nonsec_el1_flags;
224 uint32_t virt_interrupt;
225 uint32_t virt_flags;
226 uint32_t nonsec_el2_interrupt;
227 uint32_t nonsec_el2_flags;
228 uint64_t cnt_read_base;
229 uint32_t platform_timer_count;
230 uint32_t platform_timer_offset;
231 } __packed;
232
233 struct acpi_madt {
234 struct acpi_table_header hdr;
235 #define MADT_SIG "APIC"
236 uint32_t local_apic_address;
237 uint32_t flags;
238 #define ACPI_APIC_PCAT_COMPAT 0x00000001
239 } __packed;
240
241 struct acpi_madt_gicc {
242 uint8_t apic_type;
243 #define ACPI_MADT_GICC 11
244 uint8_t length;
245 uint16_t reserved1;
246 uint32_t gic_id;
247 uint32_t acpi_proc_uid;
248 uint32_t flags;
249 #define ACPI_PROC_ENABLE 0x00000001
250 uint32_t parking_protocol_version;
251 uint32_t performance_interrupt;
252 uint64_t parked_address;
253 uint64_t base_address;
254 uint64_t gicv_base_address;
255 uint64_t gich_base_address;
256 uint32_t maintenance_interrupt;
257 uint64_t gicr_base_address;
258 uint64_t mpidr;
259 uint8_t efficiency_class;
260 uint8_t reserved2[3];
261 } __packed;
262
263 struct acpi_madt_gicd {
264 uint8_t apic_type;
265 #define ACPI_MADT_GICD 12
266 uint8_t length;
267 uint16_t reserved1;
268 uint32_t gic_id;
269 uint64_t base_address;
270 uint32_t interrupt_base;
271 uint8_t version;
272 uint8_t reserved2[3];
273 } __packed;
274
275 struct acpi_madt_gic_msi {
276 uint8_t apic_type;
277 #define ACPI_MADT_GIC_MSI 13
278 uint8_t length;
279 uint16_t reserved1;
280 uint32_t msi_frame_id;
281 uint64_t base_address;
282 uint32_t flags;
283 #define ACPI_MADT_GIC_MSI_SPI_SELECT 0x00000001
284 uint16_t spi_count;
285 uint16_t spi_base;
286 } __packed;
287
288 struct acpi_madt_gicr {
289 uint8_t apic_type;
290 #define ACPI_MADT_GICR 14
291 uint8_t length;
292 uint16_t reserved1;
293 uint64_t discovery_base_address;
294 uint32_t discovery_length;
295 } __packed;
296
297 struct acpi_madt_gic_its {
298 uint8_t apic_type;
299 #define ACPI_MADT_GIC_ITS 15
300 uint8_t length;
301 uint16_t reserved1;
302 uint32_t gic_its_id;
303 uint64_t base_address;
304 uint32_t reserved2;
305 } __packed;
306
307 union acpi_madt_entry {
308 struct acpi_madt_gicc madt_gicc;
309 struct acpi_madt_gicd madt_gicd;
310 struct acpi_madt_gic_msi madt_gic_msi;
311 struct acpi_madt_gicr madt_gicr;
312 struct acpi_madt_gic_its madt_gic_its;
313 } __packed;
314
315 struct acpi_spcr {
316 struct acpi_table_header hdr;
317 #define SPCR_SIG "SPCR"
318 uint8_t interface_type;
319 #define SPCR_16550 0
320 #define SPCR_16450 1
321 #define SPCR_ARM_PL011 3
322 #define SPCR_ARM_SBSA 14
323 uint8_t reserved1[3];
324 struct acpi_gas base_address;
325 uint8_t interrupt_type;
326 uint8_t irq;
327 uint32_t gsiv;
328 uint8_t baud_rate;
329 uint8_t parity;
330 uint8_t stop_bits;
331 uint8_t flow_control;
332 uint8_t terminal_type;
333 uint8_t reserved2;
334 uint16_t pci_device_id;
335 uint16_t pci_vendor_id;
336 uint8_t pci_bus;
337 uint8_t pci_device;
338 uint8_t pci_function;
339 uint32_t pci_flags;
340 uint8_t pci_segment;
341 uint32_t reserved3;
342 } __packed;
343
344 /* We'll never see ACPI 1.0 tables on ARM. */
345 static EFI_GUID acpi_guid = ACPI_20_TABLE_GUID;
346
347 static int psci = 0;
348
349 void
efi_acpi_fadt(struct acpi_table_header * hdr)350 efi_acpi_fadt(struct acpi_table_header *hdr)
351 {
352 struct acpi_fadt *fadt = (struct acpi_fadt *)hdr;
353 void *node;
354
355 /*
356 * The PSCI flags were introduced in ACPI 5.1. The relevant
357 * field is set to zero for ACPU 5.0.
358 */
359 if (fadt->hdr_revision < 5)
360 return;
361
362 psci = fadt->arm_boot_arch & FADT_PSCI_COMPLIANT;
363
364 node = fdt_find_node("/psci");
365 if (fadt->arm_boot_arch & FADT_PSCI_COMPLIANT)
366 fdt_node_set_string_property(node, "status", "okay");
367 if (fadt->arm_boot_arch & FADT_PSCI_USE_HVC)
368 fdt_node_set_string_property(node, "method", "hvc");
369 }
370
371 void
efi_acpi_gtdt(struct acpi_table_header * hdr)372 efi_acpi_gtdt(struct acpi_table_header *hdr)
373 {
374 struct acpi_gtdt *gtdt = (struct acpi_gtdt *)hdr;
375 const uint32_t map[] = { 0x4, 0x1, 0x8, 0x2 };
376 const uint32_t mask = ACPI_GTDT_TIMER_TRIGGER_EDGE |
377 ACPI_GTDT_TIMER_POLARITY_LOW;
378 uint32_t interrupts[12];
379 void *node;
380
381 /* All interrupts are supposed to be PPIs. */
382 interrupts[0] = htobe32(1);
383 interrupts[1] = htobe32(gtdt->sec_el1_interrupt - 16);
384 interrupts[2] = htobe32(map[gtdt->sec_el1_flags & mask]);
385 interrupts[3] = htobe32(1);
386 interrupts[4] = htobe32(gtdt->nonsec_el1_interrupt - 16);
387 interrupts[5] = htobe32(map[gtdt->nonsec_el1_flags & mask]);
388 interrupts[6] = htobe32(1);
389 interrupts[7] = htobe32(gtdt->virt_interrupt - 16);
390 interrupts[8] = htobe32(map[gtdt->virt_flags & mask]);
391 interrupts[9] = htobe32(1);
392 interrupts[10] = htobe32(gtdt->nonsec_el2_interrupt - 16);
393 interrupts[11] = htobe32(map[gtdt->virt_flags & mask]);
394
395 node = fdt_find_node("/timer");
396 fdt_node_set_property(node, "interrupts",
397 interrupts, sizeof(interrupts));
398 fdt_node_set_string_property(node, "status", "okay");
399 }
400
401 static int gic_version;
402 static uint64_t gicc_base;
403 static uint64_t gicd_base;
404 static uint64_t gicr_base;
405 static uint64_t gicr_size;
406 static uint64_t gicr_stride;
407
408 void
efi_acpi_madt_gicc(struct acpi_madt_gicc * gicc)409 efi_acpi_madt_gicc(struct acpi_madt_gicc *gicc)
410 {
411 uint64_t mpidr = gicc->mpidr;
412 void *node, *child;
413 uint64_t reg;
414 char name[32];
415
416 /* Skip disabled CPUs. */
417 if ((gicc->flags & ACPI_PROC_ENABLE) == 0)
418 return;
419
420 /*
421 * MPIDR field was introduced in ACPI 5.1. Fall back on the
422 * ACPI Processor UID on ACPI 5.0.
423 */
424 mpidr = (gicc->length >= 76) ? gicc->mpidr : gicc->acpi_proc_uid;
425
426 snprintf(name, sizeof(name), "cpu@%llx", mpidr);
427 reg = htobe64(mpidr);
428
429 /* Create "cpu" node. */
430 node = fdt_find_node("/cpus");
431 fdt_node_add_node(node, name, &child);
432 fdt_node_add_string_property(child, "device_type", "cpu");
433 fdt_node_add_string_property(child, "compatible", "arm,armv8");
434 fdt_node_add_property(child, "reg", ®, sizeof(reg));
435 if (gicc->parking_protocol_version == 0 || psci)
436 fdt_node_add_string_property(child, "enable-method", "psci");
437
438 /* Stash GIC information. */
439 gicc_base = gicc->base_address;
440
441 /*
442 * The redistributor base address may be specified per-CPU.
443 * In that case we will need to reconstruct the base, size and
444 * stride to use for the redistributor registers.
445 */
446 if (gicc->gicr_base_address > 0) {
447 if (gicr_base > 0) {
448 uint32_t size;
449
450 if (gicc->gicr_base_address < gicr_base)
451 size = gicr_base - gicc->gicr_base_address;
452 else
453 size = gicc->gicr_base_address - gicr_base;
454 if (gicr_stride == 0 || size < gicr_stride)
455 gicr_stride = size;
456 if (gicr_size == 0 || size > gicr_size)
457 gicr_size = size;
458 gicr_base = MIN(gicr_base, gicc->gicr_base_address);
459 } else {
460 gicr_base = gicc->gicr_base_address;
461 gicr_size = 0x20000;
462 }
463 }
464 }
465
466 void
efi_acpi_madt_gicd(struct acpi_madt_gicd * gicd)467 efi_acpi_madt_gicd(struct acpi_madt_gicd *gicd)
468 {
469 /* Stash GIC information. */
470 gic_version = gicd->version;
471 gicd_base = gicd->base_address;
472 }
473
474 void
efi_acpi_madt_gic_msi(struct acpi_madt_gic_msi * msi)475 efi_acpi_madt_gic_msi(struct acpi_madt_gic_msi *msi)
476 {
477 static uint32_t phandle = 2;
478 void *node, *child;
479 uint64_t reg[2];
480 char name[32];
481
482 snprintf(name, sizeof(name), "v2m@%llx", msi->base_address);
483 reg[0] = htobe64(msi->base_address);
484 reg[1] = htobe64(0x1000);
485
486 /* Create "v2m" node. */
487 node = fdt_find_node("/interrupt-controller");
488 fdt_node_add_node(node, name, &child);
489 fdt_node_add_string_property(child, "compatible", "arm,gic-v2m-frame");
490 fdt_node_add_property(child, "msi-controller", NULL, 0);
491 fdt_node_add_property(child, "reg", reg, sizeof(reg));
492 if (msi->flags & ACPI_MADT_GIC_MSI_SPI_SELECT) {
493 uint32_t spi_base = htobe32(msi->spi_base);
494 uint32_t spi_count = htobe32(msi->spi_count);
495
496 fdt_node_add_property(child, "arm,msi-base-spi",
497 &spi_base, sizeof(spi_base));
498 fdt_node_add_property(child, "arm,msi-num-spis",
499 &spi_count, sizeof(spi_count));
500 }
501 fdt_node_add_property(child, "phandle", &phandle, sizeof(phandle));
502 phandle++;
503 }
504
505 void
efi_acpi_madt_gicr(struct acpi_madt_gicr * gicr)506 efi_acpi_madt_gicr(struct acpi_madt_gicr *gicr)
507 {
508 /* Stash GIC information. */
509 gicr_base = gicr->discovery_base_address;
510 gicr_size = gicr->discovery_length;
511 }
512
513 void
efi_acpi_madt_gic_its(struct acpi_madt_gic_its * its)514 efi_acpi_madt_gic_its(struct acpi_madt_gic_its *its)
515 {
516 static uint32_t phandle = 2;
517 void *node, *child;
518 uint64_t reg[2];
519 uint32_t its_id;
520 char name[32];
521
522 snprintf(name, sizeof(name), "gic-its@%llx", its->base_address);
523 reg[0] = htobe64(its->base_address);
524 reg[1] = htobe64(0x20000);
525 its_id = htobe32(its->gic_its_id);
526
527 /* Create "gic-its" node. */
528 node = fdt_find_node("/interrupt-controller");
529 fdt_node_add_node(node, name, &child);
530 fdt_node_add_string_property(child, "compatible", "arm,gic-v3-its");
531 fdt_node_add_property(child, "msi-controller", NULL, 0);
532 fdt_node_add_property(child, "reg", reg, sizeof(reg));
533 fdt_node_add_property(child, "phandle", &phandle, sizeof(phandle));
534 fdt_node_add_property(child, "openbsd,gic-its-id", &its_id,
535 sizeof(its_id));
536 phandle++;
537 }
538
539 void
efi_acpi_madt(struct acpi_table_header * hdr)540 efi_acpi_madt(struct acpi_table_header *hdr)
541 {
542 struct acpi_madt *madt = (struct acpi_madt *)hdr;
543 char *compat;
544 uint64_t reg[4];
545 char *addr;
546 void *node;
547
548 /* GIC support was introduced in ACPI 5.0. */
549 if (madt->hdr_revision < 3)
550 return;
551
552 addr = (char *)(madt + 1);
553 while (addr < (char *)madt + madt->hdr.length) {
554 union acpi_madt_entry *entry = (union acpi_madt_entry *)addr;
555 uint8_t length = entry->madt_gicc.length;
556
557 if (length < 2)
558 return;
559
560 if (addr + length > (char *)madt + madt->hdr_length)
561 return;
562
563 switch (entry->madt_gicc.apic_type) {
564 case ACPI_MADT_GICC:
565 efi_acpi_madt_gicc(&entry->madt_gicc);
566 break;
567 case ACPI_MADT_GICD:
568 efi_acpi_madt_gicd(&entry->madt_gicd);
569 break;
570 case ACPI_MADT_GIC_MSI:
571 efi_acpi_madt_gic_msi(&entry->madt_gic_msi);
572 break;
573 case ACPI_MADT_GICR:
574 efi_acpi_madt_gicr(&entry->madt_gicr);
575 break;
576 case ACPI_MADT_GIC_ITS:
577 efi_acpi_madt_gic_its(&entry->madt_gic_its);
578 break;
579 }
580
581 addr += length;
582 }
583
584 /*
585 * Now that we've collected all the necessary information, fix
586 * up the "interrupt-controller" node.
587 */
588
589 switch (gic_version) {
590 case 0:
591 /* ACPI 5.0 doesn't provide a version; assume GICv2 */
592 case 2:
593 /* GICv2 */
594 compat = "arm,gic-400";
595 reg[0] = htobe64(gicd_base);
596 reg[1] = htobe64(0x1000);
597 reg[2] = htobe64(gicc_base);
598 reg[3] = htobe64(0x100);
599 break;
600 case 3:
601 case 4:
602 /* GICv3 and GICv4 */
603 compat = "arm,gic-v3";
604 reg[0] = htobe64(gicd_base);
605 reg[1] = htobe64(0x10000);
606 reg[2] = htobe64(gicr_base);
607 reg[3] = htobe64(gicr_size + gicr_stride);
608 break;
609 default:
610 return;
611 }
612
613 /* Update "interrupt-controller" node. */
614 node = fdt_find_node("/interrupt-controller");
615 fdt_node_set_string_property(node, "compatible", compat);
616 fdt_node_set_property(node, "reg", reg, sizeof(reg));
617 if (gicr_stride > 0) {
618 uint64_t stride = htobe64(gicr_stride);
619 fdt_node_add_property(node, "redistributor-stride",
620 &stride, sizeof(stride));
621 }
622 fdt_node_set_string_property(node, "status", "okay");
623 }
624
625 static int serial = 0;
626
627 void
efi_acpi_spcr(struct acpi_table_header * hdr)628 efi_acpi_spcr(struct acpi_table_header *hdr)
629 {
630 struct acpi_spcr *spcr = (struct acpi_spcr *)hdr;
631 uint64_t reg[2], reg_shift, reg_io_width;
632 void *node;
633
634 /* Minimal revision required by Server Base Boot Requirements is 2. */
635 if (spcr->hdr_revision < 2)
636 return;
637
638 /* No idea how to support anything else on ARM. */
639 if (spcr->base_address.address_space_id != GAS_SYSTEM_MEMORY)
640 return;
641
642 reg[0] = htobe64(spcr->base_address.address);
643
644 switch (spcr->base_address.access_size) {
645 case GAS_ACCESS_BYTE:
646 reg_io_width = 1;
647 break;
648 case GAS_ACCESS_WORD:
649 reg_io_width = 2;
650 break;
651 case GAS_ACCESS_DWORD:
652 reg_io_width = 4;
653 break;
654 case GAS_ACCESS_QWORD:
655 reg_io_width = 8;
656 break;
657 default:
658 return;
659 }
660 reg_io_width = htobe32(reg_io_width);
661
662 reg_shift = 0;
663 if (spcr->base_address.register_bit_width > 8)
664 reg_shift = 1;
665 if (spcr->base_address.register_bit_width > 16)
666 reg_shift = 2;
667 if (spcr->base_address.register_bit_width > 32)
668 reg_shift = 3;
669 reg_shift = htobe32(reg_shift);
670
671 /* Update "serial" node. */
672 node = fdt_find_node("/serial");
673 switch (spcr->interface_type) {
674 case SPCR_16550:
675 case SPCR_16450:
676 fdt_node_set_string_property(node, "compatible",
677 "snps,dw-apb-uart");
678 fdt_node_add_property(node, "reg-shift",
679 ®_shift, sizeof(reg_shift));
680 fdt_node_add_property(node, "reg-io-width",
681 ®_io_width, sizeof(reg_io_width));
682 reg[1] = htobe64(0x100);
683 break;
684 case SPCR_ARM_PL011:
685 case SPCR_ARM_SBSA:
686 fdt_node_set_string_property(node, "compatible", "arm,pl011");
687 reg[1] = htobe64(0x1000);
688 break;
689 default:
690 return;
691 }
692 fdt_node_set_property(node, "reg", reg, sizeof(reg));
693 serial = 1;
694 }
695
696 void *
efi_acpi(void)697 efi_acpi(void)
698 {
699 extern uint64_t dma_constraint[2];
700 extern u_char dt_blob_start[];
701 void *fdt = dt_blob_start;
702 struct acpi_table_header *hdr;
703 struct acpi_rsdp *rsdp = NULL;
704 struct acpi_xsdt *xsdt;
705 uint64_t reg[2];
706 int i, ntables;
707 size_t len;
708 void *node;
709
710 for (i = 0; i < ST->NumberOfTableEntries; i++) {
711 if (efi_guidcmp(&acpi_guid,
712 &ST->ConfigurationTable[i].VendorGuid) == 0)
713 rsdp = ST->ConfigurationTable[i].VendorTable;
714 }
715
716 if (rsdp == NULL)
717 return NULL;
718
719 if (memcmp(rsdp->rsdp_signature, RSDP_SIG, 8) != 0 ||
720 rsdp->rsdp_revision < 2)
721 return NULL;
722
723 xsdt = (struct acpi_xsdt *)rsdp->rsdp_xsdt;
724 len = xsdt->hdr.length;
725 ntables = (len - sizeof(struct acpi_table_header)) /
726 sizeof(xsdt->table_offsets[0]);
727 if (ntables == 0)
728 return NULL;
729
730 if (!fdt_init(fdt))
731 return NULL;
732
733 for (i = 0; i < ntables; i++) {
734 hdr = (struct acpi_table_header *)xsdt->table_offsets[i];
735 printf("%c%c%c%c ", hdr->signature[0], hdr->signature[1],
736 hdr->signature[2], hdr->signature[3]);
737 if (memcmp(hdr->signature, FADT_SIG, 4) == 0)
738 efi_acpi_fadt(hdr);
739 if (memcmp(hdr->signature, GTDT_SIG, 4) == 0)
740 efi_acpi_gtdt(hdr);
741 if (memcmp(hdr->signature, MADT_SIG, 4) == 0)
742 efi_acpi_madt(hdr);
743 if (memcmp(hdr->signature, SPCR_SIG, 4) == 0)
744 efi_acpi_spcr(hdr);
745 }
746 printf("\n");
747
748 reg[0] = htobe64((uint64_t)rsdp);
749 reg[1] = htobe64(rsdp->rsdp_length);
750
751 /* Update "acpi" node. */
752 node = fdt_find_node("/acpi");
753 fdt_node_set_property(node, "reg", reg, sizeof(reg));
754
755 /* Use framebuffer if SPCR is absent or unusable. */
756 if (!serial)
757 cnset(ttydev("fb0"));
758
759 /* Raspberry Pi 4 is "special". */
760 if (memcmp(xsdt->hdr_oemid, "RPIFDN", 6) == 0 &&
761 memcmp(xsdt->hdr_oemtableid, "RPI4", 4) == 0)
762 dma_constraint[1] = htobe64(0x3bffffff);
763
764 fdt_finalize();
765
766 return fdt;
767 }
768