acpi.c revision 85323
1/*- 2 * Copyright (c) 1998 Doug Rabson 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 * $Id: acpi.c,v 1.4 2000/08/09 14:47:52 iwasaki Exp $ 28 * $FreeBSD: head/usr.sbin/acpi/acpidump/acpi.c 85323 2001-10-22 17:25:32Z iwasaki $ 29 */ 30 31#include <sys/param.h> 32#include <sys/stat.h> 33 34#include <assert.h> 35#include <err.h> 36#include <fcntl.h> 37#include <stdio.h> 38#include <unistd.h> 39 40#include "acpidump.h" 41 42#include "aml/aml_env.h" 43#include "aml/aml_common.h" 44 45#define BEGIN_COMMENT "/*\n" 46#define END_COMMENT " */\n" 47 48struct ACPIsdt dsdt_header = { 49 "DSDT", 0, 1, 0, "OEMID", "OEMTBLID", 0x12345678, "CRTR", 0x12345678 50}; 51 52static void 53acpi_trim_string(char *s, size_t length) 54{ 55 56 /* Trim trailing spaces and NULLs */ 57 while (length > 0 && (s[length - 1] == ' ' || s[length - 1] == '\0')) 58 s[length-- - 1] = '\0'; 59} 60 61static void 62acpi_print_dsdt_definition(void) 63{ 64 char oemid[6 + 1]; 65 char oemtblid[8 + 1]; 66 67 acpi_trim_string(dsdt_header.oemid, 6); 68 acpi_trim_string(dsdt_header.oemtblid, 8); 69 strncpy(oemid, dsdt_header.oemid, 6); 70 oemid[6] = '\0'; 71 strncpy(oemtblid, dsdt_header.oemtblid, 8); 72 oemtblid[8] = '\0'; 73 74 printf("DefinitionBlock ( 75 \"acpi_dsdt.aml\", //Output filename 76 \"DSDT\", //Signature 77 0x%x, //DSDT Revision 78 \"%s\", //OEMID 79 \"%s\", //TABLE ID 80 0x%x //OEM Revision\n)\n", 81 dsdt_header.rev, oemid, oemtblid, dsdt_header.oemrev); 82} 83 84static void 85acpi_print_string(char *s, size_t length) 86{ 87 int c; 88 89 /* Trim trailing spaces and NULLs */ 90 while (length > 0 && (s[length - 1] == ' ' || s[length - 1] == '\0')) 91 length--; 92 93 while (length--) { 94 c = *s++; 95 putchar(c); 96 } 97} 98 99static void 100acpi_handle_dsdt(struct ACPIsdt *dsdp) 101{ 102 u_int8_t *dp; 103 u_int8_t *end; 104 105 acpi_print_dsdt(dsdp); 106 dp = (u_int8_t *)dsdp->body; 107 end = (u_int8_t *)dsdp + dsdp->len; 108 109 acpi_dump_dsdt(dp, end); 110} 111 112static void 113acpi_handle_facp(struct FACPbody *facp) 114{ 115 struct ACPIsdt *dsdp; 116 117 acpi_print_facp(facp); 118 dsdp = (struct ACPIsdt *) acpi_map_sdt(facp->dsdt_ptr); 119 if (acpi_checksum(dsdp, dsdp->len)) 120 errx(1, "DSDT is corrupt\n"); 121 acpi_handle_dsdt(dsdp); 122 aml_dump(dsdp); 123} 124 125static void 126init_namespace() 127{ 128 struct aml_environ env; 129 struct aml_name *newname; 130 131 aml_new_name_group(AML_NAME_GROUP_OS_DEFINED); 132 env.curname = aml_get_rootname(); 133 newname = aml_create_name(&env, "\\_OS_"); 134 newname->property = aml_alloc_object(aml_t_string, NULL); 135 newname->property->str.needfree = 0; 136 newname->property->str.string = "Microsoft Windows NT"; 137} 138 139/* 140 * Public interfaces 141 */ 142 143void 144acpi_dump_dsdt(u_int8_t *dp, u_int8_t *end) 145{ 146 extern struct aml_environ asl_env; 147 148 acpi_print_dsdt_definition(); 149 150 /* 1st stage: parse only w/o printing */ 151 init_namespace(); 152 aml_new_name_group((int)dp); 153 bzero(&asl_env, sizeof(asl_env)); 154 155 asl_env.dp = dp; 156 asl_env.end = end; 157 asl_env.curname = aml_get_rootname(); 158 159 aml_local_stack_push(aml_local_stack_create()); 160 aml_parse_objectlist(&asl_env, 0); 161 aml_local_stack_delete(aml_local_stack_pop()); 162 163 assert(asl_env.dp == asl_env.end); 164 asl_env.dp = dp; 165 166 /* 2nd stage: dump whole object list */ 167 printf("\n{\n"); 168 asl_dump_objectlist(&dp, end, 0); 169 printf("\n}\n"); 170 assert(dp == end); 171} 172void 173acpi_print_sdt(struct ACPIsdt *sdp) 174{ 175 176 printf(BEGIN_COMMENT); 177 acpi_print_string(sdp->signature, 4); 178 printf(": Length=%d, Revision=%d, Checksum=%d,\n", 179 sdp->len, sdp->rev, sdp->check); 180 printf("\tOEMID="); 181 acpi_print_string(sdp->oemid, 6); 182 printf(", OEM Table ID="); 183 acpi_print_string(sdp->oemtblid, 8); 184 printf(", OEM Revision=0x%x,\n", sdp->oemrev); 185 printf("\tCreator ID="); 186 acpi_print_string(sdp->creator, 4); 187 printf(", Creator Revision=0x%x\n", sdp->crerev); 188 printf(END_COMMENT); 189 if (!memcmp(sdp->signature, "DSDT", 4)) { 190 memcpy(&dsdt_header, sdp, sizeof(dsdt_header)); 191 } 192} 193 194void 195acpi_print_rsdt(struct ACPIsdt *rsdp) 196{ 197 int i, entries; 198 199 acpi_print_sdt(rsdp); 200 entries = (rsdp->len - SIZEOF_SDT_HDR) / sizeof(u_int32_t); 201 printf(BEGIN_COMMENT); 202 printf("\tEntries={ "); 203 for (i = 0; i < entries; i++) { 204 if (i > 0) 205 printf(", "); 206 printf("0x%08x", rsdp->body[i]); 207 } 208 printf(" }\n"); 209 printf(END_COMMENT); 210} 211 212void 213acpi_print_facp(struct FACPbody *facp) 214{ 215 char sep; 216 217 printf(BEGIN_COMMENT); 218 printf("\tDSDT=0x%x\n", facp->dsdt_ptr); 219 printf("\tINT_MODEL=%s\n", facp->int_model ? "APIC" : "PIC"); 220 printf("\tSCI_INT=%d\n", facp->sci_int); 221 printf("\tSMI_CMD=0x%x, ", facp->smi_cmd); 222 printf("ACPI_ENABLE=0x%x, ", facp->acpi_enable); 223 printf("ACPI_DISABLE=0x%x, ", facp->acpi_disable); 224 printf("S4BIOS_REQ=0x%x\n", facp->s4biosreq); 225 if (facp->pm1a_evt_blk) 226 printf("\tPM1a_EVT_BLK=0x%x-0x%x\n", 227 facp->pm1a_evt_blk, 228 facp->pm1a_evt_blk + facp->pm1_evt_len - 1); 229 if (facp->pm1b_evt_blk) 230 printf("\tPM1b_EVT_BLK=0x%x-0x%x\n", 231 facp->pm1b_evt_blk, 232 facp->pm1b_evt_blk + facp->pm1_evt_len - 1); 233 if (facp->pm1a_cnt_blk) 234 printf("\tPM1a_CNT_BLK=0x%x-0x%x\n", 235 facp->pm1a_cnt_blk, 236 facp->pm1a_cnt_blk + facp->pm1_cnt_len - 1); 237 if (facp->pm1b_cnt_blk) 238 printf("\tPM1b_CNT_BLK=0x%x-0x%x\n", 239 facp->pm1b_cnt_blk, 240 facp->pm1b_cnt_blk + facp->pm1_cnt_len - 1); 241 if (facp->pm2_cnt_blk) 242 printf("\tPM2_CNT_BLK=0x%x-0x%x\n", 243 facp->pm2_cnt_blk, 244 facp->pm2_cnt_blk + facp->pm2_cnt_len - 1); 245 if (facp->pm_tmr_blk) 246 printf("\tPM2_TMR_BLK=0x%x-0x%x\n", 247 facp->pm_tmr_blk, 248 facp->pm_tmr_blk + facp->pm_tmr_len - 1); 249 if (facp->gpe0_blk) 250 printf("\tPM2_GPE0_BLK=0x%x-0x%x\n", 251 facp->gpe0_blk, 252 facp->gpe0_blk + facp->gpe0_len - 1); 253 if (facp->gpe1_blk) 254 printf("\tPM2_GPE1_BLK=0x%x-0x%x, GPE1_BASE=%d\n", 255 facp->gpe1_blk, 256 facp->gpe1_blk + facp->gpe1_len - 1, 257 facp->gpe1_base); 258 printf("\tP_LVL2_LAT=%dms, P_LVL3_LAT=%dms\n", 259 facp->p_lvl2_lat, facp->p_lvl3_lat); 260 printf("\tFLUSH_SIZE=%d, FLUSH_STRIDE=%d\n", 261 facp->flush_size, facp->flush_stride); 262 printf("\tDUTY_OFFSET=%d, DUTY_WIDTH=%d\n", 263 facp->duty_off, facp->duty_width); 264 printf("\tDAY_ALRM=%d, MON_ALRM=%d, CENTURY=%d\n", 265 facp->day_alrm, facp->mon_alrm, facp->century); 266 printf("\tFlags="); 267 sep = '{'; 268 269#define PRINTFLAG(xx) do { \ 270 if (facp->flags & ACPI_FACP_FLAG_## xx) { \ 271 printf("%c%s", sep, #xx); sep = ','; \ 272 } \ 273} while (0) 274 275 PRINTFLAG(WBINVD); 276 PRINTFLAG(WBINVD_FLUSH); 277 PRINTFLAG(PROC_C1); 278 PRINTFLAG(P_LVL2_UP); 279 PRINTFLAG(PWR_BUTTON); 280 PRINTFLAG(SLP_BUTTON); 281 PRINTFLAG(FIX_RTC); 282 PRINTFLAG(RTC_S4); 283 PRINTFLAG(TMR_VAL_EXT); 284 PRINTFLAG(DCK_CAP); 285 286#undef PRINTFLAG 287 288 printf("}\n"); 289 printf(END_COMMENT); 290} 291 292void 293acpi_print_dsdt(struct ACPIsdt *dsdp) 294{ 295 296 acpi_print_sdt(dsdp); 297} 298 299int 300acpi_checksum(void *p, size_t length) 301{ 302 u_int8_t *bp; 303 u_int8_t sum; 304 305 bp = p; 306 sum = 0; 307 while (length--) 308 sum += *bp++; 309 310 return (sum); 311} 312 313struct ACPIsdt * 314acpi_map_sdt(vm_offset_t pa) 315{ 316 struct ACPIsdt *sp; 317 318 sp = acpi_map_physical(pa, sizeof(struct ACPIsdt)); 319 sp = acpi_map_physical(pa, sp->len); 320 return (sp); 321} 322 323void 324acpi_print_rsd_ptr(struct ACPIrsdp *rp) 325{ 326 327 printf(BEGIN_COMMENT); 328 printf("RSD PTR: Checksum=%d, OEMID=", rp->sum); 329 acpi_print_string(rp->oem, 6); 330 printf(", RsdtAddress=0x%08x\n", rp->addr); 331 printf(END_COMMENT); 332} 333 334void 335acpi_handle_rsdt(struct ACPIsdt *rsdp) 336{ 337 int i; 338 int entries; 339 struct ACPIsdt *sdp; 340 341 entries = (rsdp->len - SIZEOF_SDT_HDR) / sizeof(u_int32_t); 342 acpi_print_rsdt(rsdp); 343 for (i = 0; i < entries; i++) { 344 sdp = (struct ACPIsdt *) acpi_map_sdt(rsdp->body[i]); 345 if (acpi_checksum(sdp, sdp->len)) 346 errx(1, "RSDT entry %d is corrupt\n", i); 347 if (!memcmp(sdp->signature, "FACP", 4)) { 348 acpi_handle_facp((struct FACPbody *) sdp->body); 349 } else { 350 acpi_print_sdt(sdp); 351 } 352 } 353} 354 355/* 356 * Dummy functions 357 */ 358 359void 360aml_dbgr(struct aml_environ *env1, struct aml_environ *env2) 361{ 362 /* do nothing */ 363} 364 365int 366aml_region_read_simple(struct aml_region_handle *h, vm_offset_t offset, 367 u_int32_t *valuep) 368{ 369 return (0); 370} 371 372int 373aml_region_write_simple(struct aml_region_handle *h, vm_offset_t offset, 374 u_int32_t value) 375{ 376 return (0); 377} 378 379u_int32_t 380aml_region_prompt_read(struct aml_region_handle *h, u_int32_t value) 381{ 382 return (0); 383} 384 385u_int32_t 386aml_region_prompt_write(struct aml_region_handle *h, u_int32_t value) 387{ 388 return (0); 389} 390 391int 392aml_region_prompt_update_value(u_int32_t orgval, u_int32_t value, 393 struct aml_region_handle *h) 394{ 395 return (0); 396} 397 398u_int32_t 399aml_region_read(struct aml_environ *env, int regtype, u_int32_t flags, 400 u_int32_t addr, u_int32_t bitoffset, u_int32_t bitlen) 401{ 402 return (0); 403} 404 405int 406aml_region_write(struct aml_environ *env, int regtype, u_int32_t flags, 407 u_int32_t value, u_int32_t addr, u_int32_t bitoffset, u_int32_t bitlen) 408{ 409 return (0); 410} 411 412int 413aml_region_write_from_buffer(struct aml_environ *env, int regtype, 414 u_int32_t flags, u_int8_t *buffer, u_int32_t addr, u_int32_t bitoffset, 415 u_int32_t bitlen) 416{ 417 return (0); 418} 419 420int 421aml_region_bcopy(struct aml_environ *env, int regtype, u_int32_t flags, 422 u_int32_t addr, u_int32_t bitoffset, u_int32_t bitlen, 423 u_int32_t dflags, u_int32_t daddr, 424 u_int32_t dbitoffset, u_int32_t dbitlen) 425{ 426 return (0); 427} 428 429int 430aml_region_read_into_buffer(struct aml_environ *env, int regtype, 431 u_int32_t flags, u_int32_t addr, u_int32_t bitoffset, 432 u_int32_t bitlen, u_int8_t *buffer) 433{ 434 return (0); 435} 436 437