GCC Code Coverage Report
Directory: ./ Exec Total Coverage
File: usr.sbin/acpidump/acpidump.c Lines: 0 217 0.0 %
Date: 2017-11-07 Branches: 0 120 0.0 %

Line Branch Exec Source
1
/*	$OpenBSD: acpidump.c,v 1.17 2016/09/26 19:58:26 kettenis 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
int		aml_dumpdir;
171
FILE		*fhdr;
172
173
int	acpi_checksum(void *_p, size_t _length);
174
struct acpi_user_mapping *acpi_user_find_mapping(vm_offset_t _pa, size_t _size);
175
void	*acpi_map_physical(vm_offset_t _pa, size_t _size);
176
void	acpi_user_init(void);
177
struct ACPIrsdp *acpi_find_rsd_ptr(void);
178
void	acpi_print_string(char *_s, size_t _length);
179
void	acpi_print_rsd_ptr(struct ACPIrsdp *_rp);
180
struct ACPIsdt *acpi_map_sdt(vm_offset_t _pa);
181
void	aml_dump(struct ACPIsdt *_hdr);
182
void	acpi_print_sdt(struct ACPIsdt *_sdp);
183
void	acpi_print_rsdt(struct ACPIsdt *_rsdp);
184
void	acpi_print_facp(struct FACPbody *_facp);
185
void	acpi_print_dsdt(struct ACPIsdt *_dsdp);
186
void	acpi_handle_dsdt(struct ACPIsdt *_dsdp);
187
void	acpi_handle_facp(struct FACPbody *_facp);
188
void	acpi_handle_rsdt(struct ACPIsdt *_rsdp);
189
void	asl_dump_from_devmem(void);
190
void	usage(void);
191
u_long	bios_acpi_addr(void);
192
193
194
struct ACPIsdt	dsdt_header = {
195
	"DSDT", 0, 1, 0, "OEMID", "OEMTBLID", 0x12345678, "CRTR", 0x12345678
196
};
197
198
int
199
acpi_checksum(void *p, size_t length)
200
{
201
	u_int8_t	*bp;
202
	u_int8_t	sum;
203
204
	bp = p;
205
	sum = 0;
206
	while (length--)
207
		sum += *bp++;
208
209
	return (sum);
210
}
211
212
struct acpi_user_mapping *
213
acpi_user_find_mapping(vm_offset_t pa, size_t size)
214
{
215
	struct acpi_user_mapping	*map;
216
	int	page_mask = getpagesize() - 1;
217
218
	/* First search for an existing mapping */
219
	for (map = LIST_FIRST(&maplist); map; map = LIST_NEXT(map, link)) {
220
		if (map->pa <= pa && map->size >= pa + size - map->pa)
221
			return (map);
222
	}
223
224
	/* Then create a new one */
225
#undef round_page
226
#undef trunc_page
227
#define	round_page(x)	(((x) + page_mask) & ~page_mask)
228
#define	trunc_page(x)	((x) & ~page_mask)
229
	size = round_page(pa + size) - trunc_page(pa);
230
	pa = trunc_page(pa);
231
#undef round_page
232
#undef trunc_page
233
	map = malloc(sizeof(struct acpi_user_mapping));
234
	if (!map)
235
		errx(1, "out of memory");
236
	map->pa = pa;
237
	map->va = mmap(0, size, PROT_READ, MAP_SHARED, acpi_mem_fd, pa);
238
	map->size = size;
239
	if (map->va == MAP_FAILED)
240
		err(1, "can't map address");
241
	LIST_INSERT_HEAD(&maplist, map, link);
242
243
	return (map);
