acpi.c revision 119515
1127664Sbms/*- 2127664Sbms * Copyright (c) 1998 Doug Rabson 3127664Sbms * Copyright (c) 2000 Mitsuru IWASAKI <iwasaki@FreeBSD.org> 4127664Sbms * All rights reserved. 5127664Sbms * 6127664Sbms * Redistribution and use in source and binary forms, with or without 7127664Sbms * modification, are permitted provided that the following conditions 8127664Sbms * are met: 9127664Sbms * 1. Redistributions of source code must retain the above copyright 10127664Sbms * notice, this list of conditions and the following disclaimer. 11127664Sbms * 2. Redistributions in binary form must reproduce the above copyright 12127664Sbms * notice, this list of conditions and the following disclaimer in the 13127664Sbms * documentation and/or other materials provided with the distribution. 14127664Sbms * 15127664Sbms * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 16127664Sbms * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 17127664Sbms * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 18127664Sbms * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 19127664Sbms * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 20127664Sbms * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 21127664Sbms * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 22127664Sbms * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 23127664Sbms * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 24127664Sbms * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 25127664Sbms * SUCH DAMAGE. 26127664Sbms * 27127664Sbms * $FreeBSD: head/usr.sbin/acpi/acpidump/acpi.c 119515 2003-08-28 03:33:07Z njl $ 28127664Sbms */ 29127664Sbms 30127664Sbms#include <sys/types.h> 31127664Sbms#include <sys/param.h> 32190225Srpaulo#include <sys/stat.h> 33127664Sbms#include <sys/wait.h> 34127664Sbms#include <assert.h> 35127664Sbms#include <err.h> 36127664Sbms#include <fcntl.h> 37127664Sbms#include <stdio.h> 38190225Srpaulo#include <string.h> 39190225Srpaulo#include <unistd.h> 40190225Srpaulo 41190225Srpaulo#include "acpidump.h" 42190225Srpaulo 43190225Srpaulo#define BEGIN_COMMENT "/*\n" 44127664Sbms#define END_COMMENT " */\n" 45127664Sbms 46127664Sbmsstatic void acpi_print_string(char *s, size_t length); 47127664Sbmsstatic void acpi_handle_facp(struct FACPbody *facp); 48127664Sbmsstatic void acpi_print_cpu(u_char cpu_id); 49127664Sbmsstatic void acpi_print_local_apic(u_char cpu_id, u_char apic_id, 50127664Sbms u_int32_t flags); 51127664Sbmsstatic void acpi_print_io_apic(u_char apic_id, u_int32_t int_base, 52127664Sbms u_int64_t apic_addr); 53127664Sbmsstatic void acpi_print_mps_flags(u_int16_t flags); 54127664Sbmsstatic void acpi_print_intr(u_int32_t intr, u_int16_t mps_flags); 55127664Sbmsstatic void acpi_print_apic(struct MADT_APIC *mp); 56127664Sbmsstatic void acpi_handle_apic(struct ACPIsdt *sdp); 57127664Sbmsstatic void acpi_handle_hpet(struct ACPIsdt *sdp); 58127664Sbmsstatic void acpi_print_sdt(struct ACPIsdt *sdp, int endcomment); 59127664Sbmsstatic void acpi_print_facp(struct FACPbody *facp); 60127664Sbmsstatic void acpi_print_dsdt(struct ACPIsdt *dsdp); 61127664Sbmsstatic struct ACPIsdt * 62127664Sbms acpi_map_sdt(vm_offset_t pa); 63127664Sbmsstatic void acpi_print_rsd_ptr(struct ACPIrsdp *rp); 64127664Sbmsstatic void acpi_handle_rsdt(struct ACPIsdt *rsdp); 65127664Sbms 66127664Sbmsstatic void 67127664Sbmsacpi_print_string(char *s, size_t length) 68127664Sbms{ 69127664Sbms int c; 70127664Sbms 71127664Sbms /* Trim trailing spaces and NULLs */ 72127664Sbms while (length > 0 && (s[length - 1] == ' ' || s[length - 1] == '\0')) 73127664Sbms length--; 74127664Sbms 75127664Sbms while (length--) { 76127664Sbms c = *s++; 77127664Sbms putchar(c); 78127664Sbms } 79127664Sbms} 80127664Sbms 81127664Sbmsstatic void 82127664Sbmsacpi_handle_facp(struct FACPbody *facp) 83127664Sbms{ 84127664Sbms struct ACPIsdt *dsdp; 85127664Sbms 86127664Sbms acpi_print_facp(facp); 87127664Sbms dsdp = (struct ACPIsdt *)acpi_map_sdt(facp->dsdt_ptr); 88 if (acpi_checksum(dsdp, dsdp->len)) 89 errx(1, "DSDT is corrupt"); 90 acpi_print_dsdt(dsdp); 91} 92 93static void 94acpi_print_cpu(u_char cpu_id) 95{ 96 97 printf("\tACPI CPU="); 98 if (cpu_id == 0xff) 99 printf("ALL\n"); 100 else 101 printf("%d\n", (u_int)cpu_id); 102} 103 104static void 105acpi_print_local_apic(u_char cpu_id, u_char apic_id, u_int32_t flags) 106{ 107 acpi_print_cpu(cpu_id); 108 printf("\tFlags={"); 109 if (flags & ACPI_MADT_APIC_LOCAL_FLAG_ENABLED) 110 printf("ENABLED"); 111 else 112 printf("DISABLED"); 113 printf("}\n"); 114 printf("\tAPIC ID=%d\n", (u_int)apic_id); 115} 116 117static void 118acpi_print_io_apic(u_char apic_id, u_int32_t int_base, u_int64_t apic_addr) 119{ 120 printf("\tAPIC ID=%d\n", (u_int)apic_id); 121 printf("\tINT BASE=%d\n", int_base); 122 printf("\tADDR=0x%016jx\n", apic_addr); 123} 124 125static void 126acpi_print_mps_flags(u_int16_t flags) 127{ 128 129 printf("\tFlags={Polarity="); 130 switch (flags & MPS_INT_FLAG_POLARITY_MASK) { 131 case MPS_INT_FLAG_POLARITY_CONFORM: 132 printf("conforming"); 133 break; 134 case MPS_INT_FLAG_POLARITY_HIGH: 135 printf("active-hi"); 136 break; 137 case MPS_INT_FLAG_POLARITY_LOW: 138 printf("active-lo"); 139 break; 140 default: 141 printf("0x%x", flags & MPS_INT_FLAG_POLARITY_MASK); 142 break; 143 } 144 printf(", Trigger="); 145 switch (flags & MPS_INT_FLAG_TRIGGER_MASK) { 146 case MPS_INT_FLAG_TRIGGER_CONFORM: 147 printf("conforming"); 148 break; 149 case MPS_INT_FLAG_TRIGGER_EDGE: 150 printf("edge"); 151 break; 152 case MPS_INT_FLAG_TRIGGER_LEVEL: 153 printf("level"); 154 break; 155 default: 156 printf("0x%x", (flags & MPS_INT_FLAG_TRIGGER_MASK) >> 2); 157 } 158 printf("}\n"); 159} 160 161static void 162acpi_print_intr(u_int32_t intr, u_int16_t mps_flags) 163{ 164 165 printf("\tINTR=%d\n", (u_int)intr); 166 acpi_print_mps_flags(mps_flags); 167} 168 169const char *apic_types[] = { "Local APIC", "IO APIC", "INT Override", "NMI", 170 "Local NMI", "Local APIC Override", "IO SAPIC", 171 "Local SAPIC", "Platform Interrupt" }; 172const char *platform_int_types[] = { "PMI", "INIT", 173 "Corrected Platform Error" }; 174 175static void 176acpi_print_apic(struct MADT_APIC *mp) 177{ 178 179 printf("\tType=%s\n", apic_types[mp->type]); 180 switch (mp->type) { 181 case ACPI_MADT_APIC_TYPE_LOCAL_APIC: 182 acpi_print_local_apic(mp->body.local_apic.cpu_id, 183 mp->body.local_apic.apic_id, mp->body.local_apic.flags); 184 break; 185 case ACPI_MADT_APIC_TYPE_IO_APIC: 186 acpi_print_io_apic(mp->body.io_apic.apic_id, 187 mp->body.io_apic.int_base, 188 mp->body.io_apic.apic_addr); 189 break; 190 case ACPI_MADT_APIC_TYPE_INT_OVERRIDE: 191 printf("\tBUS=%d\n", (u_int)mp->body.int_override.bus); 192 printf("\tIRQ=%d\n", (u_int)mp->body.int_override.source); 193 acpi_print_intr(mp->body.int_override.intr, 194 mp->body.int_override.mps_flags); 195 break; 196 case ACPI_MADT_APIC_TYPE_NMI: 197 acpi_print_intr(mp->body.nmi.intr, mp->body.nmi.mps_flags); 198 break; 199 case ACPI_MADT_APIC_TYPE_LOCAL_NMI: 200 acpi_print_cpu(mp->body.local_nmi.cpu_id); 201 printf("\tLINT Pin=%d\n", mp->body.local_nmi.lintpin); 202 acpi_print_mps_flags(mp->body.local_nmi.mps_flags); 203 break; 204 case ACPI_MADT_APIC_TYPE_LOCAL_OVERRIDE: 205 printf("\tLocal APIC ADDR=0x%016jx\n", 206 mp->body.local_apic_override.apic_addr); 207 break; 208 case ACPI_MADT_APIC_TYPE_IO_SAPIC: 209 acpi_print_io_apic(mp->body.io_sapic.apic_id, 210 mp->body.io_sapic.int_base, 211 mp->body.io_sapic.apic_addr); 212 break; 213 case ACPI_MADT_APIC_TYPE_LOCAL_SAPIC: 214 acpi_print_local_apic(mp->body.local_sapic.cpu_id, 215 mp->body.local_sapic.apic_id, mp->body.local_sapic.flags); 216 printf("\tAPIC EID=%d\n", (u_int)mp->body.local_sapic.apic_eid); 217 break; 218 case ACPI_MADT_APIC_TYPE_INT_SRC: 219 printf("\tType=%s\n", 220 platform_int_types[mp->body.int_src.type]); 221 printf("\tCPU ID=%d\n", (u_int)mp->body.int_src.cpu_id); 222 printf("\tCPU EID=%d\n", (u_int)mp->body.int_src.cpu_id); 223 printf("\tSAPIC Vector=%d\n", 224 (u_int)mp->body.int_src.sapic_vector); 225 acpi_print_intr(mp->body.int_src.intr, 226 mp->body.int_src.mps_flags); 227 break; 228 default: 229 printf("\tUnknown type %d\n", (u_int)mp->type); 230 break; 231 } 232} 233 234static void 235acpi_handle_apic(struct ACPIsdt *sdp) 236{ 237 struct MADTbody *madtp; 238 struct MADT_APIC *madt_apicp; 239 240 acpi_print_sdt(sdp, /*endcomment*/0); 241 madtp = (struct MADTbody *) sdp->body; 242 printf("\tLocal APIC ADDR=0x%08x\n", madtp->lapic_addr); 243 printf("\tFlags={"); 244 if (madtp->flags & ACPI_APIC_FLAG_PCAT_COMPAT) 245 printf("PC-AT"); 246 printf("}\n"); 247 madt_apicp = (struct MADT_APIC *)madtp->body; 248 while (((uintptr_t)madt_apicp) - ((uintptr_t)sdp) < sdp->len) { 249 printf("\n"); 250 acpi_print_apic(madt_apicp); 251 madt_apicp = (struct MADT_APIC *) ((char *)madt_apicp + 252 madt_apicp->len); 253 } 254 printf(END_COMMENT); 255} 256 257static void 258acpi_handle_hpet(struct ACPIsdt *sdp) 259{ 260 struct HPETbody *hpetp; 261 262 acpi_print_sdt(sdp, /*endcomment*/0); 263 hpetp = (struct HPETbody *) sdp->body; 264 printf("\tHPET Number=%d\n", hpetp->hpet_number); 265 printf("\tADDR=0x%08x\n", hpetp->base_addr); 266 printf("\tHW Rev=0x%x\n", hpetp->block_hwrev); 267 printf("\tComparitors=%d\n", hpetp->block_comparitors); 268 printf("\tCounter Size=%d\n", hpetp->block_counter_size); 269 printf("\tLegacy IRQ routing capable={"); 270 if (hpetp->block_legacy_capable) 271 printf("TRUE}\n"); 272 else 273 printf("FALSE}\n"); 274 printf("\tPCI Vendor ID=0x%04x\n", hpetp->block_pcivendor); 275 printf("\tMinimal Tick=%d\n", hpetp->clock_tick); 276 printf(END_COMMENT); 277} 278 279static void 280acpi_print_sdt(struct ACPIsdt *sdp, int endcomment) 281{ 282 printf(BEGIN_COMMENT " "); 283 acpi_print_string(sdp->signature, 4); 284 printf(": Length=%d, Revision=%d, Checksum=%d,\n", 285 sdp->len, sdp->rev, sdp->check); 286 printf("\tOEMID="); 287 acpi_print_string(sdp->oemid, 6); 288 printf(", OEM Table ID="); 289 acpi_print_string(sdp->oemtblid, 8); 290 printf(", OEM Revision=0x%x,\n", sdp->oemrev); 291 printf("\tCreator ID="); 292 acpi_print_string(sdp->creator, 4); 293 printf(", Creator Revision=0x%x\n", sdp->crerev); 294 if (endcomment) 295 printf(END_COMMENT); 296} 297 298static void 299acpi_print_rsdt(struct ACPIsdt *rsdp) 300{ 301 int i, entries; 302 303 acpi_print_sdt(rsdp, /*endcomment*/0); 304 entries = (rsdp->len - SIZEOF_SDT_HDR) / sizeof(u_int32_t); 305 printf("\tEntries={ "); 306 for (i = 0; i < entries; i++) { 307 if (i > 0) 308 printf(", "); 309 printf("0x%08x", rsdp->body[i]); 310 } 311 printf(" }\n"); 312 printf(END_COMMENT); 313} 314 315static void 316acpi_print_facp(struct FACPbody *facp) 317{ 318 char sep; 319 320 printf(BEGIN_COMMENT); 321 printf(" FACP:\tDSDT=0x%x\n", facp->dsdt_ptr); 322 printf("\tINT_MODEL=%s\n", facp->int_model ? "APIC" : "PIC"); 323 printf("\tSCI_INT=%d\n", facp->sci_int); 324 printf("\tSMI_CMD=0x%x, ", facp->smi_cmd); 325 printf("ACPI_ENABLE=0x%x, ", facp->acpi_enable); 326 printf("ACPI_DISABLE=0x%x, ", facp->acpi_disable); 327 printf("S4BIOS_REQ=0x%x\n", facp->s4biosreq); 328 if (facp->pm1a_evt_blk) 329 printf("\tPM1a_EVT_BLK=0x%x-0x%x\n", 330 facp->pm1a_evt_blk, 331 facp->pm1a_evt_blk + facp->pm1_evt_len - 1); 332 if (facp->pm1b_evt_blk) 333 printf("\tPM1b_EVT_BLK=0x%x-0x%x\n", 334 facp->pm1b_evt_blk, 335 facp->pm1b_evt_blk + facp->pm1_evt_len - 1); 336 if (facp->pm1a_cnt_blk) 337 printf("\tPM1a_CNT_BLK=0x%x-0x%x\n", 338 facp->pm1a_cnt_blk, 339 facp->pm1a_cnt_blk + facp->pm1_cnt_len - 1); 340 if (facp->pm1b_cnt_blk) 341 printf("\tPM1b_CNT_BLK=0x%x-0x%x\n", 342 facp->pm1b_cnt_blk, 343 facp->pm1b_cnt_blk + facp->pm1_cnt_len - 1); 344 if (facp->pm2_cnt_blk) 345 printf("\tPM2_CNT_BLK=0x%x-0x%x\n", 346 facp->pm2_cnt_blk, 347 facp->pm2_cnt_blk + facp->pm2_cnt_len - 1); 348 if (facp->pm_tmr_blk) 349 printf("\tPM2_TMR_BLK=0x%x-0x%x\n", 350 facp->pm_tmr_blk, 351 facp->pm_tmr_blk + facp->pm_tmr_len - 1); 352 if (facp->gpe0_blk) 353 printf("\tPM2_GPE0_BLK=0x%x-0x%x\n", 354 facp->gpe0_blk, 355 facp->gpe0_blk + facp->gpe0_len - 1); 356 if (facp->gpe1_blk) 357 printf("\tPM2_GPE1_BLK=0x%x-0x%x, GPE1_BASE=%d\n", 358 facp->gpe1_blk, 359 facp->gpe1_blk + facp->gpe1_len - 1, 360 facp->gpe1_base); 361 printf("\tP_LVL2_LAT=%dms, P_LVL3_LAT=%dms\n", 362 facp->p_lvl2_lat, facp->p_lvl3_lat); 363 printf("\tFLUSH_SIZE=%d, FLUSH_STRIDE=%d\n", 364 facp->flush_size, facp->flush_stride); 365 printf("\tDUTY_OFFSET=%d, DUTY_WIDTH=%d\n", 366 facp->duty_off, facp->duty_width); 367 printf("\tDAY_ALRM=%d, MON_ALRM=%d, CENTURY=%d\n", 368 facp->day_alrm, facp->mon_alrm, facp->century); 369 printf("\tFlags="); 370 sep = '{'; 371 372#define PRINTFLAG(xx) do { \ 373 if (facp->flags & ACPI_FACP_FLAG_## xx) { \ 374 printf("%c%s", sep, #xx); sep = ','; \ 375 } \ 376} while (0) 377 378 PRINTFLAG(WBINVD); 379 PRINTFLAG(WBINVD_FLUSH); 380 PRINTFLAG(PROC_C1); 381 PRINTFLAG(P_LVL2_UP); 382 PRINTFLAG(PWR_BUTTON); 383 PRINTFLAG(SLP_BUTTON); 384 PRINTFLAG(FIX_RTC); 385 PRINTFLAG(RTC_S4); 386 PRINTFLAG(TMR_VAL_EXT); 387 PRINTFLAG(DCK_CAP); 388 389#undef PRINTFLAG 390 391 printf("}\n"); 392 printf(END_COMMENT); 393} 394 395static void 396acpi_print_dsdt(struct ACPIsdt *dsdp) 397{ 398 acpi_print_sdt(dsdp, /*endcomment*/1); 399} 400 401int 402acpi_checksum(void *p, size_t length) 403{ 404 u_int8_t *bp; 405 u_int8_t sum; 406 407 bp = p; 408 sum = 0; 409 while (length--) 410 sum += *bp++; 411 412 return (sum); 413} 414 415static struct ACPIsdt * 416acpi_map_sdt(vm_offset_t pa) 417{ 418 struct ACPIsdt *sp; 419 420 sp = acpi_map_physical(pa, sizeof(struct ACPIsdt)); 421 sp = acpi_map_physical(pa, sp->len); 422 return (sp); 423} 424 425static void 426acpi_print_rsd_ptr(struct ACPIrsdp *rp) 427{ 428 429 printf(BEGIN_COMMENT); 430 printf(" RSD PTR: Checksum=%d, OEMID=", rp->sum); 431 acpi_print_string(rp->oem, 6); 432 printf(", RsdtAddress=0x%08x\n", rp->rsdt_addr); 433 printf(END_COMMENT); 434} 435 436static void 437acpi_handle_rsdt(struct ACPIsdt *rsdp) 438{ 439 int i; 440 int entries; 441 struct ACPIsdt *sdp; 442 443 entries = (rsdp->len - SIZEOF_SDT_HDR) / sizeof(u_int32_t); 444 acpi_print_rsdt(rsdp); 445 for (i = 0; i < entries; i++) { 446 sdp = (struct ACPIsdt *)acpi_map_sdt(rsdp->body[i]); 447 if (acpi_checksum(sdp, sdp->len)) 448 errx(1, "RSDT entry %d is corrupt", i); 449 if (!memcmp(sdp->signature, "FACP", 4)) 450 acpi_handle_facp((struct FACPbody *) sdp->body); 451 else if (!memcmp(sdp->signature, "APIC", 4)) 452 acpi_handle_apic(sdp); 453 else if (!memcmp(sdp->signature, "HPET", 4)) 454 acpi_handle_hpet(sdp); 455 else 456 acpi_print_sdt(sdp, /*endcomment*/1); 457 } 458} 459 460struct ACPIsdt * 461sdt_load_devmem() 462{ 463 struct ACPIrsdp *rp; 464 struct ACPIsdt *rsdp; 465 466 rp = acpi_find_rsd_ptr(); 467 if (!rp) 468 errx(1, "Can't find ACPI information"); 469 470 if (tflag) 471 acpi_print_rsd_ptr(rp); 472 rsdp = (struct ACPIsdt *)acpi_map_sdt(rp->rsdt_addr); 473 if (memcmp(rsdp->signature, "RSDT", 4) != 0 || 474 acpi_checksum(rsdp, rsdp->len) != 0) 475 errx(1, "RSDT is corrupted"); 476 477 return (rsdp); 478} 479 480void 481dsdt_save_file(char *outfile, struct ACPIsdt *dsdp) 482{ 483 int fd; 484 mode_t mode; 485 486 assert(outfile != NULL); 487 mode = S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH; 488 fd = open(outfile, O_WRONLY | O_CREAT | O_TRUNC, mode); 489 if (fd == -1) { 490 perror("dsdt_save_file"); 491 return; 492 } 493 write(fd, dsdp, SIZEOF_SDT_HDR); 494 write(fd, dsdp->body, dsdp->len - SIZEOF_SDT_HDR); 495 close(fd); 496} 497 498void 499aml_disassemble(struct ACPIsdt *dsdp) 500{ 501 char tmpstr[32], buf[256]; 502 FILE *fp; 503 int fd, len; 504 505 strcpy(tmpstr, "/tmp/acpidump.XXXXXX"); 506 fd = mkstemp(tmpstr); 507 if (fd < 0) { 508 perror("iasl tmp file"); 509 return; 510 } 511 512 /* Dump DSDT to the temp file */ 513 write(fd, dsdp, SIZEOF_SDT_HDR); 514 write(fd, dsdp->body, dsdp->len - SIZEOF_SDT_HDR); 515 close(fd); 516 517 /* Run iasl -d on the temp file */ 518 if (fork() == 0) { 519 close(STDOUT_FILENO); 520 if (vflag == 0) 521 close(STDERR_FILENO); 522 execl("/usr/sbin/iasl", "iasl", "-d", tmpstr, 0); 523 err(1, "exec"); 524 } 525 526 wait(NULL); 527 unlink(tmpstr); 528 529 /* Dump iasl's output to stdout */ 530 fp = fopen("acpidump.dsl", "r"); 531 unlink("acpidump.dsl"); 532 if (fp == NULL) { 533 perror("iasl tmp file (read)"); 534 return; 535 } 536 while ((len = fread(buf, 1, sizeof(buf), fp)) > 0) 537 fwrite(buf, 1, len, stdout); 538 fclose(fp); 539} 540 541void 542sdt_print_all(struct ACPIsdt *rsdp) 543{ 544 acpi_handle_rsdt(rsdp); 545} 546 547/* Fetch a table matching the given signature via the RSDT */ 548struct ACPIsdt * 549sdt_from_rsdt(struct ACPIsdt *rsdt, const char *sig) 550{ 551 int i; 552 int entries; 553 struct ACPIsdt *sdt; 554 555 entries = (rsdt->len - SIZEOF_SDT_HDR) / sizeof(uint32_t); 556 for (i = 0; i < entries; i++) { 557 sdt = (struct ACPIsdt *)acpi_map_sdt(rsdt->body[i]); 558 if (acpi_checksum(sdt, sdt->len)) 559 errx(1, "RSDT entry %d is corrupt", i); 560 if (!memcmp(sdt->signature, sig, strlen(sig))) 561 return (sdt); 562 } 563 564 return (NULL); 565} 566 567struct ACPIsdt * 568dsdt_from_facp(struct FACPbody *facp) 569{ 570 struct ACPIsdt *sdt; 571 572 sdt = (struct ACPIsdt *)acpi_map_sdt(facp->dsdt_ptr); 573 if (acpi_checksum(sdt, sdt->len)) 574 errx(1, "DSDT is corrupt\n"); 575 return (sdt); 576} 577