xref: /openbsd-src/sys/arch/arm64/stand/efiboot/efiacpi.c (revision 3fe0bd1a994b92f835ed79b4c99bf1aab23ddbfb)
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", &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 		    &reg_shift, sizeof(reg_shift));
680 		fdt_node_add_property(node, "reg-io-width",
681 		    &reg_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