aboutsummaryrefslogtreecommitdiffstats
path: root/tools/power
diff options
context:
space:
mode:
authorLen Brown <len.brown@intel.com>2012-09-22 23:09:15 -0400
committerLen Brown <len.brown@intel.com>2012-09-22 23:09:15 -0400
commitd4bb1c90c850c5163f28b1c04d16c5d85aaaf815 (patch)
treef5b0918d472bd0c2ea48bff49034fdcff643df69 /tools/power
parent39a55ff2c34a11ab9bbc8ba6f4dfb5d366cb2532 (diff)
tools/power/acpi/acpidump: version 20101221 - find dynamic tables in sysfs
This is unchanged version 20101221, plus a small bit in DEFINE_ALTERNATE_TYPES to enable building with latest kernel headers. This version finds dynamic tables exported by Linux in /sys/firmware/acpi/tables/dynamic Signed-off-by: Len Brown <len.brown@intel.com>
Diffstat (limited to 'tools/power')
-rw-r--r--tools/power/acpi/acpidump.c187
1 files changed, 89 insertions, 98 deletions
diff --git a/tools/power/acpi/acpidump.c b/tools/power/acpi/acpidump.c
index a63dee960311..07779871421c 100644
--- a/tools/power/acpi/acpidump.c
+++ b/tools/power/acpi/acpidump.c
@@ -1,6 +1,5 @@
1/* 1/*
2 * (c) Alexey Starikovskiy, Intel, 2005-2006. 2 * (c) Alexey Starikovskiy, Intel, 2005-2006.
3 * (c) Len Brown, Intel, 2007.
4 * All rights reserved. 3 * All rights reserved.
5 * 4 *
6 * Redistribution and use in source and binary forms, with or without 5 * Redistribution and use in source and binary forms, with or without
@@ -63,6 +62,8 @@ typedef long long s64;
63#include <unistd.h> 62#include <unistd.h>
64#include <getopt.h> 63#include <getopt.h>
65 64
65#include <sys/types.h>
66#include <dirent.h>
66 67
67#include <acpi/acconfig.h> 68#include <acpi/acconfig.h>
68#include <acpi/platform/acenv.h> 69#include <acpi/platform/acenv.h>
@@ -186,40 +187,6 @@ static void acpi_show_data(int fd, u8 * data, int size)
186/* 187/*
187 * Output ACPI table 188 * Output ACPI table
188 */ 189 */
189
190#define MAX_TABLES 128
191int next_table_dump;
192u64 dumped_tables[MAX_TABLES];
193
194void
195set_table_dumped(u64 address) {
196 if (next_table_dump >= MAX_TABLES) {
197 printf("increase MAX_TABLES\n");
198 exit(1);
199 }
200 dumped_tables[next_table_dump++] = address;
201}
202
203/*
204 * list the tables as they are dumped
205 * check the list so that they are not dumped twice.
206 *
207 * this is needed because we follow both the XSDT and RSDT
208 * which generally point to all duplicate tables
209 * except the FADT
210 */
211int
212check_table_dumped(u64 address) {
213 int i;
214
215 for (i = 0; i < MAX_TABLES; ++i) {
216 if (address == dumped_tables[i])
217 return 1;
218 if (dumped_tables[i] == 0)
219 return 0;
220 }
221 return 0;
222}
223static void acpi_show_table(int fd, struct acpi_table_header *table, unsigned long addr) 190static void acpi_show_table(int fd, struct acpi_table_header *table, unsigned long addr)
224{ 191{
225 char buff[80]; 192 char buff[80];
@@ -233,10 +200,6 @@ static void acpi_show_table(int fd, struct acpi_table_header *table, unsigned lo
233static void write_table(int fd, struct acpi_table_header *tbl, unsigned long addr) 200static void write_table(int fd, struct acpi_table_header *tbl, unsigned long addr)
234{ 201{
235 static int select_done = 0; 202 static int select_done = 0;
236
237 if (check_table_dumped((u64)addr))
238 return;
239
240 if (!select_sig[0]) { 203 if (!select_sig[0]) {
241 if (print) { 204 if (print) {
242 acpi_show_table(fd, tbl, addr); 205 acpi_show_table(fd, tbl, addr);
@@ -255,7 +218,6 @@ static void write_table(int fd, struct acpi_table_header *tbl, unsigned long add
255 } 218 }
256 select_done = 1; 219 select_done = 1;
257 } 220 }
258 set_table_dumped((u64) addr);
259} 221}
260 222
261static void acpi_dump_FADT(int fd, struct acpi_table_header *tbl, unsigned long xaddr) { 223static void acpi_dump_FADT(int fd, struct acpi_table_header *tbl, unsigned long xaddr) {
@@ -312,26 +274,30 @@ no_facs:
312 write_table(fd, (struct acpi_table_header *)&x, xaddr); 274 write_table(fd, (struct acpi_table_header *)&x, xaddr);
313} 275}
314 276
315 277static int acpi_dump_SDT(int fd, struct acpi_rsdp_descriptor *rsdp)
316static int acpi_dump_RSDT(int fd, struct acpi_rsdp_descriptor *rsdp)
317{ 278{
318 struct acpi_table_header *sdt, *tbl = 0; 279 struct acpi_table_header *sdt, *tbl = 0;
319 int i, num; 280 int xsdt = 1, i, num;
320 char *offset; 281 char *offset;
321 unsigned long addr; 282 unsigned long addr;
322 283 if (rsdp->revision > 1 && rsdp->xsdt_physical_address) {
323 tbl = acpi_map_table(rsdp->rsdt_physical_address, "RSDT"); 284 tbl = acpi_map_table(rsdp->xsdt_physical_address, "XSDT");
285 }
286 if (!tbl && rsdp->rsdt_physical_address) {
287 xsdt = 0;
288 tbl = acpi_map_table(rsdp->rsdt_physical_address, "RSDT");
289 }
324 if (!tbl) return 0; 290 if (!tbl) return 0;
325
326 sdt = malloc(tbl->length); 291 sdt = malloc(tbl->length);
327 memcpy(sdt, tbl, tbl->length); 292 memcpy(sdt, tbl, tbl->length);
328 acpi_unmap_table(tbl); 293 acpi_unmap_table(tbl);
329 if (checksum((u8 *)sdt, sdt->length)) 294 if (checksum((u8 *)sdt, sdt->length))
330 fprintf(stderr, "Wrong checksum for %s!\n", "RSDT"); 295 fprintf(stderr, "Wrong checksum for %s!\n", (xsdt)?"XSDT":"RSDT");
331 num = (sdt->length - sizeof(struct acpi_table_header))/sizeof(u32); 296 num = (sdt->length - sizeof(struct acpi_table_header))/((xsdt)?sizeof(u64):sizeof(u32));
332 offset = (char *)sdt + sizeof(struct acpi_table_header); 297 offset = (char *)sdt + sizeof(struct acpi_table_header);
333 for (i = 0; i < num; ++i, offset += sizeof(u32)) { 298 for (i = 0; i < num; ++i, offset += ((xsdt) ? sizeof(u64) : sizeof(u32))) {
334 addr = (unsigned long)(*(u32 *)offset); 299 addr = (xsdt) ? (unsigned long)(*(u64 *)offset):
300 (unsigned long)(*(u32 *)offset);
335 if (!addr) continue; 301 if (!addr) continue;
336 tbl = acpi_map_table(addr, 0); 302 tbl = acpi_map_table(addr, 0);
337 if (!tbl) continue; 303 if (!tbl) continue;
@@ -339,66 +305,92 @@ static int acpi_dump_RSDT(int fd, struct acpi_rsdp_descriptor *rsdp)
339 acpi_dump_FADT(fd, tbl, addr); 305 acpi_dump_FADT(fd, tbl, addr);
340 } else { 306 } else {
341 if (checksum((u8 *)tbl, tbl->length)) 307 if (checksum((u8 *)tbl, tbl->length))
342 fprintf(stderr, "Wrong checksum for %.4s!\n", tbl->signature); 308 fprintf(stderr, "Wrong checksum for generic table!\n");
343 write_table(fd, tbl, addr); 309 write_table(fd, tbl, addr);
344 } 310 }
345 acpi_unmap_table(tbl); 311 acpi_unmap_table(tbl);
346 if (connect) { 312 if (connect) {
347 (*(u32*)offset) = lseek(fd, 0, SEEK_CUR); 313 if (xsdt)
314 (*(u64*)offset) = lseek(fd, 0, SEEK_CUR);
315 else
316 (*(u32*)offset) = lseek(fd, 0, SEEK_CUR);
348 } 317 }
349 } 318 }
350 addr = (unsigned long)rsdp->rsdt_physical_address; 319 if (xsdt) {
351 if (connect) { 320 addr = (unsigned long)rsdp->xsdt_physical_address;
352 rsdp->rsdt_physical_address = lseek(fd, 0, SEEK_CUR); 321 if (connect) {
322 rsdp->xsdt_physical_address = lseek(fd, 0, SEEK_CUR);
323 }
324 } else {
325 addr = (unsigned long)rsdp->rsdt_physical_address;
326 if (connect) {
327 rsdp->rsdt_physical_address = lseek(fd, 0, SEEK_CUR);
328 }
353 } 329 }
354 write_table(fd, sdt, addr); 330 write_table(fd, sdt, addr);
355 free (sdt); 331 free (sdt);
356 return 1; 332 return 1;
357} 333}
358 334
335#define DYNAMIC_SSDT "/sys/firmware/acpi/tables/dynamic"
359 336
360static int acpi_dump_XSDT(int fd, struct acpi_rsdp_descriptor *rsdp) 337static void acpi_dump_dynamic_SSDT(int fd)
361{ 338{
362 struct acpi_table_header *sdt, *tbl = 0; 339 struct stat file_stat;
363 int i, num; 340 char filename[256], *ptr;
364 char *offset; 341 DIR *tabledir;
365 unsigned long addr; 342 struct dirent *entry;
366 if (rsdp->revision > 1 && rsdp->xsdt_physical_address) { 343 FILE *fp;
367 tbl = acpi_map_table(rsdp->xsdt_physical_address, "XSDT"); 344 int count, readcount, length;
345 struct acpi_table_header table_header, *ptable;
346
347 if (stat(DYNAMIC_SSDT, &file_stat) == -1) {
348 /* The directory doesn't exist */
349 return;
368 } 350 }
369 if (!tbl) return 0; 351 tabledir = opendir(DYNAMIC_SSDT);
370 352 if(!tabledir){
371 sdt = malloc(tbl->length); 353 /*can't open the directory */
372 memcpy(sdt, tbl, tbl->length); 354 return;
373 acpi_unmap_table(tbl); 355 }
374 if (checksum((u8 *)sdt, sdt->length)) 356
375 fprintf(stderr, "Wrong checksum for %s!\n", "XSDT"); 357 while ((entry = readdir(tabledir)) != 0){
376 num = (sdt->length - sizeof(struct acpi_table_header))/sizeof(u64); 358 /* skip the file of . /.. */
377 offset = (char *)sdt + sizeof(struct acpi_table_header); 359 if (entry->d_name[0] == '.')
378 for (i = 0; i < num; ++i, offset += sizeof(u64)) { 360 continue;
379 addr = (unsigned long)(*(u64 *)offset); 361
380 if (!addr) continue; 362 sprintf(filename, "%s/%s", DYNAMIC_SSDT, entry->d_name);
381 tbl = acpi_map_table(addr, 0); 363 fp = fopen(filename, "r");
382 if (!tbl) continue; 364 if (fp == NULL) {
383 if (!memcmp(tbl->signature, FADT_SIG, 4)) { 365 fprintf(stderr, "Can't open the file of %s\n",
384 acpi_dump_FADT(fd, tbl, addr); 366 filename);
385 } else { 367 continue;
386 if (checksum((u8 *)tbl, tbl->length))
387 fprintf(stderr, "Wrong checksum for %.4s\n", tbl->signature);
388 write_table(fd, tbl, addr);
389 } 368 }
390 acpi_unmap_table(tbl); 369 /* Read the Table header to parse the table length */
391 if (connect) { 370 count = fread(&table_header, 1, sizeof(struct acpi_table_header), fp);
392 (*(u64*)offset) = lseek(fd, 0, SEEK_CUR); 371 if (count < sizeof(table_header)) {
372 /* the length is lessn than ACPI table header. skip it */
373 fclose(fp);
374 continue;
393 } 375 }
376 length = table_header.length;
377 ptr = malloc(table_header.length);
378 fseek(fp, 0, SEEK_SET);
379 readcount = 0;
380 while(!feof(fp) && readcount < length) {
381 count = fread(ptr + readcount, 1, 256, fp);
382 readcount += count;
383 }
384 fclose(fp);
385 ptable = (struct acpi_table_header *) ptr;
386 if (checksum((u8 *) ptable, ptable->length))
387 fprintf(stderr, "Wrong checksum "
388 "for dynamic SSDT table!\n");
389 write_table(fd, ptable, 0);
390 free(ptr);
394 } 391 }
395 addr = (unsigned long)rsdp->xsdt_physical_address; 392 closedir(tabledir);
396 if (connect) { 393 return;
397 rsdp->xsdt_physical_address = lseek(fd, 0, SEEK_CUR);
398 }
399 write_table(fd, sdt, addr);
400 free (sdt);
401 return 1;
402} 394}
403 395
404static void usage(const char *progname) 396static void usage(const char *progname)
@@ -518,6 +510,7 @@ int main(int argc, char **argv)
518 goto not_found; 510 goto not_found;
519 write(fd, raw, length); 511 write(fd, raw, length);
520 acpi_unmap_memory(raw, length); 512 acpi_unmap_memory(raw, length);
513 close(fd);
521 return 0; 514 return 0;
522 } 515 }
523 516
@@ -540,12 +533,7 @@ int main(int argc, char **argv)
540 if (connect) { 533 if (connect) {
541 lseek(fd, sizeof(struct acpi_rsdp_descriptor), SEEK_SET); 534 lseek(fd, sizeof(struct acpi_rsdp_descriptor), SEEK_SET);
542 } 535 }
543 if (rsdpx.revision > 1 && rsdpx.xsdt_physical_address) { 536 if (!acpi_dump_SDT(fd, &rsdpx))
544 /* ACPIDUMP uses xsdt table */
545 if (!acpi_dump_XSDT(fd, &rsdpx))
546 goto not_found;
547 }
548 if (!acpi_dump_RSDT(fd, &rsdpx))
549 goto not_found; 537 goto not_found;
550 if (connect) { 538 if (connect) {
551 lseek(fd, 0, SEEK_SET); 539 lseek(fd, 0, SEEK_SET);
@@ -560,8 +548,11 @@ int main(int argc, char **argv)
560 buff[0] = '\n'; 548 buff[0] = '\n';
561 write(fd, buff, 1); 549 write(fd, buff, 1);
562 } 550 }
551 acpi_dump_dynamic_SSDT(fd);
552 close(fd);
563 return 0; 553 return 0;
564not_found: 554not_found:
555 close(fd);
565 fprintf(stderr, "ACPI tables were not found. If you know location " 556 fprintf(stderr, "ACPI tables were not found. If you know location "
566 "of RSD PTR table (from dmesg, etc), " 557 "of RSD PTR table (from dmesg, etc), "
567 "supply it with either --addr or -a option\n"); 558 "supply it with either --addr or -a option\n");