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