GCC Code Coverage Report
Directory: ./ Exec Total Coverage
File: usr.sbin/acpidump/acpidump.c Lines: 0 197 0.0 %
Date: 2016-12-06 Branches: 0 116 0.0 %

Line Branch Exec Source
1
/*	$OpenBSD: acpidump.c,v 1.16 2015/10/12 04:02:57 semarie Exp $	*/
2
/*
3
 * Copyright (c) 2000 Mitsuru IWASAKI <iwasaki@FreeBSD.org>
4
 * All rights reserved.
5
 *
6
 * Redistribution and use in source and binary forms, with or without
7
 * modification, are permitted provided that the following conditions
8
 * are met:
9
 * 1. Redistributions of source code must retain the above copyright
10
 *    notice, this list of conditions and the following disclaimer.
11
 * 2. Redistributions in binary form must reproduce the above copyright
12
 *    notice, this list of conditions and the following disclaimer in the
13
 *    documentation and/or other materials provided with the distribution.
14
 *
15
 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
16
 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
17
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
18
 * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
19
 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
20
 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
21
 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
22
 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
23
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
24
 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
25
 * SUCH DAMAGE.
26
 *
27
 */
28
29
#include <sys/types.h>
30
#include <sys/mman.h>
31
#include <sys/queue.h>
32
#include <sys/stat.h>
33
#include <machine/biosvar.h>
34
35
#include <assert.h>
36
#include <err.h>
37
#include <fcntl.h>
38
#include <kvm.h>
39
#include <stdio.h>
40
#include <stdlib.h>
41
#include <string.h>
42
#include <unistd.h>
43
#include <limits.h>
44
45
46
#define vm_page_size sysconf(_SC_PAGESIZE)
47
#define PRINTFLAG(xx)							\
48
	do {								\
49
		if (facp->flags & ACPI_FACP_FLAG_## xx) {		\
50
			fprintf(fhdr, "%c%s", sep, #xx); sep = ',';	\
51
		}							\
52
	} while (0)
53
54
55
typedef unsigned long	vm_offset_t;
56
57
struct ACPIrsdp {
58
	u_char		signature[8];
59
	u_char		sum;
60
	u_char		oem[6];
61
	u_char		res;
62
	u_int32_t	addr;
63
} __packed;
64
65
struct ACPIsdt {
66
	u_char		signature[4];
67
	u_int32_t	len;
68
	u_char		rev;
69
	u_char		check;
70
	u_char		oemid[6];
71
	u_char		oemtblid[8];
72
	u_int32_t	oemrev;
73
	u_char		creator[4];
74
	u_int32_t	crerev;
75
#define SIZEOF_SDT_HDR	36	/* struct size except body */
76
	u_int32_t	body[1];/* This member should be casted */
77
} __packed;
78
79
struct ACPIgas {
80
	u_int8_t	address_space_id;
81
#define ACPI_GAS_MEMORY		0
82
#define ACPI_GAS_IO		1
83
#define ACPI_GAS_PCI		2
84
#define ACPI_GAS_EMBEDDED	3
85
#define ACPI_GAS_SMBUS		4
86
#define ACPI_GAS_FIXED		0x7f
87
	u_int8_t	register_bit_width;
88
	u_int8_t	register_bit_offset;
89
	u_int8_t	res;
90
	u_int64_t	address;
91
} __packed;
92
93
struct FACPbody {
94
	u_int32_t	facs_ptr;
95
	u_int32_t	dsdt_ptr;
96
	u_int8_t	int_model;
97
#define ACPI_FACP_INTMODEL_PIC	0	/* Standard PC-AT PIC */
98
#define ACPI_FACP_INTMODEL_APIC	1	/* Multiple APIC */
99
	u_char		reserved1;
100
	u_int16_t	sci_int;
101
	u_int32_t	smi_cmd;
102
	u_int8_t	acpi_enable;
103
	u_int8_t	acpi_disable;
104
	u_int8_t	s4biosreq;
105
	u_int8_t	reserved2;
106
	u_int32_t	pm1a_evt_blk;
107
	u_int32_t	pm1b_evt_blk;
108
	u_int32_t	pm1a_cnt_blk;
109
	u_int32_t	pm1b_cnt_blk;
110
	u_int32_t	pm2_cnt_blk;
111
	u_int32_t	pm_tmr_blk;
112
	u_int32_t	gpe0_blk;
113
	u_int32_t	gpe1_blk;
114
	u_int8_t	pm1_evt_len;
115
	u_int8_t	pm1_cnt_len;
116
	u_int8_t	pm2_cnt_len;
117
	u_int8_t	pm_tmr_len;
118
	u_int8_t	gpe0_len;
119
	u_int8_t	gpe1_len;
120
	u_int8_t	gpe1_base;
121
	u_int8_t	reserved3;
122
	u_int16_t	p_lvl2_lat;
123
	u_int16_t	p_lvl3_lat;
124
	u_int16_t	flush_size;
125
	u_int16_t	flush_stride;
126
	u_int8_t	duty_off;
127
	u_int8_t	duty_width;
128
	u_int8_t	day_alrm;
129
	u_int8_t	mon_alrm;
130
	u_int8_t	century;
131
	u_int16_t	iapc_boot_arch;
132
	u_char		reserved4[1];
133
	u_int32_t	flags;
134
#define ACPI_FACP_FLAG_WBINVD	1	/* WBINVD is correctly supported */
135
#define ACPI_FACP_FLAG_WBINVD_FLUSH 2	/* WBINVD flushes caches */
136
#define ACPI_FACP_FLAG_PROC_C1	4	/* C1 power state supported */
137
#define ACPI_FACP_FLAG_P_LVL2_UP 8	/* C2 power state works on SMP */
138
#define ACPI_FACP_FLAG_PWR_BUTTON 16	/* Power button uses control method */
139
#define ACPI_FACP_FLAG_SLP_BUTTON 32	/* Sleep button uses control method */
140
#define ACPI_FACP_FLAG_FIX_RTC	64	/* RTC wakeup not supported */
141
#define ACPI_FACP_FLAG_RTC_S4	128	/* RTC can wakeup from S4 state */
142
#define ACPI_FACP_FLAG_TMR_VAL_EXT 256	/* TMR_VAL is 32bit */
143
#define ACPI_FACP_FLAG_DCK_CAP	512	/* Can support docking */
144
	struct ACPIgas	reset_reg;
145
	u_int8_t	reset_value;
146
	u_int8_t	reserved5[3];
147
	u_int64_t	x_firmware_ctrl;
148
	u_int64_t	x_dsdt;
149
	struct ACPIgas	x_pm1a_evt_blk;
150
	struct ACPIgas	x_pm1b_evt_blk;
151
	struct ACPIgas	x_pm1a_cnt_blk;
152
	struct ACPIgas	x_pm1b_cnt_blk;
153
	struct ACPIgas	x_pm2_cnt_blk;
154
	struct ACPIgas	x_pm_tmr_blk;
155
	struct ACPIgas	x_gpe0_blk;
156
	struct ACPIgas	x_gpe1_blk;
157
} __packed;
158
159
struct acpi_user_mapping {
160
	LIST_ENTRY(acpi_user_mapping)	link;
161
	vm_offset_t			pa;
162
	caddr_t				va;
163
	size_t				size;
164
};
165
166
LIST_HEAD(acpi_user_mapping_list, acpi_user_mapping) maplist;
167
168
int		acpi_mem_fd = -1;
169
char		*aml_dumpfile;
170
FILE		*fhdr;
171
172
int	acpi_checksum(void *_p, size_t _length);
173
struct acpi_user_mapping *acpi_user_find_mapping(vm_offset_t _pa, size_t _size);
174
void	*acpi_map_physical(vm_offset_t _pa, size_t _size);
175
void	acpi_user_init(void);
176
struct ACPIrsdp *acpi_find_rsd_ptr(void);
177
void	acpi_print_string(char *_s, size_t _length);
178
void	acpi_print_rsd_ptr(struct ACPIrsdp *_rp);
179
struct ACPIsdt *acpi_map_sdt(vm_offset_t _pa);
180
void	aml_dump(struct ACPIsdt *_hdr);
181
void	acpi_print_sdt(struct ACPIsdt *_sdp);
182
void	acpi_print_rsdt(struct ACPIsdt *_rsdp);
183
void	acpi_print_facp(struct FACPbody *_facp);
184
void	acpi_print_dsdt(struct ACPIsdt *_dsdp);
185
void	acpi_handle_dsdt(struct ACPIsdt *_dsdp);
186
void	acpi_handle_facp(struct FACPbody *_facp);
187
void	acpi_handle_rsdt(struct ACPIsdt *_rsdp);
188
void	asl_dump_from_devmem(void);
189
void	usage(void);
190
u_long	bios_acpi_addr(void);
191
192
193
struct ACPIsdt	dsdt_header = {
194
	"DSDT", 0, 1, 0, "OEMID", "OEMTBLID", 0x12345678, "CRTR", 0x12345678
195
};
196
197
int
198
acpi_checksum(void *p, size_t length)
199
{
200
	u_int8_t	*bp;
201
	u_int8_t	sum;
202
203
	bp = p;
204
	sum = 0;
205
	while (length--)
206
		sum += *bp++;
207
208
	return (sum);
209
}
210
211
struct acpi_user_mapping *
212
acpi_user_find_mapping(vm_offset_t pa, size_t size)
213
{
214
	struct acpi_user_mapping	*map;
215
	int	page_mask = getpagesize() - 1;
216
217
	/* First search for an existing mapping */
218
	for (map = LIST_FIRST(&maplist); map; map = LIST_NEXT(map, link)) {
219
		if (map->pa <= pa && map->size >= pa + size - map->pa)
220
			return (map);
221
	}
222
223
	/* Then create a new one */
224
#undef round_page
225
#undef trunc_page
226
#define	round_page(x)	(((x) + page_mask) & ~page_mask)
227
#define	trunc_page(x)	((x) & ~page_mask)
228
	size = round_page(pa + size) - trunc_page(pa);
229
	pa = trunc_page(pa);
230
#undef round_page
231
#undef trunc_page
232
	map = malloc(sizeof(struct acpi_user_mapping));
233
	if (!map)
234
		errx(1, "out of memory");
235
	map->pa = pa;
236
	map->va = mmap(0, size, PROT_READ, MAP_SHARED, acpi_mem_fd, pa);
237
	map->size = size;
238
	if (map->va == MAP_FAILED)
239
		err(1, "can't map address");
240
	LIST_INSERT_HEAD(&maplist, map, link);
241
242
	return (map);
243
}
244
245
void *
246
acpi_map_physical(vm_offset_t pa, size_t size)
247
{
248
	struct acpi_user_mapping	*map;
249
250
	map = acpi_user_find_mapping(pa, size);
251
	return (map->va + (pa - map->pa));
252
}
253
254
void
255
acpi_user_init(void)
256
{
257
	if (acpi_mem_fd == -1) {
258
		acpi_mem_fd = open("/dev/mem", O_RDONLY);
259
		if (acpi_mem_fd == -1)
260
			err(1, "opening /dev/mem");
261
		LIST_INIT(&maplist);
262
	}
263
}
264
265
struct ACPIrsdp *
266
acpi_find_rsd_ptr(void)
267
{
268
	int		i;
269
	u_int8_t	buf[sizeof(struct ACPIrsdp)];
270
	u_long		addr;
271
272
	if ((addr = bios_acpi_addr()) != 0) {
273
		lseek(acpi_mem_fd, addr, SEEK_SET);
274
		read(acpi_mem_fd, buf, 16);
275
		if (!memcmp(buf, "RSD PTR ", 8)) {
276
			read(acpi_mem_fd, buf + 16,
277
			    sizeof(struct ACPIrsdp) - 16);
278
			if (!acpi_checksum(buf, sizeof(struct ACPIrsdp)))
279
				return (acpi_map_physical(addr,
280
				    sizeof(struct ACPIrsdp)));
281
		}
282
		lseek(acpi_mem_fd, 0, SEEK_SET);
283
	}
284
	for (i = 0; i < 1024 * 1024; i += 16) {
285
		lseek(acpi_mem_fd, i, SEEK_SET);
286
		read(acpi_mem_fd, buf, 16);
287
		if (!memcmp(buf, "RSD PTR ", 8)) {
288
			/* Read the rest of the structure */
289
			read(acpi_mem_fd, buf + 16,
290
			    sizeof(struct ACPIrsdp) - 16);
291
292
			/* Verify checksum before accepting it. */
293
			if (acpi_checksum(buf, sizeof(struct ACPIrsdp)))
294
				continue;
295
296
			return (acpi_map_physical(i, sizeof(struct ACPIrsdp)));
297
		}
298
	}
299
300
	return (0);
301
}
302
303
void
304
acpi_print_string(char *s, size_t length)
305
{
306
	int		c;
307
308
	/* Trim trailing spaces and NULLs */
309
	while (length > 0 && (s[length - 1] == ' ' || s[length - 1] == '\0'))
310
		length--;
311
312
	while (length--) {
313
		c = *s++;
314
		fputc(c, fhdr);
315
	}
316
}
317
318
void
319
acpi_print_rsd_ptr(struct ACPIrsdp *rp)
320
{
321
	fprintf(fhdr, "\n");
322
	fprintf(fhdr, "RSD PTR: Checksum=%d, OEMID=", rp->sum);
323
	acpi_print_string(rp->oem, 6);
324
	fprintf(fhdr, ", RsdtAddress=0x%08x\n", rp->addr);
325
	fprintf(fhdr, "\n");
326
}
327
328
struct ACPIsdt *
329
acpi_map_sdt(vm_offset_t pa)
330
{
331
	struct ACPIsdt	*sp;
332
333
	sp = acpi_map_physical(pa, sizeof(struct ACPIsdt));
334
	sp = acpi_map_physical(pa, sp->len);
335
	return (sp);
336
}
337
338
void
339
aml_dump(struct ACPIsdt *hdr)
340
{
341
	static int	hdr_index;
342
	char		name[PATH_MAX];
343
	int		fd;
344
	mode_t		mode;
345
346
	snprintf(name, sizeof(name), "%s.%c%c%c%c.%d",
347
	    aml_dumpfile, hdr->signature[0], hdr->signature[1],
348
	    hdr->signature[2], hdr->signature[3],
349
	    hdr_index++);
350
351
	mode = (S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH);
352
	fd = open(name, O_WRONLY | O_CREAT | O_TRUNC, mode);
353
	if (fd == -1)
354
		err(1, "aml_dump");
355
356
	write(fd, hdr, SIZEOF_SDT_HDR);
357
	write(fd, hdr->body, hdr->len - SIZEOF_SDT_HDR);
358
	close(fd);
359
}
360
361
void
362
acpi_print_sdt(struct ACPIsdt *sdp)
363
{
364
	fprintf(fhdr, "\n");
365
	acpi_print_string(sdp->signature, 4);
366
	fprintf(fhdr, ": Length=%d, Revision=%d, Checksum=%d,\n",
367
	       sdp->len, sdp->rev, sdp->check);
368
	fprintf(fhdr, "\tOEMID=");
369
	acpi_print_string(sdp->oemid, 6);
370
	fprintf(fhdr, ", OEM Table ID=");
371
	acpi_print_string(sdp->oemtblid, 8);
372
	fprintf(fhdr, ", OEM Revision=0x%x,\n", sdp->oemrev);
373
	fprintf(fhdr, "\tCreator ID=");
374
	acpi_print_string(sdp->creator, 4);
375
	fprintf(fhdr, ", Creator Revision=0x%x\n", sdp->crerev);
376
	fprintf(fhdr, "\n");
377
	if (!memcmp(sdp->signature, "DSDT", 4))
378
		memcpy(&dsdt_header, sdp, sizeof(dsdt_header));
379
}
380
381
void
382
acpi_print_rsdt(struct ACPIsdt *rsdp)
383
{
384
	int		i, entries;
385
386
	acpi_print_sdt(rsdp);
387
	entries = (rsdp->len - SIZEOF_SDT_HDR) / sizeof(u_int32_t);
388
	fprintf(fhdr, "\n");
389
	fprintf(fhdr, "\tEntries={ ");
390
	for (i = 0; i < entries; i++) {
391
		if (i > 0)
392
			fprintf(fhdr, ", ");
393
		fprintf(fhdr, "0x%08x", rsdp->body[i]);
394
	}
395
	fprintf(fhdr, " }\n");
396
	fprintf(fhdr, "\n");
397
}
398
399
void
400
acpi_print_facp(struct FACPbody *facp)
401
{
402
	char		sep;
403
404
	fprintf(fhdr, "\n");
405
	fprintf(fhdr, "\tDSDT=0x%x\n", facp->dsdt_ptr);
406
	fprintf(fhdr, "\tINT_MODEL=%s\n", facp->int_model ? "APIC" : "PIC");
407
	fprintf(fhdr, "\tSCI_INT=%d\n", facp->sci_int);
408
	fprintf(fhdr, "\tSMI_CMD=0x%x, ", facp->smi_cmd);
409
	fprintf(fhdr, "ACPI_ENABLE=0x%x, ", facp->acpi_enable);
410
	fprintf(fhdr, "ACPI_DISABLE=0x%x, ", facp->acpi_disable);
411
	fprintf(fhdr, "S4BIOS_REQ=0x%x\n", facp->s4biosreq);
412
	if (facp->pm1a_evt_blk)
413
		fprintf(fhdr, "\tPM1a_EVT_BLK=0x%x-0x%x\n",
414
		    facp->pm1a_evt_blk,
415
		    facp->pm1a_evt_blk + facp->pm1_evt_len - 1);
416
	if (facp->pm1b_evt_blk)
417
		fprintf(fhdr, "\tPM1b_EVT_BLK=0x%x-0x%x\n",
418
		    facp->pm1b_evt_blk,
419
		    facp->pm1b_evt_blk + facp->pm1_evt_len - 1);
420
	if (facp->pm1a_cnt_blk)
421
		fprintf(fhdr, "\tPM1a_CNT_BLK=0x%x-0x%x\n",
422
		    facp->pm1a_cnt_blk,
423
		    facp->pm1a_cnt_blk + facp->pm1_cnt_len - 1);
424
	if (facp->pm1b_cnt_blk)
425
		fprintf(fhdr, "\tPM1b_CNT_BLK=0x%x-0x%x\n",
426
		    facp->pm1b_cnt_blk,
427
		    facp->pm1b_cnt_blk + facp->pm1_cnt_len - 1);
428
	if (facp->pm2_cnt_blk)
429
		fprintf(fhdr, "\tPM2_CNT_BLK=0x%x-0x%x\n",
430
		    facp->pm2_cnt_blk,
431
		    facp->pm2_cnt_blk + facp->pm2_cnt_len - 1);
432
	if (facp->pm_tmr_blk)
433
		fprintf(fhdr, "\tPM2_TMR_BLK=0x%x-0x%x\n",
434
		    facp->pm_tmr_blk,
435
		    facp->pm_tmr_blk + facp->pm_tmr_len - 1);
436
	if (facp->gpe0_blk)
437
		fprintf(fhdr, "\tPM2_GPE0_BLK=0x%x-0x%x\n",
438
		    facp->gpe0_blk,
439
		    facp->gpe0_blk + facp->gpe0_len - 1);
440
	if (facp->gpe1_blk)
441
		fprintf(fhdr, "\tPM2_GPE1_BLK=0x%x-0x%x, GPE1_BASE=%d\n",
442
		    facp->gpe1_blk,
443
		    facp->gpe1_blk + facp->gpe1_len - 1,
444
		    facp->gpe1_base);
445
	fprintf(fhdr, "\tP_LVL2_LAT=%dms, P_LVL3_LAT=%dms\n",
446
	    facp->p_lvl2_lat, facp->p_lvl3_lat);
447
	fprintf(fhdr, "\tFLUSH_SIZE=%d, FLUSH_STRIDE=%d\n",
448
	    facp->flush_size, facp->flush_stride);
449
	fprintf(fhdr, "\tDUTY_OFFSET=%d, DUTY_WIDTH=%d\n",
450
	    facp->duty_off, facp->duty_width);
451
	fprintf(fhdr, "\tDAY_ALRM=%d, MON_ALRM=%d, CENTURY=%d\n",
452
	    facp->day_alrm, facp->mon_alrm, facp->century);
453
	fprintf(fhdr, "\tFlags=");
454
	sep = '{';
455
456
	PRINTFLAG(WBINVD);
457
	PRINTFLAG(WBINVD_FLUSH);
458
	PRINTFLAG(PROC_C1);
459
	PRINTFLAG(P_LVL2_UP);
460
	PRINTFLAG(PWR_BUTTON);
461
	PRINTFLAG(SLP_BUTTON);
462
	PRINTFLAG(FIX_RTC);
463
	PRINTFLAG(RTC_S4);
464
	PRINTFLAG(TMR_VAL_EXT);
465
	PRINTFLAG(DCK_CAP);
466
467
	fprintf(fhdr, "}\n");
468
	fprintf(fhdr, "\n");
469
}
470
471
void
472
acpi_print_dsdt(struct ACPIsdt *dsdp)
473
{
474
	acpi_print_sdt(dsdp);
475
}
476
477
void
478
acpi_handle_dsdt(struct ACPIsdt *dsdp)
479
{
480
	u_int8_t	*dp;
481
	u_int8_t	*end;
482
483
	acpi_print_dsdt(dsdp);
484
485
	dp = (u_int8_t *)dsdp->body;
486
	end = (u_int8_t *)dsdp + dsdp->len;
487
}
488
489
void
490
acpi_handle_facp(struct FACPbody *facp)
491
{
492
	struct ACPIsdt	*dsdp;
493
494
	acpi_print_facp(facp);
495
	dsdp = (struct ACPIsdt *) acpi_map_sdt(facp->dsdt_ptr);
496
	if (acpi_checksum(dsdp, dsdp->len))
497
		errx(1, "DSDT is corrupt");
498
	acpi_handle_dsdt(dsdp);
499
	aml_dump(dsdp);
500
}
501
502
void
503
acpi_handle_rsdt(struct ACPIsdt *rsdp)
504
{
505
	int		i;
506
	int		entries;
507
	struct ACPIsdt	*sdp;
508
509
	aml_dump(rsdp);
510
	entries = (rsdp->len - SIZEOF_SDT_HDR) / sizeof(u_int32_t);
511
	acpi_print_rsdt(rsdp);
512
	for (i = 0; i < entries; i++) {
513
		sdp = (struct ACPIsdt *) acpi_map_sdt(rsdp->body[i]);
514
		if (acpi_checksum(sdp, sdp->len))
515
			errx(1, "RSDT entry %d is corrupt", i);
516
		aml_dump(sdp);
517
		if (!memcmp(sdp->signature, "FACP", 4)) {
518
			acpi_handle_facp((struct FACPbody *) sdp->body);
519
		} else {
520
			acpi_print_sdt(sdp);
521
		}
522
	}
523
}
524
525
void
526
asl_dump_from_devmem(void)
527
{
528
	struct ACPIrsdp	*rp;
529
	struct ACPIsdt	*rsdp;
530
	char		name[PATH_MAX];
531
532
	snprintf(name, sizeof(name), "%s.headers", aml_dumpfile);
533
534
	acpi_user_init();
535
536
	if (pledge("stdio rpath wpath cpath", NULL) == -1)
537
		err(1, "pledge");
538
539
	rp = acpi_find_rsd_ptr();
540
	if (!rp)
541
		errx(1, "Can't find ACPI information");
542
543
	fhdr = fopen(name, "w");
544
	if (fhdr == NULL)
545
		err(1, "asl_dump_from_devmem");
546
547
	acpi_print_rsd_ptr(rp);
548
	rsdp = (struct ACPIsdt *) acpi_map_sdt(rp->addr);
549
	if (memcmp(rsdp->signature, "RSDT", 4) ||
550
	    acpi_checksum(rsdp, rsdp->len))
551
		errx(1, "RSDT is corrupted");
552
553
	acpi_handle_rsdt(rsdp);
554
555
	fclose(fhdr);
556
}
557
558
void
559
usage(void)
560
{
561
	extern char	*__progname;
562
563
	fprintf(stderr, "usage: %s -o prefix_for_output\n", __progname);
564
	exit(1);
565
}
566
567
int
568
main(int argc, char *argv[])
569
{
570
	char		c;
571
572
	while ((c = getopt(argc, argv, "o:")) != -1) {
573
		switch (c) {
574
		case 'o':
575
			aml_dumpfile = optarg;
576
			break;
577
		default:
578
			usage();
579
			break;
580
		}
581
	}
582
583
	if (aml_dumpfile == NULL)
584
		usage();
585
586
	asl_dump_from_devmem();
587
588
	return (0);
589
}
590
591
u_long
592
bios_acpi_addr(void)
593
{
594
	kvm_t		*kd;
595
	struct nlist	 nl[2];
596
	bios_efiinfo_t	 efiinfo;
597
	u_long	 ptr;
598
599
	memset(&nl, 0, sizeof(nl));
600
	kd = kvm_openfiles(NULL, NULL, NULL, O_RDONLY, NULL);
601
	if (kd == NULL)
602
		goto on_error;
603
	nl[0].n_name = "_bios_efiinfo";
604
	if (kvm_nlist(kd, nl) == -1)
605
		goto on_error;
606
	if (kvm_read(kd, nl[0].n_value, &ptr, sizeof(ptr)) == -1)
607
		goto on_error;
608
	if (kvm_read(kd, ptr, &efiinfo, sizeof(efiinfo)) == -1)
609
		goto on_error;
610
611
	kvm_close(kd);
612
	return (efiinfo.config_acpi);
613
614
on_error:
615
	if (kd != NULL)
616
		kvm_close(kd);
617
	return (0);
618
}