acpi.c revision 119912
165285Siwasaki/*-
265285Siwasaki * Copyright (c) 1998 Doug Rabson
365285Siwasaki * Copyright (c) 2000 Mitsuru IWASAKI <iwasaki@FreeBSD.org>
465285Siwasaki * All rights reserved.
565285Siwasaki *
665285Siwasaki * Redistribution and use in source and binary forms, with or without
765285Siwasaki * modification, are permitted provided that the following conditions
865285Siwasaki * are met:
965285Siwasaki * 1. Redistributions of source code must retain the above copyright
1065285Siwasaki *    notice, this list of conditions and the following disclaimer.
1165285Siwasaki * 2. Redistributions in binary form must reproduce the above copyright
1265285Siwasaki *    notice, this list of conditions and the following disclaimer in the
1365285Siwasaki *    documentation and/or other materials provided with the distribution.
1465285Siwasaki *
1565285Siwasaki * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
1665285Siwasaki * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
1765285Siwasaki * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
1865285Siwasaki * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
1965285Siwasaki * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
2065285Siwasaki * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
2165285Siwasaki * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
2265285Siwasaki * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
2365285Siwasaki * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
2465285Siwasaki * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
2565285Siwasaki * SUCH DAMAGE.
2665285Siwasaki *
2765285Siwasaki *	$FreeBSD: head/usr.sbin/acpi/acpidump/acpi.c 119912 2003-09-09 08:31:58Z njl $
2865285Siwasaki */
2965285Siwasaki
30119515Snjl#include <sys/types.h>
3165285Siwasaki#include <sys/param.h>
3265285Siwasaki#include <sys/stat.h>
33119515Snjl#include <sys/wait.h>
3465285Siwasaki#include <assert.h>
3565285Siwasaki#include <err.h>
3665285Siwasaki#include <fcntl.h>
3765285Siwasaki#include <stdio.h>
38119515Snjl#include <string.h>
3965285Siwasaki#include <unistd.h>
4065285Siwasaki
4165285Siwasaki#include "acpidump.h"
4265285Siwasaki
4385323Siwasaki#define BEGIN_COMMENT	"/*\n"
4485323Siwasaki#define END_COMMENT	" */\n"
4585323Siwasaki
46119515Snjlstatic void	acpi_print_string(char *s, size_t length);
47119912Snjlstatic void	acpi_print_gas(struct ACPIgas *gas);
48119912Snjlstatic void	acpi_handle_fadt(struct FADTbody *fadt);
49119515Snjlstatic void	acpi_print_cpu(u_char cpu_id);
50119515Snjlstatic void	acpi_print_local_apic(u_char cpu_id, u_char apic_id,
51119515Snjl				      u_int32_t flags);
52119515Snjlstatic void	acpi_print_io_apic(u_char apic_id, u_int32_t int_base,
53119515Snjl				   u_int64_t apic_addr);
54119515Snjlstatic void	acpi_print_mps_flags(u_int16_t flags);
55119515Snjlstatic void	acpi_print_intr(u_int32_t intr, u_int16_t mps_flags);
56119515Snjlstatic void	acpi_print_apic(struct MADT_APIC *mp);
57119515Snjlstatic void	acpi_handle_apic(struct ACPIsdt *sdp);
58119515Snjlstatic void	acpi_handle_hpet(struct ACPIsdt *sdp);
59119515Snjlstatic void	acpi_print_sdt(struct ACPIsdt *sdp, int endcomment);
60119912Snjlstatic void	acpi_print_fadt(struct FADTbody *fadt);
61119912Snjlstatic void	acpi_print_facs(struct FACSbody *facs);
62119515Snjlstatic void	acpi_print_dsdt(struct ACPIsdt *dsdp);
63119515Snjlstatic struct ACPIsdt *
64119515Snjl		acpi_map_sdt(vm_offset_t pa);
65119515Snjlstatic void	acpi_print_rsd_ptr(struct ACPIrsdp *rp);
66119515Snjlstatic void	acpi_handle_rsdt(struct ACPIsdt *rsdp);
6785323Siwasaki
6865285Siwasakistatic void
6965285Siwasakiacpi_print_string(char *s, size_t length)
7065285Siwasaki{
7165285Siwasaki	int	c;
7265285Siwasaki
7365285Siwasaki	/* Trim trailing spaces and NULLs */
7465285Siwasaki	while (length > 0 && (s[length - 1] == ' ' || s[length - 1] == '\0'))
7565285Siwasaki		length--;
7665285Siwasaki
7765285Siwasaki	while (length--) {
7865285Siwasaki		c = *s++;
7965285Siwasaki		putchar(c);
8065285Siwasaki	}
8165285Siwasaki}
8265285Siwasaki
8365285Siwasakistatic void
84119912Snjlacpi_print_gas(struct ACPIgas *gas)
8565285Siwasaki{
86119912Snjl	switch(gas->address_space_id) {
87119912Snjl	case ACPI_GAS_MEMORY:
88119912Snjl		printf("0x%08lx:%u[%u] (Memory)\n", (u_long)gas->address,
89119912Snjl		       gas->bit_offset, gas->bit_width);
90119912Snjl		break;
91119912Snjl	case ACPI_GAS_IO:
92119912Snjl		printf("0x%08lx:%u[%u] (IO)\n", (u_long)gas->address,
93119912Snjl		       gas->bit_offset, gas->bit_width);
94119912Snjl		break;
95119912Snjl	case ACPI_GAS_PCI:
96119912Snjl		printf("%x:%x+%#x (PCI)\n", (uint16_t)(gas->address >> 32),
97119912Snjl		       (uint16_t)((gas->address >> 16) & 0xffff),
98119912Snjl		       (uint16_t)gas->address);
99119912Snjl		break;
100119912Snjl	/* XXX How to handle these below? */
101119912Snjl	case ACPI_GAS_EMBEDDED:
102119912Snjl		printf("0x%#x:%u[%u] (EC)\n", (uint16_t)gas->address,
103119912Snjl		       gas->bit_offset, gas->bit_width);
104119912Snjl		break;
105119912Snjl	case ACPI_GAS_SMBUS:
106119912Snjl		printf("0x%#x:%u[%u] (SMBus)\n", (uint16_t)gas->address,
107119912Snjl		       gas->bit_offset, gas->bit_width);
108119912Snjl		break;
109119912Snjl	case ACPI_GAS_FIXED:
110119912Snjl	default:
111119912Snjl		printf("0x%08lx (?)\n", (u_long)gas->address);
112119912Snjl		break;
113119912Snjl	}
114119912Snjl}
11565285Siwasaki
116119912Snjlstatic void
117119912Snjlacpi_handle_fadt(struct FADTbody *fadt)
118119912Snjl{
119119912Snjl	struct ACPIsdt	*dsdp;
120119912Snjl	struct FACSbody	*facs;
121119912Snjl
122119912Snjl	acpi_print_fadt(fadt);
123119912Snjl
124119912Snjl	facs = (struct FACSbody *)acpi_map_sdt(fadt->facs_ptr);
125119912Snjl	if (memcmp(facs->signature, "FACS", 4) != 0 || facs->len < 64)
126119912Snjl		errx(1, "FACS is corrupt");
127119912Snjl	acpi_print_facs(facs);
128119912Snjl
129119912Snjl	dsdp = (struct ACPIsdt *)acpi_map_sdt(fadt->dsdt_ptr);
13065285Siwasaki	if (acpi_checksum(dsdp, dsdp->len))
131119515Snjl		errx(1, "DSDT is corrupt");
132119515Snjl	acpi_print_dsdt(dsdp);
13365285Siwasaki}
13465285Siwasaki
13585323Siwasakistatic void
136108967Sjhbacpi_print_cpu(u_char cpu_id)
137108967Sjhb{
138108967Sjhb
139108967Sjhb	printf("\tACPI CPU=");
140108967Sjhb	if (cpu_id == 0xff)
141108967Sjhb		printf("ALL\n");
142108967Sjhb	else
143108967Sjhb		printf("%d\n", (u_int)cpu_id);
144108967Sjhb}
145108967Sjhb
146108967Sjhbstatic void
147108967Sjhbacpi_print_local_apic(u_char cpu_id, u_char apic_id, u_int32_t flags)
148108967Sjhb{
149108967Sjhb	acpi_print_cpu(cpu_id);
150108967Sjhb	printf("\tFlags={");
151108967Sjhb	if (flags & ACPI_MADT_APIC_LOCAL_FLAG_ENABLED)
152108967Sjhb		printf("ENABLED");
153108967Sjhb	else
154108967Sjhb		printf("DISABLED");
155108967Sjhb	printf("}\n");
156108967Sjhb	printf("\tAPIC ID=%d\n", (u_int)apic_id);
157108967Sjhb}
158108967Sjhb
159108967Sjhbstatic void
160108967Sjhbacpi_print_io_apic(u_char apic_id, u_int32_t int_base, u_int64_t apic_addr)
161108967Sjhb{
162108967Sjhb	printf("\tAPIC ID=%d\n", (u_int)apic_id);
163108967Sjhb	printf("\tINT BASE=%d\n", int_base);
164119515Snjl	printf("\tADDR=0x%016jx\n", apic_addr);
165108967Sjhb}
166108967Sjhb
167108967Sjhbstatic void
168108967Sjhbacpi_print_mps_flags(u_int16_t flags)
169108967Sjhb{
170108967Sjhb
171108967Sjhb	printf("\tFlags={Polarity=");
172108967Sjhb	switch (flags & MPS_INT_FLAG_POLARITY_MASK) {
173108967Sjhb	case MPS_INT_FLAG_POLARITY_CONFORM:
174108967Sjhb		printf("conforming");
175108967Sjhb		break;
176108967Sjhb	case MPS_INT_FLAG_POLARITY_HIGH:
177108967Sjhb		printf("active-hi");
178108967Sjhb		break;
179108967Sjhb	case MPS_INT_FLAG_POLARITY_LOW:
180108967Sjhb		printf("active-lo");
181108967Sjhb		break;
182108967Sjhb	default:
183108967Sjhb		printf("0x%x", flags & MPS_INT_FLAG_POLARITY_MASK);
184108967Sjhb		break;
185108967Sjhb	}
186108967Sjhb	printf(", Trigger=");
187108967Sjhb	switch (flags & MPS_INT_FLAG_TRIGGER_MASK) {
188108967Sjhb	case MPS_INT_FLAG_TRIGGER_CONFORM:
189108967Sjhb		printf("conforming");
190108967Sjhb		break;
191108967Sjhb	case MPS_INT_FLAG_TRIGGER_EDGE:
192108967Sjhb		printf("edge");
193108967Sjhb		break;
194108967Sjhb	case MPS_INT_FLAG_TRIGGER_LEVEL:
195108967Sjhb		printf("level");
196108967Sjhb		break;
197108967Sjhb	default:
198108967Sjhb		printf("0x%x", (flags & MPS_INT_FLAG_TRIGGER_MASK) >> 2);
199108967Sjhb	}
200108967Sjhb	printf("}\n");
201108967Sjhb}
202108967Sjhb
203108967Sjhbstatic void
204108967Sjhbacpi_print_intr(u_int32_t intr, u_int16_t mps_flags)
205108967Sjhb{
206108967Sjhb
207108967Sjhb	printf("\tINTR=%d\n", (u_int)intr);
208108967Sjhb	acpi_print_mps_flags(mps_flags);
209108967Sjhb}
210108967Sjhb
211108967Sjhbconst char *apic_types[] = { "Local APIC", "IO APIC", "INT Override", "NMI",
212108967Sjhb			     "Local NMI", "Local APIC Override", "IO SAPIC",
213108967Sjhb			     "Local SAPIC", "Platform Interrupt" };
214108967Sjhbconst char *platform_int_types[] = { "PMI", "INIT",
215108967Sjhb				     "Corrected Platform Error" };
216108967Sjhb
217108967Sjhbstatic void
218108967Sjhbacpi_print_apic(struct MADT_APIC *mp)
219108967Sjhb{
220108967Sjhb
221108967Sjhb	printf("\tType=%s\n", apic_types[mp->type]);
222108967Sjhb	switch (mp->type) {
223108967Sjhb	case ACPI_MADT_APIC_TYPE_LOCAL_APIC:
224108967Sjhb		acpi_print_local_apic(mp->body.local_apic.cpu_id,
225108967Sjhb		    mp->body.local_apic.apic_id, mp->body.local_apic.flags);
226108967Sjhb		break;
227108967Sjhb	case ACPI_MADT_APIC_TYPE_IO_APIC:
228108967Sjhb		acpi_print_io_apic(mp->body.io_apic.apic_id,
229108967Sjhb		    mp->body.io_apic.int_base,
230108967Sjhb		    mp->body.io_apic.apic_addr);
231108967Sjhb		break;
232108967Sjhb	case ACPI_MADT_APIC_TYPE_INT_OVERRIDE:
233108967Sjhb		printf("\tBUS=%d\n", (u_int)mp->body.int_override.bus);
234108967Sjhb		printf("\tIRQ=%d\n", (u_int)mp->body.int_override.source);
235108967Sjhb		acpi_print_intr(mp->body.int_override.intr,
236108967Sjhb		    mp->body.int_override.mps_flags);
237108967Sjhb		break;
238108967Sjhb	case ACPI_MADT_APIC_TYPE_NMI:
239108967Sjhb		acpi_print_intr(mp->body.nmi.intr, mp->body.nmi.mps_flags);
240108967Sjhb		break;
241108967Sjhb	case ACPI_MADT_APIC_TYPE_LOCAL_NMI:
242108967Sjhb		acpi_print_cpu(mp->body.local_nmi.cpu_id);
243108967Sjhb		printf("\tLINT Pin=%d\n", mp->body.local_nmi.lintpin);
244108967Sjhb		acpi_print_mps_flags(mp->body.local_nmi.mps_flags);
245108967Sjhb		break;
246108967Sjhb	case ACPI_MADT_APIC_TYPE_LOCAL_OVERRIDE:
247119515Snjl		printf("\tLocal APIC ADDR=0x%016jx\n",
248119515Snjl		    mp->body.local_apic_override.apic_addr);
249108967Sjhb		break;
250108967Sjhb	case ACPI_MADT_APIC_TYPE_IO_SAPIC:
251108967Sjhb		acpi_print_io_apic(mp->body.io_sapic.apic_id,
252108967Sjhb		    mp->body.io_sapic.int_base,
253108967Sjhb		    mp->body.io_sapic.apic_addr);
254108967Sjhb		break;
255108967Sjhb	case ACPI_MADT_APIC_TYPE_LOCAL_SAPIC:
256108967Sjhb		acpi_print_local_apic(mp->body.local_sapic.cpu_id,
257108967Sjhb		    mp->body.local_sapic.apic_id, mp->body.local_sapic.flags);
258108967Sjhb		printf("\tAPIC EID=%d\n", (u_int)mp->body.local_sapic.apic_eid);
259108967Sjhb		break;
260108967Sjhb	case ACPI_MADT_APIC_TYPE_INT_SRC:
261108967Sjhb		printf("\tType=%s\n",
262108967Sjhb		    platform_int_types[mp->body.int_src.type]);
263108967Sjhb		printf("\tCPU ID=%d\n", (u_int)mp->body.int_src.cpu_id);
264108967Sjhb		printf("\tCPU EID=%d\n", (u_int)mp->body.int_src.cpu_id);
265108967Sjhb		printf("\tSAPIC Vector=%d\n",
266108967Sjhb		    (u_int)mp->body.int_src.sapic_vector);
267108967Sjhb		acpi_print_intr(mp->body.int_src.intr,
268108967Sjhb		    mp->body.int_src.mps_flags);
269108967Sjhb		break;
270108967Sjhb	default:
271108967Sjhb		printf("\tUnknown type %d\n", (u_int)mp->type);
272119515Snjl		break;
273108967Sjhb	}
274108967Sjhb}
275108967Sjhb
276108967Sjhbstatic void
277108967Sjhbacpi_handle_apic(struct ACPIsdt *sdp)
278108967Sjhb{
279108967Sjhb	struct MADTbody *madtp;
280108967Sjhb	struct MADT_APIC *madt_apicp;
281108967Sjhb
282119515Snjl	acpi_print_sdt(sdp, /*endcomment*/0);
283108967Sjhb	madtp = (struct MADTbody *) sdp->body;
284108967Sjhb	printf("\tLocal APIC ADDR=0x%08x\n", madtp->lapic_addr);
285108967Sjhb	printf("\tFlags={");
286108967Sjhb	if (madtp->flags & ACPI_APIC_FLAG_PCAT_COMPAT)
287108967Sjhb		printf("PC-AT");
288108967Sjhb	printf("}\n");
289119515Snjl	madt_apicp = (struct MADT_APIC *)madtp->body;
290108967Sjhb	while (((uintptr_t)madt_apicp) - ((uintptr_t)sdp) < sdp->len) {
291108967Sjhb		printf("\n");
292108967Sjhb		acpi_print_apic(madt_apicp);
293108967Sjhb		madt_apicp = (struct MADT_APIC *) ((char *)madt_apicp +
294108967Sjhb		    madt_apicp->len);
295108967Sjhb	}
296108967Sjhb	printf(END_COMMENT);
297108967Sjhb}
298108967Sjhb
299108967Sjhbstatic void
300118334Speteracpi_handle_hpet(struct ACPIsdt *sdp)
301118334Speter{
302118334Speter	struct HPETbody *hpetp;
303118334Speter
304119515Snjl	acpi_print_sdt(sdp, /*endcomment*/0);
305118334Speter	hpetp = (struct HPETbody *) sdp->body;
306118334Speter	printf("\tHPET Number=%d\n", hpetp->hpet_number);
307118334Speter	printf("\tADDR=0x%08x\n", hpetp->base_addr);
308118334Speter	printf("\tHW Rev=0x%x\n", hpetp->block_hwrev);
309118334Speter	printf("\tComparitors=%d\n", hpetp->block_comparitors);
310118334Speter	printf("\tCounter Size=%d\n", hpetp->block_counter_size);
311118334Speter	printf("\tLegacy IRQ routing capable={");
312118334Speter	if (hpetp->block_legacy_capable)
313118334Speter		printf("TRUE}\n");
314118334Speter	else
315118334Speter		printf("FALSE}\n");
316118334Speter	printf("\tPCI Vendor ID=0x%04x\n", hpetp->block_pcivendor);
317118335Speter	printf("\tMinimal Tick=%d\n", hpetp->clock_tick);
318118334Speter	printf(END_COMMENT);
319118334Speter}
320118334Speter
321118334Speterstatic void
322119515Snjlacpi_print_sdt(struct ACPIsdt *sdp, int endcomment)
32385323Siwasaki{
324119515Snjl	printf(BEGIN_COMMENT "  ");
32565285Siwasaki	acpi_print_string(sdp->signature, 4);
32685323Siwasaki	printf(": Length=%d, Revision=%d, Checksum=%d,\n",
32765285Siwasaki	       sdp->len, sdp->rev, sdp->check);
32865285Siwasaki	printf("\tOEMID=");
32965285Siwasaki	acpi_print_string(sdp->oemid, 6);
33065285Siwasaki	printf(", OEM Table ID=");
33165285Siwasaki	acpi_print_string(sdp->oemtblid, 8);
33265285Siwasaki	printf(", OEM Revision=0x%x,\n", sdp->oemrev);
33365285Siwasaki	printf("\tCreator ID=");
33465285Siwasaki	acpi_print_string(sdp->creator, 4);
33565285Siwasaki	printf(", Creator Revision=0x%x\n", sdp->crerev);
336119515Snjl	if (endcomment)
337119515Snjl		printf(END_COMMENT);
33865285Siwasaki}
33965285Siwasaki
340119515Snjlstatic void
34165285Siwasakiacpi_print_rsdt(struct ACPIsdt *rsdp)
34265285Siwasaki{
34365285Siwasaki	int	i, entries;
34465285Siwasaki
345119515Snjl	acpi_print_sdt(rsdp, /*endcomment*/0);
34665285Siwasaki	entries = (rsdp->len - SIZEOF_SDT_HDR) / sizeof(u_int32_t);
34765285Siwasaki	printf("\tEntries={ ");
34865285Siwasaki	for (i = 0; i < entries; i++) {
34965285Siwasaki		if (i > 0)
35065285Siwasaki			printf(", ");
35165285Siwasaki		printf("0x%08x", rsdp->body[i]);
35265285Siwasaki	}
35365285Siwasaki	printf(" }\n");
35485323Siwasaki	printf(END_COMMENT);
35565285Siwasaki}
35665285Siwasaki
357119912Snjlstatic const char *acpi_pm_profiles[] = {
358119912Snjl	"Unspecified", "Desktop", "Mobile", "Workstation",
359119912Snjl	"Enterprise Server", "SOHO Server", "Appliance PC"
360119912Snjl};
361119912Snjl
362119515Snjlstatic void
363119912Snjlacpi_print_fadt(struct FADTbody *fadt)
36465285Siwasaki{
365119912Snjl	const char *pm;
366119912Snjl	char	    sep;
36765285Siwasaki
36885323Siwasaki	printf(BEGIN_COMMENT);
369119912Snjl	printf("  FADT:\tFACS=0x%x, DSDT=0x%x\n", fadt->facs_ptr,
370119912Snjl	       fadt->dsdt_ptr);
371119912Snjl	printf("\tINT_MODEL=%s\n", fadt->int_model ? "APIC" : "PIC");
372119912Snjl	if (fadt->pm_profile >= sizeof(acpi_pm_profiles) / sizeof(char *))
373119912Snjl		pm = "Reserved";
374119912Snjl	else
375119912Snjl		pm = acpi_pm_profiles[fadt->pm_profile];
376119912Snjl	printf("\tPreferred_PM_Profile=%s (%d)\n", pm, fadt->pm_profile);
377119912Snjl	printf("\tSCI_INT=%d\n", fadt->sci_int);
378119912Snjl	printf("\tSMI_CMD=0x%x, ", fadt->smi_cmd);
379119912Snjl	printf("ACPI_ENABLE=0x%x, ", fadt->acpi_enable);
380119912Snjl	printf("ACPI_DISABLE=0x%x, ", fadt->acpi_disable);
381119912Snjl	printf("S4BIOS_REQ=0x%x\n", fadt->s4biosreq);
382119912Snjl	printf("\tPSTATE_CNT=0x%x\n", fadt->pstate_cnt);
383119912Snjl	if (fadt->pm1a_evt_blk != 0)
38465285Siwasaki		printf("\tPM1a_EVT_BLK=0x%x-0x%x\n",
385119912Snjl		       fadt->pm1a_evt_blk,
386119912Snjl		       fadt->pm1a_evt_blk + fadt->pm1_evt_len - 1);
387119912Snjl	if (fadt->pm1b_evt_blk != 0)
38865285Siwasaki		printf("\tPM1b_EVT_BLK=0x%x-0x%x\n",
389119912Snjl		       fadt->pm1b_evt_blk,
390119912Snjl		       fadt->pm1b_evt_blk + fadt->pm1_evt_len - 1);
391119912Snjl	if (fadt->pm1a_cnt_blk != 0)
39265285Siwasaki		printf("\tPM1a_CNT_BLK=0x%x-0x%x\n",
393119912Snjl		       fadt->pm1a_cnt_blk,
394119912Snjl		       fadt->pm1a_cnt_blk + fadt->pm1_cnt_len - 1);
395119912Snjl	if (fadt->pm1b_cnt_blk != 0)
39665285Siwasaki		printf("\tPM1b_CNT_BLK=0x%x-0x%x\n",
397119912Snjl		       fadt->pm1b_cnt_blk,
398119912Snjl		       fadt->pm1b_cnt_blk + fadt->pm1_cnt_len - 1);
399119912Snjl	if (fadt->pm2_cnt_blk != 0)
40065285Siwasaki		printf("\tPM2_CNT_BLK=0x%x-0x%x\n",
401119912Snjl		       fadt->pm2_cnt_blk,
402119912Snjl		       fadt->pm2_cnt_blk + fadt->pm2_cnt_len - 1);
403119912Snjl	if (fadt->pm_tmr_blk != 0)
40465285Siwasaki		printf("\tPM2_TMR_BLK=0x%x-0x%x\n",
405119912Snjl		       fadt->pm_tmr_blk,
406119912Snjl		       fadt->pm_tmr_blk + fadt->pm_tmr_len - 1);
407119912Snjl	if (fadt->gpe0_blk != 0)
408119912Snjl		printf("\tGPE0_BLK=0x%x-0x%x\n",
409119912Snjl		       fadt->gpe0_blk,
410119912Snjl		       fadt->gpe0_blk + fadt->gpe0_len - 1);
411119912Snjl	if (fadt->gpe1_blk != 0)
412119912Snjl		printf("\tGPE1_BLK=0x%x-0x%x, GPE1_BASE=%d\n",
413119912Snjl		       fadt->gpe1_blk,
414119912Snjl		       fadt->gpe1_blk + fadt->gpe1_len - 1,
415119912Snjl		       fadt->gpe1_base);
416119912Snjl	if (fadt->cst_cnt != 0)
417119912Snjl		printf("\tCST_CNT=0x%x\n", fadt->cst_cnt);
41865285Siwasaki	printf("\tP_LVL2_LAT=%dms, P_LVL3_LAT=%dms\n",
419119912Snjl	       fadt->p_lvl2_lat, fadt->p_lvl3_lat);
42065285Siwasaki	printf("\tFLUSH_SIZE=%d, FLUSH_STRIDE=%d\n",
421119912Snjl	       fadt->flush_size, fadt->flush_stride);
42265285Siwasaki	printf("\tDUTY_OFFSET=%d, DUTY_WIDTH=%d\n",
423119912Snjl	       fadt->duty_off, fadt->duty_width);
42465285Siwasaki	printf("\tDAY_ALRM=%d, MON_ALRM=%d, CENTURY=%d\n",
425119912Snjl	       fadt->day_alrm, fadt->mon_alrm, fadt->century);
42665285Siwasaki
427119912Snjl#define PRINTFLAG(var, flag) do {			\
428119912Snjl	if ((var) & FADT_FLAG_## flag) {		\
429119912Snjl		printf("%c%s", sep, #flag); sep = ',';	\
430119912Snjl	}						\
43165285Siwasaki} while (0)
43265285Siwasaki
433119912Snjl	printf("\tIAPC_BOOT_ARCH=");
434119912Snjl	sep = '{';
435119912Snjl	PRINTFLAG(fadt->iapc_boot_arch, LEGACY_DEV);
436119912Snjl	PRINTFLAG(fadt->iapc_boot_arch, 8042);
437119912Snjl	printf("}\n");
43865285Siwasaki
439119912Snjl	printf("\tFlags=");
440119912Snjl	sep = '{';
441119912Snjl	PRINTFLAG(fadt->flags, WBINVD);
442119912Snjl	PRINTFLAG(fadt->flags, WBINVD_FLUSH);
443119912Snjl	PRINTFLAG(fadt->flags, PROC_C1);
444119912Snjl	PRINTFLAG(fadt->flags, P_LVL2_UP);
445119912Snjl	PRINTFLAG(fadt->flags, PWR_BUTTON);
446119912Snjl	PRINTFLAG(fadt->flags, SLP_BUTTON);
447119912Snjl	PRINTFLAG(fadt->flags, FIX_RTC);
448119912Snjl	PRINTFLAG(fadt->flags, RTC_S4);
449119912Snjl	PRINTFLAG(fadt->flags, TMR_VAL_EXT);
450119912Snjl	PRINTFLAG(fadt->flags, DCK_CAP);
451119912Snjl	PRINTFLAG(fadt->flags, RESET_REG);
452119912Snjl	PRINTFLAG(fadt->flags, SEALED_CASE);
453119912Snjl	PRINTFLAG(fadt->flags, HEADLESS);
454119912Snjl	PRINTFLAG(fadt->flags, CPU_SW_SLP);
455119912Snjl	printf("}\n");
456119912Snjl
45765285Siwasaki#undef PRINTFLAG
45865285Siwasaki
459119912Snjl	if (fadt->flags & FADT_FLAG_RESET_REG) {
460119912Snjl		printf("\tRESET_REG=");
461119912Snjl		acpi_print_gas(&fadt->reset_reg);
462119912Snjl		printf(", RESET_VALUE=%#x\n", fadt->reset_value);
463119912Snjl	}
464119912Snjl
465119912Snjl	printf(END_COMMENT);
466119912Snjl}
467119912Snjl
468119912Snjlstatic void
469119912Snjlacpi_print_facs(struct FACSbody *facs)
470119912Snjl{
471119912Snjl	printf(BEGIN_COMMENT);
472119912Snjl	printf("  FACS:\tLength=%u, ", facs->len);
473119912Snjl	printf("HwSig=0x%08x, ", facs->hw_sig);
474119912Snjl	printf("Firm_Wake_Vec=0x%08x\n", facs->firm_wake_vec);
475119912Snjl
476119912Snjl	printf("\tGlobal_Lock={");
477119912Snjl	if (facs->global_lock != 0) {
478119912Snjl		if (facs->global_lock & FACS_FLAG_LOCK_PENDING)
479119912Snjl			printf("PENDING,");
480119912Snjl		if (facs->global_lock & FACS_FLAG_LOCK_OWNED)
481119912Snjl			printf("OWNED");
482119912Snjl	}
48365285Siwasaki	printf("}\n");
484119912Snjl
485119912Snjl	printf("\tFlags={");
486119912Snjl	if (facs->flags & FACS_FLAG_S4BIOS_F)
487119912Snjl		printf("S4BIOS");
488119912Snjl	printf("}\n");
489119912Snjl
490119912Snjl	if (facs->x_firm_wake_vec != 0) {
491119912Snjl		printf("\tX_Firm_Wake_Vec=%08lx\n",
492119912Snjl		       (u_long)facs->x_firm_wake_vec);
493119912Snjl	}
494119912Snjl
49585323Siwasaki	printf(END_COMMENT);
49665285Siwasaki}
49765285Siwasaki
498119515Snjlstatic void
49965285Siwasakiacpi_print_dsdt(struct ACPIsdt *dsdp)
50065285Siwasaki{
501119515Snjl	acpi_print_sdt(dsdp, /*endcomment*/1);
50265285Siwasaki}
50365285Siwasaki
50465285Siwasakiint
50565285Siwasakiacpi_checksum(void *p, size_t length)
50665285Siwasaki{
50765285Siwasaki	u_int8_t	*bp;
50865285Siwasaki	u_int8_t	sum;
50965285Siwasaki
51065285Siwasaki	bp = p;
51165285Siwasaki	sum = 0;
51265285Siwasaki	while (length--)
51365285Siwasaki		sum += *bp++;
51465285Siwasaki
51565285Siwasaki	return (sum);
51665285Siwasaki}
51765285Siwasaki
518119515Snjlstatic struct ACPIsdt *
51965285Siwasakiacpi_map_sdt(vm_offset_t pa)
52065285Siwasaki{
52165285Siwasaki	struct	ACPIsdt *sp;
52265285Siwasaki
52365285Siwasaki	sp = acpi_map_physical(pa, sizeof(struct ACPIsdt));
52465285Siwasaki	sp = acpi_map_physical(pa, sp->len);
52565285Siwasaki	return (sp);
52665285Siwasaki}
52765285Siwasaki
528119515Snjlstatic void
52965285Siwasakiacpi_print_rsd_ptr(struct ACPIrsdp *rp)
53065285Siwasaki{
53165285Siwasaki
53285323Siwasaki	printf(BEGIN_COMMENT);
533119515Snjl	printf("  RSD PTR: Checksum=%d, OEMID=", rp->sum);
53465285Siwasaki	acpi_print_string(rp->oem, 6);
535108082Smarcel	printf(", RsdtAddress=0x%08x\n", rp->rsdt_addr);
53685323Siwasaki	printf(END_COMMENT);
53765285Siwasaki}
53865285Siwasaki
539119515Snjlstatic void
54065285Siwasakiacpi_handle_rsdt(struct ACPIsdt *rsdp)
54165285Siwasaki{
54265285Siwasaki	int	i;
54365285Siwasaki	int	entries;
54465285Siwasaki	struct	ACPIsdt *sdp;
54565285Siwasaki
54665285Siwasaki	entries = (rsdp->len - SIZEOF_SDT_HDR) / sizeof(u_int32_t);
54765285Siwasaki	acpi_print_rsdt(rsdp);
54865285Siwasaki	for (i = 0; i < entries; i++) {
549119515Snjl		sdp = (struct ACPIsdt *)acpi_map_sdt(rsdp->body[i]);
55065285Siwasaki		if (acpi_checksum(sdp, sdp->len))
551119515Snjl			errx(1, "RSDT entry %d is corrupt", i);
552119515Snjl		if (!memcmp(sdp->signature, "FACP", 4))
553119912Snjl			acpi_handle_fadt((struct FADTbody *) sdp->body);
554119515Snjl		else if (!memcmp(sdp->signature, "APIC", 4))
555108967Sjhb			acpi_handle_apic(sdp);
556119515Snjl		else if (!memcmp(sdp->signature, "HPET", 4))
557118334Speter			acpi_handle_hpet(sdp);
558119515Snjl		else
559119515Snjl			acpi_print_sdt(sdp, /*endcomment*/1);
56065285Siwasaki	}
56165285Siwasaki}
56285323Siwasaki
563119515Snjlstruct ACPIsdt *
564119515Snjlsdt_load_devmem()
56585323Siwasaki{
566119515Snjl	struct	ACPIrsdp *rp;
567119515Snjl	struct	ACPIsdt *rsdp;
56885323Siwasaki
569119515Snjl	rp = acpi_find_rsd_ptr();
570119515Snjl	if (!rp)
571119515Snjl		errx(1, "Can't find ACPI information");
572119515Snjl
573119515Snjl	if (tflag)
574119515Snjl		acpi_print_rsd_ptr(rp);
575119515Snjl	rsdp = (struct ACPIsdt *)acpi_map_sdt(rp->rsdt_addr);
576119515Snjl	if (memcmp(rsdp->signature, "RSDT", 4) != 0 ||
577119515Snjl	    acpi_checksum(rsdp, rsdp->len) != 0)
578119515Snjl		errx(1, "RSDT is corrupted");
579119515Snjl
580119515Snjl	return (rsdp);
58185323Siwasaki}
58285323Siwasaki
583119515Snjlvoid
584119515Snjldsdt_save_file(char *outfile, struct ACPIsdt *dsdp)
58585323Siwasaki{
586119515Snjl	int	fd;
587119515Snjl	mode_t	mode;
58885323Siwasaki
589119515Snjl	assert(outfile != NULL);
590119515Snjl	mode = S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH;
591119515Snjl	fd = open(outfile, O_WRONLY | O_CREAT | O_TRUNC, mode);
592119515Snjl	if (fd == -1) {
593119515Snjl		perror("dsdt_save_file");
594119515Snjl		return;
595119515Snjl	}
596119515Snjl	write(fd, dsdp, SIZEOF_SDT_HDR);
597119515Snjl	write(fd, dsdp->body, dsdp->len - SIZEOF_SDT_HDR);
598119515Snjl	close(fd);
59985323Siwasaki}
60085323Siwasaki
601119515Snjlvoid
602119515Snjlaml_disassemble(struct ACPIsdt *dsdp)
60385323Siwasaki{
604119515Snjl	char tmpstr[32], buf[256];
605119515Snjl	FILE *fp;
606119515Snjl	int fd, len;
60785323Siwasaki
608119515Snjl	strcpy(tmpstr, "/tmp/acpidump.XXXXXX");
609119515Snjl	fd = mkstemp(tmpstr);
610119515Snjl	if (fd < 0) {
611119515Snjl		perror("iasl tmp file");
612119515Snjl		return;
613119515Snjl	}
614119515Snjl
615119515Snjl	/* Dump DSDT to the temp file */
616119515Snjl	write(fd, dsdp, SIZEOF_SDT_HDR);
617119515Snjl	write(fd, dsdp->body, dsdp->len - SIZEOF_SDT_HDR);
618119515Snjl	close(fd);
619119515Snjl
620119515Snjl	/* Run iasl -d on the temp file */
621119515Snjl	if (fork() == 0) {
622119515Snjl		close(STDOUT_FILENO);
623119515Snjl		if (vflag == 0)
624119515Snjl			close(STDERR_FILENO);
625119515Snjl		execl("/usr/sbin/iasl", "iasl", "-d", tmpstr, 0);
626119515Snjl		err(1, "exec");
627119515Snjl	}
628119515Snjl
629119515Snjl	wait(NULL);
630119515Snjl	unlink(tmpstr);
631119515Snjl
632119515Snjl	/* Dump iasl's output to stdout */
633119515Snjl	fp = fopen("acpidump.dsl", "r");
634119515Snjl	unlink("acpidump.dsl");
635119515Snjl	if (fp == NULL) {
636119515Snjl		perror("iasl tmp file (read)");
637119515Snjl		return;
638119515Snjl	}
639119515Snjl	while ((len = fread(buf, 1, sizeof(buf), fp)) > 0)
640119515Snjl		fwrite(buf, 1, len, stdout);
641119515Snjl	fclose(fp);
64285323Siwasaki}
64385323Siwasaki
644119515Snjlvoid
645119515Snjlsdt_print_all(struct ACPIsdt *rsdp)
64685323Siwasaki{
647119515Snjl	acpi_handle_rsdt(rsdp);
64885323Siwasaki}
64985323Siwasaki
650119515Snjl/* Fetch a table matching the given signature via the RSDT */
651119515Snjlstruct ACPIsdt *
652119515Snjlsdt_from_rsdt(struct ACPIsdt *rsdt, const char *sig)
65385323Siwasaki{
654119515Snjl	int	i;
655119515Snjl	int	entries;
656119515Snjl	struct	ACPIsdt *sdt;
65785323Siwasaki
658119515Snjl	entries = (rsdt->len - SIZEOF_SDT_HDR) / sizeof(uint32_t);
659119515Snjl	for (i = 0; i < entries; i++) {
660119515Snjl		sdt = (struct ACPIsdt *)acpi_map_sdt(rsdt->body[i]);
661119515Snjl		if (acpi_checksum(sdt, sdt->len))
662119515Snjl			errx(1, "RSDT entry %d is corrupt", i);
663119515Snjl		if (!memcmp(sdt->signature, sig, strlen(sig)))
664119515Snjl			return (sdt);
665119515Snjl	}
666119515Snjl
667119515Snjl	return (NULL);
66885323Siwasaki}
66985323Siwasaki
670119515Snjlstruct ACPIsdt *
671119912Snjldsdt_from_fadt(struct FADTbody *fadt)
67285323Siwasaki{
673119515Snjl	struct	ACPIsdt *sdt;
67485323Siwasaki
675119912Snjl	sdt = (struct ACPIsdt *)acpi_map_sdt(fadt->dsdt_ptr);
676119515Snjl	if (acpi_checksum(sdt, sdt->len))
677119515Snjl		errx(1, "DSDT is corrupt\n");
678119515Snjl	return (sdt);
67985323Siwasaki}
680