1 /* $OpenBSD: acpidump.c,v 1.25 2022/09/11 10:40:35 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 34 #include <assert.h> 35 #include <err.h> 36 #include <fcntl.h> 37 #include <kvm.h> 38 #include <stdio.h> 39 #include <stdlib.h> 40 #include <string.h> 41 #include <unistd.h> 42 #include <limits.h> 43 #include <paths.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 rev; 62 u_int32_t addr; 63 #define SIZEOF_RSDP_REV_0 20 64 u_int32_t len; 65 u_int64_t xaddr; 66 u_char xsum; 67 u_char xres[3]; 68 } __packed; 69 70 struct ACPIsdt { 71 u_char signature[4]; 72 u_int32_t len; 73 u_char rev; 74 u_char check; 75 u_char oemid[6]; 76 u_char oemtblid[8]; 77 u_int32_t oemrev; 78 u_char creator[4]; 79 u_int32_t crerev; 80 #define SIZEOF_SDT_HDR 36 /* struct size except body */ 81 u_int32_t body[1];/* This member should be casted */ 82 } __packed; 83 84 struct ACPIgas { 85 u_int8_t address_space_id; 86 #define ACPI_GAS_MEMORY 0 87 #define ACPI_GAS_IO 1 88 #define ACPI_GAS_PCI 2 89 #define ACPI_GAS_EMBEDDED 3 90 #define ACPI_GAS_SMBUS 4 91 #define ACPI_GAS_FIXED 0x7f 92 u_int8_t register_bit_width; 93 u_int8_t register_bit_offset; 94 u_int8_t res; 95 u_int64_t address; 96 } __packed; 97 98 struct FACPbody { 99 u_int32_t facs_ptr; 100 u_int32_t dsdt_ptr; 101 u_int8_t int_model; 102 #define ACPI_FACP_INTMODEL_PIC 0 /* Standard PC-AT PIC */ 103 #define ACPI_FACP_INTMODEL_APIC 1 /* Multiple APIC */ 104 u_char reserved1; 105 u_int16_t sci_int; 106 u_int32_t smi_cmd; 107 u_int8_t acpi_enable; 108 u_int8_t acpi_disable; 109 u_int8_t s4biosreq; 110 u_int8_t reserved2; 111 u_int32_t pm1a_evt_blk; 112 u_int32_t pm1b_evt_blk; 113 u_int32_t pm1a_cnt_blk; 114 u_int32_t pm1b_cnt_blk; 115 u_int32_t pm2_cnt_blk; 116 u_int32_t pm_tmr_blk; 117 u_int32_t gpe0_blk; 118 u_int32_t gpe1_blk; 119 u_int8_t pm1_evt_len; 120 u_int8_t pm1_cnt_len; 121 u_int8_t pm2_cnt_len; 122 u_int8_t pm_tmr_len; 123 u_int8_t gpe0_len; 124 u_int8_t gpe1_len; 125 u_int8_t gpe1_base; 126 u_int8_t reserved3; 127 u_int16_t p_lvl2_lat; 128 u_int16_t p_lvl3_lat; 129 u_int16_t flush_size; 130 u_int16_t flush_stride; 131 u_int8_t duty_off; 132 u_int8_t duty_width; 133 u_int8_t day_alrm; 134 u_int8_t mon_alrm; 135 u_int8_t century; 136 u_int16_t iapc_boot_arch; 137 u_char reserved4[1]; 138 u_int32_t flags; 139 #define ACPI_FACP_FLAG_WBINVD 1 /* WBINVD is correctly supported */ 140 #define ACPI_FACP_FLAG_WBINVD_FLUSH 2 /* WBINVD flushes caches */ 141 #define ACPI_FACP_FLAG_PROC_C1 4 /* C1 power state supported */ 142 #define ACPI_FACP_FLAG_P_LVL2_UP 8 /* C2 power state works on SMP */ 143 #define ACPI_FACP_FLAG_PWR_BUTTON 16 /* Power button uses control method */ 144 #define ACPI_FACP_FLAG_SLP_BUTTON 32 /* Sleep button uses control method */ 145 #define ACPI_FACP_FLAG_FIX_RTC 64 /* RTC wakeup not supported */ 146 #define ACPI_FACP_FLAG_RTC_S4 128 /* RTC can wakeup from S4 state */ 147 #define ACPI_FACP_FLAG_TMR_VAL_EXT 256 /* TMR_VAL is 32bit */ 148 #define ACPI_FACP_FLAG_DCK_CAP 512 /* Can support docking */ 149 struct ACPIgas reset_reg; 150 u_int8_t reset_value; 151 u_int8_t reserved5[3]; 152 u_int64_t x_firmware_ctrl; 153 u_int64_t x_dsdt; 154 struct ACPIgas x_pm1a_evt_blk; 155 struct ACPIgas x_pm1b_evt_blk; 156 struct ACPIgas x_pm1a_cnt_blk; 157 struct ACPIgas x_pm1b_cnt_blk; 158 struct ACPIgas x_pm2_cnt_blk; 159 struct ACPIgas x_pm_tmr_blk; 160 struct ACPIgas x_gpe0_blk; 161 struct ACPIgas x_gpe1_blk; 162 } __packed; 163 164 struct acpi_user_mapping { 165 LIST_ENTRY(acpi_user_mapping) link; 166 vm_offset_t pa; 167 caddr_t va; 168 size_t size; 169 }; 170 171 LIST_HEAD(acpi_user_mapping_list, acpi_user_mapping) maplist; 172 173 int acpi_mem_fd = -1; 174 char *aml_dumpfile; 175 int aml_dumpdir; 176 FILE *fhdr; 177 int quiet; 178 179 int acpi_checksum(void *_p, size_t _length); 180 struct acpi_user_mapping *acpi_user_find_mapping(vm_offset_t _pa, size_t _size); 181 void *acpi_map_physical(vm_offset_t _pa, size_t _size); 182 void acpi_user_init(void); 183 struct ACPIrsdp *acpi_check_rsd_ptr(vm_offset_t _pa); 184 struct ACPIrsdp *acpi_find_rsd_ptr(void); 185 void acpi_print_string(char *_s, size_t _length); 186 void acpi_print_rsd_ptr(struct ACPIrsdp *_rp); 187 struct ACPIsdt *acpi_map_sdt(vm_offset_t _pa); 188 void aml_dump(struct ACPIsdt *_hdr); 189 void acpi_print_sdt(struct ACPIsdt *_sdp); 190 void acpi_print_rsdt(struct ACPIsdt *_rsdp); 191 void acpi_print_xsdt(struct ACPIsdt *_rsdp); 192 void acpi_print_facp(struct FACPbody *_facp); 193 void acpi_print_dsdt(struct ACPIsdt *_dsdp); 194 void acpi_handle_dsdt(struct ACPIsdt *_dsdp); 195 void acpi_handle_facp(struct FACPbody *_facp); 196 void acpi_handle_rsdt(struct ACPIsdt *_rsdp); 197 void acpi_handle_xsdt(struct ACPIsdt *_rsdp); 198 void asl_dump_from_devmem(void); 199 void usage(void); 200 u_long efi_acpi_addr(void); 201 202 203 struct ACPIsdt dsdt_header = { 204 "DSDT", 0, 1, 0, "OEMID", "OEMTBLID", 0x12345678, "CRTR", 0x12345678 205 }; 206 207 int 208 acpi_checksum(void *p, size_t length) 209 { 210 u_int8_t *bp; 211 u_int8_t sum; 212 213 bp = p; 214 sum = 0; 215 while (length--) 216 sum += *bp++; 217 218 return (sum); 219 } 220 221 struct acpi_user_mapping * 222 acpi_user_find_mapping(vm_offset_t pa, size_t size) 223 { 224 struct acpi_user_mapping *map; 225 int page_mask = getpagesize() - 1; 226 227 /* First search for an existing mapping */ 228 for (map = LIST_FIRST(&maplist); map; map = LIST_NEXT(map, link)) { 229 if (map->pa <= pa && map->size >= pa + size - map->pa) 230 return (map); 231 } 232 233 /* Then create a new one */ 234 #undef round_page 235 #undef trunc_page 236 #define round_page(x) (((x) + page_mask) & ~page_mask) 237 #define trunc_page(x) ((x) & ~page_mask) 238 size = round_page(pa + size) - trunc_page(pa); 239 pa = trunc_page(pa); 240 #undef round_page 241 #undef trunc_page 242 map = malloc(sizeof(struct acpi_user_mapping)); 243 if (!map) 244 errx(1, "out of memory"); 245 map->pa = pa; 246 map->va = mmap(0, size, PROT_READ, MAP_SHARED, acpi_mem_fd, pa); 247 map->size = size; 248 if (map->va == MAP_FAILED) 249 err(1, "can't map address"); 250 LIST_INSERT_HEAD(&maplist, map, link); 251 252 return (map); 253 } 254 255 void * 256 acpi_map_physical(vm_offset_t pa, size_t size) 257 { 258 struct acpi_user_mapping *map; 259 260 map = acpi_user_find_mapping(pa, size); 261 return (map->va + (pa - map->pa)); 262 } 263 264 void 265 acpi_user_init(void) 266 { 267 if (acpi_mem_fd == -1) { 268 acpi_mem_fd = open("/dev/mem", O_RDONLY); 269 if (acpi_mem_fd == -1) 270 err(1, "opening /dev/mem"); 271 LIST_INIT(&maplist); 272 } 273 } 274 275 struct ACPIrsdp * 276 acpi_check_rsd_ptr(vm_offset_t pa) 277 { 278 struct ACPIrsdp rp; 279 280 lseek(acpi_mem_fd, pa, SEEK_SET); 281 read(acpi_mem_fd, &rp, SIZEOF_RSDP_REV_0); 282 if (memcmp(rp.signature, "RSD PTR ", 8) != 0) 283 return NULL; 284 285 if (rp.rev >= 2) { 286 read(acpi_mem_fd, &(rp.len), 287 sizeof(struct ACPIrsdp) - SIZEOF_RSDP_REV_0); 288 if (acpi_checksum(&rp, sizeof(struct ACPIrsdp)) == 0) 289 return acpi_map_physical(pa, sizeof(struct ACPIrsdp)); 290 } 291 292 if (acpi_checksum(&rp, SIZEOF_RSDP_REV_0) == 0) 293 return (acpi_map_physical(pa, SIZEOF_RSDP_REV_0)); 294 295 return NULL; 296 } 297 298 struct ACPIrsdp * 299 acpi_find_rsd_ptr(void) 300 { 301 struct ACPIrsdp *rp; 302 u_long addr; 303 304 if ((addr = efi_acpi_addr()) != 0) { 305 if ((rp = acpi_check_rsd_ptr(addr))) 306 return rp; 307 } 308 309 #if defined(__amd64__) || defined (__i386__) 310 for (addr = 0; addr < 1024 * 1024; addr += 16) { 311 if ((rp = acpi_check_rsd_ptr(addr))) 312 return rp; 313 } 314 #endif 315 316 return NULL; 317 } 318 319 void 320 acpi_print_string(char *s, size_t length) 321 { 322 int c; 323 324 /* Trim trailing spaces and NULLs */ 325 while (length > 0 && (s[length - 1] == ' ' || s[length - 1] == '\0')) 326 length--; 327 328 while (length--) { 329 c = *s++; 330 fputc(c, fhdr); 331 } 332 } 333 334 void 335 acpi_print_rsd_ptr(struct ACPIrsdp *rp) 336 { 337 fprintf(fhdr, "\n"); 338 fprintf(fhdr, "RSD PTR: Checksum=%d, OEMID=", rp->sum); 339 acpi_print_string(rp->oem, 6); 340 fprintf(fhdr, ", Revision=%d", rp->rev); 341 fprintf(fhdr, ", RsdtAddress=0x%08x\n", rp->addr); 342 if (rp->rev >= 2) { 343 fprintf(fhdr, "\tLength=%d", rp->len); 344 fprintf(fhdr, ", XsdtAddress=0x%016llx", rp->xaddr); 345 fprintf(fhdr, ", Extended Checksum=%d\n", rp->xsum); 346 } 347 fprintf(fhdr, "\n"); 348 } 349 350 struct ACPIsdt * 351 acpi_map_sdt(vm_offset_t pa) 352 { 353 struct ACPIsdt *sp; 354 355 sp = acpi_map_physical(pa, sizeof(struct ACPIsdt)); 356 sp = acpi_map_physical(pa, sp->len); 357 return (sp); 358 } 359 360 void 361 aml_dump(struct ACPIsdt *hdr) 362 { 363 static int hdr_index; 364 char name[PATH_MAX]; 365 int fd; 366 mode_t mode; 367 368 snprintf(name, sizeof(name), "%s%c%c%c%c%c.%d", 369 aml_dumpfile, aml_dumpdir ? '/' : '.', 370 hdr->signature[0], hdr->signature[1], 371 hdr->signature[2], hdr->signature[3], 372 hdr_index++); 373 374 mode = (S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH); 375 fd = open(name, O_WRONLY | O_CREAT | O_TRUNC, mode); 376 if (fd == -1) 377 err(1, "aml_dump"); 378 379 write(fd, hdr, SIZEOF_SDT_HDR); 380 write(fd, hdr->body, hdr->len - SIZEOF_SDT_HDR); 381 close(fd); 382 } 383 384 void 385 acpi_print_sdt(struct ACPIsdt *sdp) 386 { 387 fprintf(fhdr, "\n"); 388 acpi_print_string(sdp->signature, 4); 389 fprintf(fhdr, ": Length=%d, Revision=%d, Checksum=%d,\n", 390 sdp->len, sdp->rev, sdp->check); 391 fprintf(fhdr, "\tOEMID="); 392 acpi_print_string(sdp->oemid, 6); 393 fprintf(fhdr, ", OEM Table ID="); 394 acpi_print_string(sdp->oemtblid, 8); 395 fprintf(fhdr, ", OEM Revision=0x%x,\n", sdp->oemrev); 396 fprintf(fhdr, "\tCreator ID="); 397 acpi_print_string(sdp->creator, 4); 398 fprintf(fhdr, ", Creator Revision=0x%x\n", sdp->crerev); 399 fprintf(fhdr, "\n"); 400 if (!memcmp(sdp->signature, "DSDT", 4)) 401 memcpy(&dsdt_header, sdp, sizeof(dsdt_header)); 402 } 403 404 void 405 acpi_print_rsdt(struct ACPIsdt *rsdp) 406 { 407 int i, entries; 408 409 acpi_print_sdt(rsdp); 410 entries = (rsdp->len - SIZEOF_SDT_HDR) / sizeof(u_int32_t); 411 fprintf(fhdr, "\n"); 412 fprintf(fhdr, "\tEntries={ "); 413 for (i = 0; i < entries; i++) { 414 if (i > 0) 415 fprintf(fhdr, ", "); 416 fprintf(fhdr, "0x%08x", rsdp->body[i]); 417 } 418 fprintf(fhdr, " }\n"); 419 fprintf(fhdr, "\n"); 420 } 421 422 void 423 acpi_print_xsdt(struct ACPIsdt *rsdp) 424 { 425 int i, entries; 426 u_int64_t *body = (u_int64_t *) rsdp->body; 427 428 acpi_print_sdt(rsdp); 429 entries = (rsdp->len - SIZEOF_SDT_HDR) / sizeof(u_int64_t); 430 fprintf(fhdr, "\n"); 431 fprintf(fhdr, "\tEntries={ "); 432 for (i = 0; i < entries; i++) { 433 if (i > 0) 434 fprintf(fhdr, ", "); 435 fprintf(fhdr, "0x%016llx", body[i]); 436 } 437 fprintf(fhdr, " }\n"); 438 fprintf(fhdr, "\n"); 439 } 440 441 void 442 acpi_print_facp(struct FACPbody *facp) 443 { 444 char sep; 445 446 fprintf(fhdr, "\n"); 447 fprintf(fhdr, "\tDSDT=0x%x\n", facp->dsdt_ptr); 448 fprintf(fhdr, "\tINT_MODEL=%s\n", facp->int_model ? "APIC" : "PIC"); 449 fprintf(fhdr, "\tSCI_INT=%d\n", facp->sci_int); 450 fprintf(fhdr, "\tSMI_CMD=0x%x, ", facp->smi_cmd); 451 fprintf(fhdr, "ACPI_ENABLE=0x%x, ", facp->acpi_enable); 452 fprintf(fhdr, "ACPI_DISABLE=0x%x, ", facp->acpi_disable); 453 fprintf(fhdr, "S4BIOS_REQ=0x%x\n", facp->s4biosreq); 454 if (facp->pm1a_evt_blk) 455 fprintf(fhdr, "\tPM1a_EVT_BLK=0x%x-0x%x\n", 456 facp->pm1a_evt_blk, 457 facp->pm1a_evt_blk + facp->pm1_evt_len - 1); 458 if (facp->pm1b_evt_blk) 459 fprintf(fhdr, "\tPM1b_EVT_BLK=0x%x-0x%x\n", 460 facp->pm1b_evt_blk, 461 facp->pm1b_evt_blk + facp->pm1_evt_len - 1); 462 if (facp->pm1a_cnt_blk) 463 fprintf(fhdr, "\tPM1a_CNT_BLK=0x%x-0x%x\n", 464 facp->pm1a_cnt_blk, 465 facp->pm1a_cnt_blk + facp->pm1_cnt_len - 1); 466 if (facp->pm1b_cnt_blk) 467 fprintf(fhdr, "\tPM1b_CNT_BLK=0x%x-0x%x\n", 468 facp->pm1b_cnt_blk, 469 facp->pm1b_cnt_blk + facp->pm1_cnt_len - 1); 470 if (facp->pm2_cnt_blk) 471 fprintf(fhdr, "\tPM2_CNT_BLK=0x%x-0x%x\n", 472 facp->pm2_cnt_blk, 473 facp->pm2_cnt_blk + facp->pm2_cnt_len - 1); 474 if (facp->pm_tmr_blk) 475 fprintf(fhdr, "\tPM2_TMR_BLK=0x%x-0x%x\n", 476 facp->pm_tmr_blk, 477 facp->pm_tmr_blk + facp->pm_tmr_len - 1); 478 if (facp->gpe0_blk) 479 fprintf(fhdr, "\tPM2_GPE0_BLK=0x%x-0x%x\n", 480 facp->gpe0_blk, 481 facp->gpe0_blk + facp->gpe0_len - 1); 482 if (facp->gpe1_blk) 483 fprintf(fhdr, "\tPM2_GPE1_BLK=0x%x-0x%x, GPE1_BASE=%d\n", 484 facp->gpe1_blk, 485 facp->gpe1_blk + facp->gpe1_len - 1, 486 facp->gpe1_base); 487 fprintf(fhdr, "\tP_LVL2_LAT=%dms, P_LVL3_LAT=%dms\n", 488 facp->p_lvl2_lat, facp->p_lvl3_lat); 489 fprintf(fhdr, "\tFLUSH_SIZE=%d, FLUSH_STRIDE=%d\n", 490 facp->flush_size, facp->flush_stride); 491 fprintf(fhdr, "\tDUTY_OFFSET=%d, DUTY_WIDTH=%d\n", 492 facp->duty_off, facp->duty_width); 493 fprintf(fhdr, "\tDAY_ALRM=%d, MON_ALRM=%d, CENTURY=%d\n", 494 facp->day_alrm, facp->mon_alrm, facp->century); 495 fprintf(fhdr, "\tFlags="); 496 sep = '{'; 497 498 PRINTFLAG(WBINVD); 499 PRINTFLAG(WBINVD_FLUSH); 500 PRINTFLAG(PROC_C1); 501 PRINTFLAG(P_LVL2_UP); 502 PRINTFLAG(PWR_BUTTON); 503 PRINTFLAG(SLP_BUTTON); 504 PRINTFLAG(FIX_RTC); 505 PRINTFLAG(RTC_S4); 506 PRINTFLAG(TMR_VAL_EXT); 507 PRINTFLAG(DCK_CAP); 508 509 fprintf(fhdr, "}\n"); 510 fprintf(fhdr, "\n"); 511 } 512 513 void 514 acpi_print_dsdt(struct ACPIsdt *dsdp) 515 { 516 acpi_print_sdt(dsdp); 517 } 518 519 void 520 acpi_handle_dsdt(struct ACPIsdt *dsdp) 521 { 522 u_int8_t *dp; 523 u_int8_t *end; 524 525 acpi_print_dsdt(dsdp); 526 527 dp = (u_int8_t *)dsdp->body; 528 end = (u_int8_t *)dsdp + dsdp->len; 529 } 530 531 void 532 acpi_handle_facp(struct FACPbody *facp) 533 { 534 struct ACPIsdt *dsdp; 535 536 acpi_print_facp(facp); 537 if (facp->dsdt_ptr == 0) 538 dsdp = (struct ACPIsdt *) acpi_map_sdt(facp->x_dsdt); 539 else 540 dsdp = (struct ACPIsdt *) acpi_map_sdt(facp->dsdt_ptr); 541 if (acpi_checksum(dsdp, dsdp->len)) 542 errx(1, "DSDT is corrupt"); 543 acpi_handle_dsdt(dsdp); 544 aml_dump(dsdp); 545 } 546 547 void 548 acpi_handle_rsdt(struct ACPIsdt *rsdp) 549 { 550 int i; 551 int entries; 552 struct ACPIsdt *sdp; 553 554 aml_dump(rsdp); 555 entries = (rsdp->len - SIZEOF_SDT_HDR) / sizeof(u_int32_t); 556 acpi_print_rsdt(rsdp); 557 for (i = 0; i < entries; i++) { 558 sdp = (struct ACPIsdt *) acpi_map_sdt(rsdp->body[i]); 559 if (acpi_checksum(sdp, sdp->len)) 560 errx(1, "RSDT entry %d is corrupt", i); 561 aml_dump(sdp); 562 if (!memcmp(sdp->signature, "FACP", 4)) { 563 acpi_handle_facp((struct FACPbody *) sdp->body); 564 } else { 565 acpi_print_sdt(sdp); 566 } 567 } 568 } 569 570 void 571 acpi_handle_xsdt(struct ACPIsdt *rsdp) 572 { 573 int i; 574 int entries; 575 struct ACPIsdt *sdp; 576 u_int64_t *body = (u_int64_t *) rsdp->body; 577 578 aml_dump(rsdp); 579 entries = (rsdp->len - SIZEOF_SDT_HDR) / sizeof(u_int64_t); 580 acpi_print_xsdt(rsdp); 581 for (i = 0; i < entries; i++) { 582 sdp = (struct ACPIsdt *) acpi_map_sdt(body[i]); 583 if (acpi_checksum(sdp, sdp->len)) 584 errx(1, "XSDT entry %d is corrupt", i); 585 aml_dump(sdp); 586 if (!memcmp(sdp->signature, "FACP", 4)) { 587 acpi_handle_facp((struct FACPbody *) sdp->body); 588 } else { 589 acpi_print_sdt(sdp); 590 } 591 } 592 } 593 594 void 595 asl_dump_from_devmem(void) 596 { 597 struct ACPIrsdp *rp; 598 struct ACPIsdt *rsdp; 599 char name[PATH_MAX]; 600 601 snprintf(name, sizeof(name), "%s%cheaders", aml_dumpfile, 602 aml_dumpdir ? '/' : '.'); 603 604 acpi_user_init(); 605 606 /* Can only unveil if being dumped to a dir */ 607 if (aml_dumpdir) { 608 if (unveil(aml_dumpfile, "wc") == -1) 609 err(1, "unveil %s", aml_dumpfile); 610 } else if (aml_dumpfile[0] == '/') { /* admittedly pretty shitty */ 611 if (unveil("/", "wc") == -1) 612 err(1, "unveil /"); 613 } else { 614 if (unveil(".", "wc") == -1) 615 err(1, "unveil ."); 616 } 617 618 if (unveil(_PATH_MEM, "r") == -1) 619 err(1, "unveil %s", _PATH_MEM); 620 if (unveil(_PATH_KMEM, "r") == -1) 621 err(1, "unveil %s", _PATH_KMEM); 622 if (unveil(_PATH_KVMDB, "r") == -1) 623 err(1, "unveil %s", _PATH_KVMDB); 624 if (unveil(_PATH_KSYMS, "r") == -1) 625 err(1, "unveil %s", _PATH_KSYMS); 626 if (unveil(_PATH_UNIX, "r") == -1) 627 err(1, "unveil %s", _PATH_UNIX); 628 if (pledge("stdio rpath wpath cpath", NULL) == -1) 629 err(1, "pledge"); 630 631 rp = acpi_find_rsd_ptr(); 632 if (!rp) { 633 if (!quiet) 634 warnx("Can't find ACPI information"); 635 exit(1); 636 } 637 638 fhdr = fopen(name, "w"); 639 if (fhdr == NULL) 640 err(1, "asl_dump_from_devmem"); 641 642 acpi_print_rsd_ptr(rp); 643 644 if (rp->rev == 2 && rp->xaddr) { 645 rsdp = (struct ACPIsdt *) acpi_map_sdt(rp->xaddr); 646 if (memcmp(rsdp->signature, "XSDT", 4) || 647 acpi_checksum(rsdp, rsdp->len)) 648 errx(1, "XSDT is corrupted"); 649 650 acpi_handle_xsdt(rsdp); 651 } else if (rp->addr) { 652 rsdp = (struct ACPIsdt *) acpi_map_sdt(rp->addr); 653 if (memcmp(rsdp->signature, "RSDT", 4) || 654 acpi_checksum(rsdp, rsdp->len)) 655 errx(1, "RSDT is corrupted"); 656 657 acpi_handle_rsdt(rsdp); 658 } else 659 errx(1, "XSDT or RSDT not found"); 660 661 fclose(fhdr); 662 } 663 664 void 665 usage(void) 666 { 667 extern char *__progname; 668 669 fprintf(stderr, "usage: %s -o prefix\n", __progname); 670 exit(1); 671 } 672 673 int 674 main(int argc, char *argv[]) 675 { 676 struct stat st; 677 int c; 678 679 while ((c = getopt(argc, argv, "o:q")) != -1) { 680 switch (c) { 681 case 'o': 682 aml_dumpfile = optarg; 683 break; 684 case 'q': 685 quiet = 1; 686 break; 687 default: 688 usage(); 689 break; 690 } 691 } 692 693 if (aml_dumpfile == NULL) 694 usage(); 695 696 if (stat(aml_dumpfile, &st) == 0 && S_ISDIR(st.st_mode)) 697 aml_dumpdir = 1; 698 699 asl_dump_from_devmem(); 700 701 return (0); 702 } 703 704 #ifdef __aarch64__ 705 706 u_long 707 efi_acpi_addr(void) 708 { 709 kvm_t *kd; 710 struct nlist nl[2]; 711 uint64_t table; 712 713 memset(&nl, 0, sizeof(nl)); 714 kd = kvm_openfiles(NULL, NULL, NULL, O_RDONLY, NULL); 715 if (kd == NULL) 716 goto on_error; 717 nl[0].n_name = "_efi_acpi_table"; 718 if (kvm_nlist(kd, nl) != 0) 719 goto on_error; 720 if (kvm_read(kd, nl[0].n_value, &table, sizeof(table)) == -1) 721 goto on_error; 722 723 kvm_close(kd); 724 return table; 725 726 on_error: 727 if (kd != NULL) 728 kvm_close(kd); 729 return (0); 730 } 731 732 #else 733 734 #include <machine/biosvar.h> 735 736 u_long 737 efi_acpi_addr(void) 738 { 739 kvm_t *kd; 740 struct nlist nl[2]; 741 bios_efiinfo_t efiinfo; 742 u_long ptr; 743 744 memset(&nl, 0, sizeof(nl)); 745 kd = kvm_openfiles(NULL, NULL, NULL, O_RDONLY, NULL); 746 if (kd == NULL) 747 goto on_error; 748 nl[0].n_name = "_bios_efiinfo"; 749 if (kvm_nlist(kd, nl) != 0) 750 goto on_error; 751 if (kvm_read(kd, nl[0].n_value, &ptr, sizeof(ptr)) == -1) 752 goto on_error; 753 if (kvm_read(kd, ptr, &efiinfo, sizeof(efiinfo)) == -1) 754 goto on_error; 755 756 kvm_close(kd); 757 return (efiinfo.config_acpi); 758 759 on_error: 760 if (kd != NULL) 761 kvm_close(kd); 762 return (0); 763 } 764 765 #endif 766