xref: /illumos-gate/usr/src/boot/efi/libefi/acpi.c (revision 7249bc1087a62c0594078dc84de55f3cadcae5d2)
1c9301135SToomas Soome /*
2c9301135SToomas Soome  * This file and its contents are supplied under the terms of the
3c9301135SToomas Soome  * Common Development and Distribution License ("CDDL"), version 1.0.
4c9301135SToomas Soome  * You may only use this file in accordance with the terms of version
5c9301135SToomas Soome  * 1.0 of the CDDL.
6c9301135SToomas Soome  *
7c9301135SToomas Soome  * A full copy of the text of the CDDL should have accompanied this
8c9301135SToomas Soome  * source.  A copy of the CDDL is also available via the Internet at
9c9301135SToomas Soome  * http://www.illumos.org/license/CDDL.
10c9301135SToomas Soome  */
11c9301135SToomas Soome 
12c9301135SToomas Soome /*
13c9301135SToomas Soome  * Copyright 2016 Tooams Soome <tsoome@me.com>
14c9301135SToomas Soome  */
15c9301135SToomas Soome 
16c9301135SToomas Soome #include <sys/cdefs.h>
17c9301135SToomas Soome 
18c9301135SToomas Soome #include <stand.h>
19c9301135SToomas Soome #include <sys/stdint.h>
20c9301135SToomas Soome #include <machine/stdarg.h>
21c9301135SToomas Soome #include <bootstrap.h>
22c9301135SToomas Soome #include <efi.h>
23c9301135SToomas Soome #include <efilib.h>
24c9301135SToomas Soome #include <Guid/Acpi.h>
25c9301135SToomas Soome 
26c9301135SToomas Soome #include "platform/acfreebsd.h"
27c9301135SToomas Soome #include "acconfig.h"
28c9301135SToomas Soome #define	ACPI_SYSTEM_XFACE
29c9301135SToomas Soome #include "actypes.h"
30c9301135SToomas Soome #include "actbl.h"
31c9301135SToomas Soome 
32c9301135SToomas Soome ACPI_TABLE_RSDP	*rsdp;
33c9301135SToomas Soome EFI_GUID gEfiAcpiTableGuid = ACPI_TABLE_GUID;
34c9301135SToomas Soome EFI_GUID gEfiAcpi20TableGuid = EFI_ACPI_TABLE_GUID;
35c9301135SToomas Soome 
36c9301135SToomas Soome static void *
acpi_map_sdt(vm_offset_t addr)37c9301135SToomas Soome acpi_map_sdt(vm_offset_t addr)
38c9301135SToomas Soome {
39c9301135SToomas Soome 	/* PA == VA */
40c9301135SToomas Soome 	return ((void *)addr);
41c9301135SToomas Soome }
42c9301135SToomas Soome 
43c9301135SToomas Soome static uint8_t
acpi_checksum(const void * p,size_t length)44c9301135SToomas Soome acpi_checksum(const void *p, size_t length)
45c9301135SToomas Soome {
46c9301135SToomas Soome 	const uint8_t *bp;
47c9301135SToomas Soome 	uint8_t sum;
48c9301135SToomas Soome 
49c9301135SToomas Soome 	bp = p;
50c9301135SToomas Soome 	sum = 0;
51c9301135SToomas Soome 	while (length--)
52c9301135SToomas Soome 		sum += *bp++;
53c9301135SToomas Soome 
54c9301135SToomas Soome 	return (sum);
55c9301135SToomas Soome }
56c9301135SToomas Soome 
57c9301135SToomas Soome /*
58c9301135SToomas Soome  * We have duplication there, the same implementation is also
59c9301135SToomas Soome  * in libi386/biosacpi.c. We will address this duplication later.
60c9301135SToomas Soome  */
61c9301135SToomas Soome void *
acpi_find_table(const char * sig)62c9301135SToomas Soome acpi_find_table(const char *sig)
63c9301135SToomas Soome {
64c9301135SToomas Soome 	uint_t entries, i;
65c9301135SToomas Soome 	ACPI_TABLE_HEADER *sdp;
66c9301135SToomas Soome 	ACPI_TABLE_RSDT *rsdt;
67c9301135SToomas Soome 	ACPI_TABLE_XSDT *xsdt;
68c9301135SToomas Soome 
69c9301135SToomas Soome 	if (rsdp == NULL)
70c9301135SToomas Soome 		return (NULL);
71c9301135SToomas Soome 
72c9301135SToomas Soome 	/*
73c9301135SToomas Soome 	 * Note, we need to check both address value and size there,
74c9301135SToomas Soome 	 * as 32-bit code can not access 64-bit address space.
75c9301135SToomas Soome 	 */
76c9301135SToomas Soome 	if (rsdp->Revision >= 2 &&
77c9301135SToomas Soome 	    rsdp->XsdtPhysicalAddress != 0 &&
78c9301135SToomas Soome 	    rsdp->XsdtPhysicalAddress < UINTPTR_MAX) {
79c9301135SToomas Soome 		xsdt = acpi_map_sdt(rsdp->XsdtPhysicalAddress);
80c9301135SToomas Soome 		sdp = (ACPI_TABLE_HEADER *)xsdt;
81c9301135SToomas Soome 		if (sdp->Length < sizeof (ACPI_TABLE_HEADER)) {
82c9301135SToomas Soome 			entries = 0;
83c9301135SToomas Soome 		} else {
84c9301135SToomas Soome 			entries = sdp->Length - sizeof (ACPI_TABLE_HEADER);
85c9301135SToomas Soome 			entries /= ACPI_XSDT_ENTRY_SIZE;
86c9301135SToomas Soome 		}
87c9301135SToomas Soome 		for (i = 0; i < entries; i++) {
88c9301135SToomas Soome 			if (xsdt->TableOffsetEntry[i] == 0 ||
89c9301135SToomas Soome 			    xsdt->TableOffsetEntry[i] >= UINTPTR_MAX)
90c9301135SToomas Soome 				continue;
91c9301135SToomas Soome 			sdp = acpi_map_sdt(xsdt->TableOffsetEntry[i]);
92c9301135SToomas Soome 			if (sdp->Length < sizeof (ACPI_TABLE_HEADER))
93c9301135SToomas Soome 				continue;
94c9301135SToomas Soome 
95c9301135SToomas Soome 			if (acpi_checksum(sdp, sdp->Length))
96c9301135SToomas Soome 				continue;
97c9301135SToomas Soome 
98c9301135SToomas Soome 			if (ACPI_COMPARE_NAME(sig, sdp->Signature))
99c9301135SToomas Soome 				return (sdp);
100c9301135SToomas Soome 		}
101c9301135SToomas Soome 	}
102c9301135SToomas Soome 
103c9301135SToomas Soome 	if (rsdp->RsdtPhysicalAddress != 0) {
104c9301135SToomas Soome 		rsdt = acpi_map_sdt(rsdp->RsdtPhysicalAddress);
105c9301135SToomas Soome 		sdp = (ACPI_TABLE_HEADER *)rsdt;
106c9301135SToomas Soome 		if (sdp->Length < sizeof (ACPI_TABLE_HEADER)) {
107c9301135SToomas Soome 			entries = 0;
108c9301135SToomas Soome 		} else {
109c9301135SToomas Soome 			entries = sdp->Length - sizeof (ACPI_TABLE_HEADER);
110c9301135SToomas Soome 			entries /= ACPI_RSDT_ENTRY_SIZE;
111c9301135SToomas Soome 		}
112c9301135SToomas Soome 		for (i = 0; i < entries; i++) {
113c9301135SToomas Soome 			if (rsdt->TableOffsetEntry[i] == 0)
114c9301135SToomas Soome 				continue;
115c9301135SToomas Soome 			sdp = acpi_map_sdt(rsdt->TableOffsetEntry[i]);
116c9301135SToomas Soome 			if (sdp->Length < sizeof (ACPI_TABLE_HEADER))
117c9301135SToomas Soome 				continue;
118c9301135SToomas Soome 
119c9301135SToomas Soome 			if (acpi_checksum(sdp, sdp->Length))
120c9301135SToomas Soome 				continue;
121c9301135SToomas Soome 
122c9301135SToomas Soome 			if (ACPI_COMPARE_NAME(sig, sdp->Signature))
123c9301135SToomas Soome 				return (sdp);
124c9301135SToomas Soome 		}
125c9301135SToomas Soome 	}
126c9301135SToomas Soome 	return (NULL);
127c9301135SToomas Soome }
128c9301135SToomas Soome 
129c9301135SToomas Soome void
acpi_detect(void)130c9301135SToomas Soome acpi_detect(void)
131c9301135SToomas Soome {
132c9301135SToomas Soome 	char	buf[24];
133c9301135SToomas Soome 	int	revision;
134c9301135SToomas Soome 
135c9301135SToomas Soome 	if ((rsdp = efi_get_table(&gEfiAcpi20TableGuid)) == NULL)
136c9301135SToomas Soome 		rsdp = efi_get_table(&gEfiAcpiTableGuid);
137c9301135SToomas Soome 
138c9301135SToomas Soome 	if (rsdp == NULL)
139c9301135SToomas Soome 		return;
140c9301135SToomas Soome 
141c9301135SToomas Soome 	/* export values from the RSDP */
142c9301135SToomas Soome #ifdef _LP64
143c9301135SToomas Soome 	snprintf(buf, sizeof (buf), "0x%016llx", (unsigned long long)rsdp);
144c9301135SToomas Soome #else
145c9301135SToomas Soome 	snprintf(buf, sizeof (buf), "0x%08x", (unsigned int)rsdp);
146c9301135SToomas Soome #endif
147*7249bc10SDan McDonald 	setenv("acpi.rsdp", buf, 1);
148c9301135SToomas Soome 	revision = rsdp->Revision;
149c9301135SToomas Soome 	if (revision == 0)
150c9301135SToomas Soome 		revision = 1;
151c9301135SToomas Soome 	snprintf(buf, sizeof (buf), "%d", revision);
152c9301135SToomas Soome 	setenv("acpi.revision", buf, 1);
153c9301135SToomas Soome 	strncpy(buf, rsdp->OemId, sizeof (rsdp->OemId));
154c9301135SToomas Soome 	buf[sizeof (rsdp->OemId)] = '\0';
155c9301135SToomas Soome 	setenv("acpi.oem", buf, 1);
156c9301135SToomas Soome #ifdef _LP64
157c9301135SToomas Soome 	snprintf(buf, sizeof (buf), "0x%016llx",
158c9301135SToomas Soome 	    (unsigned long long)rsdp->RsdtPhysicalAddress);
159c9301135SToomas Soome #else
160c9301135SToomas Soome 	snprintf(buf, sizeof (buf), "0x%08x", rsdp->RsdtPhysicalAddress);
161c9301135SToomas Soome #endif
162c9301135SToomas Soome 	setenv("acpi.rsdt", buf, 1);
163c9301135SToomas Soome 	if (revision >= 2) {
164c9301135SToomas Soome 		snprintf(buf, sizeof (buf), "0x%016llx",
165c9301135SToomas Soome 		    (unsigned long long)rsdp->XsdtPhysicalAddress);
166c9301135SToomas Soome 		setenv("acpi.xsdt", buf, 1);
167c9301135SToomas Soome 		snprintf(buf, sizeof (buf), "%d", rsdp->Length);
168c9301135SToomas Soome 		setenv("acpi.xsdt_length", buf, 1);
169c9301135SToomas Soome 	}
170c9301135SToomas Soome }
171