244
}
245
246
void *
247
acpi_map_physical(vm_offset_t pa, size_t size)
248
{
249
	struct acpi_user_mapping	*map;
250
251
	map = acpi_user_find_mapping(pa, size);
252
	return (map->va + (pa - map->pa));
253
}
254
255
void
256
acpi_user_init(void)
257
{
258
	if (acpi_mem_fd == -1) {
259
		acpi_mem_fd = open("/dev/mem", O_RDONLY);
260
		if (acpi_mem_fd == -1)
261
			err(1, "opening /dev/mem");
262
		LIST_INIT(&maplist);
263
	}
264
}
265
266
struct ACPIrsdp *
267
acpi_find_rsd_ptr(void)
268
{
269
	int		i;
270
	u_int8_t	buf[sizeof(struct ACPIrsdp)];
271
	u_long		addr;
272
273
	if ((addr = bios_acpi_addr()) != 0) {
274
		lseek(acpi_mem_fd, addr, SEEK_SET);
275
		read(acpi_mem_fd, buf, 16);
276
		if (!memcmp(buf, "RSD PTR ", 8)) {
277
			read(acpi_mem_fd, buf + 16,
278
			    sizeof(struct ACPIrsdp) - 16);
279
			if (!acpi_checksum(buf, sizeof(struct ACPIrsdp)))
280
				return (acpi_map_physical(addr,
281
				    sizeof(struct ACPIrsdp)));
282
		}
283
		lseek(acpi_mem_fd, 0, SEEK_SET);
284
	}
285
	for (i = 0; i < 1024 * 1024; i += 16) {
286
		lseek(acpi_mem_fd, i, SEEK_SET);
287
		read(acpi_mem_fd, buf, 16);
288
		if (!memcmp(buf, "RSD PTR ", 8)) {
289
			/* Read the rest of the structure */
290
			read(acpi_mem_fd, buf + 16,
291
			    sizeof(struct ACPIrsdp) - 16);
292
293
			/* Verify checksum before accepting it. */
294
			if (acpi_checksum(buf, sizeof(struct ACPIrsdp)))
295
				continue;
296
297
			return (acpi_map_physical(i, sizeof(struct ACPIrsdp)));
298
		}
299
	}
300
301
	return (0);
302
}
303
304
void
305
acpi_print_string(char *s, size_t length)
306
{
307
	int		c;
308
309
	/* Trim trailing spaces and NULLs */
310
	while (length > 0 && (s[length - 1] == ' ' || s[length - 1] == '\0'))
311
		length--;
312
313
	while (length--) {
314
		c = *s++;
315
		fputc(c, fhdr);
316
	}
317
}
318
319
void
320
acpi_print_rsd_ptr(struct ACPIrsdp *rp)
321
{
322
	fprintf(fhdr, "\n");
323
	fprintf(fhdr, "RSD PTR: Checksum=%d, OEMID=", rp->sum);
324
	acpi_print_string(rp->oem, 6);
325
	fprintf(fhdr, ", RsdtAddress=0x%08x\n", rp->addr);
326
	fprintf(fhdr, "\n");
327
}
328
329
struct ACPIsdt *
330
acpi_map_sdt(vm_offset_t pa)
331
{
332
	struct ACPIsdt	*sp;
333
334
	sp = acpi_map_physical(pa, sizeof(struct ACPIsdt));
335
	sp = acpi_map_physical(pa, sp->len);
336
	return (sp);
337
}
338
339
void
340
aml_dump(struct ACPIsdt *hdr)
341
{
342
	static int	hdr_index;
343
	char		name[PATH_MAX];
344
	int		fd;
345
	mode_t		mode;
346
347
	snprintf(name, sizeof(name), "%s%c%c%c%c%c.%d",
348
	    aml_dumpfile, aml_dumpdir ? '/' : '.',
349
	    hdr->signature[0], hdr->signature[1],
350
	    hdr->signature[2], hdr->signature[3],
351
	    hdr_index++);
352
353
	mode = (S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH);
354
	fd = open(name, O_WRONLY | O_CREAT | O_TRUNC, mode);
355
	if (fd == -1)
356
		err(1, "aml_dump");
357
358
	write(fd, hdr, SIZEOF_SDT_HDR);
359
	write(fd, hdr->body, hdr->len - SIZEOF_SDT_HDR);
360
	close(fd);
361
}
362
363
void
364
acpi_print_sdt(struct ACPIsdt *sdp)
365
{
366
	fprintf(fhdr, "\n");
367
	acpi_print_string(sdp->signature, 4);
368
	fprintf(fhdr, ": Length=%d, Revision=%d, Checksum=%d,\n",
369
	       sdp->len, sdp->rev, sdp->check);
370
	fprintf(fhdr, "\tOEMID=");
371
	acpi_print_string(sdp->oemid, 6);
372
	fprintf(fhdr, ", OEM Table ID=");
373
	acpi_print_string(sdp->oemtblid, 8);
374
	fprintf(fhdr, ", OEM Revision=0x%x,\n", sdp->oemrev);
375
	fprintf(fhdr, "\tCreator ID=");
376
	acpi_print_string(sdp->creator, 4);
377
	fprintf(fhdr, ", Creator Revision=0x%x\n", sdp->crerev);
378
	fprintf(fhdr, "\n");
379
	if (!memcmp(sdp->signature, "DSDT", 4))
380
		memcpy(&dsdt_header, sdp, sizeof(dsdt_header));
381
}
382
383
void
384
acpi_print_rsdt(struct ACPIsdt *rsdp)
385
{
386
	int		i, entries;
387
388
	acpi_print_sdt(rsdp);
389
	entries = (rsdp->len - SIZEOF_SDT_HDR) / sizeof(u_int32_t);
390
	fprintf(fhdr, "\n");
391
	fprintf(fhdr, "\tEntries={ ");
392
	for (i = 0; i < entries; i++) {
393
		if (i > 0)
394
			fprintf(fhdr, ", ");
395
		fprintf(fhdr, "0x%08x", rsdp->body[i]);
396
	}
397
	fprintf(fhdr, " }\n");
398
	fprintf(fhdr, "\n");
399
}
400
401
void
402
acpi_print_facp(struct FACPbody *facp)
403
{
404
	char		sep;
405
406
	fprintf(fhdr, "\n");
407
	fprintf(fhdr, "\tDSDT=0x%x\n", facp->dsdt_ptr);
408
	fprintf(fhdr, "\tINT_MODEL=%s\n", facp->int_model ? "APIC" : "PIC");
409
	fprintf(fhdr, "\tSCI_INT=%d\n", facp->sci_int);
410
	fprintf(fhdr, "\tSMI_CMD=0x%x, ", facp->smi_cmd);
411
	fprintf(fhdr, "ACPI_ENABLE=0x%x, ", facp->acpi_enable);
412
	fprintf(fhdr, "ACPI_DISABLE=0x%x, ", facp->acpi_disable);
413
	fprintf(fhdr, "S4BIOS_REQ=0x%x\n", facp->s4biosreq);
414
	if (facp->pm1a_evt_blk)
415
		fprintf(fhdr, "\tPM1a_EVT_BLK=0x%x-0x%x\n",
416
		    facp->pm1a_evt_blk,
417
		    facp->pm1a_evt_blk + facp->pm1_evt_len - 1);
418
	if (facp->pm1b_evt_blk)
419
		fprintf(fhdr, "\tPM1b_EVT_BLK=0x%x-0x%x\n",
420
		    facp->pm1b_evt_blk,
421
		    facp->pm1b_evt_blk + facp->pm1_evt_len - 1);
422
	if (facp->pm1a_cnt_blk)
423
		fprintf(fhdr, "\tPM1a_CNT_BLK=0x%x-0x%x\n",
424
		    facp->pm1a_cnt_blk,
425
		    facp->pm1a_cnt_blk + facp->pm1_cnt_len - 1);
426
	if (facp->pm1b_cnt_blk)
427
		fprintf(fhdr, "\tPM1b_CNT_BLK=0x%x-0x%x\n",
428
		    facp->pm1b_cnt_blk,
429
		    facp->pm1b_cnt_blk + facp->pm1_cnt_len - 1);
430
	if (facp->pm2_cnt_blk)
431
		fprintf(fhdr, "\tPM2_CNT_BLK=0x%x-0x%x\n",
432
		    facp->pm2_cnt_blk,
433
		    facp->pm2_cnt_blk + facp->pm2_cnt_len - 1);
434
	if (facp->pm_tmr_blk)
435
		fprintf(fhdr, "\tPM2_TMR_BLK=0x%x-0x%x\n",
436
		    facp->pm_tmr_blk,
437
		    facp->pm_tmr_blk + facp->pm_tmr_len - 1);
438
	if (facp->gpe0_blk)
439
		fprintf(fhdr, "\tPM2_GPE0_BLK=0x%x-0x%x\n",
440
		    facp->gpe0_blk,
441
		    facp->gpe0_blk + facp->gpe0_len - 1);
442
	if (facp->gpe1_blk)
443
		fprintf(fhdr, "\tPM2_GPE1_BLK=0x%x-0x%x, GPE1_BASE=%d\n",
444
		    facp->gpe1_blk,
445
		    facp->gpe1_blk + facp->gpe1_len - 1,
446
		    facp->gpe1_base);
447
	fprintf(fhdr, "\tP_LVL2_LAT=%dms, P_LVL3_LAT=%dms\n",
448
	    facp->p_lvl2_lat, facp->p_lvl3_lat);
449
	fprintf(fhdr, "\tFLUSH_SIZE=%d, FLUSH_STRIDE=%d\n",
450
	    facp->flush_size, facp->flush_stride);
451
	fprintf(fhdr, "\tDUTY_OFFSET=%d, DUTY_WIDTH=%d\n",
452
	    facp->duty_off, facp->duty_width);
453
	fprintf(fhdr, "\tDAY_ALRM=%d, MON_ALRM=%d, CENTURY=%d\n",
454
	    facp->day_alrm, facp->mon_alrm, facp->century);
455
	fprintf(fhdr, "\tFlags=");
456
	sep = '{';
457
458
	PRINTFLAG(WBINVD);
459
	PRINTFLAG(WBINVD_FLUSH);
460
	PRINTFLAG(PROC_C1);
461
	PRINTFLAG(P_LVL2_UP);
462
	PRINTFLAG(PWR_BUTTON);
463
	PRINTFLAG(SLP_BUTTON);
464
	PRINTFLAG(FIX_RTC);
465
	PRINTFLAG(RTC_S4);
466
	PRINTFLAG(TMR_VAL_EXT);
467
	PRINTFLAG(DCK_CAP);
468
469
	fprintf(fhdr, "}\n");
470
	fprintf(fhdr, "\n");
471
}
472
473
void
474
acpi_print_dsdt(struct ACPIsdt *dsdp)
475
{
476
	acpi_print_sdt(dsdp);
477
}
478
479
void
480
acpi_handle_dsdt(struct ACPIsdt *dsdp)
481
{
482
	u_int8_t	*dp;
483
	u_int8_t	*end;
484
485
	acpi_print_dsdt(dsdp);
486
487
	dp = (u_int8_t *)dsdp->body;
488
	end = (u_int8_t *)dsdp + dsdp->len;
489
}
490
491
void
492
acpi_handle_facp(struct FACPbody *facp)
493
{
494
	struct ACPIsdt	*dsdp;
495
496
	acpi_print_facp(facp);
497
	dsdp = (struct ACPIsdt *) acpi_map_sdt(facp->dsdt_ptr);
498
	if (acpi_checksum(dsdp, dsdp->len))
499
		errx(1, "DSDT is corrupt");
500
	acpi_handle_dsdt(dsdp);
501
	aml_dump(dsdp);
502
}
503
504
void
505
acpi_handle_rsdt(struct ACPIsdt *rsdp)
506
{
507
	int		i;
508
	int		entries;
509
	struct ACPIsdt	*sdp;
510
511
	aml_dump(rsdp);
512
	entries = (rsdp->len - SIZEOF_SDT_HDR) / sizeof(u_int32_t);
513
	acpi_print_rsdt(rsdp);
514
	for (i = 0; i < entries; i++) {
515
		sdp = (struct ACPIsdt *) acpi_map_sdt(rsdp->body[i]);
516
		if (acpi_checksum(sdp, sdp->len))
517
			errx(1, "RSDT entry %d is corrupt", i);
518
		aml_dump(sdp);
519
		if (!memcmp(sdp->signature, "FACP", 4)) {
520
			acpi_handle_facp((struct FACPbody *) sdp->body);
521
		} else {
522
			acpi_print_sdt(sdp);
523
		}
524
	}
525
}
526
527
void
528
asl_dump_from_devmem(void)
529
{
530
	struct ACPIrsdp	*rp;
531
	struct ACPIsdt	*rsdp;
532
	char		name[PATH_MAX];
533
534
	snprintf(name, sizeof(name), "%s%cheaders", aml_dumpfile,
535
	    aml_dumpdir ? '/' : '.');
536
537
	acpi_user_init();
538
539
	if (pledge("stdio rpath wpath cpath flock", NULL) == -1)
540
		err(1, "pledge");
541
542
	rp = acpi_find_rsd_ptr();
543
	if (!rp)
544
		errx(1, "Can't find ACPI information");
545
546
	fhdr = fopen(name, "w");
547
	if (fhdr == NULL)
548
		err(1, "asl_dump_from_devmem");
549
550
	acpi_print_rsd_ptr(rp);
551
	rsdp = (struct ACPIsdt *) acpi_map_sdt(rp->addr);
552
	if (memcmp(rsdp->signature, "RSDT", 4) ||
553
	    acpi_checksum(rsdp, rsdp->len))
554
		errx(1, "RSDT is corrupted");
555
556
	acpi_handle_rsdt(rsdp);
557
558
	fclose(fhdr);
559
}
560
561
void
562
usage(void)
563
{
564
	extern char	*__progname;
565
566
	fprintf(stderr, "usage: %s -o prefix\n", __progname);
567
	exit(1);
568
}
569
570
int
571
main(int argc, char *argv[])
572
{
573
	struct stat	st;
574
	char		c;
575
576
	while ((c = getopt(argc, argv, "o:")) != -1) {
577
		switch (c) {
578
		case 'o':
579
			aml_dumpfile = optarg;
580
			break;
581
		default:
582
			usage();
583
			break;
584
		}
585
	}
586
587
	if (aml_dumpfile == NULL)
588
		usage();
589
590
	if (stat(aml_dumpfile, &st) == 0 && S_ISDIR(st.st_mode))
591
		aml_dumpdir = 1;
592
593
	asl_dump_from_devmem();
594
595
	return (0);
596
}
597
598
u_long
599
bios_acpi_addr(void)
600
{
601
	kvm_t		*kd;
602
	struct nlist	 nl[2];
603
	bios_efiinfo_t	 efiinfo;
604
	u_long	 ptr;
605
606
	memset(&nl, 0, sizeof(nl));
607
	kd = kvm_openfiles(NULL, NULL, NULL, O_RDONLY, NULL);
608
	if (kd == NULL)
609
		goto on_error;
610
	nl[0].n_name = "_bios_efiinfo";
611
	if (kvm_nlist(kd, nl) == -1)
612
		goto on_error;
613
	if (kvm_read(kd, nl[0].n_value, &ptr, sizeof(ptr)) == -1)
614
		goto on_error;
615
	if (kvm_read(kd, ptr, &efiinfo, sizeof(efiinfo)) == -1)
616
		goto on_error;
617
618
	kvm_close(kd);
619
	return (efiinfo.config_acpi);
620
621
on_error:
622
	if (kd != NULL)
623
		kvm_close(kd);
624
	return (0);
625
}