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$ 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 48 struct ACPIsdt dsdt_header = { 49 "DSDT", 0, 1, 0, "OEMID", "OEMTBLID", 0x12345678, "CRTR", 0x12345678 50 }; 51 52 static void 53 acpi_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 61 static void 62 acpi_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 84 static void 85 acpi_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 99 static void 100 acpi_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 112 static void 113 acpi_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 125 static void 126 init_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 143 void 144 acpi_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 } 172 void 173 acpi_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 194 void 195 acpi_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 212 void 213 acpi_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 292 void 293 acpi_print_dsdt(struct ACPIsdt *dsdp) 294 { 295 296 acpi_print_sdt(dsdp); 297 } 298 299 int 300 acpi_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 313 struct ACPIsdt * 314 acpi_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 323 void 324 acpi_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 334 void 335 acpi_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 359 void 360 aml_dbgr(struct aml_environ *env1, struct aml_environ *env2) 361 { 362 /* do nothing */ 363 } 364 365 int 366 aml_region_read_simple(struct aml_region_handle *h, vm_offset_t offset, 367 u_int32_t *valuep) 368 { 369 return (0); 370 } 371 372 int 373 aml_region_write_simple(struct aml_region_handle *h, vm_offset_t offset, 374 u_int32_t value) 375 { 376 return (0); 377 } 378 379 u_int32_t 380 aml_region_prompt_read(struct aml_region_handle *h, u_int32_t value) 381 { 382 return (0); 383 } 384 385 u_int32_t 386 aml_region_prompt_write(struct aml_region_handle *h, u_int32_t value) 387 { 388 return (0); 389 } 390 391 int 392 aml_region_prompt_update_value(u_int32_t orgval, u_int32_t value, 393 struct aml_region_handle *h) 394 { 395 return (0); 396 } 397 398 u_int32_t 399 aml_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 405 int 406 aml_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 412 int 413 aml_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 420 int 421 aml_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 429 int 430 aml_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