1*c3c82401Skettenis /* $OpenBSD: acpidump.c,v 1.25 2022/09/11 10:40:35 kettenis Exp $ */
212793204Smarco /*
37934d707Stholo * Copyright (c) 2000 Mitsuru IWASAKI <iwasaki@FreeBSD.org>
47934d707Stholo * All rights reserved.
57934d707Stholo *
67934d707Stholo * Redistribution and use in source and binary forms, with or without
77934d707Stholo * modification, are permitted provided that the following conditions
87934d707Stholo * are met:
97934d707Stholo * 1. Redistributions of source code must retain the above copyright
107934d707Stholo * notice, this list of conditions and the following disclaimer.
117934d707Stholo * 2. Redistributions in binary form must reproduce the above copyright
127934d707Stholo * notice, this list of conditions and the following disclaimer in the
137934d707Stholo * documentation and/or other materials provided with the distribution.
147934d707Stholo *
157934d707Stholo * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
167934d707Stholo * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
177934d707Stholo * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
187934d707Stholo * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
197934d707Stholo * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
207934d707Stholo * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
217934d707Stholo * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
227934d707Stholo * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
237934d707Stholo * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
247934d707Stholo * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
257934d707Stholo * SUCH DAMAGE.
267934d707Stholo *
277934d707Stholo */
287934d707Stholo
297934d707Stholo #include <sys/types.h>
30d0c9fa7cSderaadt #include <sys/mman.h>
31d0c9fa7cSderaadt #include <sys/queue.h>
32d0c9fa7cSderaadt #include <sys/stat.h>
33d0c9fa7cSderaadt
347934d707Stholo #include <assert.h>
357934d707Stholo #include <err.h>
3612793204Smarco #include <fcntl.h>
3788448ec7Syasuoka #include <kvm.h>
387934d707Stholo #include <stdio.h>
3912793204Smarco #include <stdlib.h>
4087e993edSmiod #include <string.h>
417934d707Stholo #include <unistd.h>
42d0c9fa7cSderaadt #include <limits.h>
43bc30430aSderaadt #include <paths.h>
447934d707Stholo
4512793204Smarco
4612793204Smarco #define vm_page_size sysconf(_SC_PAGESIZE)
4712793204Smarco #define PRINTFLAG(xx) \
4812793204Smarco do { \
4912793204Smarco if (facp->flags & ACPI_FACP_FLAG_## xx) { \
5012793204Smarco fprintf(fhdr, "%c%s", sep, #xx); sep = ','; \
5112793204Smarco } \
5212793204Smarco } while (0)
5312793204Smarco
5412793204Smarco
5512793204Smarco typedef unsigned long vm_offset_t;
5612793204Smarco
5712793204Smarco struct ACPIrsdp {
5812793204Smarco u_char signature[8];
5912793204Smarco u_char sum;
6012793204Smarco u_char oem[6];
616988a5d7Skettenis u_char rev;
6212793204Smarco u_int32_t addr;
636988a5d7Skettenis #define SIZEOF_RSDP_REV_0 20
646988a5d7Skettenis u_int32_t len;
656988a5d7Skettenis u_int64_t xaddr;
666988a5d7Skettenis u_char xsum;
676988a5d7Skettenis u_char xres[3];
6812793204Smarco } __packed;
6912793204Smarco
7012793204Smarco struct ACPIsdt {
7112793204Smarco u_char signature[4];
7212793204Smarco u_int32_t len;
7312793204Smarco u_char rev;
7412793204Smarco u_char check;
7512793204Smarco u_char oemid[6];
7612793204Smarco u_char oemtblid[8];
7712793204Smarco u_int32_t oemrev;
7812793204Smarco u_char creator[4];
7912793204Smarco u_int32_t crerev;
8012793204Smarco #define SIZEOF_SDT_HDR 36 /* struct size except body */
8112793204Smarco u_int32_t body[1];/* This member should be casted */
8212793204Smarco } __packed;
8312793204Smarco
8412793204Smarco struct ACPIgas {
8512793204Smarco u_int8_t address_space_id;
8612793204Smarco #define ACPI_GAS_MEMORY 0
8712793204Smarco #define ACPI_GAS_IO 1
8812793204Smarco #define ACPI_GAS_PCI 2
8912793204Smarco #define ACPI_GAS_EMBEDDED 3
9012793204Smarco #define ACPI_GAS_SMBUS 4
9112793204Smarco #define ACPI_GAS_FIXED 0x7f
9212793204Smarco u_int8_t register_bit_width;
9312793204Smarco u_int8_t register_bit_offset;
9412793204Smarco u_int8_t res;
9512793204Smarco u_int64_t address;
9612793204Smarco } __packed;
9712793204Smarco
9812793204Smarco struct FACPbody {
9912793204Smarco u_int32_t facs_ptr;
10012793204Smarco u_int32_t dsdt_ptr;
10112793204Smarco u_int8_t int_model;
10212793204Smarco #define ACPI_FACP_INTMODEL_PIC 0 /* Standard PC-AT PIC */
10312793204Smarco #define ACPI_FACP_INTMODEL_APIC 1 /* Multiple APIC */
10412793204Smarco u_char reserved1;
10512793204Smarco u_int16_t sci_int;
10612793204Smarco u_int32_t smi_cmd;
10712793204Smarco u_int8_t acpi_enable;
10812793204Smarco u_int8_t acpi_disable;
10912793204Smarco u_int8_t s4biosreq;
11012793204Smarco u_int8_t reserved2;
11112793204Smarco u_int32_t pm1a_evt_blk;
11212793204Smarco u_int32_t pm1b_evt_blk;
11312793204Smarco u_int32_t pm1a_cnt_blk;
11412793204Smarco u_int32_t pm1b_cnt_blk;
11512793204Smarco u_int32_t pm2_cnt_blk;
11612793204Smarco u_int32_t pm_tmr_blk;
11712793204Smarco u_int32_t gpe0_blk;
11812793204Smarco u_int32_t gpe1_blk;
11912793204Smarco u_int8_t pm1_evt_len;
12012793204Smarco u_int8_t pm1_cnt_len;
12112793204Smarco u_int8_t pm2_cnt_len;
12212793204Smarco u_int8_t pm_tmr_len;
12312793204Smarco u_int8_t gpe0_len;
12412793204Smarco u_int8_t gpe1_len;
12512793204Smarco u_int8_t gpe1_base;
12612793204Smarco u_int8_t reserved3;
12712793204Smarco u_int16_t p_lvl2_lat;
12812793204Smarco u_int16_t p_lvl3_lat;
12912793204Smarco u_int16_t flush_size;
13012793204Smarco u_int16_t flush_stride;
13112793204Smarco u_int8_t duty_off;
13212793204Smarco u_int8_t duty_width;
13312793204Smarco u_int8_t day_alrm;
13412793204Smarco u_int8_t mon_alrm;
13512793204Smarco u_int8_t century;
13612793204Smarco u_int16_t iapc_boot_arch;
13712793204Smarco u_char reserved4[1];
13812793204Smarco u_int32_t flags;
13912793204Smarco #define ACPI_FACP_FLAG_WBINVD 1 /* WBINVD is correctly supported */
14012793204Smarco #define ACPI_FACP_FLAG_WBINVD_FLUSH 2 /* WBINVD flushes caches */
14112793204Smarco #define ACPI_FACP_FLAG_PROC_C1 4 /* C1 power state supported */
14212793204Smarco #define ACPI_FACP_FLAG_P_LVL2_UP 8 /* C2 power state works on SMP */
14312793204Smarco #define ACPI_FACP_FLAG_PWR_BUTTON 16 /* Power button uses control method */
14412793204Smarco #define ACPI_FACP_FLAG_SLP_BUTTON 32 /* Sleep button uses control method */
14512793204Smarco #define ACPI_FACP_FLAG_FIX_RTC 64 /* RTC wakeup not supported */
14612793204Smarco #define ACPI_FACP_FLAG_RTC_S4 128 /* RTC can wakeup from S4 state */
14712793204Smarco #define ACPI_FACP_FLAG_TMR_VAL_EXT 256 /* TMR_VAL is 32bit */
14812793204Smarco #define ACPI_FACP_FLAG_DCK_CAP 512 /* Can support docking */
14912793204Smarco struct ACPIgas reset_reg;
15012793204Smarco u_int8_t reset_value;
15112793204Smarco u_int8_t reserved5[3];
15212793204Smarco u_int64_t x_firmware_ctrl;
15312793204Smarco u_int64_t x_dsdt;
15412793204Smarco struct ACPIgas x_pm1a_evt_blk;
15512793204Smarco struct ACPIgas x_pm1b_evt_blk;
15612793204Smarco struct ACPIgas x_pm1a_cnt_blk;
15712793204Smarco struct ACPIgas x_pm1b_cnt_blk;
15812793204Smarco struct ACPIgas x_pm2_cnt_blk;
15912793204Smarco struct ACPIgas x_pm_tmr_blk;
16012793204Smarco struct ACPIgas x_gpe0_blk;
16112793204Smarco struct ACPIgas x_gpe1_blk;
16212793204Smarco } __packed;
16312793204Smarco
16412793204Smarco struct acpi_user_mapping {
16512793204Smarco LIST_ENTRY(acpi_user_mapping) link;
16612793204Smarco vm_offset_t pa;
16712793204Smarco caddr_t va;
16812793204Smarco size_t size;
16912793204Smarco };
17012793204Smarco
17112793204Smarco LIST_HEAD(acpi_user_mapping_list, acpi_user_mapping) maplist;
17212793204Smarco
17312793204Smarco int acpi_mem_fd = -1;
17412793204Smarco char *aml_dumpfile;
175c8dab64cSkettenis int aml_dumpdir;
17612793204Smarco FILE *fhdr;
17717033bfcSkettenis int quiet;
17812793204Smarco
1790a667195Sderaadt int acpi_checksum(void *_p, size_t _length);
1800a667195Sderaadt struct acpi_user_mapping *acpi_user_find_mapping(vm_offset_t _pa, size_t _size);
1810a667195Sderaadt void *acpi_map_physical(vm_offset_t _pa, size_t _size);
1820a667195Sderaadt void acpi_user_init(void);
1836988a5d7Skettenis struct ACPIrsdp *acpi_check_rsd_ptr(vm_offset_t _pa);
1840a667195Sderaadt struct ACPIrsdp *acpi_find_rsd_ptr(void);
1850a667195Sderaadt void acpi_print_string(char *_s, size_t _length);
1860a667195Sderaadt void acpi_print_rsd_ptr(struct ACPIrsdp *_rp);
1870a667195Sderaadt struct ACPIsdt *acpi_map_sdt(vm_offset_t _pa);
1880a667195Sderaadt void aml_dump(struct ACPIsdt *_hdr);
1890a667195Sderaadt void acpi_print_sdt(struct ACPIsdt *_sdp);
1900a667195Sderaadt void acpi_print_rsdt(struct ACPIsdt *_rsdp);
1916988a5d7Skettenis void acpi_print_xsdt(struct ACPIsdt *_rsdp);
1920a667195Sderaadt void acpi_print_facp(struct FACPbody *_facp);
1930a667195Sderaadt void acpi_print_dsdt(struct ACPIsdt *_dsdp);
1940a667195Sderaadt void acpi_handle_dsdt(struct ACPIsdt *_dsdp);
1950a667195Sderaadt void acpi_handle_facp(struct FACPbody *_facp);
1960a667195Sderaadt void acpi_handle_rsdt(struct ACPIsdt *_rsdp);
1976988a5d7Skettenis void acpi_handle_xsdt(struct ACPIsdt *_rsdp);
1980a667195Sderaadt void asl_dump_from_devmem(void);
1990a667195Sderaadt void usage(void);
2006988a5d7Skettenis u_long efi_acpi_addr(void);
2010a667195Sderaadt
2020a667195Sderaadt
20312793204Smarco struct ACPIsdt dsdt_header = {
20412793204Smarco "DSDT", 0, 1, 0, "OEMID", "OEMTBLID", 0x12345678, "CRTR", 0x12345678
20512793204Smarco };
20612793204Smarco
20712793204Smarco int
acpi_checksum(void * p,size_t length)20812793204Smarco acpi_checksum(void *p, size_t length)
20912793204Smarco {
21012793204Smarco u_int8_t *bp;
21112793204Smarco u_int8_t sum;
21212793204Smarco
21312793204Smarco bp = p;
21412793204Smarco sum = 0;
21512793204Smarco while (length--)
21612793204Smarco sum += *bp++;
21712793204Smarco
21812793204Smarco return (sum);
21912793204Smarco }
22012793204Smarco
22112793204Smarco struct acpi_user_mapping *
acpi_user_find_mapping(vm_offset_t pa,size_t size)22212793204Smarco acpi_user_find_mapping(vm_offset_t pa, size_t size)
22312793204Smarco {
22412793204Smarco struct acpi_user_mapping *map;
225fadb1e41Sderaadt int page_mask = getpagesize() - 1;
22612793204Smarco
22712793204Smarco /* First search for an existing mapping */
22812793204Smarco for (map = LIST_FIRST(&maplist); map; map = LIST_NEXT(map, link)) {
22912793204Smarco if (map->pa <= pa && map->size >= pa + size - map->pa)
23012793204Smarco return (map);
23112793204Smarco }
23212793204Smarco
23312793204Smarco /* Then create a new one */
234fadb1e41Sderaadt #undef round_page
235fadb1e41Sderaadt #undef trunc_page
236fadb1e41Sderaadt #define round_page(x) (((x) + page_mask) & ~page_mask)
237fadb1e41Sderaadt #define trunc_page(x) ((x) & ~page_mask)
23812793204Smarco size = round_page(pa + size) - trunc_page(pa);
23912793204Smarco pa = trunc_page(pa);
240fadb1e41Sderaadt #undef round_page
241fadb1e41Sderaadt #undef trunc_page
24212793204Smarco map = malloc(sizeof(struct acpi_user_mapping));
24312793204Smarco if (!map)
24412793204Smarco errx(1, "out of memory");
24512793204Smarco map->pa = pa;
24612793204Smarco map->va = mmap(0, size, PROT_READ, MAP_SHARED, acpi_mem_fd, pa);
24712793204Smarco map->size = size;
24812793204Smarco if (map->va == MAP_FAILED)
24912793204Smarco err(1, "can't map address");
25012793204Smarco LIST_INSERT_HEAD(&maplist, map, link);
25112793204Smarco
25212793204Smarco return (map);
25312793204Smarco }
25412793204Smarco
25512793204Smarco void *
acpi_map_physical(vm_offset_t pa,size_t size)25612793204Smarco acpi_map_physical(vm_offset_t pa, size_t size)
25712793204Smarco {
25812793204Smarco struct acpi_user_mapping *map;
25912793204Smarco
26012793204Smarco map = acpi_user_find_mapping(pa, size);
26112793204Smarco return (map->va + (pa - map->pa));
26212793204Smarco }
26312793204Smarco
26412793204Smarco void
acpi_user_init(void)26512793204Smarco acpi_user_init(void)
26612793204Smarco {
26712793204Smarco if (acpi_mem_fd == -1) {
26812793204Smarco acpi_mem_fd = open("/dev/mem", O_RDONLY);
26912793204Smarco if (acpi_mem_fd == -1)
27012793204Smarco err(1, "opening /dev/mem");
27112793204Smarco LIST_INIT(&maplist);
27212793204Smarco }
27312793204Smarco }
27412793204Smarco
27512793204Smarco struct ACPIrsdp *
acpi_check_rsd_ptr(vm_offset_t pa)2766988a5d7Skettenis acpi_check_rsd_ptr(vm_offset_t pa)
2776988a5d7Skettenis {
2786988a5d7Skettenis struct ACPIrsdp rp;
2796988a5d7Skettenis
2806988a5d7Skettenis lseek(acpi_mem_fd, pa, SEEK_SET);
2816988a5d7Skettenis read(acpi_mem_fd, &rp, SIZEOF_RSDP_REV_0);
2826988a5d7Skettenis if (memcmp(rp.signature, "RSD PTR ", 8) != 0)
2836988a5d7Skettenis return NULL;
2846988a5d7Skettenis
2856988a5d7Skettenis if (rp.rev >= 2) {
2866988a5d7Skettenis read(acpi_mem_fd, &(rp.len),
2876988a5d7Skettenis sizeof(struct ACPIrsdp) - SIZEOF_RSDP_REV_0);
2886988a5d7Skettenis if (acpi_checksum(&rp, sizeof(struct ACPIrsdp)) == 0)
2896988a5d7Skettenis return acpi_map_physical(pa, sizeof(struct ACPIrsdp));
2906988a5d7Skettenis }
2916988a5d7Skettenis
2926988a5d7Skettenis if (acpi_checksum(&rp, SIZEOF_RSDP_REV_0) == 0)
2936988a5d7Skettenis return (acpi_map_physical(pa, SIZEOF_RSDP_REV_0));
2946988a5d7Skettenis
2956988a5d7Skettenis return NULL;
2966988a5d7Skettenis }
2976988a5d7Skettenis
2986988a5d7Skettenis struct ACPIrsdp *
acpi_find_rsd_ptr(void)2990a667195Sderaadt acpi_find_rsd_ptr(void)
30012793204Smarco {
3016988a5d7Skettenis struct ACPIrsdp *rp;
30288448ec7Syasuoka u_long addr;
30312793204Smarco
3046988a5d7Skettenis if ((addr = efi_acpi_addr()) != 0) {
3056988a5d7Skettenis if ((rp = acpi_check_rsd_ptr(addr)))
3066988a5d7Skettenis return rp;
30712793204Smarco }
30812793204Smarco
3096988a5d7Skettenis #if defined(__amd64__) || defined (__i386__)
3106988a5d7Skettenis for (addr = 0; addr < 1024 * 1024; addr += 16) {
3116988a5d7Skettenis if ((rp = acpi_check_rsd_ptr(addr)))
3126988a5d7Skettenis return rp;
3136988a5d7Skettenis }
3146988a5d7Skettenis #endif
3156988a5d7Skettenis
3166988a5d7Skettenis return NULL;
31712793204Smarco }
31812793204Smarco
31912793204Smarco void
acpi_print_string(char * s,size_t length)32012793204Smarco acpi_print_string(char *s, size_t length)
32112793204Smarco {
32212793204Smarco int c;
32312793204Smarco
32412793204Smarco /* Trim trailing spaces and NULLs */
32512793204Smarco while (length > 0 && (s[length - 1] == ' ' || s[length - 1] == '\0'))
32612793204Smarco length--;
32712793204Smarco
32812793204Smarco while (length--) {
32912793204Smarco c = *s++;
33012793204Smarco fputc(c, fhdr);
33112793204Smarco }
33212793204Smarco }
33312793204Smarco
33412793204Smarco void
acpi_print_rsd_ptr(struct ACPIrsdp * rp)33512793204Smarco acpi_print_rsd_ptr(struct ACPIrsdp *rp)
33612793204Smarco {
33712793204Smarco fprintf(fhdr, "\n");
33812793204Smarco fprintf(fhdr, "RSD PTR: Checksum=%d, OEMID=", rp->sum);
33912793204Smarco acpi_print_string(rp->oem, 6);
3406988a5d7Skettenis fprintf(fhdr, ", Revision=%d", rp->rev);
34112793204Smarco fprintf(fhdr, ", RsdtAddress=0x%08x\n", rp->addr);
3426988a5d7Skettenis if (rp->rev >= 2) {
3436988a5d7Skettenis fprintf(fhdr, "\tLength=%d", rp->len);
3446988a5d7Skettenis fprintf(fhdr, ", XsdtAddress=0x%016llx", rp->xaddr);
3456988a5d7Skettenis fprintf(fhdr, ", Extended Checksum=%d\n", rp->xsum);
3466988a5d7Skettenis }
34712793204Smarco fprintf(fhdr, "\n");
34812793204Smarco }
34912793204Smarco
35012793204Smarco struct ACPIsdt *
acpi_map_sdt(vm_offset_t pa)35112793204Smarco acpi_map_sdt(vm_offset_t pa)
35212793204Smarco {
35312793204Smarco struct ACPIsdt *sp;
35412793204Smarco
35512793204Smarco sp = acpi_map_physical(pa, sizeof(struct ACPIsdt));
35612793204Smarco sp = acpi_map_physical(pa, sp->len);
35712793204Smarco return (sp);
35812793204Smarco }
35912793204Smarco
36012793204Smarco void
aml_dump(struct ACPIsdt * hdr)36112793204Smarco aml_dump(struct ACPIsdt *hdr)
36212793204Smarco {
36312793204Smarco static int hdr_index;
36412793204Smarco char name[PATH_MAX];
36512793204Smarco int fd;
36612793204Smarco mode_t mode;
36712793204Smarco
368c8dab64cSkettenis snprintf(name, sizeof(name), "%s%c%c%c%c%c.%d",
369c8dab64cSkettenis aml_dumpfile, aml_dumpdir ? '/' : '.',
370c8dab64cSkettenis hdr->signature[0], hdr->signature[1],
37112793204Smarco hdr->signature[2], hdr->signature[3],
37212793204Smarco hdr_index++);
37312793204Smarco
37412793204Smarco mode = (S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH);
37512793204Smarco fd = open(name, O_WRONLY | O_CREAT | O_TRUNC, mode);
37612793204Smarco if (fd == -1)
37712793204Smarco err(1, "aml_dump");
37812793204Smarco
37912793204Smarco write(fd, hdr, SIZEOF_SDT_HDR);
38012793204Smarco write(fd, hdr->body, hdr->len - SIZEOF_SDT_HDR);
38112793204Smarco close(fd);
38212793204Smarco }
38312793204Smarco
38412793204Smarco void
acpi_print_sdt(struct ACPIsdt * sdp)38512793204Smarco acpi_print_sdt(struct ACPIsdt *sdp)
38612793204Smarco {
38712793204Smarco fprintf(fhdr, "\n");
38812793204Smarco acpi_print_string(sdp->signature, 4);
38912793204Smarco fprintf(fhdr, ": Length=%d, Revision=%d, Checksum=%d,\n",
39012793204Smarco sdp->len, sdp->rev, sdp->check);
39112793204Smarco fprintf(fhdr, "\tOEMID=");
39212793204Smarco acpi_print_string(sdp->oemid, 6);
39312793204Smarco fprintf(fhdr, ", OEM Table ID=");
39412793204Smarco acpi_print_string(sdp->oemtblid, 8);
39512793204Smarco fprintf(fhdr, ", OEM Revision=0x%x,\n", sdp->oemrev);
39612793204Smarco fprintf(fhdr, "\tCreator ID=");
39712793204Smarco acpi_print_string(sdp->creator, 4);
39812793204Smarco fprintf(fhdr, ", Creator Revision=0x%x\n", sdp->crerev);
39912793204Smarco fprintf(fhdr, "\n");
40012793204Smarco if (!memcmp(sdp->signature, "DSDT", 4))
40112793204Smarco memcpy(&dsdt_header, sdp, sizeof(dsdt_header));
40212793204Smarco }
40312793204Smarco
40412793204Smarco void
acpi_print_rsdt(struct ACPIsdt * rsdp)40512793204Smarco acpi_print_rsdt(struct ACPIsdt *rsdp)
40612793204Smarco {
40712793204Smarco int i, entries;
40812793204Smarco
40912793204Smarco acpi_print_sdt(rsdp);
41012793204Smarco entries = (rsdp->len - SIZEOF_SDT_HDR) / sizeof(u_int32_t);
41112793204Smarco fprintf(fhdr, "\n");
41212793204Smarco fprintf(fhdr, "\tEntries={ ");
41312793204Smarco for (i = 0; i < entries; i++) {
41412793204Smarco if (i > 0)
41512793204Smarco fprintf(fhdr, ", ");
41612793204Smarco fprintf(fhdr, "0x%08x", rsdp->body[i]);
41712793204Smarco }
41812793204Smarco fprintf(fhdr, " }\n");
41912793204Smarco fprintf(fhdr, "\n");
42012793204Smarco }
42112793204Smarco
42212793204Smarco void
acpi_print_xsdt(struct ACPIsdt * rsdp)4236988a5d7Skettenis acpi_print_xsdt(struct ACPIsdt *rsdp)
4246988a5d7Skettenis {
4256988a5d7Skettenis int i, entries;
4266988a5d7Skettenis u_int64_t *body = (u_int64_t *) rsdp->body;
4276988a5d7Skettenis
4286988a5d7Skettenis acpi_print_sdt(rsdp);
4296988a5d7Skettenis entries = (rsdp->len - SIZEOF_SDT_HDR) / sizeof(u_int64_t);
4306988a5d7Skettenis fprintf(fhdr, "\n");
4316988a5d7Skettenis fprintf(fhdr, "\tEntries={ ");
4326988a5d7Skettenis for (i = 0; i < entries; i++) {
4336988a5d7Skettenis if (i > 0)
4346988a5d7Skettenis fprintf(fhdr, ", ");
4356988a5d7Skettenis fprintf(fhdr, "0x%016llx", body[i]);
4366988a5d7Skettenis }
4376988a5d7Skettenis fprintf(fhdr, " }\n");
4386988a5d7Skettenis fprintf(fhdr, "\n");
4396988a5d7Skettenis }
4406988a5d7Skettenis
4416988a5d7Skettenis void
acpi_print_facp(struct FACPbody * facp)44212793204Smarco acpi_print_facp(struct FACPbody *facp)
44312793204Smarco {
44412793204Smarco char sep;
44512793204Smarco
44612793204Smarco fprintf(fhdr, "\n");
44712793204Smarco fprintf(fhdr, "\tDSDT=0x%x\n", facp->dsdt_ptr);
44812793204Smarco fprintf(fhdr, "\tINT_MODEL=%s\n", facp->int_model ? "APIC" : "PIC");
44912793204Smarco fprintf(fhdr, "\tSCI_INT=%d\n", facp->sci_int);
45012793204Smarco fprintf(fhdr, "\tSMI_CMD=0x%x, ", facp->smi_cmd);
45112793204Smarco fprintf(fhdr, "ACPI_ENABLE=0x%x, ", facp->acpi_enable);
45212793204Smarco fprintf(fhdr, "ACPI_DISABLE=0x%x, ", facp->acpi_disable);
45312793204Smarco fprintf(fhdr, "S4BIOS_REQ=0x%x\n", facp->s4biosreq);
45412793204Smarco if (facp->pm1a_evt_blk)
45512793204Smarco fprintf(fhdr, "\tPM1a_EVT_BLK=0x%x-0x%x\n",
45612793204Smarco facp->pm1a_evt_blk,
45712793204Smarco facp->pm1a_evt_blk + facp->pm1_evt_len - 1);
45812793204Smarco if (facp->pm1b_evt_blk)
45912793204Smarco fprintf(fhdr, "\tPM1b_EVT_BLK=0x%x-0x%x\n",
46012793204Smarco facp->pm1b_evt_blk,
46112793204Smarco facp->pm1b_evt_blk + facp->pm1_evt_len - 1);
46212793204Smarco if (facp->pm1a_cnt_blk)
46312793204Smarco fprintf(fhdr, "\tPM1a_CNT_BLK=0x%x-0x%x\n",
46412793204Smarco facp->pm1a_cnt_blk,
46512793204Smarco facp->pm1a_cnt_blk + facp->pm1_cnt_len - 1);
46612793204Smarco if (facp->pm1b_cnt_blk)
46712793204Smarco fprintf(fhdr, "\tPM1b_CNT_BLK=0x%x-0x%x\n",
46812793204Smarco facp->pm1b_cnt_blk,
46912793204Smarco facp->pm1b_cnt_blk + facp->pm1_cnt_len - 1);
47012793204Smarco if (facp->pm2_cnt_blk)
47112793204Smarco fprintf(fhdr, "\tPM2_CNT_BLK=0x%x-0x%x\n",
47212793204Smarco facp->pm2_cnt_blk,
47312793204Smarco facp->pm2_cnt_blk + facp->pm2_cnt_len - 1);
47412793204Smarco if (facp->pm_tmr_blk)
47512793204Smarco fprintf(fhdr, "\tPM2_TMR_BLK=0x%x-0x%x\n",
47612793204Smarco facp->pm_tmr_blk,
47712793204Smarco facp->pm_tmr_blk + facp->pm_tmr_len - 1);
47812793204Smarco if (facp->gpe0_blk)
47912793204Smarco fprintf(fhdr, "\tPM2_GPE0_BLK=0x%x-0x%x\n",
48012793204Smarco facp->gpe0_blk,
48112793204Smarco facp->gpe0_blk + facp->gpe0_len - 1);
48212793204Smarco if (facp->gpe1_blk)
48312793204Smarco fprintf(fhdr, "\tPM2_GPE1_BLK=0x%x-0x%x, GPE1_BASE=%d\n",
48412793204Smarco facp->gpe1_blk,
48512793204Smarco facp->gpe1_blk + facp->gpe1_len - 1,
48612793204Smarco facp->gpe1_base);
48712793204Smarco fprintf(fhdr, "\tP_LVL2_LAT=%dms, P_LVL3_LAT=%dms\n",
48812793204Smarco facp->p_lvl2_lat, facp->p_lvl3_lat);
48912793204Smarco fprintf(fhdr, "\tFLUSH_SIZE=%d, FLUSH_STRIDE=%d\n",
49012793204Smarco facp->flush_size, facp->flush_stride);
49112793204Smarco fprintf(fhdr, "\tDUTY_OFFSET=%d, DUTY_WIDTH=%d\n",
49212793204Smarco facp->duty_off, facp->duty_width);
49312793204Smarco fprintf(fhdr, "\tDAY_ALRM=%d, MON_ALRM=%d, CENTURY=%d\n",
49412793204Smarco facp->day_alrm, facp->mon_alrm, facp->century);
49512793204Smarco fprintf(fhdr, "\tFlags=");
49612793204Smarco sep = '{';
49712793204Smarco
49812793204Smarco PRINTFLAG(WBINVD);
49912793204Smarco PRINTFLAG(WBINVD_FLUSH);
50012793204Smarco PRINTFLAG(PROC_C1);
50112793204Smarco PRINTFLAG(P_LVL2_UP);
50212793204Smarco PRINTFLAG(PWR_BUTTON);
50312793204Smarco PRINTFLAG(SLP_BUTTON);
50412793204Smarco PRINTFLAG(FIX_RTC);
50512793204Smarco PRINTFLAG(RTC_S4);
50612793204Smarco PRINTFLAG(TMR_VAL_EXT);
50712793204Smarco PRINTFLAG(DCK_CAP);
50812793204Smarco
50912793204Smarco fprintf(fhdr, "}\n");
51012793204Smarco fprintf(fhdr, "\n");
51112793204Smarco }
51212793204Smarco
51312793204Smarco void
acpi_print_dsdt(struct ACPIsdt * dsdp)51412793204Smarco acpi_print_dsdt(struct ACPIsdt *dsdp)
51512793204Smarco {
51612793204Smarco acpi_print_sdt(dsdp);
51712793204Smarco }
51812793204Smarco
51912793204Smarco void
acpi_handle_dsdt(struct ACPIsdt * dsdp)52012793204Smarco acpi_handle_dsdt(struct ACPIsdt *dsdp)
5217934d707Stholo {
5227934d707Stholo u_int8_t *dp;
5237934d707Stholo u_int8_t *end;
5247934d707Stholo
52512793204Smarco acpi_print_dsdt(dsdp);
52612793204Smarco
52712793204Smarco dp = (u_int8_t *)dsdp->body;
52812793204Smarco end = (u_int8_t *)dsdp + dsdp->len;
5297934d707Stholo }
5307934d707Stholo
53112793204Smarco void
acpi_handle_facp(struct FACPbody * facp)53212793204Smarco acpi_handle_facp(struct FACPbody *facp)
53312793204Smarco {
53412793204Smarco struct ACPIsdt *dsdp;
53512793204Smarco
53612793204Smarco acpi_print_facp(facp);
537113b2535Skettenis if (facp->dsdt_ptr == 0)
538113b2535Skettenis dsdp = (struct ACPIsdt *) acpi_map_sdt(facp->x_dsdt);
539113b2535Skettenis else
54012793204Smarco dsdp = (struct ACPIsdt *) acpi_map_sdt(facp->dsdt_ptr);
54112793204Smarco if (acpi_checksum(dsdp, dsdp->len))
54212793204Smarco errx(1, "DSDT is corrupt");
54312793204Smarco acpi_handle_dsdt(dsdp);
54412793204Smarco aml_dump(dsdp);
54512793204Smarco }
54612793204Smarco
54712793204Smarco void
acpi_handle_rsdt(struct ACPIsdt * rsdp)54812793204Smarco acpi_handle_rsdt(struct ACPIsdt *rsdp)
54912793204Smarco {
55012793204Smarco int i;
55112793204Smarco int entries;
55212793204Smarco struct ACPIsdt *sdp;
55312793204Smarco
55412793204Smarco aml_dump(rsdp);
55512793204Smarco entries = (rsdp->len - SIZEOF_SDT_HDR) / sizeof(u_int32_t);
55612793204Smarco acpi_print_rsdt(rsdp);
55712793204Smarco for (i = 0; i < entries; i++) {
55812793204Smarco sdp = (struct ACPIsdt *) acpi_map_sdt(rsdp->body[i]);
55912793204Smarco if (acpi_checksum(sdp, sdp->len))
56012793204Smarco errx(1, "RSDT entry %d is corrupt", i);
56112793204Smarco aml_dump(sdp);
56212793204Smarco if (!memcmp(sdp->signature, "FACP", 4)) {
56312793204Smarco acpi_handle_facp((struct FACPbody *) sdp->body);
56412793204Smarco } else {
56512793204Smarco acpi_print_sdt(sdp);
56612793204Smarco }
56712793204Smarco }
56812793204Smarco }
56912793204Smarco
57012793204Smarco void
acpi_handle_xsdt(struct ACPIsdt * rsdp)5716988a5d7Skettenis acpi_handle_xsdt(struct ACPIsdt *rsdp)
5726988a5d7Skettenis {
5736988a5d7Skettenis int i;
5746988a5d7Skettenis int entries;
5756988a5d7Skettenis struct ACPIsdt *sdp;
5766988a5d7Skettenis u_int64_t *body = (u_int64_t *) rsdp->body;
5776988a5d7Skettenis
5786988a5d7Skettenis aml_dump(rsdp);
5796988a5d7Skettenis entries = (rsdp->len - SIZEOF_SDT_HDR) / sizeof(u_int64_t);
5806988a5d7Skettenis acpi_print_xsdt(rsdp);
5816988a5d7Skettenis for (i = 0; i < entries; i++) {
5826988a5d7Skettenis sdp = (struct ACPIsdt *) acpi_map_sdt(body[i]);
5836988a5d7Skettenis if (acpi_checksum(sdp, sdp->len))
5846988a5d7Skettenis errx(1, "XSDT entry %d is corrupt", i);
5856988a5d7Skettenis aml_dump(sdp);
5866988a5d7Skettenis if (!memcmp(sdp->signature, "FACP", 4)) {
5876988a5d7Skettenis acpi_handle_facp((struct FACPbody *) sdp->body);
5886988a5d7Skettenis } else {
5896988a5d7Skettenis acpi_print_sdt(sdp);
5906988a5d7Skettenis }
5916988a5d7Skettenis }
5926988a5d7Skettenis }
5936988a5d7Skettenis
5946988a5d7Skettenis void
asl_dump_from_devmem(void)59512793204Smarco asl_dump_from_devmem(void)
5967934d707Stholo {
5977934d707Stholo struct ACPIrsdp *rp;
5987934d707Stholo struct ACPIsdt *rsdp;
59912793204Smarco char name[PATH_MAX];
60012793204Smarco
601c8dab64cSkettenis snprintf(name, sizeof(name), "%s%cheaders", aml_dumpfile,
602c8dab64cSkettenis aml_dumpdir ? '/' : '.');
6037934d707Stholo
604d2f88ac2Sderaadt acpi_user_init();
605d2f88ac2Sderaadt
606bc30430aSderaadt /* Can only unveil if being dumped to a dir */
607bc30430aSderaadt if (aml_dumpdir) {
608bc30430aSderaadt if (unveil(aml_dumpfile, "wc") == -1)
609bc5a8259Sbeck err(1, "unveil %s", aml_dumpfile);
6100c9a99e6Sderaadt } else if (aml_dumpfile[0] == '/') { /* admittedly pretty shitty */
6110c9a99e6Sderaadt if (unveil("/", "wc") == -1)
612bc5a8259Sbeck err(1, "unveil /");
6130c9a99e6Sderaadt } else {
6140c9a99e6Sderaadt if (unveil(".", "wc") == -1)
615bc5a8259Sbeck err(1, "unveil .");
6160c9a99e6Sderaadt }
6170c9a99e6Sderaadt
618bc30430aSderaadt if (unveil(_PATH_MEM, "r") == -1)
619bc5a8259Sbeck err(1, "unveil %s", _PATH_MEM);
620bc30430aSderaadt if (unveil(_PATH_KMEM, "r") == -1)
621bc5a8259Sbeck err(1, "unveil %s", _PATH_KMEM);
622bc30430aSderaadt if (unveil(_PATH_KVMDB, "r") == -1)
623bc5a8259Sbeck err(1, "unveil %s", _PATH_KVMDB);
624bc30430aSderaadt if (unveil(_PATH_KSYMS, "r") == -1)
625bc5a8259Sbeck err(1, "unveil %s", _PATH_KSYMS);
626bc30430aSderaadt if (unveil(_PATH_UNIX, "r") == -1)
627bc5a8259Sbeck err(1, "unveil %s", _PATH_UNIX);
6280462adfaSsemarie if (pledge("stdio rpath wpath cpath", NULL) == -1)
6290bd1216cSderaadt err(1, "pledge");
630d2f88ac2Sderaadt
6317934d707Stholo rp = acpi_find_rsd_ptr();
63217033bfcSkettenis if (!rp) {
63317033bfcSkettenis if (!quiet)
63417033bfcSkettenis warnx("Can't find ACPI information");
63517033bfcSkettenis exit(1);
63617033bfcSkettenis }
6377934d707Stholo
63812793204Smarco fhdr = fopen(name, "w");
63912793204Smarco if (fhdr == NULL)
64012793204Smarco err(1, "asl_dump_from_devmem");
64112793204Smarco
6427934d707Stholo acpi_print_rsd_ptr(rp);
6437934d707Stholo
6442a1d3267Slteo if (rp->rev == 2 && rp->xaddr) {
6456988a5d7Skettenis rsdp = (struct ACPIsdt *) acpi_map_sdt(rp->xaddr);
6466988a5d7Skettenis if (memcmp(rsdp->signature, "XSDT", 4) ||
6476988a5d7Skettenis acpi_checksum(rsdp, rsdp->len))
6486988a5d7Skettenis errx(1, "XSDT is corrupted");
6496988a5d7Skettenis
6506988a5d7Skettenis acpi_handle_xsdt(rsdp);
6512a1d3267Slteo } else if (rp->addr) {
6522a1d3267Slteo rsdp = (struct ACPIsdt *) acpi_map_sdt(rp->addr);
6532a1d3267Slteo if (memcmp(rsdp->signature, "RSDT", 4) ||
6542a1d3267Slteo acpi_checksum(rsdp, rsdp->len))
6552a1d3267Slteo errx(1, "RSDT is corrupted");
6562a1d3267Slteo
6572a1d3267Slteo acpi_handle_rsdt(rsdp);
6582a1d3267Slteo } else
6592a1d3267Slteo errx(1, "XSDT or RSDT not found");
66012793204Smarco
66112793204Smarco fclose(fhdr);
6627934d707Stholo }
6637934d707Stholo
66412793204Smarco void
usage(void)66568f43119Sderaadt usage(void)
6667934d707Stholo {
66712793204Smarco extern char *__progname;
6687934d707Stholo
669c8dab64cSkettenis fprintf(stderr, "usage: %s -o prefix\n", __progname);
6707934d707Stholo exit(1);
6717934d707Stholo }
6727934d707Stholo
6737934d707Stholo int
main(int argc,char * argv[])6747934d707Stholo main(int argc, char *argv[])
6757934d707Stholo {
676c8dab64cSkettenis struct stat st;
6776988a5d7Skettenis int c;
6787934d707Stholo
67917033bfcSkettenis while ((c = getopt(argc, argv, "o:q")) != -1) {
680d2f88ac2Sderaadt switch (c) {
681d2f88ac2Sderaadt case 'o':
6827934d707Stholo aml_dumpfile = optarg;
683d2f88ac2Sderaadt break;
68417033bfcSkettenis case 'q':
68517033bfcSkettenis quiet = 1;
68617033bfcSkettenis break;
687d2f88ac2Sderaadt default:
68868f43119Sderaadt usage();
689d2f88ac2Sderaadt break;
690d2f88ac2Sderaadt }
6917934d707Stholo }
69212793204Smarco
69312793204Smarco if (aml_dumpfile == NULL)
69412793204Smarco usage();
6957934d707Stholo
696c8dab64cSkettenis if (stat(aml_dumpfile, &st) == 0 && S_ISDIR(st.st_mode))
697c8dab64cSkettenis aml_dumpdir = 1;
698c8dab64cSkettenis
6997934d707Stholo asl_dump_from_devmem();
70012793204Smarco
7017934d707Stholo return (0);
7027934d707Stholo }
70388448ec7Syasuoka
7046988a5d7Skettenis #ifdef __aarch64__
7056988a5d7Skettenis
70688448ec7Syasuoka u_long
efi_acpi_addr(void)7076988a5d7Skettenis efi_acpi_addr(void)
7086988a5d7Skettenis {
7096988a5d7Skettenis kvm_t *kd;
7106988a5d7Skettenis struct nlist nl[2];
7116988a5d7Skettenis uint64_t table;
7126988a5d7Skettenis
7136988a5d7Skettenis memset(&nl, 0, sizeof(nl));
7146988a5d7Skettenis kd = kvm_openfiles(NULL, NULL, NULL, O_RDONLY, NULL);
7156988a5d7Skettenis if (kd == NULL)
7166988a5d7Skettenis goto on_error;
717*c3c82401Skettenis nl[0].n_name = "_efi_acpi_table";
718*c3c82401Skettenis if (kvm_nlist(kd, nl) != 0)
7196988a5d7Skettenis goto on_error;
7206988a5d7Skettenis if (kvm_read(kd, nl[0].n_value, &table, sizeof(table)) == -1)
7216988a5d7Skettenis goto on_error;
7226988a5d7Skettenis
7236988a5d7Skettenis kvm_close(kd);
7246988a5d7Skettenis return table;
7256988a5d7Skettenis
7266988a5d7Skettenis on_error:
7276988a5d7Skettenis if (kd != NULL)
7286988a5d7Skettenis kvm_close(kd);
7296988a5d7Skettenis return (0);
7306988a5d7Skettenis }
7316988a5d7Skettenis
7326988a5d7Skettenis #else
7336988a5d7Skettenis
7346988a5d7Skettenis #include <machine/biosvar.h>
7356988a5d7Skettenis
7366988a5d7Skettenis u_long
efi_acpi_addr(void)7376988a5d7Skettenis efi_acpi_addr(void)
73888448ec7Syasuoka {
73988448ec7Syasuoka kvm_t *kd;
74088448ec7Syasuoka struct nlist nl[2];
74188448ec7Syasuoka bios_efiinfo_t efiinfo;
74288448ec7Syasuoka u_long ptr;
74388448ec7Syasuoka
74488448ec7Syasuoka memset(&nl, 0, sizeof(nl));
74588448ec7Syasuoka kd = kvm_openfiles(NULL, NULL, NULL, O_RDONLY, NULL);
74688448ec7Syasuoka if (kd == NULL)
74788448ec7Syasuoka goto on_error;
74888448ec7Syasuoka nl[0].n_name = "_bios_efiinfo";
749*c3c82401Skettenis if (kvm_nlist(kd, nl) != 0)
75088448ec7Syasuoka goto on_error;
75188448ec7Syasuoka if (kvm_read(kd, nl[0].n_value, &ptr, sizeof(ptr)) == -1)
75288448ec7Syasuoka goto on_error;
75388448ec7Syasuoka if (kvm_read(kd, ptr, &efiinfo, sizeof(efiinfo)) == -1)
75488448ec7Syasuoka goto on_error;
75588448ec7Syasuoka
75688448ec7Syasuoka kvm_close(kd);
75788448ec7Syasuoka return (efiinfo.config_acpi);
75888448ec7Syasuoka
75988448ec7Syasuoka on_error:
76088448ec7Syasuoka if (kd != NULL)
76188448ec7Syasuoka kvm_close(kd);
76288448ec7Syasuoka return (0);
76388448ec7Syasuoka }
7646988a5d7Skettenis
7656988a5d7Skettenis #endif
766