diff options
Diffstat (limited to 'tools')
38 files changed, 3549 insertions, 777 deletions
diff --git a/tools/Makefile b/tools/Makefile index bcae806b0c39..9a617adc6675 100644 --- a/tools/Makefile +++ b/tools/Makefile | |||
@@ -44,6 +44,9 @@ cpupower: FORCE | |||
44 | cgroup firewire hv guest usb virtio vm net: FORCE | 44 | cgroup firewire hv guest usb virtio vm net: FORCE |
45 | $(call descend,$@) | 45 | $(call descend,$@) |
46 | 46 | ||
47 | liblockdep: FORCE | ||
48 | $(call descend,lib/lockdep) | ||
49 | |||
47 | libapikfs: FORCE | 50 | libapikfs: FORCE |
48 | $(call descend,lib/api) | 51 | $(call descend,lib/api) |
49 | 52 | ||
@@ -91,6 +94,9 @@ cpupower_clean: | |||
91 | cgroup_clean hv_clean firewire_clean lguest_clean usb_clean virtio_clean vm_clean net_clean: | 94 | cgroup_clean hv_clean firewire_clean lguest_clean usb_clean virtio_clean vm_clean net_clean: |
92 | $(call descend,$(@:_clean=),clean) | 95 | $(call descend,$(@:_clean=),clean) |
93 | 96 | ||
97 | liblockdep_clean: | ||
98 | $(call descend,lib/lockdep,clean) | ||
99 | |||
94 | libapikfs_clean: | 100 | libapikfs_clean: |
95 | $(call descend,lib/api,clean) | 101 | $(call descend,lib/api,clean) |
96 | 102 | ||
diff --git a/tools/lib/api/fs/debugfs.c b/tools/lib/api/fs/debugfs.c index 7c4347962353..a74fba6d7743 100644 --- a/tools/lib/api/fs/debugfs.c +++ b/tools/lib/api/fs/debugfs.c | |||
@@ -12,8 +12,8 @@ | |||
12 | char debugfs_mountpoint[PATH_MAX + 1] = "/sys/kernel/debug"; | 12 | char debugfs_mountpoint[PATH_MAX + 1] = "/sys/kernel/debug"; |
13 | 13 | ||
14 | static const char * const debugfs_known_mountpoints[] = { | 14 | static const char * const debugfs_known_mountpoints[] = { |
15 | "/sys/kernel/debug/", | 15 | "/sys/kernel/debug", |
16 | "/debug/", | 16 | "/debug", |
17 | 0, | 17 | 0, |
18 | }; | 18 | }; |
19 | 19 | ||
diff --git a/tools/lib/lockdep/Makefile b/tools/lib/lockdep/Makefile index cb09d3ff8f58..bba2f5253b6e 100644 --- a/tools/lib/lockdep/Makefile +++ b/tools/lib/lockdep/Makefile | |||
@@ -1,8 +1,7 @@ | |||
1 | # file format version | 1 | # file format version |
2 | FILE_VERSION = 1 | 2 | FILE_VERSION = 1 |
3 | 3 | ||
4 | MAKEFLAGS += --no-print-directory | 4 | LIBLOCKDEP_VERSION=$(shell make --no-print-directory -sC ../../.. kernelversion) |
5 | LIBLOCKDEP_VERSION=$(shell make -sC ../../.. kernelversion) | ||
6 | 5 | ||
7 | # Makefiles suck: This macro sets a default value of $(2) for the | 6 | # Makefiles suck: This macro sets a default value of $(2) for the |
8 | # variable named by $(1), unless the variable has been set by | 7 | # variable named by $(1), unless the variable has been set by |
@@ -231,7 +230,7 @@ install_lib: all_cmd | |||
231 | install: install_lib | 230 | install: install_lib |
232 | 231 | ||
233 | clean: | 232 | clean: |
234 | $(RM) *.o *~ $(TARGETS) *.a *.so $(VERSION_FILES) .*.d | 233 | $(RM) *.o *~ $(TARGETS) *.a *liblockdep*.so* $(VERSION_FILES) .*.d |
235 | $(RM) tags TAGS | 234 | $(RM) tags TAGS |
236 | 235 | ||
237 | endif # skip-makefile | 236 | endif # skip-makefile |
diff --git a/tools/lib/traceevent/event-parse.c b/tools/lib/traceevent/event-parse.c index baec7d887da4..b83184f2d484 100644 --- a/tools/lib/traceevent/event-parse.c +++ b/tools/lib/traceevent/event-parse.c | |||
@@ -4344,6 +4344,7 @@ static void pretty_print(struct trace_seq *s, void *data, int size, struct event | |||
4344 | format, len_arg, arg); | 4344 | format, len_arg, arg); |
4345 | trace_seq_terminate(&p); | 4345 | trace_seq_terminate(&p); |
4346 | trace_seq_puts(s, p.buffer); | 4346 | trace_seq_puts(s, p.buffer); |
4347 | trace_seq_destroy(&p); | ||
4347 | arg = arg->next; | 4348 | arg = arg->next; |
4348 | break; | 4349 | break; |
4349 | default: | 4350 | default: |
diff --git a/tools/lib/traceevent/event-parse.h b/tools/lib/traceevent/event-parse.h index 791c539374c7..feab94281634 100644 --- a/tools/lib/traceevent/event-parse.h +++ b/tools/lib/traceevent/event-parse.h | |||
@@ -876,8 +876,8 @@ struct event_filter { | |||
876 | struct event_filter *pevent_filter_alloc(struct pevent *pevent); | 876 | struct event_filter *pevent_filter_alloc(struct pevent *pevent); |
877 | 877 | ||
878 | /* for backward compatibility */ | 878 | /* for backward compatibility */ |
879 | #define FILTER_NONE PEVENT_ERRNO__FILTER_NOT_FOUND | 879 | #define FILTER_NONE PEVENT_ERRNO__NO_FILTER |
880 | #define FILTER_NOEXIST PEVENT_ERRNO__NO_FILTER | 880 | #define FILTER_NOEXIST PEVENT_ERRNO__FILTER_NOT_FOUND |
881 | #define FILTER_MISS PEVENT_ERRNO__FILTER_MISS | 881 | #define FILTER_MISS PEVENT_ERRNO__FILTER_MISS |
882 | #define FILTER_MATCH PEVENT_ERRNO__FILTER_MATCH | 882 | #define FILTER_MATCH PEVENT_ERRNO__FILTER_MATCH |
883 | 883 | ||
diff --git a/tools/net/bpf_dbg.c b/tools/net/bpf_dbg.c index bb31813e43dd..9a287bec695a 100644 --- a/tools/net/bpf_dbg.c +++ b/tools/net/bpf_dbg.c | |||
@@ -820,7 +820,7 @@ do_div: | |||
820 | r->A &= r->X; | 820 | r->A &= r->X; |
821 | break; | 821 | break; |
822 | case BPF_ALU_AND | BPF_K: | 822 | case BPF_ALU_AND | BPF_K: |
823 | r->A &= r->X; | 823 | r->A &= K; |
824 | break; | 824 | break; |
825 | case BPF_ALU_OR | BPF_X: | 825 | case BPF_ALU_OR | BPF_X: |
826 | r->A |= r->X; | 826 | r->A |= r->X; |
diff --git a/tools/perf/Makefile.perf b/tools/perf/Makefile.perf index e96923310d57..895edd32930c 100644 --- a/tools/perf/Makefile.perf +++ b/tools/perf/Makefile.perf | |||
@@ -589,7 +589,7 @@ $(GTK_OBJS): $(OUTPUT)%.o: %.c $(LIB_H) | |||
589 | $(QUIET_CC)$(CC) -o $@ -c -fPIC $(CFLAGS) $(GTK_CFLAGS) $< | 589 | $(QUIET_CC)$(CC) -o $@ -c -fPIC $(CFLAGS) $(GTK_CFLAGS) $< |
590 | 590 | ||
591 | $(OUTPUT)libperf-gtk.so: $(GTK_OBJS) $(PERFLIBS) | 591 | $(OUTPUT)libperf-gtk.so: $(GTK_OBJS) $(PERFLIBS) |
592 | $(QUIET_LINK)$(CC) -o $@ -shared $(ALL_LDFLAGS) $(filter %.o,$^) $(GTK_LIBS) | 592 | $(QUIET_LINK)$(CC) -o $@ -shared $(LDFLAGS) $(filter %.o,$^) $(GTK_LIBS) |
593 | 593 | ||
594 | $(OUTPUT)builtin-help.o: builtin-help.c $(OUTPUT)common-cmds.h $(OUTPUT)PERF-CFLAGS | 594 | $(OUTPUT)builtin-help.o: builtin-help.c $(OUTPUT)common-cmds.h $(OUTPUT)PERF-CFLAGS |
595 | $(QUIET_CC)$(CC) -o $@ -c $(CFLAGS) \ | 595 | $(QUIET_CC)$(CC) -o $@ -c $(CFLAGS) \ |
diff --git a/tools/perf/arch/x86/tests/dwarf-unwind.c b/tools/perf/arch/x86/tests/dwarf-unwind.c index b602ad93ce63..83bc2385e6d3 100644 --- a/tools/perf/arch/x86/tests/dwarf-unwind.c +++ b/tools/perf/arch/x86/tests/dwarf-unwind.c | |||
@@ -23,9 +23,10 @@ static int sample_ustack(struct perf_sample *sample, | |||
23 | 23 | ||
24 | sp = (unsigned long) regs[PERF_REG_X86_SP]; | 24 | sp = (unsigned long) regs[PERF_REG_X86_SP]; |
25 | 25 | ||
26 | map = map_groups__find(&thread->mg, MAP__FUNCTION, (u64) sp); | 26 | map = map_groups__find(&thread->mg, MAP__VARIABLE, (u64) sp); |
27 | if (!map) { | 27 | if (!map) { |
28 | pr_debug("failed to get stack map\n"); | 28 | pr_debug("failed to get stack map\n"); |
29 | free(buf); | ||
29 | return -1; | 30 | return -1; |
30 | } | 31 | } |
31 | 32 | ||
diff --git a/tools/perf/arch/x86/tests/regs_load.S b/tools/perf/arch/x86/tests/regs_load.S index 99167bf644ea..60875d5c556c 100644 --- a/tools/perf/arch/x86/tests/regs_load.S +++ b/tools/perf/arch/x86/tests/regs_load.S | |||
@@ -1,4 +1,3 @@ | |||
1 | |||
2 | #include <linux/linkage.h> | 1 | #include <linux/linkage.h> |
3 | 2 | ||
4 | #define AX 0 | 3 | #define AX 0 |
@@ -90,3 +89,10 @@ ENTRY(perf_regs_load) | |||
90 | ret | 89 | ret |
91 | ENDPROC(perf_regs_load) | 90 | ENDPROC(perf_regs_load) |
92 | #endif | 91 | #endif |
92 | |||
93 | /* | ||
94 | * We need to provide note.GNU-stack section, saying that we want | ||
95 | * NOT executable stack. Otherwise the final linking will assume that | ||
96 | * the ELF stack should not be restricted at all and set it RWX. | ||
97 | */ | ||
98 | .section .note.GNU-stack,"",@progbits | ||
diff --git a/tools/perf/config/Makefile b/tools/perf/config/Makefile index ee21fa95ebcf..802cf544202b 100644 --- a/tools/perf/config/Makefile +++ b/tools/perf/config/Makefile | |||
@@ -34,6 +34,14 @@ ifeq ($(ARCH),arm) | |||
34 | LIBUNWIND_LIBS = -lunwind -lunwind-arm | 34 | LIBUNWIND_LIBS = -lunwind -lunwind-arm |
35 | endif | 35 | endif |
36 | 36 | ||
37 | # So far there's only x86 libdw unwind support merged in perf. | ||
38 | # Disable it on all other architectures in case libdw unwind | ||
39 | # support is detected in system. Add supported architectures | ||
40 | # to the check. | ||
41 | ifneq ($(ARCH),x86) | ||
42 | NO_LIBDW_DWARF_UNWIND := 1 | ||
43 | endif | ||
44 | |||
37 | ifeq ($(LIBUNWIND_LIBS),) | 45 | ifeq ($(LIBUNWIND_LIBS),) |
38 | NO_LIBUNWIND := 1 | 46 | NO_LIBUNWIND := 1 |
39 | else | 47 | else |
@@ -109,6 +117,10 @@ CFLAGS += -Wall | |||
109 | CFLAGS += -Wextra | 117 | CFLAGS += -Wextra |
110 | CFLAGS += -std=gnu99 | 118 | CFLAGS += -std=gnu99 |
111 | 119 | ||
120 | # Enforce a non-executable stack, as we may regress (again) in the future by | ||
121 | # adding assembler files missing the .GNU-stack linker note. | ||
122 | LDFLAGS += -Wl,-z,noexecstack | ||
123 | |||
112 | EXTLIBS = -lelf -lpthread -lrt -lm -ldl | 124 | EXTLIBS = -lelf -lpthread -lrt -lm -ldl |
113 | 125 | ||
114 | ifneq ($(OUTPUT),) | 126 | ifneq ($(OUTPUT),) |
@@ -186,7 +198,10 @@ VF_FEATURE_TESTS = \ | |||
186 | stackprotector-all \ | 198 | stackprotector-all \ |
187 | timerfd \ | 199 | timerfd \ |
188 | libunwind-debug-frame \ | 200 | libunwind-debug-frame \ |
189 | bionic | 201 | bionic \ |
202 | liberty \ | ||
203 | liberty-z \ | ||
204 | cplus-demangle | ||
190 | 205 | ||
191 | # Set FEATURE_CHECK_(C|LD)FLAGS-all for all CORE_FEATURE_TESTS features. | 206 | # Set FEATURE_CHECK_(C|LD)FLAGS-all for all CORE_FEATURE_TESTS features. |
192 | # If in the future we need per-feature checks/flags for features not | 207 | # If in the future we need per-feature checks/flags for features not |
@@ -504,7 +519,21 @@ else | |||
504 | endif | 519 | endif |
505 | 520 | ||
506 | ifeq ($(feature-libbfd), 1) | 521 | ifeq ($(feature-libbfd), 1) |
507 | EXTLIBS += -lbfd -lz -liberty | 522 | EXTLIBS += -lbfd |
523 | |||
524 | # call all detections now so we get correct | ||
525 | # status in VF output | ||
526 | $(call feature_check,liberty) | ||
527 | $(call feature_check,liberty-z) | ||
528 | $(call feature_check,cplus-demangle) | ||
529 | |||
530 | ifeq ($(feature-liberty), 1) | ||
531 | EXTLIBS += -liberty | ||
532 | else | ||
533 | ifeq ($(feature-liberty-z), 1) | ||
534 | EXTLIBS += -liberty -lz | ||
535 | endif | ||
536 | endif | ||
508 | endif | 537 | endif |
509 | 538 | ||
510 | ifdef NO_DEMANGLE | 539 | ifdef NO_DEMANGLE |
@@ -515,15 +544,10 @@ else | |||
515 | CFLAGS += -DHAVE_CPLUS_DEMANGLE_SUPPORT | 544 | CFLAGS += -DHAVE_CPLUS_DEMANGLE_SUPPORT |
516 | else | 545 | else |
517 | ifneq ($(feature-libbfd), 1) | 546 | ifneq ($(feature-libbfd), 1) |
518 | $(call feature_check,liberty) | 547 | ifneq ($(feature-liberty), 1) |
519 | ifeq ($(feature-liberty), 1) | 548 | ifneq ($(feature-liberty-z), 1) |
520 | EXTLIBS += -lbfd -liberty | 549 | # we dont have neither HAVE_CPLUS_DEMANGLE_SUPPORT |
521 | else | 550 | # or any of 'bfd iberty z' trinity |
522 | $(call feature_check,liberty-z) | ||
523 | ifeq ($(feature-liberty-z), 1) | ||
524 | EXTLIBS += -lbfd -liberty -lz | ||
525 | else | ||
526 | $(call feature_check,cplus-demangle) | ||
527 | ifeq ($(feature-cplus-demangle), 1) | 551 | ifeq ($(feature-cplus-demangle), 1) |
528 | EXTLIBS += -liberty | 552 | EXTLIBS += -liberty |
529 | CFLAGS += -DHAVE_CPLUS_DEMANGLE_SUPPORT | 553 | CFLAGS += -DHAVE_CPLUS_DEMANGLE_SUPPORT |
diff --git a/tools/perf/tests/make b/tools/perf/tests/make index 5daeae1cb4c0..2f92d6e7ee00 100644 --- a/tools/perf/tests/make +++ b/tools/perf/tests/make | |||
@@ -46,6 +46,7 @@ make_install_man := install-man | |||
46 | make_install_html := install-html | 46 | make_install_html := install-html |
47 | make_install_info := install-info | 47 | make_install_info := install-info |
48 | make_install_pdf := install-pdf | 48 | make_install_pdf := install-pdf |
49 | make_static := LDFLAGS=-static | ||
49 | 50 | ||
50 | # all the NO_* variable combined | 51 | # all the NO_* variable combined |
51 | make_minimal := NO_LIBPERL=1 NO_LIBPYTHON=1 NO_NEWT=1 NO_GTK2=1 | 52 | make_minimal := NO_LIBPERL=1 NO_LIBPYTHON=1 NO_NEWT=1 NO_GTK2=1 |
@@ -87,6 +88,7 @@ run += make_install_bin | |||
87 | # run += make_install_info | 88 | # run += make_install_info |
88 | # run += make_install_pdf | 89 | # run += make_install_pdf |
89 | run += make_minimal | 90 | run += make_minimal |
91 | run += make_static | ||
90 | 92 | ||
91 | ifneq ($(call has,ctags),) | 93 | ifneq ($(call has,ctags),) |
92 | run += make_tags | 94 | run += make_tags |
diff --git a/tools/perf/util/machine.c b/tools/perf/util/machine.c index a53cd0b8c151..27c2a5efe450 100644 --- a/tools/perf/util/machine.c +++ b/tools/perf/util/machine.c | |||
@@ -717,7 +717,7 @@ static char *get_kernel_version(const char *root_dir) | |||
717 | } | 717 | } |
718 | 718 | ||
719 | static int map_groups__set_modules_path_dir(struct map_groups *mg, | 719 | static int map_groups__set_modules_path_dir(struct map_groups *mg, |
720 | const char *dir_name) | 720 | const char *dir_name, int depth) |
721 | { | 721 | { |
722 | struct dirent *dent; | 722 | struct dirent *dent; |
723 | DIR *dir = opendir(dir_name); | 723 | DIR *dir = opendir(dir_name); |
@@ -742,7 +742,15 @@ static int map_groups__set_modules_path_dir(struct map_groups *mg, | |||
742 | !strcmp(dent->d_name, "..")) | 742 | !strcmp(dent->d_name, "..")) |
743 | continue; | 743 | continue; |
744 | 744 | ||
745 | ret = map_groups__set_modules_path_dir(mg, path); | 745 | /* Do not follow top-level source and build symlinks */ |
746 | if (depth == 0) { | ||
747 | if (!strcmp(dent->d_name, "source") || | ||
748 | !strcmp(dent->d_name, "build")) | ||
749 | continue; | ||
750 | } | ||
751 | |||
752 | ret = map_groups__set_modules_path_dir(mg, path, | ||
753 | depth + 1); | ||
746 | if (ret < 0) | 754 | if (ret < 0) |
747 | goto out; | 755 | goto out; |
748 | } else { | 756 | } else { |
@@ -786,11 +794,11 @@ static int machine__set_modules_path(struct machine *machine) | |||
786 | if (!version) | 794 | if (!version) |
787 | return -1; | 795 | return -1; |
788 | 796 | ||
789 | snprintf(modules_path, sizeof(modules_path), "%s/lib/modules/%s/kernel", | 797 | snprintf(modules_path, sizeof(modules_path), "%s/lib/modules/%s", |
790 | machine->root_dir, version); | 798 | machine->root_dir, version); |
791 | free(version); | 799 | free(version); |
792 | 800 | ||
793 | return map_groups__set_modules_path_dir(&machine->kmaps, modules_path); | 801 | return map_groups__set_modules_path_dir(&machine->kmaps, modules_path, 0); |
794 | } | 802 | } |
795 | 803 | ||
796 | static int machine__create_module(void *arg, const char *name, u64 start) | 804 | static int machine__create_module(void *arg, const char *name, u64 start) |
diff --git a/tools/power/acpi/Makefile b/tools/power/acpi/Makefile index c225d6d9fb29..e5a3c4be2a10 100644 --- a/tools/power/acpi/Makefile +++ b/tools/power/acpi/Makefile | |||
@@ -70,7 +70,8 @@ WARNINGS += $(call cc-supports,-Wstrict-prototypes) | |||
70 | WARNINGS += $(call cc-supports,-Wdeclaration-after-statement) | 70 | WARNINGS += $(call cc-supports,-Wdeclaration-after-statement) |
71 | 71 | ||
72 | KERNEL_INCLUDE := ../../../include | 72 | KERNEL_INCLUDE := ../../../include |
73 | CFLAGS += -D_LINUX -DDEFINE_ALTERNATE_TYPES -I$(KERNEL_INCLUDE) | 73 | ACPICA_INCLUDE := ../../../drivers/acpi/acpica |
74 | CFLAGS += -D_LINUX -I$(KERNEL_INCLUDE) -I$(ACPICA_INCLUDE) | ||
74 | CFLAGS += $(WARNINGS) | 75 | CFLAGS += $(WARNINGS) |
75 | 76 | ||
76 | ifeq ($(strip $(V)),false) | 77 | ifeq ($(strip $(V)),false) |
@@ -94,10 +95,29 @@ endif | |||
94 | # --- ACPIDUMP BEGIN --- | 95 | # --- ACPIDUMP BEGIN --- |
95 | 96 | ||
96 | vpath %.c \ | 97 | vpath %.c \ |
97 | tools/acpidump | 98 | ../../../drivers/acpi/acpica\ |
99 | tools/acpidump\ | ||
100 | common\ | ||
101 | os_specific/service_layers | ||
102 | |||
103 | CFLAGS += -DACPI_DUMP_APP -Itools/acpidump | ||
98 | 104 | ||
99 | DUMP_OBJS = \ | 105 | DUMP_OBJS = \ |
100 | acpidump.o | 106 | apdump.o\ |
107 | apfiles.o\ | ||
108 | apmain.o\ | ||
109 | osunixdir.o\ | ||
110 | osunixmap.o\ | ||
111 | tbprint.o\ | ||
112 | tbxfroot.o\ | ||
113 | utbuffer.o\ | ||
114 | utexcep.o\ | ||
115 | utmath.o\ | ||
116 | utstring.o\ | ||
117 | utxferror.o\ | ||
118 | oslinuxtbl.o\ | ||
119 | cmfsize.o\ | ||
120 | getopt.o | ||
101 | 121 | ||
102 | DUMP_OBJS := $(addprefix $(OUTPUT)tools/acpidump/,$(DUMP_OBJS)) | 122 | DUMP_OBJS := $(addprefix $(OUTPUT)tools/acpidump/,$(DUMP_OBJS)) |
103 | 123 | ||
diff --git a/tools/power/acpi/common/cmfsize.c b/tools/power/acpi/common/cmfsize.c new file mode 100644 index 000000000000..5140e5edae1f --- /dev/null +++ b/tools/power/acpi/common/cmfsize.c | |||
@@ -0,0 +1,101 @@ | |||
1 | /****************************************************************************** | ||
2 | * | ||
3 | * Module Name: cfsize - Common get file size function | ||
4 | * | ||
5 | *****************************************************************************/ | ||
6 | |||
7 | /* | ||
8 | * Copyright (C) 2000 - 2014, Intel Corp. | ||
9 | * All rights reserved. | ||
10 | * | ||
11 | * Redistribution and use in source and binary forms, with or without | ||
12 | * modification, are permitted provided that the following conditions | ||
13 | * are met: | ||
14 | * 1. Redistributions of source code must retain the above copyright | ||
15 | * notice, this list of conditions, and the following disclaimer, | ||
16 | * without modification. | ||
17 | * 2. Redistributions in binary form must reproduce at minimum a disclaimer | ||
18 | * substantially similar to the "NO WARRANTY" disclaimer below | ||
19 | * ("Disclaimer") and any redistribution must be conditioned upon | ||
20 | * including a substantially similar Disclaimer requirement for further | ||
21 | * binary redistribution. | ||
22 | * 3. Neither the names of the above-listed copyright holders nor the names | ||
23 | * of any contributors may be used to endorse or promote products derived | ||
24 | * from this software without specific prior written permission. | ||
25 | * | ||
26 | * Alternatively, this software may be distributed under the terms of the | ||
27 | * GNU General Public License ("GPL") version 2 as published by the Free | ||
28 | * Software Foundation. | ||
29 | * | ||
30 | * NO WARRANTY | ||
31 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS | ||
32 | * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT | ||
33 | * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR | ||
34 | * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT | ||
35 | * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL | ||
36 | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS | ||
37 | * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) | ||
38 | * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, | ||
39 | * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING | ||
40 | * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE | ||
41 | * POSSIBILITY OF SUCH DAMAGES. | ||
42 | */ | ||
43 | |||
44 | #include <acpi/acpi.h> | ||
45 | #include "accommon.h" | ||
46 | #include "acapps.h" | ||
47 | #include <stdio.h> | ||
48 | |||
49 | #define _COMPONENT ACPI_TOOLS | ||
50 | ACPI_MODULE_NAME("cmfsize") | ||
51 | |||
52 | /******************************************************************************* | ||
53 | * | ||
54 | * FUNCTION: cm_get_file_size | ||
55 | * | ||
56 | * PARAMETERS: file - Open file descriptor | ||
57 | * | ||
58 | * RETURN: File Size. On error, -1 (ACPI_UINT32_MAX) | ||
59 | * | ||
60 | * DESCRIPTION: Get the size of a file. Uses seek-to-EOF. File must be open. | ||
61 | * Does not disturb the current file pointer. Uses perror for | ||
62 | * error messages. | ||
63 | * | ||
64 | ******************************************************************************/ | ||
65 | u32 cm_get_file_size(FILE * file) | ||
66 | { | ||
67 | long file_size; | ||
68 | long current_offset; | ||
69 | |||
70 | /* Save the current file pointer, seek to EOF to obtain file size */ | ||
71 | |||
72 | current_offset = ftell(file); | ||
73 | if (current_offset < 0) { | ||
74 | goto offset_error; | ||
75 | } | ||
76 | |||
77 | if (fseek(file, 0, SEEK_END)) { | ||
78 | goto seek_error; | ||
79 | } | ||
80 | |||
81 | file_size = ftell(file); | ||
82 | if (file_size < 0) { | ||
83 | goto offset_error; | ||
84 | } | ||
85 | |||
86 | /* Restore original file pointer */ | ||
87 | |||
88 | if (fseek(file, current_offset, SEEK_SET)) { | ||
89 | goto seek_error; | ||
90 | } | ||
91 | |||
92 | return ((u32)file_size); | ||
93 | |||
94 | offset_error: | ||
95 | perror("Could not get file offset"); | ||
96 | return (ACPI_UINT32_MAX); | ||
97 | |||
98 | seek_error: | ||
99 | perror("Could not seek file"); | ||
100 | return (ACPI_UINT32_MAX); | ||
101 | } | ||
diff --git a/tools/power/acpi/common/getopt.c b/tools/power/acpi/common/getopt.c new file mode 100644 index 000000000000..a302f52e4fd3 --- /dev/null +++ b/tools/power/acpi/common/getopt.c | |||
@@ -0,0 +1,239 @@ | |||
1 | /****************************************************************************** | ||
2 | * | ||
3 | * Module Name: getopt | ||
4 | * | ||
5 | *****************************************************************************/ | ||
6 | |||
7 | /* | ||
8 | * Copyright (C) 2000 - 2014, Intel Corp. | ||
9 | * All rights reserved. | ||
10 | * | ||
11 | * Redistribution and use in source and binary forms, with or without | ||
12 | * modification, are permitted provided that the following conditions | ||
13 | * are met: | ||
14 | * 1. Redistributions of source code must retain the above copyright | ||
15 | * notice, this list of conditions, and the following disclaimer, | ||
16 | * without modification. | ||
17 | * 2. Redistributions in binary form must reproduce at minimum a disclaimer | ||
18 | * substantially similar to the "NO WARRANTY" disclaimer below | ||
19 | * ("Disclaimer") and any redistribution must be conditioned upon | ||
20 | * including a substantially similar Disclaimer requirement for further | ||
21 | * binary redistribution. | ||
22 | * 3. Neither the names of the above-listed copyright holders nor the names | ||
23 | * of any contributors may be used to endorse or promote products derived | ||
24 | * from this software without specific prior written permission. | ||
25 | * | ||
26 | * Alternatively, this software may be distributed under the terms of the | ||
27 | * GNU General Public License ("GPL") version 2 as published by the Free | ||
28 | * Software Foundation. | ||
29 | * | ||
30 | * NO WARRANTY | ||
31 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS | ||
32 | * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT | ||
33 | * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR | ||
34 | * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT | ||
35 | * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL | ||
36 | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS | ||
37 | * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) | ||
38 | * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, | ||
39 | * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING | ||
40 | * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE | ||
41 | * POSSIBILITY OF SUCH DAMAGES. | ||
42 | */ | ||
43 | |||
44 | /* | ||
45 | * ACPICA getopt() implementation | ||
46 | * | ||
47 | * Option strings: | ||
48 | * "f" - Option has no arguments | ||
49 | * "f:" - Option requires an argument | ||
50 | * "f^" - Option has optional single-char sub-options | ||
51 | * "f|" - Option has required single-char sub-options | ||
52 | */ | ||
53 | |||
54 | #include <stdio.h> | ||
55 | #include <string.h> | ||
56 | #include <acpi/acpi.h> | ||
57 | #include "accommon.h" | ||
58 | #include "acapps.h" | ||
59 | |||
60 | #define ACPI_OPTION_ERROR(msg, badchar) \ | ||
61 | if (acpi_gbl_opterr) {fprintf (stderr, "%s%c\n", msg, badchar);} | ||
62 | |||
63 | int acpi_gbl_opterr = 1; | ||
64 | int acpi_gbl_optind = 1; | ||
65 | int acpi_gbl_sub_opt_char = 0; | ||
66 | char *acpi_gbl_optarg; | ||
67 | |||
68 | static int current_char_ptr = 1; | ||
69 | |||
70 | /******************************************************************************* | ||
71 | * | ||
72 | * FUNCTION: acpi_getopt_argument | ||
73 | * | ||
74 | * PARAMETERS: argc, argv - from main | ||
75 | * | ||
76 | * RETURN: 0 if an argument was found, -1 otherwise. Sets acpi_gbl_Optarg | ||
77 | * to point to the next argument. | ||
78 | * | ||
79 | * DESCRIPTION: Get the next argument. Used to obtain arguments for the | ||
80 | * two-character options after the original call to acpi_getopt. | ||
81 | * Note: Either the argument starts at the next character after | ||
82 | * the option, or it is pointed to by the next argv entry. | ||
83 | * (After call to acpi_getopt, we need to backup to the previous | ||
84 | * argv entry). | ||
85 | * | ||
86 | ******************************************************************************/ | ||
87 | |||
88 | int acpi_getopt_argument(int argc, char **argv) | ||
89 | { | ||
90 | acpi_gbl_optind--; | ||
91 | current_char_ptr++; | ||
92 | |||
93 | if (argv[acpi_gbl_optind][(int)(current_char_ptr + 1)] != '\0') { | ||
94 | acpi_gbl_optarg = | ||
95 | &argv[acpi_gbl_optind++][(int)(current_char_ptr + 1)]; | ||
96 | } else if (++acpi_gbl_optind >= argc) { | ||
97 | ACPI_OPTION_ERROR("Option requires an argument: -", 'v'); | ||
98 | |||
99 | current_char_ptr = 1; | ||
100 | return (-1); | ||
101 | } else { | ||
102 | acpi_gbl_optarg = argv[acpi_gbl_optind++]; | ||
103 | } | ||
104 | |||
105 | current_char_ptr = 1; | ||
106 | return (0); | ||
107 | } | ||
108 | |||
109 | /******************************************************************************* | ||
110 | * | ||
111 | * FUNCTION: acpi_getopt | ||
112 | * | ||
113 | * PARAMETERS: argc, argv - from main | ||
114 | * opts - options info list | ||
115 | * | ||
116 | * RETURN: Option character or EOF | ||
117 | * | ||
118 | * DESCRIPTION: Get the next option | ||
119 | * | ||
120 | ******************************************************************************/ | ||
121 | |||
122 | int acpi_getopt(int argc, char **argv, char *opts) | ||
123 | { | ||
124 | int current_char; | ||
125 | char *opts_ptr; | ||
126 | |||
127 | if (current_char_ptr == 1) { | ||
128 | if (acpi_gbl_optind >= argc || | ||
129 | argv[acpi_gbl_optind][0] != '-' || | ||
130 | argv[acpi_gbl_optind][1] == '\0') { | ||
131 | return (EOF); | ||
132 | } else if (strcmp(argv[acpi_gbl_optind], "--") == 0) { | ||
133 | acpi_gbl_optind++; | ||
134 | return (EOF); | ||
135 | } | ||
136 | } | ||
137 | |||
138 | /* Get the option */ | ||
139 | |||
140 | current_char = argv[acpi_gbl_optind][current_char_ptr]; | ||
141 | |||
142 | /* Make sure that the option is legal */ | ||
143 | |||
144 | if (current_char == ':' || | ||
145 | (opts_ptr = strchr(opts, current_char)) == NULL) { | ||
146 | ACPI_OPTION_ERROR("Illegal option: -", current_char); | ||
147 | |||
148 | if (argv[acpi_gbl_optind][++current_char_ptr] == '\0') { | ||
149 | acpi_gbl_optind++; | ||
150 | current_char_ptr = 1; | ||
151 | } | ||
152 | |||
153 | return ('?'); | ||
154 | } | ||
155 | |||
156 | /* Option requires an argument? */ | ||
157 | |||
158 | if (*++opts_ptr == ':') { | ||
159 | if (argv[acpi_gbl_optind][(int)(current_char_ptr + 1)] != '\0') { | ||
160 | acpi_gbl_optarg = | ||
161 | &argv[acpi_gbl_optind++][(int) | ||
162 | (current_char_ptr + 1)]; | ||
163 | } else if (++acpi_gbl_optind >= argc) { | ||
164 | ACPI_OPTION_ERROR("Option requires an argument: -", | ||
165 | current_char); | ||
166 | |||
167 | current_char_ptr = 1; | ||
168 | return ('?'); | ||
169 | } else { | ||
170 | acpi_gbl_optarg = argv[acpi_gbl_optind++]; | ||
171 | } | ||
172 | |||
173 | current_char_ptr = 1; | ||
174 | } | ||
175 | |||
176 | /* Option has an optional argument? */ | ||
177 | |||
178 | else if (*opts_ptr == '+') { | ||
179 | if (argv[acpi_gbl_optind][(int)(current_char_ptr + 1)] != '\0') { | ||
180 | acpi_gbl_optarg = | ||
181 | &argv[acpi_gbl_optind++][(int) | ||
182 | (current_char_ptr + 1)]; | ||
183 | } else if (++acpi_gbl_optind >= argc) { | ||
184 | acpi_gbl_optarg = NULL; | ||
185 | } else { | ||
186 | acpi_gbl_optarg = argv[acpi_gbl_optind++]; | ||
187 | } | ||
188 | |||
189 | current_char_ptr = 1; | ||
190 | } | ||
191 | |||
192 | /* Option has optional single-char arguments? */ | ||
193 | |||
194 | else if (*opts_ptr == '^') { | ||
195 | if (argv[acpi_gbl_optind][(int)(current_char_ptr + 1)] != '\0') { | ||
196 | acpi_gbl_optarg = | ||
197 | &argv[acpi_gbl_optind][(int)(current_char_ptr + 1)]; | ||
198 | } else { | ||
199 | acpi_gbl_optarg = "^"; | ||
200 | } | ||
201 | |||
202 | acpi_gbl_sub_opt_char = acpi_gbl_optarg[0]; | ||
203 | acpi_gbl_optind++; | ||
204 | current_char_ptr = 1; | ||
205 | } | ||
206 | |||
207 | /* Option has a required single-char argument? */ | ||
208 | |||
209 | else if (*opts_ptr == '|') { | ||
210 | if (argv[acpi_gbl_optind][(int)(current_char_ptr + 1)] != '\0') { | ||
211 | acpi_gbl_optarg = | ||
212 | &argv[acpi_gbl_optind][(int)(current_char_ptr + 1)]; | ||
213 | } else { | ||
214 | ACPI_OPTION_ERROR | ||
215 | ("Option requires a single-character suboption: -", | ||
216 | current_char); | ||
217 | |||
218 | current_char_ptr = 1; | ||
219 | return ('?'); | ||
220 | } | ||
221 | |||
222 | acpi_gbl_sub_opt_char = acpi_gbl_optarg[0]; | ||
223 | acpi_gbl_optind++; | ||
224 | current_char_ptr = 1; | ||
225 | } | ||
226 | |||
227 | /* Option with no arguments */ | ||
228 | |||
229 | else { | ||
230 | if (argv[acpi_gbl_optind][++current_char_ptr] == '\0') { | ||
231 | current_char_ptr = 1; | ||
232 | acpi_gbl_optind++; | ||
233 | } | ||
234 | |||
235 | acpi_gbl_optarg = NULL; | ||
236 | } | ||
237 | |||
238 | return (current_char); | ||
239 | } | ||
diff --git a/tools/power/acpi/man/acpidump.8 b/tools/power/acpi/man/acpidump.8 index adfa99166e5e..38f095d86b52 100644 --- a/tools/power/acpi/man/acpidump.8 +++ b/tools/power/acpi/man/acpidump.8 | |||
@@ -1,18 +1,64 @@ | |||
1 | .TH ACPIDUMP 8 | 1 | .TH ACPIDUMP 8 |
2 | .SH NAME | 2 | .SH NAME |
3 | acpidump \- Dump system's ACPI tables to an ASCII file. | 3 | acpidump \- dump a system's ACPI tables to an ASCII file |
4 | |||
4 | .SH SYNOPSIS | 5 | .SH SYNOPSIS |
5 | .ft B | 6 | .B acpidump |
6 | .B acpidump > acpidump.out | 7 | .RI [ options ] |
8 | .br | ||
9 | |||
7 | .SH DESCRIPTION | 10 | .SH DESCRIPTION |
8 | \fBacpidump \fP dumps the systems ACPI tables to an ASCII file | 11 | .B acpidump |
9 | appropriate for attaching to a bug report. | 12 | dumps the systems ACPI tables to an ASCII file appropriate for |
13 | attaching to a bug report. | ||
10 | 14 | ||
11 | Subsequently, they can be processed by utilities in the ACPICA package. | 15 | Subsequently, they can be processed by utilities in the ACPICA package. |
12 | .SS Options | 16 | |
13 | no options worth worrying about. | 17 | .SH OPTIONS |
14 | .PP | 18 | acpidump options are as follow: |
15 | .SH EXAMPLE | 19 | .TP |
20 | .B Options | ||
21 | .TP | ||
22 | .B \-b | ||
23 | Dump tables to binary files | ||
24 | .TP | ||
25 | .B \-c | ||
26 | Dump customized tables | ||
27 | .TP | ||
28 | .B \-h \-? | ||
29 | This help message | ||
30 | .TP | ||
31 | .B \-o <File> | ||
32 | Redirect output to file | ||
33 | .TP | ||
34 | .B \-r <Address> | ||
35 | Dump tables from specified RSDP | ||
36 | .TP | ||
37 | .B \-s | ||
38 | Print table summaries only | ||
39 | .TP | ||
40 | .B \-v | ||
41 | Display version information | ||
42 | .TP | ||
43 | .B \-z | ||
44 | Verbose mode | ||
45 | .TP | ||
46 | .B Table Options | ||
47 | .TP | ||
48 | .B \-a <Address> | ||
49 | Get table via a physical address | ||
50 | .TP | ||
51 | .B \-f <BinaryFile> | ||
52 | Get table via a binary file | ||
53 | .TP | ||
54 | .B \-n <Signature> | ||
55 | Get table via a name/signature | ||
56 | .TP | ||
57 | Invocation without parameters dumps all available tables | ||
58 | .TP | ||
59 | Multiple mixed instances of -a, -f, and -n are supported | ||
60 | |||
61 | .SH EXAMPLES | ||
16 | 62 | ||
17 | .nf | 63 | .nf |
18 | # acpidump > acpidump.out | 64 | # acpidump > acpidump.out |
@@ -50,10 +96,25 @@ ACPICA: https://acpica.org/ | |||
50 | .ta | 96 | .ta |
51 | .nf | 97 | .nf |
52 | /dev/mem | 98 | /dev/mem |
99 | /sys/firmware/acpi/tables/* | ||
53 | /sys/firmware/acpi/tables/dynamic/* | 100 | /sys/firmware/acpi/tables/dynamic/* |
101 | /sys/firmware/efi/systab | ||
54 | .fi | 102 | .fi |
55 | 103 | ||
56 | .PP | ||
57 | .SH AUTHOR | 104 | .SH AUTHOR |
58 | .nf | 105 | .TP |
59 | Written by Len Brown <len.brown@intel.com> | 106 | Original by: |
107 | Len Brown <len.brown@intel.com> | ||
108 | .TP | ||
109 | Written by: | ||
110 | Chao Guan <chao.guan@intel.com> | ||
111 | .TP | ||
112 | Updated by: | ||
113 | Bob Moore <robert.moore@intel.com> | ||
114 | Lv Zheng <lv.zheng@intel.com> | ||
115 | |||
116 | .SH SEE ALSO | ||
117 | \&\fIacpixtract\fR\|(8), \fIiasl\fR\|(8). | ||
118 | |||
119 | .SH COPYRIGHT | ||
120 | COPYRIGHT (c) 2013, Intel Corporation. | ||
diff --git a/tools/power/acpi/os_specific/service_layers/oslinuxtbl.c b/tools/power/acpi/os_specific/service_layers/oslinuxtbl.c new file mode 100644 index 000000000000..28c52008e854 --- /dev/null +++ b/tools/power/acpi/os_specific/service_layers/oslinuxtbl.c | |||
@@ -0,0 +1,1329 @@ | |||
1 | /****************************************************************************** | ||
2 | * | ||
3 | * Module Name: oslinuxtbl - Linux OSL for obtaining ACPI tables | ||
4 | * | ||
5 | *****************************************************************************/ | ||
6 | |||
7 | /* | ||
8 | * Copyright (C) 2000 - 2014, Intel Corp. | ||
9 | * All rights reserved. | ||
10 | * | ||
11 | * Redistribution and use in source and binary forms, with or without | ||
12 | * modification, are permitted provided that the following conditions | ||
13 | * are met: | ||
14 | * 1. Redistributions of source code must retain the above copyright | ||
15 | * notice, this list of conditions, and the following disclaimer, | ||
16 | * without modification. | ||
17 | * 2. Redistributions in binary form must reproduce at minimum a disclaimer | ||
18 | * substantially similar to the "NO WARRANTY" disclaimer below | ||
19 | * ("Disclaimer") and any redistribution must be conditioned upon | ||
20 | * including a substantially similar Disclaimer requirement for further | ||
21 | * binary redistribution. | ||
22 | * 3. Neither the names of the above-listed copyright holders nor the names | ||
23 | * of any contributors may be used to endorse or promote products derived | ||
24 | * from this software without specific prior written permission. | ||
25 | * | ||
26 | * Alternatively, this software may be distributed under the terms of the | ||
27 | * GNU General Public License ("GPL") version 2 as published by the Free | ||
28 | * Software Foundation. | ||
29 | * | ||
30 | * NO WARRANTY | ||
31 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS | ||
32 | * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT | ||
33 | * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR | ||
34 | * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT | ||
35 | * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL | ||
36 | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS | ||
37 | * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) | ||
38 | * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, | ||
39 | * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING | ||
40 | * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE | ||
41 | * POSSIBILITY OF SUCH DAMAGES. | ||
42 | */ | ||
43 | |||
44 | #include "acpidump.h" | ||
45 | |||
46 | #define _COMPONENT ACPI_OS_SERVICES | ||
47 | ACPI_MODULE_NAME("oslinuxtbl") | ||
48 | |||
49 | #ifndef PATH_MAX | ||
50 | #define PATH_MAX 256 | ||
51 | #endif | ||
52 | /* List of information about obtained ACPI tables */ | ||
53 | typedef struct osl_table_info { | ||
54 | struct osl_table_info *next; | ||
55 | u32 instance; | ||
56 | char signature[ACPI_NAME_SIZE]; | ||
57 | |||
58 | } osl_table_info; | ||
59 | |||
60 | /* Local prototypes */ | ||
61 | |||
62 | static acpi_status osl_table_initialize(void); | ||
63 | |||
64 | static acpi_status | ||
65 | osl_table_name_from_file(char *filename, char *signature, u32 *instance); | ||
66 | |||
67 | static acpi_status osl_add_table_to_list(char *signature, u32 instance); | ||
68 | |||
69 | static acpi_status | ||
70 | osl_read_table_from_file(char *filename, | ||
71 | acpi_size file_offset, | ||
72 | char *signature, struct acpi_table_header **table); | ||
73 | |||
74 | static acpi_status | ||
75 | osl_map_table(acpi_size address, | ||
76 | char *signature, struct acpi_table_header **table); | ||
77 | |||
78 | static void osl_unmap_table(struct acpi_table_header *table); | ||
79 | |||
80 | static acpi_physical_address osl_find_rsdp_via_efi(void); | ||
81 | |||
82 | static acpi_status osl_load_rsdp(void); | ||
83 | |||
84 | static acpi_status osl_list_customized_tables(char *directory); | ||
85 | |||
86 | static acpi_status | ||
87 | osl_get_customized_table(char *pathname, | ||
88 | char *signature, | ||
89 | u32 instance, | ||
90 | struct acpi_table_header **table, | ||
91 | acpi_physical_address * address); | ||
92 | |||
93 | static acpi_status osl_list_bios_tables(void); | ||
94 | |||
95 | static acpi_status | ||
96 | osl_get_bios_table(char *signature, | ||
97 | u32 instance, | ||
98 | struct acpi_table_header **table, | ||
99 | acpi_physical_address * address); | ||
100 | |||
101 | static acpi_status osl_get_last_status(acpi_status default_status); | ||
102 | |||
103 | /* File locations */ | ||
104 | |||
105 | #define DYNAMIC_TABLE_DIR "/sys/firmware/acpi/tables/dynamic" | ||
106 | #define STATIC_TABLE_DIR "/sys/firmware/acpi/tables" | ||
107 | #define EFI_SYSTAB "/sys/firmware/efi/systab" | ||
108 | |||
109 | /* Should we get dynamically loaded SSDTs from DYNAMIC_TABLE_DIR? */ | ||
110 | |||
111 | u8 gbl_dump_dynamic_tables = TRUE; | ||
112 | |||
113 | /* Initialization flags */ | ||
114 | |||
115 | u8 gbl_table_list_initialized = FALSE; | ||
116 | |||
117 | /* Local copies of main ACPI tables */ | ||
118 | |||
119 | struct acpi_table_rsdp gbl_rsdp; | ||
120 | struct acpi_table_fadt *gbl_fadt = NULL; | ||
121 | struct acpi_table_rsdt *gbl_rsdt = NULL; | ||
122 | struct acpi_table_xsdt *gbl_xsdt = NULL; | ||
123 | |||
124 | /* Table addresses */ | ||
125 | |||
126 | acpi_physical_address gbl_fadt_address = 0; | ||
127 | acpi_physical_address gbl_rsdp_address = 0; | ||
128 | |||
129 | /* Revision of RSD PTR */ | ||
130 | |||
131 | u8 gbl_revision = 0; | ||
132 | |||
133 | struct osl_table_info *gbl_table_list_head = NULL; | ||
134 | u32 gbl_table_count = 0; | ||
135 | |||
136 | /****************************************************************************** | ||
137 | * | ||
138 | * FUNCTION: osl_get_last_status | ||
139 | * | ||
140 | * PARAMETERS: default_status - Default error status to return | ||
141 | * | ||
142 | * RETURN: Status; Converted from errno. | ||
143 | * | ||
144 | * DESCRIPTION: Get last errno and conver it to acpi_status. | ||
145 | * | ||
146 | *****************************************************************************/ | ||
147 | |||
148 | static acpi_status osl_get_last_status(acpi_status default_status) | ||
149 | { | ||
150 | |||
151 | switch (errno) { | ||
152 | case EACCES: | ||
153 | case EPERM: | ||
154 | |||
155 | return (AE_ACCESS); | ||
156 | |||
157 | case ENOENT: | ||
158 | |||
159 | return (AE_NOT_FOUND); | ||
160 | |||
161 | case ENOMEM: | ||
162 | |||
163 | return (AE_NO_MEMORY); | ||
164 | |||
165 | default: | ||
166 | |||
167 | return (default_status); | ||
168 | } | ||
169 | } | ||
170 | |||
171 | /****************************************************************************** | ||
172 | * | ||
173 | * FUNCTION: acpi_os_get_table_by_address | ||
174 | * | ||
175 | * PARAMETERS: address - Physical address of the ACPI table | ||
176 | * table - Where a pointer to the table is returned | ||
177 | * | ||
178 | * RETURN: Status; Table buffer is returned if AE_OK. | ||
179 | * AE_NOT_FOUND: A valid table was not found at the address | ||
180 | * | ||
181 | * DESCRIPTION: Get an ACPI table via a physical memory address. | ||
182 | * | ||
183 | *****************************************************************************/ | ||
184 | |||
185 | acpi_status | ||
186 | acpi_os_get_table_by_address(acpi_physical_address address, | ||
187 | struct acpi_table_header ** table) | ||
188 | { | ||
189 | u32 table_length; | ||
190 | struct acpi_table_header *mapped_table; | ||
191 | struct acpi_table_header *local_table = NULL; | ||
192 | acpi_status status = AE_OK; | ||
193 | |||
194 | /* Get main ACPI tables from memory on first invocation of this function */ | ||
195 | |||
196 | status = osl_table_initialize(); | ||
197 | if (ACPI_FAILURE(status)) { | ||
198 | return (status); | ||
199 | } | ||
200 | |||
201 | /* Map the table and validate it */ | ||
202 | |||
203 | status = osl_map_table(address, NULL, &mapped_table); | ||
204 | if (ACPI_FAILURE(status)) { | ||
205 | return (status); | ||
206 | } | ||
207 | |||
208 | /* Copy table to local buffer and return it */ | ||
209 | |||
210 | table_length = ap_get_table_length(mapped_table); | ||
211 | if (table_length == 0) { | ||
212 | status = AE_BAD_HEADER; | ||
213 | goto exit; | ||
214 | } | ||
215 | |||
216 | local_table = calloc(1, table_length); | ||
217 | if (!local_table) { | ||
218 | status = AE_NO_MEMORY; | ||
219 | goto exit; | ||
220 | } | ||
221 | |||
222 | ACPI_MEMCPY(local_table, mapped_table, table_length); | ||
223 | |||
224 | exit: | ||
225 | osl_unmap_table(mapped_table); | ||
226 | *table = local_table; | ||
227 | return (status); | ||
228 | } | ||
229 | |||
230 | /****************************************************************************** | ||
231 | * | ||
232 | * FUNCTION: acpi_os_get_table_by_name | ||
233 | * | ||
234 | * PARAMETERS: signature - ACPI Signature for desired table. Must be | ||
235 | * a null terminated 4-character string. | ||
236 | * instance - Multiple table support for SSDT/UEFI (0...n) | ||
237 | * Must be 0 for other tables. | ||
238 | * table - Where a pointer to the table is returned | ||
239 | * address - Where the table physical address is returned | ||
240 | * | ||
241 | * RETURN: Status; Table buffer and physical address returned if AE_OK. | ||
242 | * AE_LIMIT: Instance is beyond valid limit | ||
243 | * AE_NOT_FOUND: A table with the signature was not found | ||
244 | * | ||
245 | * NOTE: Assumes the input signature is uppercase. | ||
246 | * | ||
247 | *****************************************************************************/ | ||
248 | |||
249 | acpi_status | ||
250 | acpi_os_get_table_by_name(char *signature, | ||
251 | u32 instance, | ||
252 | struct acpi_table_header ** table, | ||
253 | acpi_physical_address * address) | ||
254 | { | ||
255 | acpi_status status; | ||
256 | |||
257 | /* Get main ACPI tables from memory on first invocation of this function */ | ||
258 | |||
259 | status = osl_table_initialize(); | ||
260 | if (ACPI_FAILURE(status)) { | ||
261 | return (status); | ||
262 | } | ||
263 | |||
264 | /* Not a main ACPI table, attempt to extract it from the RSDT/XSDT */ | ||
265 | |||
266 | if (!gbl_dump_customized_tables) { | ||
267 | |||
268 | /* Attempt to get the table from the memory */ | ||
269 | |||
270 | status = | ||
271 | osl_get_bios_table(signature, instance, table, address); | ||
272 | } else { | ||
273 | /* Attempt to get the table from the static directory */ | ||
274 | |||
275 | status = osl_get_customized_table(STATIC_TABLE_DIR, signature, | ||
276 | instance, table, address); | ||
277 | } | ||
278 | |||
279 | if (ACPI_FAILURE(status) && status == AE_LIMIT) { | ||
280 | if (gbl_dump_dynamic_tables) { | ||
281 | |||
282 | /* Attempt to get a dynamic table */ | ||
283 | |||
284 | status = | ||
285 | osl_get_customized_table(DYNAMIC_TABLE_DIR, | ||
286 | signature, instance, table, | ||
287 | address); | ||
288 | } | ||
289 | } | ||
290 | |||
291 | return (status); | ||
292 | } | ||
293 | |||
294 | /****************************************************************************** | ||
295 | * | ||
296 | * FUNCTION: osl_add_table_to_list | ||
297 | * | ||
298 | * PARAMETERS: signature - Table signature | ||
299 | * instance - Table instance | ||
300 | * | ||
301 | * RETURN: Status; Successfully added if AE_OK. | ||
302 | * AE_NO_MEMORY: Memory allocation error | ||
303 | * | ||
304 | * DESCRIPTION: Insert a table structure into OSL table list. | ||
305 | * | ||
306 | *****************************************************************************/ | ||
307 | |||
308 | static acpi_status osl_add_table_to_list(char *signature, u32 instance) | ||
309 | { | ||
310 | struct osl_table_info *new_info; | ||
311 | struct osl_table_info *next; | ||
312 | u32 next_instance = 0; | ||
313 | u8 found = FALSE; | ||
314 | |||
315 | new_info = calloc(1, sizeof(struct osl_table_info)); | ||
316 | if (!new_info) { | ||
317 | return (AE_NO_MEMORY); | ||
318 | } | ||
319 | |||
320 | ACPI_MOVE_NAME(new_info->signature, signature); | ||
321 | |||
322 | if (!gbl_table_list_head) { | ||
323 | gbl_table_list_head = new_info; | ||
324 | } else { | ||
325 | next = gbl_table_list_head; | ||
326 | while (1) { | ||
327 | if (ACPI_COMPARE_NAME(next->signature, signature)) { | ||
328 | if (next->instance == instance) { | ||
329 | found = TRUE; | ||
330 | } | ||
331 | if (next->instance >= next_instance) { | ||
332 | next_instance = next->instance + 1; | ||
333 | } | ||
334 | } | ||
335 | |||
336 | if (!next->next) { | ||
337 | break; | ||
338 | } | ||
339 | next = next->next; | ||
340 | } | ||
341 | next->next = new_info; | ||
342 | } | ||
343 | |||
344 | if (found) { | ||
345 | if (instance) { | ||
346 | fprintf(stderr, | ||
347 | "%4.4s: Warning unmatched table instance %d, expected %d\n", | ||
348 | signature, instance, next_instance); | ||
349 | } | ||
350 | instance = next_instance; | ||
351 | } | ||
352 | |||
353 | new_info->instance = instance; | ||
354 | gbl_table_count++; | ||
355 | |||
356 | return (AE_OK); | ||
357 | } | ||
358 | |||
359 | /****************************************************************************** | ||
360 | * | ||
361 | * FUNCTION: acpi_os_get_table_by_index | ||
362 | * | ||
363 | * PARAMETERS: index - Which table to get | ||
364 | * table - Where a pointer to the table is returned | ||
365 | * instance - Where a pointer to the table instance no. is | ||
366 | * returned | ||
367 | * address - Where the table physical address is returned | ||
368 | * | ||
369 | * RETURN: Status; Table buffer and physical address returned if AE_OK. | ||
370 | * AE_LIMIT: Index is beyond valid limit | ||
371 | * | ||
372 | * DESCRIPTION: Get an ACPI table via an index value (0 through n). Returns | ||
373 | * AE_LIMIT when an invalid index is reached. Index is not | ||
374 | * necessarily an index into the RSDT/XSDT. | ||
375 | * | ||
376 | *****************************************************************************/ | ||
377 | |||
378 | acpi_status | ||
379 | acpi_os_get_table_by_index(u32 index, | ||
380 | struct acpi_table_header ** table, | ||
381 | u32 *instance, acpi_physical_address * address) | ||
382 | { | ||
383 | struct osl_table_info *info; | ||
384 | acpi_status status; | ||
385 | u32 i; | ||
386 | |||
387 | /* Get main ACPI tables from memory on first invocation of this function */ | ||
388 | |||
389 | status = osl_table_initialize(); | ||
390 | if (ACPI_FAILURE(status)) { | ||
391 | return (status); | ||
392 | } | ||
393 | |||
394 | /* Validate Index */ | ||
395 | |||
396 | if (index >= gbl_table_count) { | ||
397 | return (AE_LIMIT); | ||
398 | } | ||
399 | |||
400 | /* Point to the table list entry specified by the Index argument */ | ||
401 | |||
402 | info = gbl_table_list_head; | ||
403 | for (i = 0; i < index; i++) { | ||
404 | info = info->next; | ||
405 | } | ||
406 | |||
407 | /* Now we can just get the table via the signature */ | ||
408 | |||
409 | status = acpi_os_get_table_by_name(info->signature, info->instance, | ||
410 | table, address); | ||
411 | |||
412 | if (ACPI_SUCCESS(status)) { | ||
413 | *instance = info->instance; | ||
414 | } | ||
415 | return (status); | ||
416 | } | ||
417 | |||
418 | /****************************************************************************** | ||
419 | * | ||
420 | * FUNCTION: osl_find_rsdp_via_efi | ||
421 | * | ||
422 | * PARAMETERS: None | ||
423 | * | ||
424 | * RETURN: RSDP address if found | ||
425 | * | ||
426 | * DESCRIPTION: Find RSDP address via EFI. | ||
427 | * | ||
428 | *****************************************************************************/ | ||
429 | |||
430 | static acpi_physical_address osl_find_rsdp_via_efi(void) | ||
431 | { | ||
432 | FILE *file; | ||
433 | char buffer[80]; | ||
434 | unsigned long address = 0; | ||
435 | |||
436 | file = fopen(EFI_SYSTAB, "r"); | ||
437 | if (file) { | ||
438 | while (fgets(buffer, 80, file)) { | ||
439 | if (sscanf(buffer, "ACPI20=0x%lx", &address) == 1) { | ||
440 | break; | ||
441 | } | ||
442 | } | ||
443 | fclose(file); | ||
444 | } | ||
445 | |||
446 | return ((acpi_physical_address) (address)); | ||
447 | } | ||
448 | |||
449 | /****************************************************************************** | ||
450 | * | ||
451 | * FUNCTION: osl_load_rsdp | ||
452 | * | ||
453 | * PARAMETERS: None | ||
454 | * | ||
455 | * RETURN: Status | ||
456 | * | ||
457 | * DESCRIPTION: Scan and load RSDP. | ||
458 | * | ||
459 | *****************************************************************************/ | ||
460 | |||
461 | static acpi_status osl_load_rsdp(void) | ||
462 | { | ||
463 | struct acpi_table_header *mapped_table; | ||
464 | u8 *rsdp_address; | ||
465 | acpi_physical_address rsdp_base; | ||
466 | acpi_size rsdp_size; | ||
467 | |||
468 | /* Get RSDP from memory */ | ||
469 | |||
470 | rsdp_size = sizeof(struct acpi_table_rsdp); | ||
471 | if (gbl_rsdp_base) { | ||
472 | rsdp_base = gbl_rsdp_base; | ||
473 | } else { | ||
474 | rsdp_base = osl_find_rsdp_via_efi(); | ||
475 | } | ||
476 | |||
477 | if (!rsdp_base) { | ||
478 | rsdp_base = ACPI_HI_RSDP_WINDOW_BASE; | ||
479 | rsdp_size = ACPI_HI_RSDP_WINDOW_SIZE; | ||
480 | } | ||
481 | |||
482 | rsdp_address = acpi_os_map_memory(rsdp_base, rsdp_size); | ||
483 | if (!rsdp_address) { | ||
484 | return (osl_get_last_status(AE_BAD_ADDRESS)); | ||
485 | } | ||
486 | |||
487 | /* Search low memory for the RSDP */ | ||
488 | |||
489 | mapped_table = ACPI_CAST_PTR(struct acpi_table_header, | ||
490 | acpi_tb_scan_memory_for_rsdp(rsdp_address, | ||
491 | rsdp_size)); | ||
492 | if (!mapped_table) { | ||
493 | acpi_os_unmap_memory(rsdp_address, rsdp_size); | ||
494 | return (AE_NOT_FOUND); | ||
495 | } | ||
496 | |||
497 | gbl_rsdp_address = | ||
498 | rsdp_base + (ACPI_CAST8(mapped_table) - rsdp_address); | ||
499 | |||
500 | ACPI_MEMCPY(&gbl_rsdp, mapped_table, sizeof(struct acpi_table_rsdp)); | ||
501 | acpi_os_unmap_memory(rsdp_address, rsdp_size); | ||
502 | |||
503 | return (AE_OK); | ||
504 | } | ||
505 | |||
506 | /****************************************************************************** | ||
507 | * | ||
508 | * FUNCTION: osl_can_use_xsdt | ||
509 | * | ||
510 | * PARAMETERS: None | ||
511 | * | ||
512 | * RETURN: TRUE if XSDT is allowed to be used. | ||
513 | * | ||
514 | * DESCRIPTION: This function collects logic that can be used to determine if | ||
515 | * XSDT should be used instead of RSDT. | ||
516 | * | ||
517 | *****************************************************************************/ | ||
518 | |||
519 | static u8 osl_can_use_xsdt(void) | ||
520 | { | ||
521 | if (gbl_revision && !acpi_gbl_do_not_use_xsdt) { | ||
522 | return (TRUE); | ||
523 | } else { | ||
524 | return (FALSE); | ||
525 | } | ||
526 | } | ||
527 | |||
528 | /****************************************************************************** | ||
529 | * | ||
530 | * FUNCTION: osl_table_initialize | ||
531 | * | ||
532 | * PARAMETERS: None | ||
533 | * | ||
534 | * RETURN: Status | ||
535 | * | ||
536 | * DESCRIPTION: Initialize ACPI table data. Get and store main ACPI tables to | ||
537 | * local variables. Main ACPI tables include RSDT, FADT, RSDT, | ||
538 | * and/or XSDT. | ||
539 | * | ||
540 | *****************************************************************************/ | ||
541 | |||
542 | static acpi_status osl_table_initialize(void) | ||
543 | { | ||
544 | acpi_status status; | ||
545 | acpi_physical_address address; | ||
546 | |||
547 | if (gbl_table_list_initialized) { | ||
548 | return (AE_OK); | ||
549 | } | ||
550 | |||
551 | /* Get RSDP from memory */ | ||
552 | |||
553 | status = osl_load_rsdp(); | ||
554 | if (ACPI_FAILURE(status)) { | ||
555 | return (status); | ||
556 | } | ||
557 | |||
558 | /* Get XSDT from memory */ | ||
559 | |||
560 | if (gbl_rsdp.revision && !gbl_do_not_dump_xsdt) { | ||
561 | if (gbl_xsdt) { | ||
562 | free(gbl_xsdt); | ||
563 | gbl_xsdt = NULL; | ||
564 | } | ||
565 | |||
566 | gbl_revision = 2; | ||
567 | status = osl_get_bios_table(ACPI_SIG_XSDT, 0, | ||
568 | ACPI_CAST_PTR(struct | ||
569 | acpi_table_header *, | ||
570 | &gbl_xsdt), &address); | ||
571 | if (ACPI_FAILURE(status)) { | ||
572 | return (status); | ||
573 | } | ||
574 | } | ||
575 | |||
576 | /* Get RSDT from memory */ | ||
577 | |||
578 | if (gbl_rsdp.rsdt_physical_address) { | ||
579 | if (gbl_rsdt) { | ||
580 | free(gbl_rsdt); | ||
581 | gbl_rsdt = NULL; | ||
582 | } | ||
583 | |||
584 | status = osl_get_bios_table(ACPI_SIG_RSDT, 0, | ||
585 | ACPI_CAST_PTR(struct | ||
586 | acpi_table_header *, | ||
587 | &gbl_rsdt), &address); | ||
588 | if (ACPI_FAILURE(status)) { | ||
589 | return (status); | ||
590 | } | ||
591 | } | ||
592 | |||
593 | /* Get FADT from memory */ | ||
594 | |||
595 | if (gbl_fadt) { | ||
596 | free(gbl_fadt); | ||
597 | gbl_fadt = NULL; | ||
598 | } | ||
599 | |||
600 | status = osl_get_bios_table(ACPI_SIG_FADT, 0, | ||
601 | ACPI_CAST_PTR(struct acpi_table_header *, | ||
602 | &gbl_fadt), | ||
603 | &gbl_fadt_address); | ||
604 | if (ACPI_FAILURE(status)) { | ||
605 | return (status); | ||
606 | } | ||
607 | |||
608 | if (!gbl_dump_customized_tables) { | ||
609 | |||
610 | /* Add mandatory tables to global table list first */ | ||
611 | |||
612 | status = osl_add_table_to_list(ACPI_RSDP_NAME, 0); | ||
613 | if (ACPI_FAILURE(status)) { | ||
614 | return (status); | ||
615 | } | ||
616 | |||
617 | status = osl_add_table_to_list(ACPI_SIG_RSDT, 0); | ||
618 | if (ACPI_FAILURE(status)) { | ||
619 | return (status); | ||
620 | } | ||
621 | |||
622 | if (gbl_revision == 2) { | ||
623 | status = osl_add_table_to_list(ACPI_SIG_XSDT, 0); | ||
624 | if (ACPI_FAILURE(status)) { | ||
625 | return (status); | ||
626 | } | ||
627 | } | ||
628 | |||
629 | status = osl_add_table_to_list(ACPI_SIG_DSDT, 0); | ||
630 | if (ACPI_FAILURE(status)) { | ||
631 | return (status); | ||
632 | } | ||
633 | |||
634 | status = osl_add_table_to_list(ACPI_SIG_FACS, 0); | ||
635 | if (ACPI_FAILURE(status)) { | ||
636 | return (status); | ||
637 | } | ||
638 | |||
639 | /* Add all tables found in the memory */ | ||
640 | |||
641 | status = osl_list_bios_tables(); | ||
642 | if (ACPI_FAILURE(status)) { | ||
643 | return (status); | ||
644 | } | ||
645 | } else { | ||
646 | /* Add all tables found in the static directory */ | ||
647 | |||
648 | status = osl_list_customized_tables(STATIC_TABLE_DIR); | ||
649 | if (ACPI_FAILURE(status)) { | ||
650 | return (status); | ||
651 | } | ||
652 | } | ||
653 | |||
654 | if (gbl_dump_dynamic_tables) { | ||
655 | |||
656 | /* Add all dynamically loaded tables in the dynamic directory */ | ||
657 | |||
658 | status = osl_list_customized_tables(DYNAMIC_TABLE_DIR); | ||
659 | if (ACPI_FAILURE(status)) { | ||
660 | return (status); | ||
661 | } | ||
662 | } | ||
663 | |||
664 | gbl_table_list_initialized = TRUE; | ||
665 | return (AE_OK); | ||
666 | } | ||
667 | |||
668 | /****************************************************************************** | ||
669 | * | ||
670 | * FUNCTION: osl_list_bios_tables | ||
671 | * | ||
672 | * PARAMETERS: None | ||
673 | * | ||
674 | * RETURN: Status; Table list is initialized if AE_OK. | ||
675 | * | ||
676 | * DESCRIPTION: Add ACPI tables to the table list from memory. | ||
677 | * | ||
678 | * NOTE: This works on Linux as table customization does not modify the | ||
679 | * addresses stored in RSDP/RSDT/XSDT/FADT. | ||
680 | * | ||
681 | *****************************************************************************/ | ||
682 | |||
683 | static acpi_status osl_list_bios_tables(void) | ||
684 | { | ||
685 | struct acpi_table_header *mapped_table = NULL; | ||
686 | u8 *table_data; | ||
687 | u8 number_of_tables; | ||
688 | u8 item_size; | ||
689 | acpi_physical_address table_address = 0; | ||
690 | acpi_status status = AE_OK; | ||
691 | u32 i; | ||
692 | |||
693 | if (osl_can_use_xsdt()) { | ||
694 | item_size = sizeof(u64); | ||
695 | table_data = | ||
696 | ACPI_CAST8(gbl_xsdt) + sizeof(struct acpi_table_header); | ||
697 | number_of_tables = | ||
698 | (u8)((gbl_xsdt->header.length - | ||
699 | sizeof(struct acpi_table_header)) | ||
700 | / item_size); | ||
701 | } else { /* Use RSDT if XSDT is not available */ | ||
702 | |||
703 | item_size = sizeof(u32); | ||
704 | table_data = | ||
705 | ACPI_CAST8(gbl_rsdt) + sizeof(struct acpi_table_header); | ||
706 | number_of_tables = | ||
707 | (u8)((gbl_rsdt->header.length - | ||
708 | sizeof(struct acpi_table_header)) | ||
709 | / item_size); | ||
710 | } | ||
711 | |||
712 | /* Search RSDT/XSDT for the requested table */ | ||
713 | |||
714 | for (i = 0; i < number_of_tables; ++i, table_data += item_size) { | ||
715 | if (osl_can_use_xsdt()) { | ||
716 | table_address = | ||
717 | (acpi_physical_address) (*ACPI_CAST64(table_data)); | ||
718 | } else { | ||
719 | table_address = | ||
720 | (acpi_physical_address) (*ACPI_CAST32(table_data)); | ||
721 | } | ||
722 | |||
723 | /* Skip NULL entries in RSDT/XSDT */ | ||
724 | |||
725 | if (!table_address) { | ||
726 | continue; | ||
727 | } | ||
728 | |||
729 | status = osl_map_table(table_address, NULL, &mapped_table); | ||
730 | if (ACPI_FAILURE(status)) { | ||
731 | return (status); | ||
732 | } | ||
733 | |||
734 | osl_add_table_to_list(mapped_table->signature, 0); | ||
735 | osl_unmap_table(mapped_table); | ||
736 | } | ||
737 | |||
738 | return (AE_OK); | ||
739 | } | ||
740 | |||
741 | /****************************************************************************** | ||
742 | * | ||
743 | * FUNCTION: osl_get_bios_table | ||
744 | * | ||
745 | * PARAMETERS: signature - ACPI Signature for common table. Must be | ||
746 | * a null terminated 4-character string. | ||
747 | * instance - Multiple table support for SSDT/UEFI (0...n) | ||
748 | * Must be 0 for other tables. | ||
749 | * table - Where a pointer to the table is returned | ||
750 | * address - Where the table physical address is returned | ||
751 | * | ||
752 | * RETURN: Status; Table buffer and physical address returned if AE_OK. | ||
753 | * AE_LIMIT: Instance is beyond valid limit | ||
754 | * AE_NOT_FOUND: A table with the signature was not found | ||
755 | * | ||
756 | * DESCRIPTION: Get a BIOS provided ACPI table | ||
757 | * | ||
758 | * NOTE: Assumes the input signature is uppercase. | ||
759 | * | ||
760 | *****************************************************************************/ | ||
761 | |||
762 | static acpi_status | ||
763 | osl_get_bios_table(char *signature, | ||
764 | u32 instance, | ||
765 | struct acpi_table_header **table, | ||
766 | acpi_physical_address * address) | ||
767 | { | ||
768 | struct acpi_table_header *local_table = NULL; | ||
769 | struct acpi_table_header *mapped_table = NULL; | ||
770 | u8 *table_data; | ||
771 | u8 number_of_tables; | ||
772 | u8 item_size; | ||
773 | u32 current_instance = 0; | ||
774 | acpi_physical_address table_address = 0; | ||
775 | u32 table_length = 0; | ||
776 | acpi_status status = AE_OK; | ||
777 | u32 i; | ||
778 | |||
779 | /* Handle special tables whose addresses are not in RSDT/XSDT */ | ||
780 | |||
781 | if (ACPI_COMPARE_NAME(signature, ACPI_RSDP_NAME) || | ||
782 | ACPI_COMPARE_NAME(signature, ACPI_SIG_RSDT) || | ||
783 | ACPI_COMPARE_NAME(signature, ACPI_SIG_XSDT) || | ||
784 | ACPI_COMPARE_NAME(signature, ACPI_SIG_DSDT) || | ||
785 | ACPI_COMPARE_NAME(signature, ACPI_SIG_FACS)) { | ||
786 | if (instance > 0) { | ||
787 | return (AE_LIMIT); | ||
788 | } | ||
789 | |||
790 | /* | ||
791 | * Get the appropriate address, either 32-bit or 64-bit. Be very | ||
792 | * careful about the FADT length and validate table addresses. | ||
793 | * Note: The 64-bit addresses have priority. | ||
794 | */ | ||
795 | if (ACPI_COMPARE_NAME(signature, ACPI_SIG_DSDT)) { | ||
796 | if ((gbl_fadt->header.length >= MIN_FADT_FOR_XDSDT) && | ||
797 | gbl_fadt->Xdsdt) { | ||
798 | table_address = | ||
799 | (acpi_physical_address) gbl_fadt->Xdsdt; | ||
800 | } else | ||
801 | if ((gbl_fadt->header.length >= MIN_FADT_FOR_DSDT) | ||
802 | && gbl_fadt->dsdt) { | ||
803 | table_address = | ||
804 | (acpi_physical_address) gbl_fadt->dsdt; | ||
805 | } | ||
806 | } else if (ACPI_COMPARE_NAME(signature, ACPI_SIG_FACS)) { | ||
807 | if ((gbl_fadt->header.length >= MIN_FADT_FOR_XFACS) && | ||
808 | gbl_fadt->Xfacs) { | ||
809 | table_address = | ||
810 | (acpi_physical_address) gbl_fadt->Xfacs; | ||
811 | } else | ||
812 | if ((gbl_fadt->header.length >= MIN_FADT_FOR_FACS) | ||
813 | && gbl_fadt->facs) { | ||
814 | table_address = | ||
815 | (acpi_physical_address) gbl_fadt->facs; | ||
816 | } | ||
817 | } else if (ACPI_COMPARE_NAME(signature, ACPI_SIG_XSDT)) { | ||
818 | if (!gbl_revision) { | ||
819 | return (AE_BAD_SIGNATURE); | ||
820 | } | ||
821 | table_address = | ||
822 | (acpi_physical_address) gbl_rsdp. | ||
823 | xsdt_physical_address; | ||
824 | } else if (ACPI_COMPARE_NAME(signature, ACPI_SIG_RSDT)) { | ||
825 | table_address = | ||
826 | (acpi_physical_address) gbl_rsdp. | ||
827 | rsdt_physical_address; | ||
828 | } else { | ||
829 | table_address = | ||
830 | (acpi_physical_address) gbl_rsdp_address; | ||
831 | signature = ACPI_SIG_RSDP; | ||
832 | } | ||
833 | |||
834 | /* Now we can get the requested special table */ | ||
835 | |||
836 | status = osl_map_table(table_address, signature, &mapped_table); | ||
837 | if (ACPI_FAILURE(status)) { | ||
838 | return (status); | ||
839 | } | ||
840 | |||
841 | table_length = ap_get_table_length(mapped_table); | ||
842 | } else { /* Case for a normal ACPI table */ | ||
843 | |||
844 | if (osl_can_use_xsdt()) { | ||
845 | item_size = sizeof(u64); | ||
846 | table_data = | ||
847 | ACPI_CAST8(gbl_xsdt) + | ||
848 | sizeof(struct acpi_table_header); | ||
849 | number_of_tables = | ||
850 | (u8)((gbl_xsdt->header.length - | ||
851 | sizeof(struct acpi_table_header)) | ||
852 | / item_size); | ||
853 | } else { /* Use RSDT if XSDT is not available */ | ||
854 | |||
855 | item_size = sizeof(u32); | ||
856 | table_data = | ||
857 | ACPI_CAST8(gbl_rsdt) + | ||
858 | sizeof(struct acpi_table_header); | ||
859 | number_of_tables = | ||
860 | (u8)((gbl_rsdt->header.length - | ||
861 | sizeof(struct acpi_table_header)) | ||
862 | / item_size); | ||
863 | } | ||
864 | |||
865 | /* Search RSDT/XSDT for the requested table */ | ||
866 | |||
867 | for (i = 0; i < number_of_tables; ++i, table_data += item_size) { | ||
868 | if (osl_can_use_xsdt()) { | ||
869 | table_address = | ||
870 | (acpi_physical_address) (*ACPI_CAST64 | ||
871 | (table_data)); | ||
872 | } else { | ||
873 | table_address = | ||
874 | (acpi_physical_address) (*ACPI_CAST32 | ||
875 | (table_data)); | ||
876 | } | ||
877 | |||
878 | /* Skip NULL entries in RSDT/XSDT */ | ||
879 | |||
880 | if (!table_address) { | ||
881 | continue; | ||
882 | } | ||
883 | |||
884 | status = | ||
885 | osl_map_table(table_address, NULL, &mapped_table); | ||
886 | if (ACPI_FAILURE(status)) { | ||
887 | return (status); | ||
888 | } | ||
889 | table_length = mapped_table->length; | ||
890 | |||
891 | /* Does this table match the requested signature? */ | ||
892 | |||
893 | if (!ACPI_COMPARE_NAME | ||
894 | (mapped_table->signature, signature)) { | ||
895 | osl_unmap_table(mapped_table); | ||
896 | mapped_table = NULL; | ||
897 | continue; | ||
898 | } | ||
899 | |||
900 | /* Match table instance (for SSDT/UEFI tables) */ | ||
901 | |||
902 | if (current_instance != instance) { | ||
903 | osl_unmap_table(mapped_table); | ||
904 | mapped_table = NULL; | ||
905 | current_instance++; | ||
906 | continue; | ||
907 | } | ||
908 | |||
909 | break; | ||
910 | } | ||
911 | } | ||
912 | |||
913 | if (!mapped_table) { | ||
914 | return (AE_LIMIT); | ||
915 | } | ||
916 | |||
917 | if (table_length == 0) { | ||
918 | status = AE_BAD_HEADER; | ||
919 | goto exit; | ||
920 | } | ||
921 | |||
922 | /* Copy table to local buffer and return it */ | ||
923 | |||
924 | local_table = calloc(1, table_length); | ||
925 | if (!local_table) { | ||
926 | status = AE_NO_MEMORY; | ||
927 | goto exit; | ||
928 | } | ||
929 | |||
930 | ACPI_MEMCPY(local_table, mapped_table, table_length); | ||
931 | *address = table_address; | ||
932 | *table = local_table; | ||
933 | |||
934 | exit: | ||
935 | osl_unmap_table(mapped_table); | ||
936 | return (status); | ||
937 | } | ||
938 | |||
939 | /****************************************************************************** | ||
940 | * | ||
941 | * FUNCTION: osl_list_customized_tables | ||
942 | * | ||
943 | * PARAMETERS: directory - Directory that contains the tables | ||
944 | * | ||
945 | * RETURN: Status; Table list is initialized if AE_OK. | ||
946 | * | ||
947 | * DESCRIPTION: Add ACPI tables to the table list from a directory. | ||
948 | * | ||
949 | *****************************************************************************/ | ||
950 | |||
951 | static acpi_status osl_list_customized_tables(char *directory) | ||
952 | { | ||
953 | void *table_dir; | ||
954 | u32 instance; | ||
955 | char temp_name[ACPI_NAME_SIZE]; | ||
956 | char *filename; | ||
957 | acpi_status status = AE_OK; | ||
958 | |||
959 | /* Open the requested directory */ | ||
960 | |||
961 | table_dir = acpi_os_open_directory(directory, "*", REQUEST_FILE_ONLY); | ||
962 | if (!table_dir) { | ||
963 | return (osl_get_last_status(AE_NOT_FOUND)); | ||
964 | } | ||
965 | |||
966 | /* Examine all entries in this directory */ | ||
967 | |||
968 | while ((filename = acpi_os_get_next_filename(table_dir))) { | ||
969 | |||
970 | /* Extract table name and instance number */ | ||
971 | |||
972 | status = | ||
973 | osl_table_name_from_file(filename, temp_name, &instance); | ||
974 | |||
975 | /* Ignore meaningless files */ | ||
976 | |||
977 | if (ACPI_FAILURE(status)) { | ||
978 | continue; | ||
979 | } | ||
980 | |||
981 | /* Add new info node to global table list */ | ||
982 | |||
983 | status = osl_add_table_to_list(temp_name, instance); | ||
984 | if (ACPI_FAILURE(status)) { | ||
985 | break; | ||
986 | } | ||
987 | } | ||
988 | |||
989 | acpi_os_close_directory(table_dir); | ||
990 | return (status); | ||
991 | } | ||
992 | |||
993 | /****************************************************************************** | ||
994 | * | ||
995 | * FUNCTION: osl_map_table | ||
996 | * | ||
997 | * PARAMETERS: address - Address of the table in memory | ||
998 | * signature - Optional ACPI Signature for desired table. | ||
999 | * Null terminated 4-character string. | ||
1000 | * table - Where a pointer to the mapped table is | ||
1001 | * returned | ||
1002 | * | ||
1003 | * RETURN: Status; Mapped table is returned if AE_OK. | ||
1004 | * AE_NOT_FOUND: A valid table was not found at the address | ||
1005 | * | ||
1006 | * DESCRIPTION: Map entire ACPI table into caller's address space. | ||
1007 | * | ||
1008 | *****************************************************************************/ | ||
1009 | |||
1010 | static acpi_status | ||
1011 | osl_map_table(acpi_size address, | ||
1012 | char *signature, struct acpi_table_header **table) | ||
1013 | { | ||
1014 | struct acpi_table_header *mapped_table; | ||
1015 | u32 length; | ||
1016 | |||
1017 | if (!address) { | ||
1018 | return (AE_BAD_ADDRESS); | ||
1019 | } | ||
1020 | |||
1021 | /* | ||
1022 | * Map the header so we can get the table length. | ||
1023 | * Use sizeof (struct acpi_table_header) as: | ||
1024 | * 1. it is bigger than 24 to include RSDP->Length | ||
1025 | * 2. it is smaller than sizeof (struct acpi_table_rsdp) | ||
1026 | */ | ||
1027 | mapped_table = | ||
1028 | acpi_os_map_memory(address, sizeof(struct acpi_table_header)); | ||
1029 | if (!mapped_table) { | ||
1030 | fprintf(stderr, "Could not map table header at 0x%8.8X%8.8X\n", | ||
1031 | ACPI_FORMAT_UINT64(address)); | ||
1032 | return (osl_get_last_status(AE_BAD_ADDRESS)); | ||
1033 | } | ||
1034 | |||
1035 | /* If specified, signature must match */ | ||
1036 | |||
1037 | if (signature) { | ||
1038 | if (ACPI_VALIDATE_RSDP_SIG(signature)) { | ||
1039 | if (!ACPI_VALIDATE_RSDP_SIG(mapped_table->signature)) { | ||
1040 | acpi_os_unmap_memory(mapped_table, | ||
1041 | sizeof(struct | ||
1042 | acpi_table_header)); | ||
1043 | return (AE_BAD_SIGNATURE); | ||
1044 | } | ||
1045 | } else | ||
1046 | if (!ACPI_COMPARE_NAME(signature, mapped_table->signature)) | ||
1047 | { | ||
1048 | acpi_os_unmap_memory(mapped_table, | ||
1049 | sizeof(struct acpi_table_header)); | ||
1050 | return (AE_BAD_SIGNATURE); | ||
1051 | } | ||
1052 | } | ||
1053 | |||
1054 | /* Map the entire table */ | ||
1055 | |||
1056 | length = ap_get_table_length(mapped_table); | ||
1057 | acpi_os_unmap_memory(mapped_table, sizeof(struct acpi_table_header)); | ||
1058 | if (length == 0) { | ||
1059 | return (AE_BAD_HEADER); | ||
1060 | } | ||
1061 | |||
1062 | mapped_table = acpi_os_map_memory(address, length); | ||
1063 | if (!mapped_table) { | ||
1064 | fprintf(stderr, | ||
1065 | "Could not map table at 0x%8.8X%8.8X length %8.8X\n", | ||
1066 | ACPI_FORMAT_UINT64(address), length); | ||
1067 | return (osl_get_last_status(AE_INVALID_TABLE_LENGTH)); | ||
1068 | } | ||
1069 | |||
1070 | (void)ap_is_valid_checksum(mapped_table); | ||
1071 | |||
1072 | *table = mapped_table; | ||
1073 | return (AE_OK); | ||
1074 | } | ||
1075 | |||
1076 | /****************************************************************************** | ||
1077 | * | ||
1078 | * FUNCTION: osl_unmap_table | ||
1079 | * | ||
1080 | * PARAMETERS: table - A pointer to the mapped table | ||
1081 | * | ||
1082 | * RETURN: None | ||
1083 | * | ||
1084 | * DESCRIPTION: Unmap entire ACPI table. | ||
1085 | * | ||
1086 | *****************************************************************************/ | ||
1087 | |||
1088 | static void osl_unmap_table(struct acpi_table_header *table) | ||
1089 | { | ||
1090 | if (table) { | ||
1091 | acpi_os_unmap_memory(table, ap_get_table_length(table)); | ||
1092 | } | ||
1093 | } | ||
1094 | |||
1095 | /****************************************************************************** | ||
1096 | * | ||
1097 | * FUNCTION: osl_table_name_from_file | ||
1098 | * | ||
1099 | * PARAMETERS: filename - File that contains the desired table | ||
1100 | * signature - Pointer to 4-character buffer to store | ||
1101 | * extracted table signature. | ||
1102 | * instance - Pointer to integer to store extracted | ||
1103 | * table instance number. | ||
1104 | * | ||
1105 | * RETURN: Status; Table name is extracted if AE_OK. | ||
1106 | * | ||
1107 | * DESCRIPTION: Extract table signature and instance number from a table file | ||
1108 | * name. | ||
1109 | * | ||
1110 | *****************************************************************************/ | ||
1111 | |||
1112 | static acpi_status | ||
1113 | osl_table_name_from_file(char *filename, char *signature, u32 *instance) | ||
1114 | { | ||
1115 | |||
1116 | /* Ignore meaningless files */ | ||
1117 | |||
1118 | if (strlen(filename) < ACPI_NAME_SIZE) { | ||
1119 | return (AE_BAD_SIGNATURE); | ||
1120 | } | ||
1121 | |||
1122 | /* Extract instance number */ | ||
1123 | |||
1124 | if (isdigit((int)filename[ACPI_NAME_SIZE])) { | ||
1125 | sscanf(&filename[ACPI_NAME_SIZE], "%d", instance); | ||
1126 | } else if (strlen(filename) != ACPI_NAME_SIZE) { | ||
1127 | return (AE_BAD_SIGNATURE); | ||
1128 | } else { | ||
1129 | *instance = 0; | ||
1130 | } | ||
1131 | |||
1132 | /* Extract signature */ | ||
1133 | |||
1134 | ACPI_MOVE_NAME(signature, filename); | ||
1135 | return (AE_OK); | ||
1136 | } | ||
1137 | |||
1138 | /****************************************************************************** | ||
1139 | * | ||
1140 | * FUNCTION: osl_read_table_from_file | ||
1141 | * | ||
1142 | * PARAMETERS: filename - File that contains the desired table | ||
1143 | * file_offset - Offset of the table in file | ||
1144 | * signature - Optional ACPI Signature for desired table. | ||
1145 | * A null terminated 4-character string. | ||
1146 | * table - Where a pointer to the table is returned | ||
1147 | * | ||
1148 | * RETURN: Status; Table buffer is returned if AE_OK. | ||
1149 | * | ||
1150 | * DESCRIPTION: Read a ACPI table from a file. | ||
1151 | * | ||
1152 | *****************************************************************************/ | ||
1153 | |||
1154 | static acpi_status | ||
1155 | osl_read_table_from_file(char *filename, | ||
1156 | acpi_size file_offset, | ||
1157 | char *signature, struct acpi_table_header **table) | ||
1158 | { | ||
1159 | FILE *table_file; | ||
1160 | struct acpi_table_header header; | ||
1161 | struct acpi_table_header *local_table = NULL; | ||
1162 | u32 table_length; | ||
1163 | s32 count; | ||
1164 | acpi_status status = AE_OK; | ||
1165 | |||
1166 | /* Open the file */ | ||
1167 | |||
1168 | table_file = fopen(filename, "rb"); | ||
1169 | if (table_file == NULL) { | ||
1170 | fprintf(stderr, "Could not open table file: %s\n", filename); | ||
1171 | return (osl_get_last_status(AE_NOT_FOUND)); | ||
1172 | } | ||
1173 | |||
1174 | fseek(table_file, file_offset, SEEK_SET); | ||
1175 | |||
1176 | /* Read the Table header to get the table length */ | ||
1177 | |||
1178 | count = fread(&header, 1, sizeof(struct acpi_table_header), table_file); | ||
1179 | if (count != sizeof(struct acpi_table_header)) { | ||
1180 | fprintf(stderr, "Could not read table header: %s\n", filename); | ||
1181 | status = AE_BAD_HEADER; | ||
1182 | goto exit; | ||
1183 | } | ||
1184 | |||
1185 | /* If signature is specified, it must match the table */ | ||
1186 | |||
1187 | if (signature) { | ||
1188 | if (ACPI_VALIDATE_RSDP_SIG(signature)) { | ||
1189 | if (!ACPI_VALIDATE_RSDP_SIG(header.signature)) { | ||
1190 | fprintf(stderr, | ||
1191 | "Incorrect RSDP signature: found %8.8s\n", | ||
1192 | header.signature); | ||
1193 | status = AE_BAD_SIGNATURE; | ||
1194 | goto exit; | ||
1195 | } | ||
1196 | } else if (!ACPI_COMPARE_NAME(signature, header.signature)) { | ||
1197 | fprintf(stderr, | ||
1198 | "Incorrect signature: Expecting %4.4s, found %4.4s\n", | ||
1199 | signature, header.signature); | ||
1200 | status = AE_BAD_SIGNATURE; | ||
1201 | goto exit; | ||
1202 | } | ||
1203 | } | ||
1204 | |||
1205 | table_length = ap_get_table_length(&header); | ||
1206 | if (table_length == 0) { | ||
1207 | status = AE_BAD_HEADER; | ||
1208 | goto exit; | ||
1209 | } | ||
1210 | |||
1211 | /* Read the entire table into a local buffer */ | ||
1212 | |||
1213 | local_table = calloc(1, table_length); | ||
1214 | if (!local_table) { | ||
1215 | fprintf(stderr, | ||
1216 | "%4.4s: Could not allocate buffer for table of length %X\n", | ||
1217 | header.signature, table_length); | ||
1218 | status = AE_NO_MEMORY; | ||
1219 | goto exit; | ||
1220 | } | ||
1221 | |||
1222 | fseek(table_file, file_offset, SEEK_SET); | ||
1223 | |||
1224 | count = fread(local_table, 1, table_length, table_file); | ||
1225 | if (count != table_length) { | ||
1226 | fprintf(stderr, "%4.4s: Could not read table content\n", | ||
1227 | header.signature); | ||
1228 | status = AE_INVALID_TABLE_LENGTH; | ||
1229 | goto exit; | ||
1230 | } | ||
1231 | |||
1232 | /* Validate checksum */ | ||
1233 | |||
1234 | (void)ap_is_valid_checksum(local_table); | ||
1235 | |||
1236 | exit: | ||
1237 | fclose(table_file); | ||
1238 | *table = local_table; | ||
1239 | return (status); | ||
1240 | } | ||
1241 | |||
1242 | /****************************************************************************** | ||
1243 | * | ||
1244 | * FUNCTION: osl_get_customized_table | ||
1245 | * | ||
1246 | * PARAMETERS: pathname - Directory to find Linux customized table | ||
1247 | * signature - ACPI Signature for desired table. Must be | ||
1248 | * a null terminated 4-character string. | ||
1249 | * instance - Multiple table support for SSDT/UEFI (0...n) | ||
1250 | * Must be 0 for other tables. | ||
1251 | * table - Where a pointer to the table is returned | ||
1252 | * address - Where the table physical address is returned | ||
1253 | * | ||
1254 | * RETURN: Status; Table buffer is returned if AE_OK. | ||
1255 | * AE_LIMIT: Instance is beyond valid limit | ||
1256 | * AE_NOT_FOUND: A table with the signature was not found | ||
1257 | * | ||
1258 | * DESCRIPTION: Get an OS customized table. | ||
1259 | * | ||
1260 | *****************************************************************************/ | ||
1261 | |||
1262 | static acpi_status | ||
1263 | osl_get_customized_table(char *pathname, | ||
1264 | char *signature, | ||
1265 | u32 instance, | ||
1266 | struct acpi_table_header **table, | ||
1267 | acpi_physical_address * address) | ||
1268 | { | ||
1269 | void *table_dir; | ||
1270 | u32 current_instance = 0; | ||
1271 | char temp_name[ACPI_NAME_SIZE]; | ||
1272 | char table_filename[PATH_MAX]; | ||
1273 | char *filename; | ||
1274 | acpi_status status; | ||
1275 | |||
1276 | /* Open the directory for customized tables */ | ||
1277 | |||
1278 | table_dir = acpi_os_open_directory(pathname, "*", REQUEST_FILE_ONLY); | ||
1279 | if (!table_dir) { | ||
1280 | return (osl_get_last_status(AE_NOT_FOUND)); | ||
1281 | } | ||
1282 | |||
1283 | /* Attempt to find the table in the directory */ | ||
1284 | |||
1285 | while ((filename = acpi_os_get_next_filename(table_dir))) { | ||
1286 | |||
1287 | /* Ignore meaningless files */ | ||
1288 | |||
1289 | if (!ACPI_COMPARE_NAME(filename, signature)) { | ||
1290 | continue; | ||
1291 | } | ||
1292 | |||
1293 | /* Extract table name and instance number */ | ||
1294 | |||
1295 | status = | ||
1296 | osl_table_name_from_file(filename, temp_name, | ||
1297 | ¤t_instance); | ||
1298 | |||
1299 | /* Ignore meaningless files */ | ||
1300 | |||
1301 | if (ACPI_FAILURE(status) || current_instance != instance) { | ||
1302 | continue; | ||
1303 | } | ||
1304 | |||
1305 | /* Create the table pathname */ | ||
1306 | |||
1307 | if (instance != 0) { | ||
1308 | sprintf(table_filename, "%s/%4.4s%d", pathname, | ||
1309 | temp_name, instance); | ||
1310 | } else { | ||
1311 | sprintf(table_filename, "%s/%4.4s", pathname, | ||
1312 | temp_name); | ||
1313 | } | ||
1314 | break; | ||
1315 | } | ||
1316 | |||
1317 | acpi_os_close_directory(table_dir); | ||
1318 | |||
1319 | if (!filename) { | ||
1320 | return (AE_LIMIT); | ||
1321 | } | ||
1322 | |||
1323 | /* There is no physical address saved for customized tables, use zero */ | ||
1324 | |||
1325 | *address = 0; | ||
1326 | status = osl_read_table_from_file(table_filename, 0, NULL, table); | ||
1327 | |||
1328 | return (status); | ||
1329 | } | ||
diff --git a/tools/power/acpi/os_specific/service_layers/osunixdir.c b/tools/power/acpi/os_specific/service_layers/osunixdir.c new file mode 100644 index 000000000000..733f9e490fc4 --- /dev/null +++ b/tools/power/acpi/os_specific/service_layers/osunixdir.c | |||
@@ -0,0 +1,204 @@ | |||
1 | /****************************************************************************** | ||
2 | * | ||
3 | * Module Name: osunixdir - Unix directory access interfaces | ||
4 | * | ||
5 | *****************************************************************************/ | ||
6 | |||
7 | /* | ||
8 | * Copyright (C) 2000 - 2014, Intel Corp. | ||
9 | * All rights reserved. | ||
10 | * | ||
11 | * Redistribution and use in source and binary forms, with or without | ||
12 | * modification, are permitted provided that the following conditions | ||
13 | * are met: | ||
14 | * 1. Redistributions of source code must retain the above copyright | ||
15 | * notice, this list of conditions, and the following disclaimer, | ||
16 | * without modification. | ||
17 | * 2. Redistributions in binary form must reproduce at minimum a disclaimer | ||
18 | * substantially similar to the "NO WARRANTY" disclaimer below | ||
19 | * ("Disclaimer") and any redistribution must be conditioned upon | ||
20 | * including a substantially similar Disclaimer requirement for further | ||
21 | * binary redistribution. | ||
22 | * 3. Neither the names of the above-listed copyright holders nor the names | ||
23 | * of any contributors may be used to endorse or promote products derived | ||
24 | * from this software without specific prior written permission. | ||
25 | * | ||
26 | * Alternatively, this software may be distributed under the terms of the | ||
27 | * GNU General Public License ("GPL") version 2 as published by the Free | ||
28 | * Software Foundation. | ||
29 | * | ||
30 | * NO WARRANTY | ||
31 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS | ||
32 | * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT | ||
33 | * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR | ||
34 | * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT | ||
35 | * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL | ||
36 | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS | ||
37 | * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) | ||
38 | * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, | ||
39 | * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING | ||
40 | * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE | ||
41 | * POSSIBILITY OF SUCH DAMAGES. | ||
42 | */ | ||
43 | |||
44 | #include <acpi/acpi.h> | ||
45 | |||
46 | #include <stdio.h> | ||
47 | #include <stdlib.h> | ||
48 | #include <string.h> | ||
49 | #include <dirent.h> | ||
50 | #include <fnmatch.h> | ||
51 | #include <ctype.h> | ||
52 | #include <sys/stat.h> | ||
53 | |||
54 | /* | ||
55 | * Allocated structure returned from os_open_directory | ||
56 | */ | ||
57 | typedef struct external_find_info { | ||
58 | char *dir_pathname; | ||
59 | DIR *dir_ptr; | ||
60 | char temp_buffer[256]; | ||
61 | char *wildcard_spec; | ||
62 | char requested_file_type; | ||
63 | |||
64 | } external_find_info; | ||
65 | |||
66 | /******************************************************************************* | ||
67 | * | ||
68 | * FUNCTION: acpi_os_open_directory | ||
69 | * | ||
70 | * PARAMETERS: dir_pathname - Full pathname to the directory | ||
71 | * wildcard_spec - string of the form "*.c", etc. | ||
72 | * | ||
73 | * RETURN: A directory "handle" to be used in subsequent search operations. | ||
74 | * NULL returned on failure. | ||
75 | * | ||
76 | * DESCRIPTION: Open a directory in preparation for a wildcard search | ||
77 | * | ||
78 | ******************************************************************************/ | ||
79 | |||
80 | void *acpi_os_open_directory(char *dir_pathname, | ||
81 | char *wildcard_spec, char requested_file_type) | ||
82 | { | ||
83 | struct external_find_info *external_info; | ||
84 | DIR *dir; | ||
85 | |||
86 | /* Allocate the info struct that will be returned to the caller */ | ||
87 | |||
88 | external_info = calloc(1, sizeof(struct external_find_info)); | ||
89 | if (!external_info) { | ||
90 | return (NULL); | ||
91 | } | ||
92 | |||
93 | /* Get the directory stream */ | ||
94 | |||
95 | dir = opendir(dir_pathname); | ||
96 | if (!dir) { | ||
97 | fprintf(stderr, "Cannot open directory - %s\n", dir_pathname); | ||
98 | free(external_info); | ||
99 | return (NULL); | ||
100 | } | ||
101 | |||
102 | /* Save the info in the return structure */ | ||
103 | |||
104 | external_info->wildcard_spec = wildcard_spec; | ||
105 | external_info->requested_file_type = requested_file_type; | ||
106 | external_info->dir_pathname = dir_pathname; | ||
107 | external_info->dir_ptr = dir; | ||
108 | return (external_info); | ||
109 | } | ||
110 | |||
111 | /******************************************************************************* | ||
112 | * | ||
113 | * FUNCTION: acpi_os_get_next_filename | ||
114 | * | ||
115 | * PARAMETERS: dir_handle - Created via acpi_os_open_directory | ||
116 | * | ||
117 | * RETURN: Next filename matched. NULL if no more matches. | ||
118 | * | ||
119 | * DESCRIPTION: Get the next file in the directory that matches the wildcard | ||
120 | * specification. | ||
121 | * | ||
122 | ******************************************************************************/ | ||
123 | |||
124 | char *acpi_os_get_next_filename(void *dir_handle) | ||
125 | { | ||
126 | struct external_find_info *external_info = dir_handle; | ||
127 | struct dirent *dir_entry; | ||
128 | char *temp_str; | ||
129 | int str_len; | ||
130 | struct stat temp_stat; | ||
131 | int err; | ||
132 | |||
133 | while ((dir_entry = readdir(external_info->dir_ptr))) { | ||
134 | if (!fnmatch | ||
135 | (external_info->wildcard_spec, dir_entry->d_name, 0)) { | ||
136 | if (dir_entry->d_name[0] == '.') { | ||
137 | continue; | ||
138 | } | ||
139 | |||
140 | str_len = strlen(dir_entry->d_name) + | ||
141 | strlen(external_info->dir_pathname) + 2; | ||
142 | |||
143 | temp_str = calloc(str_len, 1); | ||
144 | if (!temp_str) { | ||
145 | fprintf(stderr, | ||
146 | "Could not allocate buffer for temporary string\n"); | ||
147 | return (NULL); | ||
148 | } | ||
149 | |||
150 | strcpy(temp_str, external_info->dir_pathname); | ||
151 | strcat(temp_str, "/"); | ||
152 | strcat(temp_str, dir_entry->d_name); | ||
153 | |||
154 | err = stat(temp_str, &temp_stat); | ||
155 | if (err == -1) { | ||
156 | fprintf(stderr, | ||
157 | "Cannot stat file (should not happen) - %s\n", | ||
158 | temp_str); | ||
159 | free(temp_str); | ||
160 | return (NULL); | ||
161 | } | ||
162 | |||
163 | free(temp_str); | ||
164 | |||
165 | if ((S_ISDIR(temp_stat.st_mode) | ||
166 | && (external_info->requested_file_type == | ||
167 | REQUEST_DIR_ONLY)) | ||
168 | || ((!S_ISDIR(temp_stat.st_mode) | ||
169 | && external_info->requested_file_type == | ||
170 | REQUEST_FILE_ONLY))) { | ||
171 | |||
172 | /* copy to a temp buffer because dir_entry struct is on the stack */ | ||
173 | |||
174 | strcpy(external_info->temp_buffer, | ||
175 | dir_entry->d_name); | ||
176 | return (external_info->temp_buffer); | ||
177 | } | ||
178 | } | ||
179 | } | ||
180 | |||
181 | return (NULL); | ||
182 | } | ||
183 | |||
184 | /******************************************************************************* | ||
185 | * | ||
186 | * FUNCTION: acpi_os_close_directory | ||
187 | * | ||
188 | * PARAMETERS: dir_handle - Created via acpi_os_open_directory | ||
189 | * | ||
190 | * RETURN: None. | ||
191 | * | ||
192 | * DESCRIPTION: Close the open directory and cleanup. | ||
193 | * | ||
194 | ******************************************************************************/ | ||
195 | |||
196 | void acpi_os_close_directory(void *dir_handle) | ||
197 | { | ||
198 | struct external_find_info *external_info = dir_handle; | ||
199 | |||
200 | /* Close the directory and free allocations */ | ||
201 | |||
202 | closedir(external_info->dir_ptr); | ||
203 | free(dir_handle); | ||
204 | } | ||
diff --git a/tools/power/acpi/os_specific/service_layers/osunixmap.c b/tools/power/acpi/os_specific/service_layers/osunixmap.c new file mode 100644 index 000000000000..99b47b6194a3 --- /dev/null +++ b/tools/power/acpi/os_specific/service_layers/osunixmap.c | |||
@@ -0,0 +1,151 @@ | |||
1 | /****************************************************************************** | ||
2 | * | ||
3 | * Module Name: osunixmap - Unix OSL for file mappings | ||
4 | * | ||
5 | *****************************************************************************/ | ||
6 | |||
7 | /* | ||
8 | * Copyright (C) 2000 - 2014, Intel Corp. | ||
9 | * All rights reserved. | ||
10 | * | ||
11 | * Redistribution and use in source and binary forms, with or without | ||
12 | * modification, are permitted provided that the following conditions | ||
13 | * are met: | ||
14 | * 1. Redistributions of source code must retain the above copyright | ||
15 | * notice, this list of conditions, and the following disclaimer, | ||
16 | * without modification. | ||
17 | * 2. Redistributions in binary form must reproduce at minimum a disclaimer | ||
18 | * substantially similar to the "NO WARRANTY" disclaimer below | ||
19 | * ("Disclaimer") and any redistribution must be conditioned upon | ||
20 | * including a substantially similar Disclaimer requirement for further | ||
21 | * binary redistribution. | ||
22 | * 3. Neither the names of the above-listed copyright holders nor the names | ||
23 | * of any contributors may be used to endorse or promote products derived | ||
24 | * from this software without specific prior written permission. | ||
25 | * | ||
26 | * Alternatively, this software may be distributed under the terms of the | ||
27 | * GNU General Public License ("GPL") version 2 as published by the Free | ||
28 | * Software Foundation. | ||
29 | * | ||
30 | * NO WARRANTY | ||
31 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS | ||
32 | * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT | ||
33 | * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR | ||
34 | * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT | ||
35 | * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL | ||
36 | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS | ||
37 | * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) | ||
38 | * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, | ||
39 | * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING | ||
40 | * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE | ||
41 | * POSSIBILITY OF SUCH DAMAGES. | ||
42 | */ | ||
43 | |||
44 | #include "acpidump.h" | ||
45 | #include <unistd.h> | ||
46 | #include <sys/mman.h> | ||
47 | #ifdef _free_BSD | ||
48 | #include <sys/param.h> | ||
49 | #endif | ||
50 | |||
51 | #define _COMPONENT ACPI_OS_SERVICES | ||
52 | ACPI_MODULE_NAME("osunixmap") | ||
53 | |||
54 | #ifndef O_BINARY | ||
55 | #define O_BINARY 0 | ||
56 | #endif | ||
57 | #ifdef _free_BSD | ||
58 | #define MMAP_FLAGS MAP_SHARED | ||
59 | #else | ||
60 | #define MMAP_FLAGS MAP_PRIVATE | ||
61 | #endif | ||
62 | #define SYSTEM_MEMORY "/dev/mem" | ||
63 | /******************************************************************************* | ||
64 | * | ||
65 | * FUNCTION: acpi_os_get_page_size | ||
66 | * | ||
67 | * PARAMETERS: None | ||
68 | * | ||
69 | * RETURN: Page size of the platform. | ||
70 | * | ||
71 | * DESCRIPTION: Obtain page size of the platform. | ||
72 | * | ||
73 | ******************************************************************************/ | ||
74 | static acpi_size acpi_os_get_page_size(void) | ||
75 | { | ||
76 | |||
77 | #ifdef PAGE_SIZE | ||
78 | return PAGE_SIZE; | ||
79 | #else | ||
80 | return sysconf(_SC_PAGESIZE); | ||
81 | #endif | ||
82 | } | ||
83 | |||
84 | /****************************************************************************** | ||
85 | * | ||
86 | * FUNCTION: acpi_os_map_memory | ||
87 | * | ||
88 | * PARAMETERS: where - Physical address of memory to be mapped | ||
89 | * length - How much memory to map | ||
90 | * | ||
91 | * RETURN: Pointer to mapped memory. Null on error. | ||
92 | * | ||
93 | * DESCRIPTION: Map physical memory into local address space. | ||
94 | * | ||
95 | *****************************************************************************/ | ||
96 | |||
97 | void *acpi_os_map_memory(acpi_physical_address where, acpi_size length) | ||
98 | { | ||
99 | u8 *mapped_memory; | ||
100 | acpi_physical_address offset; | ||
101 | acpi_size page_size; | ||
102 | int fd; | ||
103 | |||
104 | fd = open(SYSTEM_MEMORY, O_RDONLY | O_BINARY); | ||
105 | if (fd < 0) { | ||
106 | fprintf(stderr, "Cannot open %s\n", SYSTEM_MEMORY); | ||
107 | return (NULL); | ||
108 | } | ||
109 | |||
110 | /* Align the offset to use mmap */ | ||
111 | |||
112 | page_size = acpi_os_get_page_size(); | ||
113 | offset = where % page_size; | ||
114 | |||
115 | /* Map the table header to get the length of the full table */ | ||
116 | |||
117 | mapped_memory = mmap(NULL, (length + offset), PROT_READ, MMAP_FLAGS, | ||
118 | fd, (where - offset)); | ||
119 | if (mapped_memory == MAP_FAILED) { | ||
120 | fprintf(stderr, "Cannot map %s\n", SYSTEM_MEMORY); | ||
121 | close(fd); | ||
122 | return (NULL); | ||
123 | } | ||
124 | |||
125 | close(fd); | ||
126 | return (ACPI_CAST8(mapped_memory + offset)); | ||
127 | } | ||
128 | |||
129 | /****************************************************************************** | ||
130 | * | ||
131 | * FUNCTION: acpi_os_unmap_memory | ||
132 | * | ||
133 | * PARAMETERS: where - Logical address of memory to be unmapped | ||
134 | * length - How much memory to unmap | ||
135 | * | ||
136 | * RETURN: None. | ||
137 | * | ||
138 | * DESCRIPTION: Delete a previously created mapping. Where and Length must | ||
139 | * correspond to a previous mapping exactly. | ||
140 | * | ||
141 | *****************************************************************************/ | ||
142 | |||
143 | void acpi_os_unmap_memory(void *where, acpi_size length) | ||
144 | { | ||
145 | acpi_physical_address offset; | ||
146 | acpi_size page_size; | ||
147 | |||
148 | page_size = acpi_os_get_page_size(); | ||
149 | offset = (acpi_physical_address) where % page_size; | ||
150 | munmap((u8 *)where - offset, (length + offset)); | ||
151 | } | ||
diff --git a/tools/power/acpi/tools/acpidump/acpidump.c b/tools/power/acpi/tools/acpidump/acpidump.c deleted file mode 100644 index a84553a0e0df..000000000000 --- a/tools/power/acpi/tools/acpidump/acpidump.c +++ /dev/null | |||
@@ -1,559 +0,0 @@ | |||
1 | /* | ||
2 | * (c) Alexey Starikovskiy, Intel, 2005-2006. | ||
3 | * All rights reserved. | ||
4 | * | ||
5 | * Redistribution and use in source and binary forms, with or without | ||
6 | * modification, are permitted provided that the following conditions | ||
7 | * are met: | ||
8 | * 1. Redistributions of source code must retain the above copyright | ||
9 | * notice, this list of conditions, and the following disclaimer, | ||
10 | * without modification. | ||
11 | * 2. Redistributions in binary form must reproduce at minimum a disclaimer | ||
12 | * substantially similar to the "NO WARRANTY" disclaimer below | ||
13 | * ("Disclaimer") and any redistribution must be conditioned upon | ||
14 | * including a substantially similar Disclaimer requirement for further | ||
15 | * binary redistribution. | ||
16 | * 3. Neither the names of the above-listed copyright holders nor the names | ||
17 | * of any contributors may be used to endorse or promote products derived | ||
18 | * from this software without specific prior written permission. | ||
19 | * | ||
20 | * Alternatively, this software may be distributed under the terms of the | ||
21 | * GNU General Public License ("GPL") version 2 as published by the Free | ||
22 | * Software Foundation. | ||
23 | * | ||
24 | * NO WARRANTY | ||
25 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS | ||
26 | * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT | ||
27 | * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR | ||
28 | * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT | ||
29 | * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL | ||
30 | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS | ||
31 | * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) | ||
32 | * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, | ||
33 | * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING | ||
34 | * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE | ||
35 | * POSSIBILITY OF SUCH DAMAGES. | ||
36 | */ | ||
37 | |||
38 | #ifdef DEFINE_ALTERNATE_TYPES | ||
39 | /* hack to enable building old application with new headers -lenb */ | ||
40 | #define acpi_fadt_descriptor acpi_table_fadt | ||
41 | #define acpi_rsdp_descriptor acpi_table_rsdp | ||
42 | #define DSDT_SIG ACPI_SIG_DSDT | ||
43 | #define FACS_SIG ACPI_SIG_FACS | ||
44 | #define FADT_SIG ACPI_SIG_FADT | ||
45 | #define xfirmware_ctrl Xfacs | ||
46 | #define firmware_ctrl facs | ||
47 | |||
48 | typedef int s32; | ||
49 | typedef unsigned char u8; | ||
50 | typedef unsigned short u16; | ||
51 | typedef unsigned int u32; | ||
52 | typedef unsigned long long u64; | ||
53 | typedef long long s64; | ||
54 | #endif | ||
55 | |||
56 | #include <sys/mman.h> | ||
57 | #include <sys/types.h> | ||
58 | #include <sys/stat.h> | ||
59 | #include <fcntl.h> | ||
60 | #include <stdio.h> | ||
61 | #include <string.h> | ||
62 | #include <unistd.h> | ||
63 | #include <getopt.h> | ||
64 | |||
65 | #include <dirent.h> | ||
66 | |||
67 | #include <acpi/acconfig.h> | ||
68 | #include <acpi/platform/acenv.h> | ||
69 | #include <acpi/actypes.h> | ||
70 | #include <acpi/actbl.h> | ||
71 | |||
72 | static inline u8 checksum(u8 * buffer, u32 length) | ||
73 | { | ||
74 | u8 sum = 0, *i = buffer; | ||
75 | buffer += length; | ||
76 | for (; i < buffer; sum += *(i++)); | ||
77 | return sum; | ||
78 | } | ||
79 | |||
80 | static unsigned long psz, addr, length; | ||
81 | static int print, connect, skip; | ||
82 | static u8 select_sig[4]; | ||
83 | |||
84 | static unsigned long read_efi_systab( void ) | ||
85 | { | ||
86 | char buffer[80]; | ||
87 | unsigned long addr; | ||
88 | FILE *f = fopen("/sys/firmware/efi/systab", "r"); | ||
89 | if (f) { | ||
90 | while (fgets(buffer, 80, f)) { | ||
91 | if (sscanf(buffer, "ACPI20=0x%lx", &addr) == 1) | ||
92 | return addr; | ||
93 | } | ||
94 | fclose(f); | ||
95 | } | ||
96 | return 0; | ||
97 | } | ||
98 | |||
99 | static u8 *acpi_map_memory(unsigned long where, unsigned length) | ||
100 | { | ||
101 | unsigned long offset; | ||
102 | u8 *there; | ||
103 | int fd = open("/dev/mem", O_RDONLY); | ||
104 | if (fd < 0) { | ||
105 | fprintf(stderr, "acpi_os_map_memory: cannot open /dev/mem\n"); | ||
106 | exit(1); | ||
107 | } | ||
108 | offset = where % psz; | ||
109 | there = mmap(NULL, length + offset, PROT_READ, MAP_PRIVATE, | ||
110 | fd, where - offset); | ||
111 | close(fd); | ||
112 | if (there == MAP_FAILED) return 0; | ||
113 | return (there + offset); | ||
114 | } | ||
115 | |||
116 | static void acpi_unmap_memory(u8 * there, unsigned length) | ||
117 | { | ||
118 | unsigned long offset = (unsigned long)there % psz; | ||
119 | munmap(there - offset, length + offset); | ||
120 | } | ||
121 | |||
122 | static struct acpi_table_header *acpi_map_table(unsigned long where, char *sig) | ||
123 | { | ||
124 | unsigned size; | ||
125 | struct acpi_table_header *tbl = (struct acpi_table_header *) | ||
126 | acpi_map_memory(where, sizeof(struct acpi_table_header)); | ||
127 | if (!tbl || (sig && memcmp(sig, tbl->signature, 4))) return 0; | ||
128 | size = tbl->length; | ||
129 | acpi_unmap_memory((u8 *) tbl, sizeof(struct acpi_table_header)); | ||
130 | return (struct acpi_table_header *)acpi_map_memory(where, size); | ||
131 | } | ||
132 | |||
133 | static void acpi_unmap_table(struct acpi_table_header *tbl) | ||
134 | { | ||
135 | acpi_unmap_memory((u8 *)tbl, tbl->length); | ||
136 | } | ||
137 | |||
138 | static struct acpi_rsdp_descriptor *acpi_scan_for_rsdp(u8 *begin, u32 length) | ||
139 | { | ||
140 | struct acpi_rsdp_descriptor *rsdp; | ||
141 | u8 *i, *end = begin + length; | ||
142 | /* Search from given start address for the requested length */ | ||
143 | for (i = begin; i < end; i += ACPI_RSDP_SCAN_STEP) { | ||
144 | /* The signature and checksum must both be correct */ | ||
145 | if (memcmp((char *)i, "RSD PTR ", 8)) continue; | ||
146 | rsdp = (struct acpi_rsdp_descriptor *)i; | ||
147 | /* Signature matches, check the appropriate checksum */ | ||
148 | if (!checksum((u8 *) rsdp, (rsdp->revision < 2) ? | ||
149 | ACPI_RSDP_CHECKSUM_LENGTH : | ||
150 | ACPI_RSDP_XCHECKSUM_LENGTH)) | ||
151 | /* Checksum valid, we have found a valid RSDP */ | ||
152 | return rsdp; | ||
153 | } | ||
154 | /* Searched entire block, no RSDP was found */ | ||
155 | return 0; | ||
156 | } | ||
157 | |||
158 | /* | ||
159 | * Output data | ||
160 | */ | ||
161 | static void acpi_show_data(int fd, u8 * data, int size) | ||
162 | { | ||
163 | char buffer[256]; | ||
164 | int len; | ||
165 | int i, remain = size; | ||
166 | while (remain > 0) { | ||
167 | len = snprintf(buffer, 256, " %04x:", size - remain); | ||
168 | for (i = 0; i < 16 && i < remain; i++) { | ||
169 | len += | ||
170 | snprintf(&buffer[len], 256 - len, " %02x", data[i]); | ||
171 | } | ||
172 | for (; i < 16; i++) { | ||
173 | len += snprintf(&buffer[len], 256 - len, " "); | ||
174 | } | ||
175 | len += snprintf(&buffer[len], 256 - len, " "); | ||
176 | for (i = 0; i < 16 && i < remain; i++) { | ||
177 | buffer[len++] = (isprint(data[i])) ? data[i] : '.'; | ||
178 | } | ||
179 | buffer[len++] = '\n'; | ||
180 | write(fd, buffer, len); | ||
181 | data += 16; | ||
182 | remain -= 16; | ||
183 | } | ||
184 | } | ||
185 | |||
186 | /* | ||
187 | * Output ACPI table | ||
188 | */ | ||
189 | static void acpi_show_table(int fd, struct acpi_table_header *table, unsigned long addr) | ||
190 | { | ||
191 | char buff[80]; | ||
192 | int len = snprintf(buff, 80, "%.4s @ %p\n", table->signature, (void *)addr); | ||
193 | write(fd, buff, len); | ||
194 | acpi_show_data(fd, (u8 *) table, table->length); | ||
195 | buff[0] = '\n'; | ||
196 | write(fd, buff, 1); | ||
197 | } | ||
198 | |||
199 | static void write_table(int fd, struct acpi_table_header *tbl, unsigned long addr) | ||
200 | { | ||
201 | static int select_done = 0; | ||
202 | if (!select_sig[0]) { | ||
203 | if (print) { | ||
204 | acpi_show_table(fd, tbl, addr); | ||
205 | } else { | ||
206 | write(fd, tbl, tbl->length); | ||
207 | } | ||
208 | } else if (!select_done && !memcmp(select_sig, tbl->signature, 4)) { | ||
209 | if (skip > 0) { | ||
210 | --skip; | ||
211 | return; | ||
212 | } | ||
213 | if (print) { | ||
214 | acpi_show_table(fd, tbl, addr); | ||
215 | } else { | ||
216 | write(fd, tbl, tbl->length); | ||
217 | } | ||
218 | select_done = 1; | ||
219 | } | ||
220 | } | ||
221 | |||
222 | static void acpi_dump_FADT(int fd, struct acpi_table_header *tbl, unsigned long xaddr) { | ||
223 | struct acpi_fadt_descriptor x; | ||
224 | unsigned long addr; | ||
225 | size_t len = sizeof(struct acpi_fadt_descriptor); | ||
226 | if (len > tbl->length) len = tbl->length; | ||
227 | memcpy(&x, tbl, len); | ||
228 | x.header.length = len; | ||
229 | if (checksum((u8 *)tbl, len)) { | ||
230 | fprintf(stderr, "Wrong checksum for FADT!\n"); | ||
231 | } | ||
232 | if (x.header.length >= 148 && x.Xdsdt) { | ||
233 | addr = (unsigned long)x.Xdsdt; | ||
234 | if (connect) { | ||
235 | x.Xdsdt = lseek(fd, 0, SEEK_CUR); | ||
236 | } | ||
237 | } else if (x.header.length >= 44 && x.dsdt) { | ||
238 | addr = (unsigned long)x.dsdt; | ||
239 | if (connect) { | ||
240 | x.dsdt = lseek(fd, 0, SEEK_CUR); | ||
241 | } | ||
242 | } else { | ||
243 | fprintf(stderr, "No DSDT in FADT!\n"); | ||
244 | goto no_dsdt; | ||
245 | } | ||
246 | tbl = acpi_map_table(addr, DSDT_SIG); | ||
247 | if (!tbl) goto no_dsdt; | ||
248 | if (checksum((u8 *)tbl, tbl->length)) | ||
249 | fprintf(stderr, "Wrong checksum for DSDT!\n"); | ||
250 | write_table(fd, tbl, addr); | ||
251 | acpi_unmap_table(tbl); | ||
252 | no_dsdt: | ||
253 | if (x.header.length >= 140 && x.xfirmware_ctrl) { | ||
254 | addr = (unsigned long)x.xfirmware_ctrl; | ||
255 | if (connect) { | ||
256 | x.xfirmware_ctrl = lseek(fd, 0, SEEK_CUR); | ||
257 | } | ||
258 | } else if (x.header.length >= 40 && x.firmware_ctrl) { | ||
259 | addr = (unsigned long)x.firmware_ctrl; | ||
260 | if (connect) { | ||
261 | x.firmware_ctrl = lseek(fd, 0, SEEK_CUR); | ||
262 | } | ||
263 | } else { | ||
264 | fprintf(stderr, "No FACS in FADT!\n"); | ||
265 | goto no_facs; | ||
266 | } | ||
267 | tbl = acpi_map_table(addr, FACS_SIG); | ||
268 | if (!tbl) goto no_facs; | ||
269 | /* do not checksum FACS */ | ||
270 | write_table(fd, tbl, addr); | ||
271 | acpi_unmap_table(tbl); | ||
272 | no_facs: | ||
273 | write_table(fd, (struct acpi_table_header *)&x, xaddr); | ||
274 | } | ||
275 | |||
276 | static int acpi_dump_SDT(int fd, struct acpi_rsdp_descriptor *rsdp) | ||
277 | { | ||
278 | struct acpi_table_header *sdt, *tbl = 0; | ||
279 | int xsdt = 1, i, num; | ||
280 | char *offset; | ||
281 | unsigned long addr; | ||
282 | if (rsdp->revision > 1 && rsdp->xsdt_physical_address) { | ||
283 | tbl = acpi_map_table(rsdp->xsdt_physical_address, "XSDT"); | ||
284 | } | ||
285 | if (!tbl && rsdp->rsdt_physical_address) { | ||
286 | xsdt = 0; | ||
287 | tbl = acpi_map_table(rsdp->rsdt_physical_address, "RSDT"); | ||
288 | } | ||
289 | if (!tbl) return 0; | ||
290 | sdt = malloc(tbl->length); | ||
291 | memcpy(sdt, tbl, tbl->length); | ||
292 | acpi_unmap_table(tbl); | ||
293 | if (checksum((u8 *)sdt, sdt->length)) | ||
294 | fprintf(stderr, "Wrong checksum for %s!\n", (xsdt)?"XSDT":"RSDT"); | ||
295 | num = (sdt->length - sizeof(struct acpi_table_header))/((xsdt)?sizeof(u64):sizeof(u32)); | ||
296 | offset = (char *)sdt + sizeof(struct acpi_table_header); | ||
297 | for (i = 0; i < num; ++i, offset += ((xsdt) ? sizeof(u64) : sizeof(u32))) { | ||
298 | addr = (xsdt) ? (unsigned long)(*(u64 *)offset): | ||
299 | (unsigned long)(*(u32 *)offset); | ||
300 | if (!addr) continue; | ||
301 | tbl = acpi_map_table(addr, 0); | ||
302 | if (!tbl) continue; | ||
303 | if (!memcmp(tbl->signature, FADT_SIG, 4)) { | ||
304 | acpi_dump_FADT(fd, tbl, addr); | ||
305 | } else { | ||
306 | if (checksum((u8 *)tbl, tbl->length)) | ||
307 | fprintf(stderr, "Wrong checksum for generic table!\n"); | ||
308 | write_table(fd, tbl, addr); | ||
309 | } | ||
310 | acpi_unmap_table(tbl); | ||
311 | if (connect) { | ||
312 | if (xsdt) | ||
313 | (*(u64*)offset) = lseek(fd, 0, SEEK_CUR); | ||
314 | else | ||
315 | (*(u32*)offset) = lseek(fd, 0, SEEK_CUR); | ||
316 | } | ||
317 | } | ||
318 | if (xsdt) { | ||
319 | addr = (unsigned long)rsdp->xsdt_physical_address; | ||
320 | if (connect) { | ||
321 | rsdp->xsdt_physical_address = lseek(fd, 0, SEEK_CUR); | ||
322 | } | ||
323 | } else { | ||
324 | addr = (unsigned long)rsdp->rsdt_physical_address; | ||
325 | if (connect) { | ||
326 | rsdp->rsdt_physical_address = lseek(fd, 0, SEEK_CUR); | ||
327 | } | ||
328 | } | ||
329 | write_table(fd, sdt, addr); | ||
330 | free (sdt); | ||
331 | return 1; | ||
332 | } | ||
333 | |||
334 | #define DYNAMIC_SSDT "/sys/firmware/acpi/tables/dynamic" | ||
335 | |||
336 | static void acpi_dump_dynamic_SSDT(int fd) | ||
337 | { | ||
338 | struct stat file_stat; | ||
339 | char filename[256], *ptr; | ||
340 | DIR *tabledir; | ||
341 | struct dirent *entry; | ||
342 | FILE *fp; | ||
343 | int count, readcount, length; | ||
344 | struct acpi_table_header table_header, *ptable; | ||
345 | |||
346 | if (stat(DYNAMIC_SSDT, &file_stat) == -1) { | ||
347 | /* The directory doesn't exist */ | ||
348 | return; | ||
349 | } | ||
350 | tabledir = opendir(DYNAMIC_SSDT); | ||
351 | if(!tabledir){ | ||
352 | /*can't open the directory */ | ||
353 | return; | ||
354 | } | ||
355 | |||
356 | while ((entry = readdir(tabledir)) != 0){ | ||
357 | /* skip the file of . /.. */ | ||
358 | if (entry->d_name[0] == '.') | ||
359 | continue; | ||
360 | |||
361 | sprintf(filename, "%s/%s", DYNAMIC_SSDT, entry->d_name); | ||
362 | fp = fopen(filename, "r"); | ||
363 | if (fp == NULL) { | ||
364 | fprintf(stderr, "Can't open the file of %s\n", | ||
365 | filename); | ||
366 | continue; | ||
367 | } | ||
368 | /* Read the Table header to parse the table length */ | ||
369 | count = fread(&table_header, 1, sizeof(struct acpi_table_header), fp); | ||
370 | if (count < sizeof(table_header)) { | ||
371 | /* the length is lessn than ACPI table header. skip it */ | ||
372 | fclose(fp); | ||
373 | continue; | ||
374 | } | ||
375 | length = table_header.length; | ||
376 | ptr = malloc(table_header.length); | ||
377 | fseek(fp, 0, SEEK_SET); | ||
378 | readcount = 0; | ||
379 | while(!feof(fp) && readcount < length) { | ||
380 | count = fread(ptr + readcount, 1, 256, fp); | ||
381 | readcount += count; | ||
382 | } | ||
383 | fclose(fp); | ||
384 | ptable = (struct acpi_table_header *) ptr; | ||
385 | if (checksum((u8 *) ptable, ptable->length)) | ||
386 | fprintf(stderr, "Wrong checksum " | ||
387 | "for dynamic SSDT table!\n"); | ||
388 | write_table(fd, ptable, 0); | ||
389 | free(ptr); | ||
390 | } | ||
391 | closedir(tabledir); | ||
392 | return; | ||
393 | } | ||
394 | |||
395 | static void usage(const char *progname) | ||
396 | { | ||
397 | puts("Usage:"); | ||
398 | printf("%s [--addr 0x1234][--table DSDT][--output filename]" | ||
399 | "[--binary][--length 0x456][--help]\n", progname); | ||
400 | puts("\t--addr 0x1234 or -a 0x1234 -- look for tables at this physical address"); | ||
401 | puts("\t--table DSDT or -t DSDT -- only dump table with DSDT signature"); | ||
402 | puts("\t--output filename or -o filename -- redirect output from stdin to filename"); | ||
403 | puts("\t--binary or -b -- dump data in binary form rather than in hex-dump format"); | ||
404 | puts("\t--length 0x456 or -l 0x456 -- works only with --addr, dump physical memory" | ||
405 | "\n\t\tregion without trying to understand it's contents"); | ||
406 | puts("\t--skip 2 or -s 2 -- skip 2 tables of the given name and output only 3rd one"); | ||
407 | puts("\t--help or -h -- this help message"); | ||
408 | exit(0); | ||
409 | } | ||
410 | |||
411 | static struct option long_options[] = { | ||
412 | {"addr", 1, 0, 0}, | ||
413 | {"table", 1, 0, 0}, | ||
414 | {"output", 1, 0, 0}, | ||
415 | {"binary", 0, 0, 0}, | ||
416 | {"length", 1, 0, 0}, | ||
417 | {"skip", 1, 0, 0}, | ||
418 | {"help", 0, 0, 0}, | ||
419 | {0, 0, 0, 0} | ||
420 | }; | ||
421 | int main(int argc, char **argv) | ||
422 | { | ||
423 | int option_index, c, fd; | ||
424 | u8 *raw; | ||
425 | struct acpi_rsdp_descriptor rsdpx, *x = 0; | ||
426 | char *filename = 0; | ||
427 | char buff[80]; | ||
428 | memset(select_sig, 0, 4); | ||
429 | print = 1; | ||
430 | connect = 0; | ||
431 | addr = length = 0; | ||
432 | skip = 0; | ||
433 | while (1) { | ||
434 | option_index = 0; | ||
435 | c = getopt_long(argc, argv, "a:t:o:bl:s:h", | ||
436 | long_options, &option_index); | ||
437 | if (c == -1) | ||
438 | break; | ||
439 | |||
440 | switch (c) { | ||
441 | case 0: | ||
442 | switch (option_index) { | ||
443 | case 0: | ||
444 | addr = strtoul(optarg, (char **)NULL, 16); | ||
445 | break; | ||
446 | case 1: | ||
447 | memcpy(select_sig, optarg, 4); | ||
448 | break; | ||
449 | case 2: | ||
450 | filename = optarg; | ||
451 | break; | ||
452 | case 3: | ||
453 | print = 0; | ||
454 | break; | ||
455 | case 4: | ||
456 | length = strtoul(optarg, (char **)NULL, 16); | ||
457 | break; | ||
458 | case 5: | ||
459 | skip = strtoul(optarg, (char **)NULL, 10); | ||
460 | break; | ||
461 | case 6: | ||
462 | usage(argv[0]); | ||
463 | exit(0); | ||
464 | } | ||
465 | break; | ||
466 | case 'a': | ||
467 | addr = strtoul(optarg, (char **)NULL, 16); | ||
468 | break; | ||
469 | case 't': | ||
470 | memcpy(select_sig, optarg, 4); | ||
471 | break; | ||
472 | case 'o': | ||
473 | filename = optarg; | ||
474 | break; | ||
475 | case 'b': | ||
476 | print = 0; | ||
477 | break; | ||
478 | case 'l': | ||
479 | length = strtoul(optarg, (char **)NULL, 16); | ||
480 | break; | ||
481 | case 's': | ||
482 | skip = strtoul(optarg, (char **)NULL, 10); | ||
483 | break; | ||
484 | case 'h': | ||
485 | usage(argv[0]); | ||
486 | exit(0); | ||
487 | default: | ||
488 | printf("Unknown option!\n"); | ||
489 | usage(argv[0]); | ||
490 | exit(0); | ||
491 | } | ||
492 | } | ||
493 | |||
494 | fd = STDOUT_FILENO; | ||
495 | if (filename) { | ||
496 | fd = creat(filename, S_IRUSR|S_IWUSR|S_IRGRP|S_IROTH); | ||
497 | if (fd < 0) | ||
498 | return fd; | ||
499 | } | ||
500 | |||
501 | if (!select_sig[0] && !print) { | ||
502 | connect = 1; | ||
503 | } | ||
504 | |||
505 | psz = sysconf(_SC_PAGESIZE); | ||
506 | if (length && addr) { | ||
507 | /* We know length and address, it means we just want a memory dump */ | ||
508 | if (!(raw = acpi_map_memory(addr, length))) | ||
509 | goto not_found; | ||
510 | write(fd, raw, length); | ||
511 | acpi_unmap_memory(raw, length); | ||
512 | close(fd); | ||
513 | return 0; | ||
514 | } | ||
515 | |||
516 | length = sizeof(struct acpi_rsdp_descriptor); | ||
517 | if (!addr) { | ||
518 | addr = read_efi_systab(); | ||
519 | if (!addr) { | ||
520 | addr = ACPI_HI_RSDP_WINDOW_BASE; | ||
521 | length = ACPI_HI_RSDP_WINDOW_SIZE; | ||
522 | } | ||
523 | } | ||
524 | |||
525 | if (!(raw = acpi_map_memory(addr, length)) || | ||
526 | !(x = acpi_scan_for_rsdp(raw, length))) | ||
527 | goto not_found; | ||
528 | |||
529 | /* Find RSDP and print all found tables */ | ||
530 | memcpy(&rsdpx, x, sizeof(struct acpi_rsdp_descriptor)); | ||
531 | acpi_unmap_memory(raw, length); | ||
532 | if (connect) { | ||
533 | lseek(fd, sizeof(struct acpi_rsdp_descriptor), SEEK_SET); | ||
534 | } | ||
535 | if (!acpi_dump_SDT(fd, &rsdpx)) | ||
536 | goto not_found; | ||
537 | if (connect) { | ||
538 | lseek(fd, 0, SEEK_SET); | ||
539 | write(fd, x, (rsdpx.revision < 2) ? | ||
540 | ACPI_RSDP_CHECKSUM_LENGTH : ACPI_RSDP_XCHECKSUM_LENGTH); | ||
541 | } else if (!select_sig[0] || !memcmp("RSD PTR ", select_sig, 4)) { | ||
542 | addr += (long)x - (long)raw; | ||
543 | length = snprintf(buff, 80, "RSD PTR @ %p\n", (void *)addr); | ||
544 | write(fd, buff, length); | ||
545 | acpi_show_data(fd, (u8 *) & rsdpx, (rsdpx.revision < 2) ? | ||
546 | ACPI_RSDP_CHECKSUM_LENGTH : ACPI_RSDP_XCHECKSUM_LENGTH); | ||
547 | buff[0] = '\n'; | ||
548 | write(fd, buff, 1); | ||
549 | } | ||
550 | acpi_dump_dynamic_SSDT(fd); | ||
551 | close(fd); | ||
552 | return 0; | ||
553 | not_found: | ||
554 | close(fd); | ||
555 | fprintf(stderr, "ACPI tables were not found. If you know location " | ||
556 | "of RSD PTR table (from dmesg, etc), " | ||
557 | "supply it with either --addr or -a option\n"); | ||
558 | return 1; | ||
559 | } | ||
diff --git a/tools/power/acpi/tools/acpidump/acpidump.h b/tools/power/acpi/tools/acpidump/acpidump.h new file mode 100644 index 000000000000..46f519597fe5 --- /dev/null +++ b/tools/power/acpi/tools/acpidump/acpidump.h | |||
@@ -0,0 +1,130 @@ | |||
1 | /****************************************************************************** | ||
2 | * | ||
3 | * Module Name: acpidump.h - Include file for acpi_dump utility | ||
4 | * | ||
5 | *****************************************************************************/ | ||
6 | |||
7 | /* | ||
8 | * Copyright (C) 2000 - 2014, Intel Corp. | ||
9 | * All rights reserved. | ||
10 | * | ||
11 | * Redistribution and use in source and binary forms, with or without | ||
12 | * modification, are permitted provided that the following conditions | ||
13 | * are met: | ||
14 | * 1. Redistributions of source code must retain the above copyright | ||
15 | * notice, this list of conditions, and the following disclaimer, | ||
16 | * without modification. | ||
17 | * 2. Redistributions in binary form must reproduce at minimum a disclaimer | ||
18 | * substantially similar to the "NO WARRANTY" disclaimer below | ||
19 | * ("Disclaimer") and any redistribution must be conditioned upon | ||
20 | * including a substantially similar Disclaimer requirement for further | ||
21 | * binary redistribution. | ||
22 | * 3. Neither the names of the above-listed copyright holders nor the names | ||
23 | * of any contributors may be used to endorse or promote products derived | ||
24 | * from this software without specific prior written permission. | ||
25 | * | ||
26 | * Alternatively, this software may be distributed under the terms of the | ||
27 | * GNU General Public License ("GPL") version 2 as published by the Free | ||
28 | * Software Foundation. | ||
29 | * | ||
30 | * NO WARRANTY | ||
31 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS | ||
32 | * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT | ||
33 | * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR | ||
34 | * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT | ||
35 | * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL | ||
36 | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS | ||
37 | * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) | ||
38 | * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, | ||
39 | * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING | ||
40 | * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE | ||
41 | * POSSIBILITY OF SUCH DAMAGES. | ||
42 | */ | ||
43 | |||
44 | /* | ||
45 | * Global variables. Defined in main.c only, externed in all other files | ||
46 | */ | ||
47 | #ifdef _DECLARE_GLOBALS | ||
48 | #define EXTERN | ||
49 | #define INIT_GLOBAL(a,b) a=b | ||
50 | #define DEFINE_ACPI_GLOBALS 1 | ||
51 | #else | ||
52 | #define EXTERN extern | ||
53 | #define INIT_GLOBAL(a,b) a | ||
54 | #endif | ||
55 | |||
56 | #include <acpi/acpi.h> | ||
57 | #include "accommon.h" | ||
58 | #include "actables.h" | ||
59 | |||
60 | #include <stdio.h> | ||
61 | #include <fcntl.h> | ||
62 | #include <errno.h> | ||
63 | #include <sys/stat.h> | ||
64 | |||
65 | /* Globals */ | ||
66 | |||
67 | EXTERN u8 INIT_GLOBAL(gbl_summary_mode, FALSE); | ||
68 | EXTERN u8 INIT_GLOBAL(gbl_verbose_mode, FALSE); | ||
69 | EXTERN u8 INIT_GLOBAL(gbl_binary_mode, FALSE); | ||
70 | EXTERN u8 INIT_GLOBAL(gbl_dump_customized_tables, FALSE); | ||
71 | EXTERN u8 INIT_GLOBAL(gbl_do_not_dump_xsdt, FALSE); | ||
72 | EXTERN FILE INIT_GLOBAL(*gbl_output_file, NULL); | ||
73 | EXTERN char INIT_GLOBAL(*gbl_output_filename, NULL); | ||
74 | EXTERN u64 INIT_GLOBAL(gbl_rsdp_base, 0); | ||
75 | |||
76 | /* Globals required for use with ACPICA modules */ | ||
77 | |||
78 | #ifdef _DECLARE_GLOBALS | ||
79 | u8 acpi_gbl_integer_byte_width = 8; | ||
80 | #endif | ||
81 | |||
82 | /* Action table used to defer requested options */ | ||
83 | |||
84 | struct ap_dump_action { | ||
85 | char *argument; | ||
86 | u32 to_be_done; | ||
87 | }; | ||
88 | |||
89 | #define AP_MAX_ACTIONS 32 | ||
90 | |||
91 | #define AP_DUMP_ALL_TABLES 0 | ||
92 | #define AP_DUMP_TABLE_BY_ADDRESS 1 | ||
93 | #define AP_DUMP_TABLE_BY_NAME 2 | ||
94 | #define AP_DUMP_TABLE_BY_FILE 3 | ||
95 | |||
96 | #define AP_MAX_ACPI_FILES 256 /* Prevent infinite loops */ | ||
97 | |||
98 | /* Minimum FADT sizes for various table addresses */ | ||
99 | |||
100 | #define MIN_FADT_FOR_DSDT (ACPI_FADT_OFFSET (dsdt) + sizeof (u32)) | ||
101 | #define MIN_FADT_FOR_FACS (ACPI_FADT_OFFSET (facs) + sizeof (u32)) | ||
102 | #define MIN_FADT_FOR_XDSDT (ACPI_FADT_OFFSET (Xdsdt) + sizeof (u64)) | ||
103 | #define MIN_FADT_FOR_XFACS (ACPI_FADT_OFFSET (Xfacs) + sizeof (u64)) | ||
104 | |||
105 | /* | ||
106 | * apdump - Table get/dump routines | ||
107 | */ | ||
108 | int ap_dump_table_from_file(char *pathname); | ||
109 | |||
110 | int ap_dump_table_by_name(char *signature); | ||
111 | |||
112 | int ap_dump_table_by_address(char *ascii_address); | ||
113 | |||
114 | int ap_dump_all_tables(void); | ||
115 | |||
116 | u8 ap_is_valid_header(struct acpi_table_header *table); | ||
117 | |||
118 | u8 ap_is_valid_checksum(struct acpi_table_header *table); | ||
119 | |||
120 | u32 ap_get_table_length(struct acpi_table_header *table); | ||
121 | |||
122 | /* | ||
123 | * apfiles - File I/O utilities | ||
124 | */ | ||
125 | int ap_open_output_file(char *pathname); | ||
126 | |||
127 | int ap_write_to_binary_file(struct acpi_table_header *table, u32 instance); | ||
128 | |||
129 | struct acpi_table_header *ap_get_table_from_file(char *pathname, | ||
130 | u32 *file_size); | ||
diff --git a/tools/power/acpi/tools/acpidump/apdump.c b/tools/power/acpi/tools/acpidump/apdump.c new file mode 100644 index 000000000000..3cac12378366 --- /dev/null +++ b/tools/power/acpi/tools/acpidump/apdump.c | |||
@@ -0,0 +1,451 @@ | |||
1 | /****************************************************************************** | ||
2 | * | ||
3 | * Module Name: apdump - Dump routines for ACPI tables (acpidump) | ||
4 | * | ||
5 | *****************************************************************************/ | ||
6 | |||
7 | /* | ||
8 | * Copyright (C) 2000 - 2014, Intel Corp. | ||
9 | * All rights reserved. | ||
10 | * | ||
11 | * Redistribution and use in source and binary forms, with or without | ||
12 | * modification, are permitted provided that the following conditions | ||
13 | * are met: | ||
14 | * 1. Redistributions of source code must retain the above copyright | ||
15 | * notice, this list of conditions, and the following disclaimer, | ||
16 | * without modification. | ||
17 | * 2. Redistributions in binary form must reproduce at minimum a disclaimer | ||
18 | * substantially similar to the "NO WARRANTY" disclaimer below | ||
19 | * ("Disclaimer") and any redistribution must be conditioned upon | ||
20 | * including a substantially similar Disclaimer requirement for further | ||
21 | * binary redistribution. | ||
22 | * 3. Neither the names of the above-listed copyright holders nor the names | ||
23 | * of any contributors may be used to endorse or promote products derived | ||
24 | * from this software without specific prior written permission. | ||
25 | * | ||
26 | * Alternatively, this software may be distributed under the terms of the | ||
27 | * GNU General Public License ("GPL") version 2 as published by the Free | ||
28 | * Software Foundation. | ||
29 | * | ||
30 | * NO WARRANTY | ||
31 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS | ||
32 | * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT | ||
33 | * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR | ||
34 | * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT | ||
35 | * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL | ||
36 | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS | ||
37 | * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) | ||
38 | * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, | ||
39 | * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING | ||
40 | * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE | ||
41 | * POSSIBILITY OF SUCH DAMAGES. | ||
42 | */ | ||
43 | |||
44 | #include "acpidump.h" | ||
45 | |||
46 | /* Local prototypes */ | ||
47 | |||
48 | static int | ||
49 | ap_dump_table_buffer(struct acpi_table_header *table, | ||
50 | u32 instance, acpi_physical_address address); | ||
51 | |||
52 | /****************************************************************************** | ||
53 | * | ||
54 | * FUNCTION: ap_is_valid_header | ||
55 | * | ||
56 | * PARAMETERS: table - Pointer to table to be validated | ||
57 | * | ||
58 | * RETURN: TRUE if the header appears to be valid. FALSE otherwise | ||
59 | * | ||
60 | * DESCRIPTION: Check for a valid ACPI table header | ||
61 | * | ||
62 | ******************************************************************************/ | ||
63 | |||
64 | u8 ap_is_valid_header(struct acpi_table_header *table) | ||
65 | { | ||
66 | |||
67 | if (!ACPI_VALIDATE_RSDP_SIG(table->signature)) { | ||
68 | |||
69 | /* Make sure signature is all ASCII and a valid ACPI name */ | ||
70 | |||
71 | if (!acpi_ut_valid_acpi_name(table->signature)) { | ||
72 | fprintf(stderr, | ||
73 | "Table signature (0x%8.8X) is invalid\n", | ||
74 | *(u32 *)table->signature); | ||
75 | return (FALSE); | ||
76 | } | ||
77 | |||
78 | /* Check for minimum table length */ | ||
79 | |||
80 | if (table->length < sizeof(struct acpi_table_header)) { | ||
81 | fprintf(stderr, "Table length (0x%8.8X) is invalid\n", | ||
82 | table->length); | ||
83 | return (FALSE); | ||
84 | } | ||
85 | } | ||
86 | |||
87 | return (TRUE); | ||
88 | } | ||
89 | |||
90 | /****************************************************************************** | ||
91 | * | ||
92 | * FUNCTION: ap_is_valid_checksum | ||
93 | * | ||
94 | * PARAMETERS: table - Pointer to table to be validated | ||
95 | * | ||
96 | * RETURN: TRUE if the checksum appears to be valid. FALSE otherwise. | ||
97 | * | ||
98 | * DESCRIPTION: Check for a valid ACPI table checksum. | ||
99 | * | ||
100 | ******************************************************************************/ | ||
101 | |||
102 | u8 ap_is_valid_checksum(struct acpi_table_header *table) | ||
103 | { | ||
104 | acpi_status status; | ||
105 | struct acpi_table_rsdp *rsdp; | ||
106 | |||
107 | if (ACPI_VALIDATE_RSDP_SIG(table->signature)) { | ||
108 | /* | ||
109 | * Checksum for RSDP. | ||
110 | * Note: Other checksums are computed during the table dump. | ||
111 | */ | ||
112 | rsdp = ACPI_CAST_PTR(struct acpi_table_rsdp, table); | ||
113 | status = acpi_tb_validate_rsdp(rsdp); | ||
114 | } else { | ||
115 | status = acpi_tb_verify_checksum(table, table->length); | ||
116 | } | ||
117 | |||
118 | if (ACPI_FAILURE(status)) { | ||
119 | fprintf(stderr, "%4.4s: Warning: wrong checksum in table\n", | ||
120 | table->signature); | ||
121 | } | ||
122 | |||
123 | return (AE_OK); | ||
124 | } | ||
125 | |||
126 | /****************************************************************************** | ||
127 | * | ||
128 | * FUNCTION: ap_get_table_length | ||
129 | * | ||
130 | * PARAMETERS: table - Pointer to the table | ||
131 | * | ||
132 | * RETURN: Table length | ||
133 | * | ||
134 | * DESCRIPTION: Obtain table length according to table signature. | ||
135 | * | ||
136 | ******************************************************************************/ | ||
137 | |||
138 | u32 ap_get_table_length(struct acpi_table_header *table) | ||
139 | { | ||
140 | struct acpi_table_rsdp *rsdp; | ||
141 | |||
142 | /* Check if table is valid */ | ||
143 | |||
144 | if (!ap_is_valid_header(table)) { | ||
145 | return (0); | ||
146 | } | ||
147 | |||
148 | if (ACPI_VALIDATE_RSDP_SIG(table->signature)) { | ||
149 | rsdp = ACPI_CAST_PTR(struct acpi_table_rsdp, table); | ||
150 | return (rsdp->length); | ||
151 | } | ||
152 | |||
153 | /* Normal ACPI table */ | ||
154 | |||
155 | return (table->length); | ||
156 | } | ||
157 | |||
158 | /****************************************************************************** | ||
159 | * | ||
160 | * FUNCTION: ap_dump_table_buffer | ||
161 | * | ||
162 | * PARAMETERS: table - ACPI table to be dumped | ||
163 | * instance - ACPI table instance no. to be dumped | ||
164 | * address - Physical address of the table | ||
165 | * | ||
166 | * RETURN: None | ||
167 | * | ||
168 | * DESCRIPTION: Dump an ACPI table in standard ASCII hex format, with a | ||
169 | * header that is compatible with the acpi_xtract utility. | ||
170 | * | ||
171 | ******************************************************************************/ | ||
172 | |||
173 | static int | ||
174 | ap_dump_table_buffer(struct acpi_table_header *table, | ||
175 | u32 instance, acpi_physical_address address) | ||
176 | { | ||
177 | u32 table_length; | ||
178 | |||
179 | table_length = ap_get_table_length(table); | ||
180 | |||
181 | /* Print only the header if requested */ | ||
182 | |||
183 | if (gbl_summary_mode) { | ||
184 | acpi_tb_print_table_header(address, table); | ||
185 | return (0); | ||
186 | } | ||
187 | |||
188 | /* Dump to binary file if requested */ | ||
189 | |||
190 | if (gbl_binary_mode) { | ||
191 | return (ap_write_to_binary_file(table, instance)); | ||
192 | } | ||
193 | |||
194 | /* | ||
195 | * Dump the table with header for use with acpixtract utility. | ||
196 | * Note: simplest to just always emit a 64-bit address. acpi_xtract | ||
197 | * utility can handle this. | ||
198 | */ | ||
199 | printf("%4.4s @ 0x%8.8X%8.8X\n", table->signature, | ||
200 | ACPI_FORMAT_UINT64(address)); | ||
201 | |||
202 | acpi_ut_dump_buffer(ACPI_CAST_PTR(u8, table), table_length, | ||
203 | DB_BYTE_DISPLAY, 0); | ||
204 | printf("\n"); | ||
205 | return (0); | ||
206 | } | ||
207 | |||
208 | /****************************************************************************** | ||
209 | * | ||
210 | * FUNCTION: ap_dump_all_tables | ||
211 | * | ||
212 | * PARAMETERS: None | ||
213 | * | ||
214 | * RETURN: Status | ||
215 | * | ||
216 | * DESCRIPTION: Get all tables from the RSDT/XSDT (or at least all of the | ||
217 | * tables that we can possibly get). | ||
218 | * | ||
219 | ******************************************************************************/ | ||
220 | |||
221 | int ap_dump_all_tables(void) | ||
222 | { | ||
223 | struct acpi_table_header *table; | ||
224 | u32 instance = 0; | ||
225 | acpi_physical_address address; | ||
226 | acpi_status status; | ||
227 | int table_status; | ||
228 | u32 i; | ||
229 | |||
230 | /* Get and dump all available ACPI tables */ | ||
231 | |||
232 | for (i = 0; i < AP_MAX_ACPI_FILES; i++) { | ||
233 | status = | ||
234 | acpi_os_get_table_by_index(i, &table, &instance, &address); | ||
235 | if (ACPI_FAILURE(status)) { | ||
236 | |||
237 | /* AE_LIMIT means that no more tables are available */ | ||
238 | |||
239 | if (status == AE_LIMIT) { | ||
240 | return (0); | ||
241 | } else if (i == 0) { | ||
242 | fprintf(stderr, | ||
243 | "Could not get ACPI tables, %s\n", | ||
244 | acpi_format_exception(status)); | ||
245 | return (-1); | ||
246 | } else { | ||
247 | fprintf(stderr, | ||
248 | "Could not get ACPI table at index %u, %s\n", | ||
249 | i, acpi_format_exception(status)); | ||
250 | continue; | ||
251 | } | ||
252 | } | ||
253 | |||
254 | table_status = ap_dump_table_buffer(table, instance, address); | ||
255 | free(table); | ||
256 | |||
257 | if (table_status) { | ||
258 | break; | ||
259 | } | ||
260 | } | ||
261 | |||
262 | /* Something seriously bad happened if the loop terminates here */ | ||
263 | |||
264 | return (-1); | ||
265 | } | ||
266 | |||
267 | /****************************************************************************** | ||
268 | * | ||
269 | * FUNCTION: ap_dump_table_by_address | ||
270 | * | ||
271 | * PARAMETERS: ascii_address - Address for requested ACPI table | ||
272 | * | ||
273 | * RETURN: Status | ||
274 | * | ||
275 | * DESCRIPTION: Get an ACPI table via a physical address and dump it. | ||
276 | * | ||
277 | ******************************************************************************/ | ||
278 | |||
279 | int ap_dump_table_by_address(char *ascii_address) | ||
280 | { | ||
281 | acpi_physical_address address; | ||
282 | struct acpi_table_header *table; | ||
283 | acpi_status status; | ||
284 | int table_status; | ||
285 | u64 long_address; | ||
286 | |||
287 | /* Convert argument to an integer physical address */ | ||
288 | |||
289 | status = acpi_ut_strtoul64(ascii_address, 0, &long_address); | ||
290 | if (ACPI_FAILURE(status)) { | ||
291 | fprintf(stderr, "%s: Could not convert to a physical address\n", | ||
292 | ascii_address); | ||
293 | return (-1); | ||
294 | } | ||
295 | |||
296 | address = (acpi_physical_address) long_address; | ||
297 | status = acpi_os_get_table_by_address(address, &table); | ||
298 | if (ACPI_FAILURE(status)) { | ||
299 | fprintf(stderr, "Could not get table at 0x%8.8X%8.8X, %s\n", | ||
300 | ACPI_FORMAT_UINT64(address), | ||
301 | acpi_format_exception(status)); | ||
302 | return (-1); | ||
303 | } | ||
304 | |||
305 | table_status = ap_dump_table_buffer(table, 0, address); | ||
306 | free(table); | ||
307 | return (table_status); | ||
308 | } | ||
309 | |||
310 | /****************************************************************************** | ||
311 | * | ||
312 | * FUNCTION: ap_dump_table_by_name | ||
313 | * | ||
314 | * PARAMETERS: signature - Requested ACPI table signature | ||
315 | * | ||
316 | * RETURN: Status | ||
317 | * | ||
318 | * DESCRIPTION: Get an ACPI table via a signature and dump it. Handles | ||
319 | * multiple tables with the same signature (SSDTs). | ||
320 | * | ||
321 | ******************************************************************************/ | ||
322 | |||
323 | int ap_dump_table_by_name(char *signature) | ||
324 | { | ||
325 | char local_signature[ACPI_NAME_SIZE + 1]; | ||
326 | u32 instance; | ||
327 | struct acpi_table_header *table; | ||
328 | acpi_physical_address address; | ||
329 | acpi_status status; | ||
330 | int table_status; | ||
331 | |||
332 | if (strlen(signature) != ACPI_NAME_SIZE) { | ||
333 | fprintf(stderr, | ||
334 | "Invalid table signature [%s]: must be exactly 4 characters\n", | ||
335 | signature); | ||
336 | return (-1); | ||
337 | } | ||
338 | |||
339 | /* Table signatures are expected to be uppercase */ | ||
340 | |||
341 | strcpy(local_signature, signature); | ||
342 | acpi_ut_strupr(local_signature); | ||
343 | |||
344 | /* To be friendly, handle tables whose signatures do not match the name */ | ||
345 | |||
346 | if (ACPI_COMPARE_NAME(local_signature, "FADT")) { | ||
347 | strcpy(local_signature, ACPI_SIG_FADT); | ||
348 | } else if (ACPI_COMPARE_NAME(local_signature, "MADT")) { | ||
349 | strcpy(local_signature, ACPI_SIG_MADT); | ||
350 | } | ||
351 | |||
352 | /* Dump all instances of this signature (to handle multiple SSDTs) */ | ||
353 | |||
354 | for (instance = 0; instance < AP_MAX_ACPI_FILES; instance++) { | ||
355 | status = acpi_os_get_table_by_name(local_signature, instance, | ||
356 | &table, &address); | ||
357 | if (ACPI_FAILURE(status)) { | ||
358 | |||
359 | /* AE_LIMIT means that no more tables are available */ | ||
360 | |||
361 | if (status == AE_LIMIT) { | ||
362 | return (0); | ||
363 | } | ||
364 | |||
365 | fprintf(stderr, | ||
366 | "Could not get ACPI table with signature [%s], %s\n", | ||
367 | local_signature, acpi_format_exception(status)); | ||
368 | return (-1); | ||
369 | } | ||
370 | |||
371 | table_status = ap_dump_table_buffer(table, instance, address); | ||
372 | free(table); | ||
373 | |||
374 | if (table_status) { | ||
375 | break; | ||
376 | } | ||
377 | } | ||
378 | |||
379 | /* Something seriously bad happened if the loop terminates here */ | ||
380 | |||
381 | return (-1); | ||
382 | } | ||
383 | |||
384 | /****************************************************************************** | ||
385 | * | ||
386 | * FUNCTION: ap_dump_table_from_file | ||
387 | * | ||
388 | * PARAMETERS: pathname - File containing the binary ACPI table | ||
389 | * | ||
390 | * RETURN: Status | ||
391 | * | ||
392 | * DESCRIPTION: Dump an ACPI table from a binary file | ||
393 | * | ||
394 | ******************************************************************************/ | ||
395 | |||
396 | int ap_dump_table_from_file(char *pathname) | ||
397 | { | ||
398 | struct acpi_table_header *table; | ||
399 | u32 file_size = 0; | ||
400 | int table_status = -1; | ||
401 | |||
402 | /* Get the entire ACPI table from the file */ | ||
403 | |||
404 | table = ap_get_table_from_file(pathname, &file_size); | ||
405 | if (!table) { | ||
406 | return (-1); | ||
407 | } | ||
408 | |||
409 | /* File must be at least as long as the table length */ | ||
410 | |||
411 | if (table->length > file_size) { | ||
412 | fprintf(stderr, | ||
413 | "Table length (0x%X) is too large for input file (0x%X) %s\n", | ||
414 | table->length, file_size, pathname); | ||
415 | goto exit; | ||
416 | } | ||
417 | |||
418 | if (gbl_verbose_mode) { | ||
419 | fprintf(stderr, | ||
420 | "Input file: %s contains table [%4.4s], 0x%X (%u) bytes\n", | ||
421 | pathname, table->signature, file_size, file_size); | ||
422 | } | ||
423 | |||
424 | table_status = ap_dump_table_buffer(table, 0, 0); | ||
425 | |||
426 | exit: | ||
427 | free(table); | ||
428 | return (table_status); | ||
429 | } | ||
430 | |||
431 | /****************************************************************************** | ||
432 | * | ||
433 | * FUNCTION: acpi_os* print functions | ||
434 | * | ||
435 | * DESCRIPTION: Used for linkage with ACPICA modules | ||
436 | * | ||
437 | ******************************************************************************/ | ||
438 | |||
439 | void ACPI_INTERNAL_VAR_XFACE acpi_os_printf(const char *fmt, ...) | ||
440 | { | ||
441 | va_list args; | ||
442 | |||
443 | va_start(args, fmt); | ||
444 | vfprintf(stdout, fmt, args); | ||
445 | va_end(args); | ||
446 | } | ||
447 | |||
448 | void acpi_os_vprintf(const char *fmt, va_list args) | ||
449 | { | ||
450 | vfprintf(stdout, fmt, args); | ||
451 | } | ||
diff --git a/tools/power/acpi/tools/acpidump/apfiles.c b/tools/power/acpi/tools/acpidump/apfiles.c new file mode 100644 index 000000000000..4488accc010b --- /dev/null +++ b/tools/power/acpi/tools/acpidump/apfiles.c | |||
@@ -0,0 +1,228 @@ | |||
1 | /****************************************************************************** | ||
2 | * | ||
3 | * Module Name: apfiles - File-related functions for acpidump utility | ||
4 | * | ||
5 | *****************************************************************************/ | ||
6 | |||
7 | /* | ||
8 | * Copyright (C) 2000 - 2014, Intel Corp. | ||
9 | * All rights reserved. | ||
10 | * | ||
11 | * Redistribution and use in source and binary forms, with or without | ||
12 | * modification, are permitted provided that the following conditions | ||
13 | * are met: | ||
14 | * 1. Redistributions of source code must retain the above copyright | ||
15 | * notice, this list of conditions, and the following disclaimer, | ||
16 | * without modification. | ||
17 | * 2. Redistributions in binary form must reproduce at minimum a disclaimer | ||
18 | * substantially similar to the "NO WARRANTY" disclaimer below | ||
19 | * ("Disclaimer") and any redistribution must be conditioned upon | ||
20 | * including a substantially similar Disclaimer requirement for further | ||
21 | * binary redistribution. | ||
22 | * 3. Neither the names of the above-listed copyright holders nor the names | ||
23 | * of any contributors may be used to endorse or promote products derived | ||
24 | * from this software without specific prior written permission. | ||
25 | * | ||
26 | * Alternatively, this software may be distributed under the terms of the | ||
27 | * GNU General Public License ("GPL") version 2 as published by the Free | ||
28 | * Software Foundation. | ||
29 | * | ||
30 | * NO WARRANTY | ||
31 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS | ||
32 | * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT | ||
33 | * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR | ||
34 | * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT | ||
35 | * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL | ||
36 | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS | ||
37 | * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) | ||
38 | * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, | ||
39 | * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING | ||
40 | * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE | ||
41 | * POSSIBILITY OF SUCH DAMAGES. | ||
42 | */ | ||
43 | |||
44 | #include "acpidump.h" | ||
45 | #include "acapps.h" | ||
46 | |||
47 | /****************************************************************************** | ||
48 | * | ||
49 | * FUNCTION: ap_open_output_file | ||
50 | * | ||
51 | * PARAMETERS: pathname - Output filename | ||
52 | * | ||
53 | * RETURN: Open file handle | ||
54 | * | ||
55 | * DESCRIPTION: Open a text output file for acpidump. Checks if file already | ||
56 | * exists. | ||
57 | * | ||
58 | ******************************************************************************/ | ||
59 | |||
60 | int ap_open_output_file(char *pathname) | ||
61 | { | ||
62 | struct stat stat_info; | ||
63 | FILE *file; | ||
64 | |||
65 | /* If file exists, prompt for overwrite */ | ||
66 | |||
67 | if (!stat(pathname, &stat_info)) { | ||
68 | fprintf(stderr, | ||
69 | "Target path already exists, overwrite? [y|n] "); | ||
70 | |||
71 | if (getchar() != 'y') { | ||
72 | return (-1); | ||
73 | } | ||
74 | } | ||
75 | |||
76 | /* Point stdout to the file */ | ||
77 | |||
78 | file = freopen(pathname, "w", stdout); | ||
79 | if (!file) { | ||
80 | perror("Could not open output file"); | ||
81 | return (-1); | ||
82 | } | ||
83 | |||
84 | /* Save the file and path */ | ||
85 | |||
86 | gbl_output_file = file; | ||
87 | gbl_output_filename = pathname; | ||
88 | return (0); | ||
89 | } | ||
90 | |||
91 | /****************************************************************************** | ||
92 | * | ||
93 | * FUNCTION: ap_write_to_binary_file | ||
94 | * | ||
95 | * PARAMETERS: table - ACPI table to be written | ||
96 | * instance - ACPI table instance no. to be written | ||
97 | * | ||
98 | * RETURN: Status | ||
99 | * | ||
100 | * DESCRIPTION: Write an ACPI table to a binary file. Builds the output | ||
101 | * filename from the table signature. | ||
102 | * | ||
103 | ******************************************************************************/ | ||
104 | |||
105 | int ap_write_to_binary_file(struct acpi_table_header *table, u32 instance) | ||
106 | { | ||
107 | char filename[ACPI_NAME_SIZE + 16]; | ||
108 | char instance_str[16]; | ||
109 | FILE *file; | ||
110 | size_t actual; | ||
111 | u32 table_length; | ||
112 | |||
113 | /* Obtain table length */ | ||
114 | |||
115 | table_length = ap_get_table_length(table); | ||
116 | |||
117 | /* Construct lower-case filename from the table local signature */ | ||
118 | |||
119 | if (ACPI_VALIDATE_RSDP_SIG(table->signature)) { | ||
120 | ACPI_MOVE_NAME(filename, ACPI_RSDP_NAME); | ||
121 | } else { | ||
122 | ACPI_MOVE_NAME(filename, table->signature); | ||
123 | } | ||
124 | filename[0] = (char)ACPI_TOLOWER(filename[0]); | ||
125 | filename[1] = (char)ACPI_TOLOWER(filename[1]); | ||
126 | filename[2] = (char)ACPI_TOLOWER(filename[2]); | ||
127 | filename[3] = (char)ACPI_TOLOWER(filename[3]); | ||
128 | filename[ACPI_NAME_SIZE] = 0; | ||
129 | |||
130 | /* Handle multiple SSDts - create different filenames for each */ | ||
131 | |||
132 | if (instance > 0) { | ||
133 | sprintf(instance_str, "%u", instance); | ||
134 | strcat(filename, instance_str); | ||
135 | } | ||
136 | |||
137 | strcat(filename, ACPI_TABLE_FILE_SUFFIX); | ||
138 | |||
139 | if (gbl_verbose_mode) { | ||
140 | fprintf(stderr, | ||
141 | "Writing [%4.4s] to binary file: %s 0x%X (%u) bytes\n", | ||
142 | table->signature, filename, table->length, | ||
143 | table->length); | ||
144 | } | ||
145 | |||
146 | /* Open the file and dump the entire table in binary mode */ | ||
147 | |||
148 | file = fopen(filename, "wb"); | ||
149 | if (!file) { | ||
150 | perror("Could not open output file"); | ||
151 | return (-1); | ||
152 | } | ||
153 | |||
154 | actual = fwrite(table, 1, table_length, file); | ||
155 | if (actual != table_length) { | ||
156 | perror("Error writing binary output file"); | ||
157 | fclose(file); | ||
158 | return (-1); | ||
159 | } | ||
160 | |||
161 | fclose(file); | ||
162 | return (0); | ||
163 | } | ||
164 | |||
165 | /****************************************************************************** | ||
166 | * | ||
167 | * FUNCTION: ap_get_table_from_file | ||
168 | * | ||
169 | * PARAMETERS: pathname - File containing the binary ACPI table | ||
170 | * out_file_size - Where the file size is returned | ||
171 | * | ||
172 | * RETURN: Buffer containing the ACPI table. NULL on error. | ||
173 | * | ||
174 | * DESCRIPTION: Open a file and read it entirely into a new buffer | ||
175 | * | ||
176 | ******************************************************************************/ | ||
177 | |||
178 | struct acpi_table_header *ap_get_table_from_file(char *pathname, | ||
179 | u32 *out_file_size) | ||
180 | { | ||
181 | struct acpi_table_header *buffer = NULL; | ||
182 | FILE *file; | ||
183 | u32 file_size; | ||
184 | size_t actual; | ||
185 | |||
186 | /* Must use binary mode */ | ||
187 | |||
188 | file = fopen(pathname, "rb"); | ||
189 | if (!file) { | ||
190 | perror("Could not open input file"); | ||
191 | return (NULL); | ||
192 | } | ||
193 | |||
194 | /* Need file size to allocate a buffer */ | ||
195 | |||
196 | file_size = cm_get_file_size(file); | ||
197 | if (file_size == ACPI_UINT32_MAX) { | ||
198 | fprintf(stderr, | ||
199 | "Could not get input file size: %s\n", pathname); | ||
200 | goto cleanup; | ||
201 | } | ||
202 | |||
203 | /* Allocate a buffer for the entire file */ | ||
204 | |||
205 | buffer = calloc(1, file_size); | ||
206 | if (!buffer) { | ||
207 | fprintf(stderr, | ||
208 | "Could not allocate file buffer of size: %u\n", | ||
209 | file_size); | ||
210 | goto cleanup; | ||
211 | } | ||
212 | |||
213 | /* Read the entire file */ | ||
214 | |||
215 | actual = fread(buffer, 1, file_size, file); | ||
216 | if (actual != file_size) { | ||
217 | fprintf(stderr, "Could not read input file: %s\n", pathname); | ||
218 | free(buffer); | ||
219 | buffer = NULL; | ||
220 | goto cleanup; | ||
221 | } | ||
222 | |||
223 | *out_file_size = file_size; | ||
224 | |||
225 | cleanup: | ||
226 | fclose(file); | ||
227 | return (buffer); | ||
228 | } | ||
diff --git a/tools/power/acpi/tools/acpidump/apmain.c b/tools/power/acpi/tools/acpidump/apmain.c new file mode 100644 index 000000000000..51e8d638db18 --- /dev/null +++ b/tools/power/acpi/tools/acpidump/apmain.c | |||
@@ -0,0 +1,351 @@ | |||
1 | /****************************************************************************** | ||
2 | * | ||
3 | * Module Name: apmain - Main module for the acpidump utility | ||
4 | * | ||
5 | *****************************************************************************/ | ||
6 | |||
7 | /* | ||
8 | * Copyright (C) 2000 - 2014, Intel Corp. | ||
9 | * All rights reserved. | ||
10 | * | ||
11 | * Redistribution and use in source and binary forms, with or without | ||
12 | * modification, are permitted provided that the following conditions | ||
13 | * are met: | ||
14 | * 1. Redistributions of source code must retain the above copyright | ||
15 | * notice, this list of conditions, and the following disclaimer, | ||
16 | * without modification. | ||
17 | * 2. Redistributions in binary form must reproduce at minimum a disclaimer | ||
18 | * substantially similar to the "NO WARRANTY" disclaimer below | ||
19 | * ("Disclaimer") and any redistribution must be conditioned upon | ||
20 | * including a substantially similar Disclaimer requirement for further | ||
21 | * binary redistribution. | ||
22 | * 3. Neither the names of the above-listed copyright holders nor the names | ||
23 | * of any contributors may be used to endorse or promote products derived | ||
24 | * from this software without specific prior written permission. | ||
25 | * | ||
26 | * Alternatively, this software may be distributed under the terms of the | ||
27 | * GNU General Public License ("GPL") version 2 as published by the Free | ||
28 | * Software Foundation. | ||
29 | * | ||
30 | * NO WARRANTY | ||
31 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS | ||
32 | * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT | ||
33 | * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR | ||
34 | * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT | ||
35 | * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL | ||
36 | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS | ||
37 | * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) | ||
38 | * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, | ||
39 | * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING | ||
40 | * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE | ||
41 | * POSSIBILITY OF SUCH DAMAGES. | ||
42 | */ | ||
43 | |||
44 | #define _DECLARE_GLOBALS | ||
45 | #include "acpidump.h" | ||
46 | #include "acapps.h" | ||
47 | |||
48 | /* | ||
49 | * acpidump - A portable utility for obtaining system ACPI tables and dumping | ||
50 | * them in an ASCII hex format suitable for binary extraction via acpixtract. | ||
51 | * | ||
52 | * Obtaining the system ACPI tables is an OS-specific operation. | ||
53 | * | ||
54 | * This utility can be ported to any host operating system by providing a | ||
55 | * module containing system-specific versions of these interfaces: | ||
56 | * | ||
57 | * acpi_os_get_table_by_address | ||
58 | * acpi_os_get_table_by_index | ||
59 | * acpi_os_get_table_by_name | ||
60 | * | ||
61 | * See the ACPICA Reference Guide for the exact definitions of these | ||
62 | * interfaces. Also, see these ACPICA source code modules for example | ||
63 | * implementations: | ||
64 | * | ||
65 | * source/os_specific/service_layers/oswintbl.c | ||
66 | * source/os_specific/service_layers/oslinuxtbl.c | ||
67 | */ | ||
68 | |||
69 | /* Local prototypes */ | ||
70 | |||
71 | static void ap_display_usage(void); | ||
72 | |||
73 | static int ap_do_options(int argc, char **argv); | ||
74 | |||
75 | static void ap_insert_action(char *argument, u32 to_be_done); | ||
76 | |||
77 | /* Table for deferred actions from command line options */ | ||
78 | |||
79 | struct ap_dump_action action_table[AP_MAX_ACTIONS]; | ||
80 | u32 current_action = 0; | ||
81 | |||
82 | #define AP_UTILITY_NAME "ACPI Binary Table Dump Utility" | ||
83 | #define AP_SUPPORTED_OPTIONS "?a:bcf:hn:o:r:svxz" | ||
84 | |||
85 | /****************************************************************************** | ||
86 | * | ||
87 | * FUNCTION: ap_display_usage | ||
88 | * | ||
89 | * DESCRIPTION: Usage message for the acpi_dump utility | ||
90 | * | ||
91 | ******************************************************************************/ | ||
92 | |||
93 | static void ap_display_usage(void) | ||
94 | { | ||
95 | |||
96 | ACPI_USAGE_HEADER("acpidump [options]"); | ||
97 | |||
98 | ACPI_OPTION("-b", "Dump tables to binary files"); | ||
99 | ACPI_OPTION("-c", "Dump customized tables"); | ||
100 | ACPI_OPTION("-h -?", "This help message"); | ||
101 | ACPI_OPTION("-o <File>", "Redirect output to file"); | ||
102 | ACPI_OPTION("-r <Address>", "Dump tables from specified RSDP"); | ||
103 | ACPI_OPTION("-s", "Print table summaries only"); | ||
104 | ACPI_OPTION("-v", "Display version information"); | ||
105 | ACPI_OPTION("-z", "Verbose mode"); | ||
106 | |||
107 | printf("\nTable Options:\n"); | ||
108 | |||
109 | ACPI_OPTION("-a <Address>", "Get table via a physical address"); | ||
110 | ACPI_OPTION("-f <BinaryFile>", "Get table via a binary file"); | ||
111 | ACPI_OPTION("-n <Signature>", "Get table via a name/signature"); | ||
112 | ACPI_OPTION("-x", "Do not use but dump XSDT"); | ||
113 | ACPI_OPTION("-x -x", "Do not use or dump XSDT"); | ||
114 | |||
115 | printf("\n" | ||
116 | "Invocation without parameters dumps all available tables\n" | ||
117 | "Multiple mixed instances of -a, -f, and -n are supported\n\n"); | ||
118 | } | ||
119 | |||
120 | /****************************************************************************** | ||
121 | * | ||
122 | * FUNCTION: ap_insert_action | ||
123 | * | ||
124 | * PARAMETERS: argument - Pointer to the argument for this action | ||
125 | * to_be_done - What to do to process this action | ||
126 | * | ||
127 | * RETURN: None. Exits program if action table becomes full. | ||
128 | * | ||
129 | * DESCRIPTION: Add an action item to the action table | ||
130 | * | ||
131 | ******************************************************************************/ | ||
132 | |||
133 | static void ap_insert_action(char *argument, u32 to_be_done) | ||
134 | { | ||
135 | |||
136 | /* Insert action and check for table overflow */ | ||
137 | |||
138 | action_table[current_action].argument = argument; | ||
139 | action_table[current_action].to_be_done = to_be_done; | ||
140 | |||
141 | current_action++; | ||
142 | if (current_action > AP_MAX_ACTIONS) { | ||
143 | fprintf(stderr, "Too many table options (max %u)\n", | ||
144 | AP_MAX_ACTIONS); | ||
145 | exit(-1); | ||
146 | } | ||
147 | } | ||
148 | |||
149 | /****************************************************************************** | ||
150 | * | ||
151 | * FUNCTION: ap_do_options | ||
152 | * | ||
153 | * PARAMETERS: argc/argv - Standard argc/argv | ||
154 | * | ||
155 | * RETURN: Status | ||
156 | * | ||
157 | * DESCRIPTION: Command line option processing. The main actions for getting | ||
158 | * and dumping tables are deferred via the action table. | ||
159 | * | ||
160 | *****************************************************************************/ | ||
161 | |||
162 | static int ap_do_options(int argc, char **argv) | ||
163 | { | ||
164 | int j; | ||
165 | acpi_status status; | ||
166 | |||
167 | /* Command line options */ | ||
168 | |||
169 | while ((j = acpi_getopt(argc, argv, AP_SUPPORTED_OPTIONS)) != EOF) | ||
170 | switch (j) { | ||
171 | /* | ||
172 | * Global options | ||
173 | */ | ||
174 | case 'b': /* Dump all input tables to binary files */ | ||
175 | |||
176 | gbl_binary_mode = TRUE; | ||
177 | continue; | ||
178 | |||
179 | case 'c': /* Dump customized tables */ | ||
180 | |||
181 | gbl_dump_customized_tables = TRUE; | ||
182 | continue; | ||
183 | |||
184 | case 'h': | ||
185 | case '?': | ||
186 | |||
187 | ap_display_usage(); | ||
188 | exit(0); | ||
189 | |||
190 | case 'o': /* Redirect output to a single file */ | ||
191 | |||
192 | if (ap_open_output_file(acpi_gbl_optarg)) { | ||
193 | exit(-1); | ||
194 | } | ||
195 | continue; | ||
196 | |||
197 | case 'r': /* Dump tables from specified RSDP */ | ||
198 | |||
199 | status = | ||
200 | acpi_ut_strtoul64(acpi_gbl_optarg, 0, | ||
201 | &gbl_rsdp_base); | ||
202 | if (ACPI_FAILURE(status)) { | ||
203 | fprintf(stderr, | ||
204 | "%s: Could not convert to a physical address\n", | ||
205 | acpi_gbl_optarg); | ||
206 | exit(-1); | ||
207 | } | ||
208 | continue; | ||
209 | |||
210 | case 's': /* Print table summaries only */ | ||
211 | |||
212 | gbl_summary_mode = TRUE; | ||
213 | continue; | ||
214 | |||
215 | case 'x': /* Do not use XSDT */ | ||
216 | |||
217 | if (!acpi_gbl_do_not_use_xsdt) { | ||
218 | acpi_gbl_do_not_use_xsdt = TRUE; | ||
219 | } else { | ||
220 | gbl_do_not_dump_xsdt = TRUE; | ||
221 | } | ||
222 | continue; | ||
223 | |||
224 | case 'v': /* Revision/version */ | ||
225 | |||
226 | printf(ACPI_COMMON_SIGNON(AP_UTILITY_NAME)); | ||
227 | exit(0); | ||
228 | |||
229 | case 'z': /* Verbose mode */ | ||
230 | |||
231 | gbl_verbose_mode = TRUE; | ||
232 | fprintf(stderr, ACPI_COMMON_SIGNON(AP_UTILITY_NAME)); | ||
233 | continue; | ||
234 | |||
235 | /* | ||
236 | * Table options | ||
237 | */ | ||
238 | case 'a': /* Get table by physical address */ | ||
239 | |||
240 | ap_insert_action(acpi_gbl_optarg, | ||
241 | AP_DUMP_TABLE_BY_ADDRESS); | ||
242 | break; | ||
243 | |||
244 | case 'f': /* Get table from a file */ | ||
245 | |||
246 | ap_insert_action(acpi_gbl_optarg, | ||
247 | AP_DUMP_TABLE_BY_FILE); | ||
248 | break; | ||
249 | |||
250 | case 'n': /* Get table by input name (signature) */ | ||
251 | |||
252 | ap_insert_action(acpi_gbl_optarg, | ||
253 | AP_DUMP_TABLE_BY_NAME); | ||
254 | break; | ||
255 | |||
256 | default: | ||
257 | |||
258 | ap_display_usage(); | ||
259 | exit(-1); | ||
260 | } | ||
261 | |||
262 | /* If there are no actions, this means "get/dump all tables" */ | ||
263 | |||
264 | if (current_action == 0) { | ||
265 | ap_insert_action(NULL, AP_DUMP_ALL_TABLES); | ||
266 | } | ||
267 | |||
268 | return (0); | ||
269 | } | ||
270 | |||
271 | /****************************************************************************** | ||
272 | * | ||
273 | * FUNCTION: main | ||
274 | * | ||
275 | * PARAMETERS: argc/argv - Standard argc/argv | ||
276 | * | ||
277 | * RETURN: Status | ||
278 | * | ||
279 | * DESCRIPTION: C main function for acpidump utility | ||
280 | * | ||
281 | ******************************************************************************/ | ||
282 | |||
283 | int ACPI_SYSTEM_XFACE main(int argc, char *argv[]) | ||
284 | { | ||
285 | int status = 0; | ||
286 | struct ap_dump_action *action; | ||
287 | u32 file_size; | ||
288 | u32 i; | ||
289 | |||
290 | ACPI_DEBUG_INITIALIZE(); /* For debug version only */ | ||
291 | |||
292 | /* Process command line options */ | ||
293 | |||
294 | if (ap_do_options(argc, argv)) { | ||
295 | return (-1); | ||
296 | } | ||
297 | |||
298 | /* Get/dump ACPI table(s) as requested */ | ||
299 | |||
300 | for (i = 0; i < current_action; i++) { | ||
301 | action = &action_table[i]; | ||
302 | switch (action->to_be_done) { | ||
303 | case AP_DUMP_ALL_TABLES: | ||
304 | |||
305 | status = ap_dump_all_tables(); | ||
306 | break; | ||
307 | |||
308 | case AP_DUMP_TABLE_BY_ADDRESS: | ||
309 | |||
310 | status = ap_dump_table_by_address(action->argument); | ||
311 | break; | ||
312 | |||
313 | case AP_DUMP_TABLE_BY_NAME: | ||
314 | |||
315 | status = ap_dump_table_by_name(action->argument); | ||
316 | break; | ||
317 | |||
318 | case AP_DUMP_TABLE_BY_FILE: | ||
319 | |||
320 | status = ap_dump_table_from_file(action->argument); | ||
321 | break; | ||
322 | |||
323 | default: | ||
324 | |||
325 | fprintf(stderr, | ||
326 | "Internal error, invalid action: 0x%X\n", | ||
327 | action->to_be_done); | ||
328 | return (-1); | ||
329 | } | ||
330 | |||
331 | if (status) { | ||
332 | return (status); | ||
333 | } | ||
334 | } | ||
335 | |||
336 | if (gbl_output_file) { | ||
337 | if (gbl_verbose_mode) { | ||
338 | |||
339 | /* Summary for the output file */ | ||
340 | |||
341 | file_size = cm_get_file_size(gbl_output_file); | ||
342 | fprintf(stderr, | ||
343 | "Output file %s contains 0x%X (%u) bytes\n\n", | ||
344 | gbl_output_filename, file_size, file_size); | ||
345 | } | ||
346 | |||
347 | fclose(gbl_output_file); | ||
348 | } | ||
349 | |||
350 | return (status); | ||
351 | } | ||
diff --git a/tools/power/cpupower/Makefile b/tools/power/cpupower/Makefile index cbfec92af327..2e2ba2efa0d9 100644 --- a/tools/power/cpupower/Makefile +++ b/tools/power/cpupower/Makefile | |||
@@ -62,7 +62,7 @@ LIB_MAJ= 0.0.0 | |||
62 | LIB_MIN= 0 | 62 | LIB_MIN= 0 |
63 | 63 | ||
64 | PACKAGE = cpupower | 64 | PACKAGE = cpupower |
65 | PACKAGE_BUGREPORT = cpufreq@vger.kernel.org | 65 | PACKAGE_BUGREPORT = linux-pm@vger.kernel.org |
66 | LANGUAGES = de fr it cs pt | 66 | LANGUAGES = de fr it cs pt |
67 | 67 | ||
68 | 68 | ||
@@ -274,6 +274,8 @@ install-man: | |||
274 | $(INSTALL_DATA) -D man/cpupower.1 $(DESTDIR)${mandir}/man1/cpupower.1 | 274 | $(INSTALL_DATA) -D man/cpupower.1 $(DESTDIR)${mandir}/man1/cpupower.1 |
275 | $(INSTALL_DATA) -D man/cpupower-frequency-set.1 $(DESTDIR)${mandir}/man1/cpupower-frequency-set.1 | 275 | $(INSTALL_DATA) -D man/cpupower-frequency-set.1 $(DESTDIR)${mandir}/man1/cpupower-frequency-set.1 |
276 | $(INSTALL_DATA) -D man/cpupower-frequency-info.1 $(DESTDIR)${mandir}/man1/cpupower-frequency-info.1 | 276 | $(INSTALL_DATA) -D man/cpupower-frequency-info.1 $(DESTDIR)${mandir}/man1/cpupower-frequency-info.1 |
277 | $(INSTALL_DATA) -D man/cpupower-idle-set.1 $(DESTDIR)${mandir}/man1/cpupower-idle-set.1 | ||
278 | $(INSTALL_DATA) -D man/cpupower-idle-info.1 $(DESTDIR)${mandir}/man1/cpupower-idle-info.1 | ||
277 | $(INSTALL_DATA) -D man/cpupower-set.1 $(DESTDIR)${mandir}/man1/cpupower-set.1 | 279 | $(INSTALL_DATA) -D man/cpupower-set.1 $(DESTDIR)${mandir}/man1/cpupower-set.1 |
278 | $(INSTALL_DATA) -D man/cpupower-info.1 $(DESTDIR)${mandir}/man1/cpupower-info.1 | 280 | $(INSTALL_DATA) -D man/cpupower-info.1 $(DESTDIR)${mandir}/man1/cpupower-info.1 |
279 | $(INSTALL_DATA) -D man/cpupower-monitor.1 $(DESTDIR)${mandir}/man1/cpupower-monitor.1 | 281 | $(INSTALL_DATA) -D man/cpupower-monitor.1 $(DESTDIR)${mandir}/man1/cpupower-monitor.1 |
@@ -295,8 +297,12 @@ uninstall: | |||
295 | - rm -f $(DESTDIR)${libdir}/libcpupower.* | 297 | - rm -f $(DESTDIR)${libdir}/libcpupower.* |
296 | - rm -f $(DESTDIR)${includedir}/cpufreq.h | 298 | - rm -f $(DESTDIR)${includedir}/cpufreq.h |
297 | - rm -f $(DESTDIR)${bindir}/utils/cpupower | 299 | - rm -f $(DESTDIR)${bindir}/utils/cpupower |
298 | - rm -f $(DESTDIR)${mandir}/man1/cpufreq-set.1 | 300 | - rm -f $(DESTDIR)${mandir}/man1/cpupower.1 |
299 | - rm -f $(DESTDIR)${mandir}/man1/cpufreq-info.1 | 301 | - rm -f $(DESTDIR)${mandir}/man1/cpupower-frequency-set.1 |
302 | - rm -f $(DESTDIR)${mandir}/man1/cpupower-frequency-info.1 | ||
303 | - rm -f $(DESTDIR)${mandir}/man1/cpupower-set.1 | ||
304 | - rm -f $(DESTDIR)${mandir}/man1/cpupower-info.1 | ||
305 | - rm -f $(DESTDIR)${mandir}/man1/cpupower-monitor.1 | ||
300 | - for HLANG in $(LANGUAGES); do \ | 306 | - for HLANG in $(LANGUAGES); do \ |
301 | rm -f $(DESTDIR)${localedir}/$$HLANG/LC_MESSAGES/cpupower.mo; \ | 307 | rm -f $(DESTDIR)${localedir}/$$HLANG/LC_MESSAGES/cpupower.mo; \ |
302 | done; | 308 | done; |
diff --git a/tools/power/cpupower/README b/tools/power/cpupower/README index fd9d4c0d6688..1c68f47663b2 100644 --- a/tools/power/cpupower/README +++ b/tools/power/cpupower/README | |||
@@ -1,6 +1,4 @@ | |||
1 | The cpufrequtils package (homepage: | 1 | The cpupower package consists of the following elements: |
2 | http://www.kernel.org/pub/linux/utils/kernel/cpufreq/cpufrequtils.html ) | ||
3 | consists of the following elements: | ||
4 | 2 | ||
5 | requirements | 3 | requirements |
6 | ------------ | 4 | ------------ |
@@ -11,10 +9,10 @@ providing cpuid.h is needed. | |||
11 | For both it's not explicitly checked for (yet). | 9 | For both it's not explicitly checked for (yet). |
12 | 10 | ||
13 | 11 | ||
14 | libcpufreq | 12 | libcpupower |
15 | ---------- | 13 | ---------- |
16 | 14 | ||
17 | "libcpufreq" is a library which offers a unified access method for userspace | 15 | "libcpupower" is a library which offers a unified access method for userspace |
18 | tools and programs to the cpufreq core and drivers in the Linux kernel. This | 16 | tools and programs to the cpufreq core and drivers in the Linux kernel. This |
19 | allows for code reduction in userspace tools, a clean implementation of | 17 | allows for code reduction in userspace tools, a clean implementation of |
20 | the interaction to the cpufreq core, and support for both the sysfs and proc | 18 | the interaction to the cpufreq core, and support for both the sysfs and proc |
@@ -28,22 +26,22 @@ make | |||
28 | su | 26 | su |
29 | make install | 27 | make install |
30 | 28 | ||
31 | should suffice on most systems. It builds default libcpufreq, | 29 | should suffice on most systems. It builds libcpupower to put in |
32 | cpufreq-set and cpufreq-info files and installs them in /usr/lib and | 30 | /usr/lib; cpupower, cpufreq-bench_plot.sh to put in /usr/bin; and |
33 | /usr/bin, respectively. If you want to set up the paths differently and/or | 31 | cpufreq-bench to put in /usr/sbin. If you want to set up the paths |
34 | want to configure the package to your specific needs, you need to open | 32 | differently and/or want to configure the package to your specific |
35 | "Makefile" with an editor of your choice and edit the block marked | 33 | needs, you need to open "Makefile" with an editor of your choice and |
36 | CONFIGURATION. | 34 | edit the block marked CONFIGURATION. |
37 | 35 | ||
38 | 36 | ||
39 | THANKS | 37 | THANKS |
40 | ------ | 38 | ------ |
41 | Many thanks to Mattia Dongili who wrote the autotoolization and | 39 | Many thanks to Mattia Dongili who wrote the autotoolization and |
42 | libtoolization, the manpages and the italian language file for cpufrequtils; | 40 | libtoolization, the manpages and the italian language file for cpupower; |
43 | to Dave Jones for his feedback and his dump_psb tool; to Bruno Ducrot for his | 41 | to Dave Jones for his feedback and his dump_psb tool; to Bruno Ducrot for his |
44 | powernow-k8-decode and intel_gsic tools as well as the french language file; | 42 | powernow-k8-decode and intel_gsic tools as well as the french language file; |
45 | and to various others commenting on the previous (pre-)releases of | 43 | and to various others commenting on the previous (pre-)releases of |
46 | cpufrequtils. | 44 | cpupower. |
47 | 45 | ||
48 | 46 | ||
49 | Dominik Brodowski | 47 | Dominik Brodowski |
diff --git a/tools/power/cpupower/ToDo b/tools/power/cpupower/ToDo index 874b78b586ee..6e8b89f282e6 100644 --- a/tools/power/cpupower/ToDo +++ b/tools/power/cpupower/ToDo | |||
@@ -3,7 +3,6 @@ ToDos sorted by priority: | |||
3 | - Use bitmask functions to parse CPU topology more robust | 3 | - Use bitmask functions to parse CPU topology more robust |
4 | (current implementation has issues on AMD) | 4 | (current implementation has issues on AMD) |
5 | - Try to read out boost states and frequencies on Intel | 5 | - Try to read out boost states and frequencies on Intel |
6 | - Adjust README | ||
7 | - Somewhere saw the ability to read power consumption of | 6 | - Somewhere saw the ability to read power consumption of |
8 | RAM from HW on Intel SandyBridge -> another monitor? | 7 | RAM from HW on Intel SandyBridge -> another monitor? |
9 | - Add another c1e debug idle monitor | 8 | - Add another c1e debug idle monitor |
diff --git a/tools/power/cpupower/debug/kernel/cpufreq-test_tsc.c b/tools/power/cpupower/debug/kernel/cpufreq-test_tsc.c index 0f10b81e3322..5224ee5b392d 100644 --- a/tools/power/cpupower/debug/kernel/cpufreq-test_tsc.c +++ b/tools/power/cpupower/debug/kernel/cpufreq-test_tsc.c | |||
@@ -18,7 +18,7 @@ | |||
18 | * 5.) if the third value, "diff_pmtmr", changes between 2. and 4., the | 18 | * 5.) if the third value, "diff_pmtmr", changes between 2. and 4., the |
19 | * TSC-based delay routine on the Linux kernel does not correctly | 19 | * TSC-based delay routine on the Linux kernel does not correctly |
20 | * handle the cpufreq transition. Please report this to | 20 | * handle the cpufreq transition. Please report this to |
21 | * cpufreq@vger.kernel.org | 21 | * linux-pm@vger.kernel.org |
22 | */ | 22 | */ |
23 | 23 | ||
24 | #include <linux/kernel.h> | 24 | #include <linux/kernel.h> |
diff --git a/tools/power/cpupower/man/cpupower-frequency-info.1 b/tools/power/cpupower/man/cpupower-frequency-info.1 index 4a1918ea8f9c..9c85a382e355 100644 --- a/tools/power/cpupower/man/cpupower-frequency-info.1 +++ b/tools/power/cpupower/man/cpupower-frequency-info.1 | |||
@@ -50,6 +50,9 @@ Prints out information like provided by the /proc/cpufreq interface in 2.4. and | |||
50 | \fB\-m\fR \fB\-\-human\fR | 50 | \fB\-m\fR \fB\-\-human\fR |
51 | human\-readable output for the \-f, \-w, \-s and \-y parameters. | 51 | human\-readable output for the \-f, \-w, \-s and \-y parameters. |
52 | .TP | 52 | .TP |
53 | \fB\-n\fR \fB\-\-no-rounding\fR | ||
54 | Output frequencies and latencies without rounding off values. | ||
55 | .TP | ||
53 | .SH "REMARKS" | 56 | .SH "REMARKS" |
54 | .LP | 57 | .LP |
55 | By default only values of core zero are displayed. How to display settings of | 58 | By default only values of core zero are displayed. How to display settings of |
diff --git a/tools/power/cpupower/man/cpupower-idle-set.1 b/tools/power/cpupower/man/cpupower-idle-set.1 index 6b1607272a5b..3e6799d7a79f 100644 --- a/tools/power/cpupower/man/cpupower-idle-set.1 +++ b/tools/power/cpupower/man/cpupower-idle-set.1 | |||
@@ -13,11 +13,17 @@ sleep states. This can be handy for power vs performance tuning. | |||
13 | .SH "OPTIONS" | 13 | .SH "OPTIONS" |
14 | .LP | 14 | .LP |
15 | .TP | 15 | .TP |
16 | \fB\-d\fR \fB\-\-disable\fR | 16 | \fB\-d\fR \fB\-\-disable\fR <STATE_NO> |
17 | Disable a specific processor sleep state. | 17 | Disable a specific processor sleep state. |
18 | .TP | 18 | .TP |
19 | \fB\-e\fR \fB\-\-enable\fR | 19 | \fB\-e\fR \fB\-\-enable\fR <STATE_NO> |
20 | Enable a specific processor sleep state. | 20 | Enable a specific processor sleep state. |
21 | .TP | ||
22 | \fB\-D\fR \fB\-\-disable-by-latency\fR <LATENCY> | ||
23 | Disable all idle states with a equal or higher latency than <LATENCY> | ||
24 | .TP | ||
25 | \fB\-E\fR \fB\-\-enable-all\fR | ||
26 | Enable all idle states if not enabled already. | ||
21 | 27 | ||
22 | .SH "REMARKS" | 28 | .SH "REMARKS" |
23 | .LP | 29 | .LP |
diff --git a/tools/power/cpupower/man/cpupower-info.1 b/tools/power/cpupower/man/cpupower-info.1 index 58e21196f17f..340bcd0be7de 100644 --- a/tools/power/cpupower/man/cpupower-info.1 +++ b/tools/power/cpupower/man/cpupower-info.1 | |||
@@ -3,7 +3,7 @@ | |||
3 | cpupower\-info \- Shows processor power related kernel or hardware configurations | 3 | cpupower\-info \- Shows processor power related kernel or hardware configurations |
4 | .SH SYNOPSIS | 4 | .SH SYNOPSIS |
5 | .ft B | 5 | .ft B |
6 | .B cpupower info [ \-b ] [ \-s ] [ \-m ] | 6 | .B cpupower info [ \-b ] |
7 | 7 | ||
8 | .SH DESCRIPTION | 8 | .SH DESCRIPTION |
9 | \fBcpupower info \fP shows kernel configurations or processor hardware | 9 | \fBcpupower info \fP shows kernel configurations or processor hardware |
diff --git a/tools/power/cpupower/man/cpupower-set.1 b/tools/power/cpupower/man/cpupower-set.1 index 9dbd536518ab..2bcc696f4496 100644 --- a/tools/power/cpupower/man/cpupower-set.1 +++ b/tools/power/cpupower/man/cpupower-set.1 | |||
@@ -3,7 +3,7 @@ | |||
3 | cpupower\-set \- Set processor power related kernel or hardware configurations | 3 | cpupower\-set \- Set processor power related kernel or hardware configurations |
4 | .SH SYNOPSIS | 4 | .SH SYNOPSIS |
5 | .ft B | 5 | .ft B |
6 | .B cpupower set [ \-b VAL ] [ \-s VAL ] [ \-m VAL ] | 6 | .B cpupower set [ \-b VAL ] |
7 | 7 | ||
8 | 8 | ||
9 | .SH DESCRIPTION | 9 | .SH DESCRIPTION |
@@ -55,35 +55,6 @@ Use \fBcpupower -c all info -b\fP to verify. | |||
55 | 55 | ||
56 | This options needs the msr kernel driver (CONFIG_X86_MSR) loaded. | 56 | This options needs the msr kernel driver (CONFIG_X86_MSR) loaded. |
57 | .RE | 57 | .RE |
58 | .PP | ||
59 | \-\-sched\-mc, \-m [ VAL ] | ||
60 | .RE | ||
61 | \-\-sched\-smt, \-s [ VAL ] | ||
62 | .RS 4 | ||
63 | \-\-sched\-mc utilizes cores in one processor package/socket first before | ||
64 | processes are scheduled to other processor packages/sockets. | ||
65 | |||
66 | \-\-sched\-smt utilizes thread siblings of one processor core first before | ||
67 | processes are scheduled to other cores. | ||
68 | |||
69 | The impact on power consumption and performance (positiv or negativ) heavily | ||
70 | depends on processor support for deep sleep states, frequency scaling and | ||
71 | frequency boost modes and their dependencies between other thread siblings | ||
72 | and processor cores. | ||
73 | |||
74 | Taken over from kernel documentation: | ||
75 | |||
76 | Adjust the kernel's multi-core scheduler support. | ||
77 | |||
78 | Possible values are: | ||
79 | .RS 2 | ||
80 | 0 - No power saving load balance (default value) | ||
81 | |||
82 | 1 - Fill one thread/core/package first for long running threads | ||
83 | |||
84 | 2 - Also bias task wakeups to semi-idle cpu package for power | ||
85 | savings | ||
86 | .RE | ||
87 | 58 | ||
88 | .SH "SEE ALSO" | 59 | .SH "SEE ALSO" |
89 | cpupower-info(1), cpupower-monitor(1), powertop(1) | 60 | cpupower-info(1), cpupower-monitor(1), powertop(1) |
diff --git a/tools/power/cpupower/utils/cpufreq-info.c b/tools/power/cpupower/utils/cpufreq-info.c index 28953c9a7bd5..b4b90a97662c 100644 --- a/tools/power/cpupower/utils/cpufreq-info.c +++ b/tools/power/cpupower/utils/cpufreq-info.c | |||
@@ -82,29 +82,42 @@ static void proc_cpufreq_output(void) | |||
82 | } | 82 | } |
83 | } | 83 | } |
84 | 84 | ||
85 | static int no_rounding; | ||
85 | static void print_speed(unsigned long speed) | 86 | static void print_speed(unsigned long speed) |
86 | { | 87 | { |
87 | unsigned long tmp; | 88 | unsigned long tmp; |
88 | 89 | ||
89 | if (speed > 1000000) { | 90 | if (no_rounding) { |
90 | tmp = speed % 10000; | 91 | if (speed > 1000000) |
91 | if (tmp >= 5000) | 92 | printf("%u.%06u GHz", ((unsigned int) speed/1000000), |
92 | speed += 10000; | 93 | ((unsigned int) speed%1000000)); |
93 | printf("%u.%02u GHz", ((unsigned int) speed/1000000), | 94 | else if (speed > 100000) |
94 | ((unsigned int) (speed%1000000)/10000)); | 95 | printf("%u MHz", (unsigned int) speed); |
95 | } else if (speed > 100000) { | 96 | else if (speed > 1000) |
96 | tmp = speed % 1000; | 97 | printf("%u.%03u MHz", ((unsigned int) speed/1000), |
97 | if (tmp >= 500) | 98 | (unsigned int) (speed%1000)); |
98 | speed += 1000; | 99 | else |
99 | printf("%u MHz", ((unsigned int) speed / 1000)); | 100 | printf("%lu kHz", speed); |
100 | } else if (speed > 1000) { | 101 | } else { |
101 | tmp = speed % 100; | 102 | if (speed > 1000000) { |
102 | if (tmp >= 50) | 103 | tmp = speed%10000; |
103 | speed += 100; | 104 | if (tmp >= 5000) |
104 | printf("%u.%01u MHz", ((unsigned int) speed/1000), | 105 | speed += 10000; |
105 | ((unsigned int) (speed%1000)/100)); | 106 | printf("%u.%02u GHz", ((unsigned int) speed/1000000), |
106 | } else | 107 | ((unsigned int) (speed%1000000)/10000)); |
107 | printf("%lu kHz", speed); | 108 | } else if (speed > 100000) { |
109 | tmp = speed%1000; | ||
110 | if (tmp >= 500) | ||
111 | speed += 1000; | ||
112 | printf("%u MHz", ((unsigned int) speed/1000)); | ||
113 | } else if (speed > 1000) { | ||
114 | tmp = speed%100; | ||
115 | if (tmp >= 50) | ||
116 | speed += 100; | ||
117 | printf("%u.%01u MHz", ((unsigned int) speed/1000), | ||
118 | ((unsigned int) (speed%1000)/100)); | ||
119 | } | ||
120 | } | ||
108 | 121 | ||
109 | return; | 122 | return; |
110 | } | 123 | } |
@@ -113,26 +126,38 @@ static void print_duration(unsigned long duration) | |||
113 | { | 126 | { |
114 | unsigned long tmp; | 127 | unsigned long tmp; |
115 | 128 | ||
116 | if (duration > 1000000) { | 129 | if (no_rounding) { |
117 | tmp = duration % 10000; | 130 | if (duration > 1000000) |
118 | if (tmp >= 5000) | 131 | printf("%u.%06u ms", ((unsigned int) duration/1000000), |
119 | duration += 10000; | 132 | ((unsigned int) duration%1000000)); |
120 | printf("%u.%02u ms", ((unsigned int) duration/1000000), | 133 | else if (duration > 100000) |
121 | ((unsigned int) (duration%1000000)/10000)); | 134 | printf("%u us", ((unsigned int) duration/1000)); |
122 | } else if (duration > 100000) { | 135 | else if (duration > 1000) |
123 | tmp = duration % 1000; | 136 | printf("%u.%03u us", ((unsigned int) duration/1000), |
124 | if (tmp >= 500) | 137 | ((unsigned int) duration%1000)); |
125 | duration += 1000; | 138 | else |
126 | printf("%u us", ((unsigned int) duration / 1000)); | 139 | printf("%lu ns", duration); |
127 | } else if (duration > 1000) { | 140 | } else { |
128 | tmp = duration % 100; | 141 | if (duration > 1000000) { |
129 | if (tmp >= 50) | 142 | tmp = duration%10000; |
130 | duration += 100; | 143 | if (tmp >= 5000) |
131 | printf("%u.%01u us", ((unsigned int) duration/1000), | 144 | duration += 10000; |
132 | ((unsigned int) (duration%1000)/100)); | 145 | printf("%u.%02u ms", ((unsigned int) duration/1000000), |
133 | } else | 146 | ((unsigned int) (duration%1000000)/10000)); |
134 | printf("%lu ns", duration); | 147 | } else if (duration > 100000) { |
135 | 148 | tmp = duration%1000; | |
149 | if (tmp >= 500) | ||
150 | duration += 1000; | ||
151 | printf("%u us", ((unsigned int) duration / 1000)); | ||
152 | } else if (duration > 1000) { | ||
153 | tmp = duration%100; | ||
154 | if (tmp >= 50) | ||
155 | duration += 100; | ||
156 | printf("%u.%01u us", ((unsigned int) duration/1000), | ||
157 | ((unsigned int) (duration%1000)/100)); | ||
158 | } else | ||
159 | printf("%lu ns", duration); | ||
160 | } | ||
136 | return; | 161 | return; |
137 | } | 162 | } |
138 | 163 | ||
@@ -525,6 +550,7 @@ static struct option info_opts[] = { | |||
525 | { .name = "latency", .has_arg = no_argument, .flag = NULL, .val = 'y'}, | 550 | { .name = "latency", .has_arg = no_argument, .flag = NULL, .val = 'y'}, |
526 | { .name = "proc", .has_arg = no_argument, .flag = NULL, .val = 'o'}, | 551 | { .name = "proc", .has_arg = no_argument, .flag = NULL, .val = 'o'}, |
527 | { .name = "human", .has_arg = no_argument, .flag = NULL, .val = 'm'}, | 552 | { .name = "human", .has_arg = no_argument, .flag = NULL, .val = 'm'}, |
553 | { .name = "no-rounding", .has_arg = no_argument, .flag = NULL, .val = 'n'}, | ||
528 | { }, | 554 | { }, |
529 | }; | 555 | }; |
530 | 556 | ||
@@ -538,7 +564,8 @@ int cmd_freq_info(int argc, char **argv) | |||
538 | int output_param = 0; | 564 | int output_param = 0; |
539 | 565 | ||
540 | do { | 566 | do { |
541 | ret = getopt_long(argc, argv, "oefwldpgrasmyb", info_opts, NULL); | 567 | ret = getopt_long(argc, argv, "oefwldpgrasmybn", info_opts, |
568 | NULL); | ||
542 | switch (ret) { | 569 | switch (ret) { |
543 | case '?': | 570 | case '?': |
544 | output_param = '?'; | 571 | output_param = '?'; |
@@ -575,6 +602,9 @@ int cmd_freq_info(int argc, char **argv) | |||
575 | } | 602 | } |
576 | human = 1; | 603 | human = 1; |
577 | break; | 604 | break; |
605 | case 'n': | ||
606 | no_rounding = 1; | ||
607 | break; | ||
578 | default: | 608 | default: |
579 | fprintf(stderr, "invalid or unknown argument\n"); | 609 | fprintf(stderr, "invalid or unknown argument\n"); |
580 | return EXIT_FAILURE; | 610 | return EXIT_FAILURE; |
diff --git a/tools/power/cpupower/utils/cpuidle-set.c b/tools/power/cpupower/utils/cpuidle-set.c index c78141c5dfac..d45d8d775c02 100644 --- a/tools/power/cpupower/utils/cpuidle-set.c +++ b/tools/power/cpupower/utils/cpuidle-set.c | |||
@@ -13,8 +13,14 @@ | |||
13 | #include "helpers/sysfs.h" | 13 | #include "helpers/sysfs.h" |
14 | 14 | ||
15 | static struct option info_opts[] = { | 15 | static struct option info_opts[] = { |
16 | { .name = "disable", .has_arg = required_argument, .flag = NULL, .val = 'd'}, | 16 | { .name = "disable", |
17 | { .name = "enable", .has_arg = required_argument, .flag = NULL, .val = 'e'}, | 17 | .has_arg = required_argument, .flag = NULL, .val = 'd'}, |
18 | { .name = "enable", | ||
19 | .has_arg = required_argument, .flag = NULL, .val = 'e'}, | ||
20 | { .name = "disable-by-latency", | ||
21 | .has_arg = required_argument, .flag = NULL, .val = 'D'}, | ||
22 | { .name = "enable-all", | ||
23 | .has_arg = no_argument, .flag = NULL, .val = 'E'}, | ||
18 | { }, | 24 | { }, |
19 | }; | 25 | }; |
20 | 26 | ||
@@ -23,11 +29,13 @@ int cmd_idle_set(int argc, char **argv) | |||
23 | { | 29 | { |
24 | extern char *optarg; | 30 | extern char *optarg; |
25 | extern int optind, opterr, optopt; | 31 | extern int optind, opterr, optopt; |
26 | int ret = 0, cont = 1, param = 0, idlestate = 0; | 32 | int ret = 0, cont = 1, param = 0, disabled; |
27 | unsigned int cpu = 0; | 33 | unsigned long long latency = 0, state_latency; |
34 | unsigned int cpu = 0, idlestate = 0, idlestates = 0; | ||
35 | char *endptr; | ||
28 | 36 | ||
29 | do { | 37 | do { |
30 | ret = getopt_long(argc, argv, "d:e:", info_opts, NULL); | 38 | ret = getopt_long(argc, argv, "d:e:ED:", info_opts, NULL); |
31 | if (ret == -1) | 39 | if (ret == -1) |
32 | break; | 40 | break; |
33 | switch (ret) { | 41 | switch (ret) { |
@@ -53,6 +61,27 @@ int cmd_idle_set(int argc, char **argv) | |||
53 | param = ret; | 61 | param = ret; |
54 | idlestate = atoi(optarg); | 62 | idlestate = atoi(optarg); |
55 | break; | 63 | break; |
64 | case 'D': | ||
65 | if (param) { | ||
66 | param = -1; | ||
67 | cont = 0; | ||
68 | break; | ||
69 | } | ||
70 | param = ret; | ||
71 | latency = strtoull(optarg, &endptr, 10); | ||
72 | if (*endptr != '\0') { | ||
73 | printf(_("Bad latency value: %s\n"), optarg); | ||
74 | exit(EXIT_FAILURE); | ||
75 | } | ||
76 | break; | ||
77 | case 'E': | ||
78 | if (param) { | ||
79 | param = -1; | ||
80 | cont = 0; | ||
81 | break; | ||
82 | } | ||
83 | param = ret; | ||
84 | break; | ||
56 | case -1: | 85 | case -1: |
57 | cont = 0; | 86 | cont = 0; |
58 | break; | 87 | break; |
@@ -79,8 +108,14 @@ int cmd_idle_set(int argc, char **argv) | |||
79 | if (!bitmask_isbitset(cpus_chosen, cpu)) | 108 | if (!bitmask_isbitset(cpus_chosen, cpu)) |
80 | continue; | 109 | continue; |
81 | 110 | ||
82 | switch (param) { | 111 | if (sysfs_is_cpu_online(cpu) != 1) |
112 | continue; | ||
113 | |||
114 | idlestates = sysfs_get_idlestate_count(cpu); | ||
115 | if (idlestates <= 0) | ||
116 | continue; | ||
83 | 117 | ||
118 | switch (param) { | ||
84 | case 'd': | 119 | case 'd': |
85 | ret = sysfs_idlestate_disable(cpu, idlestate, 1); | 120 | ret = sysfs_idlestate_disable(cpu, idlestate, 1); |
86 | if (ret == 0) | 121 | if (ret == 0) |
@@ -107,6 +142,34 @@ int cmd_idle_set(int argc, char **argv) | |||
107 | printf(_("Idlestate %u not enabled on CPU %u\n"), | 142 | printf(_("Idlestate %u not enabled on CPU %u\n"), |
108 | idlestate, cpu); | 143 | idlestate, cpu); |
109 | break; | 144 | break; |
145 | case 'D': | ||
146 | for (idlestate = 0; idlestate < idlestates; idlestate++) { | ||
147 | disabled = sysfs_is_idlestate_disabled | ||
148 | (cpu, idlestate); | ||
149 | state_latency = sysfs_get_idlestate_latency | ||
150 | (cpu, idlestate); | ||
151 | printf("CPU: %u - idlestate %u - state_latency: %llu - latency: %llu\n", | ||
152 | cpu, idlestate, state_latency, latency); | ||
153 | if (disabled == 1 || latency > state_latency) | ||
154 | continue; | ||
155 | ret = sysfs_idlestate_disable | ||
156 | (cpu, idlestate, 1); | ||
157 | if (ret == 0) | ||
158 | printf(_("Idlestate %u disabled on CPU %u\n"), idlestate, cpu); | ||
159 | } | ||
160 | break; | ||
161 | case 'E': | ||
162 | for (idlestate = 0; idlestate < idlestates; idlestate++) { | ||
163 | disabled = sysfs_is_idlestate_disabled | ||
164 | (cpu, idlestate); | ||
165 | if (disabled == 1) { | ||
166 | ret = sysfs_idlestate_disable | ||
167 | (cpu, idlestate, 0); | ||
168 | if (ret == 0) | ||
169 | printf(_("Idlestate %u enabled on CPU %u\n"), idlestate, cpu); | ||
170 | } | ||
171 | } | ||
172 | break; | ||
110 | default: | 173 | default: |
111 | /* Not reachable with proper args checking */ | 174 | /* Not reachable with proper args checking */ |
112 | printf(_("Invalid or unknown argument\n")); | 175 | printf(_("Invalid or unknown argument\n")); |
diff --git a/tools/power/cpupower/utils/cpupower-info.c b/tools/power/cpupower/utils/cpupower-info.c index 3f68632c28c7..136d979e9586 100644 --- a/tools/power/cpupower/utils/cpupower-info.c +++ b/tools/power/cpupower/utils/cpupower-info.c | |||
@@ -18,8 +18,6 @@ | |||
18 | 18 | ||
19 | static struct option set_opts[] = { | 19 | static struct option set_opts[] = { |
20 | { .name = "perf-bias", .has_arg = optional_argument, .flag = NULL, .val = 'b'}, | 20 | { .name = "perf-bias", .has_arg = optional_argument, .flag = NULL, .val = 'b'}, |
21 | { .name = "sched-mc", .has_arg = optional_argument, .flag = NULL, .val = 'm'}, | ||
22 | { .name = "sched-smt", .has_arg = optional_argument, .flag = NULL, .val = 's'}, | ||
23 | { }, | 21 | { }, |
24 | }; | 22 | }; |
25 | 23 | ||
@@ -37,8 +35,6 @@ int cmd_info(int argc, char **argv) | |||
37 | 35 | ||
38 | union { | 36 | union { |
39 | struct { | 37 | struct { |
40 | int sched_mc:1; | ||
41 | int sched_smt:1; | ||
42 | int perf_bias:1; | 38 | int perf_bias:1; |
43 | }; | 39 | }; |
44 | int params; | 40 | int params; |
@@ -49,23 +45,13 @@ int cmd_info(int argc, char **argv) | |||
49 | textdomain(PACKAGE); | 45 | textdomain(PACKAGE); |
50 | 46 | ||
51 | /* parameter parsing */ | 47 | /* parameter parsing */ |
52 | while ((ret = getopt_long(argc, argv, "msb", set_opts, NULL)) != -1) { | 48 | while ((ret = getopt_long(argc, argv, "b", set_opts, NULL)) != -1) { |
53 | switch (ret) { | 49 | switch (ret) { |
54 | case 'b': | 50 | case 'b': |
55 | if (params.perf_bias) | 51 | if (params.perf_bias) |
56 | print_wrong_arg_exit(); | 52 | print_wrong_arg_exit(); |
57 | params.perf_bias = 1; | 53 | params.perf_bias = 1; |
58 | break; | 54 | break; |
59 | case 'm': | ||
60 | if (params.sched_mc) | ||
61 | print_wrong_arg_exit(); | ||
62 | params.sched_mc = 1; | ||
63 | break; | ||
64 | case 's': | ||
65 | if (params.sched_smt) | ||
66 | print_wrong_arg_exit(); | ||
67 | params.sched_smt = 1; | ||
68 | break; | ||
69 | default: | 55 | default: |
70 | print_wrong_arg_exit(); | 56 | print_wrong_arg_exit(); |
71 | } | 57 | } |
@@ -78,25 +64,6 @@ int cmd_info(int argc, char **argv) | |||
78 | if (bitmask_isallclear(cpus_chosen)) | 64 | if (bitmask_isallclear(cpus_chosen)) |
79 | bitmask_setbit(cpus_chosen, 0); | 65 | bitmask_setbit(cpus_chosen, 0); |
80 | 66 | ||
81 | if (params.sched_mc) { | ||
82 | ret = sysfs_get_sched("mc"); | ||
83 | printf(_("System's multi core scheduler setting: ")); | ||
84 | if (ret < 0) | ||
85 | /* if sysfs file is missing it's: errno == ENOENT */ | ||
86 | printf(_("not supported\n")); | ||
87 | else | ||
88 | printf("%d\n", ret); | ||
89 | } | ||
90 | if (params.sched_smt) { | ||
91 | ret = sysfs_get_sched("smt"); | ||
92 | printf(_("System's thread sibling scheduler setting: ")); | ||
93 | if (ret < 0) | ||
94 | /* if sysfs file is missing it's: errno == ENOENT */ | ||
95 | printf(_("not supported\n")); | ||
96 | else | ||
97 | printf("%d\n", ret); | ||
98 | } | ||
99 | |||
100 | /* Add more per cpu options here */ | 67 | /* Add more per cpu options here */ |
101 | if (!params.perf_bias) | 68 | if (!params.perf_bias) |
102 | return ret; | 69 | return ret; |
@@ -125,11 +92,12 @@ int cmd_info(int argc, char **argv) | |||
125 | if (params.perf_bias) { | 92 | if (params.perf_bias) { |
126 | ret = msr_intel_get_perf_bias(cpu); | 93 | ret = msr_intel_get_perf_bias(cpu); |
127 | if (ret < 0) { | 94 | if (ret < 0) { |
128 | printf(_("Could not read perf-bias value\n")); | 95 | fprintf(stderr, |
129 | break; | 96 | _("Could not read perf-bias value[%d]\n"), ret); |
97 | exit(EXIT_FAILURE); | ||
130 | } else | 98 | } else |
131 | printf(_("perf-bias: %d\n"), ret); | 99 | printf(_("perf-bias: %d\n"), ret); |
132 | } | 100 | } |
133 | } | 101 | } |
134 | return ret; | 102 | return 0; |
135 | } | 103 | } |
diff --git a/tools/power/cpupower/utils/cpupower-set.c b/tools/power/cpupower/utils/cpupower-set.c index bcf1d2f0b791..573c75f8e3f5 100644 --- a/tools/power/cpupower/utils/cpupower-set.c +++ b/tools/power/cpupower/utils/cpupower-set.c | |||
@@ -19,8 +19,6 @@ | |||
19 | 19 | ||
20 | static struct option set_opts[] = { | 20 | static struct option set_opts[] = { |
21 | { .name = "perf-bias", .has_arg = required_argument, .flag = NULL, .val = 'b'}, | 21 | { .name = "perf-bias", .has_arg = required_argument, .flag = NULL, .val = 'b'}, |
22 | { .name = "sched-mc", .has_arg = required_argument, .flag = NULL, .val = 'm'}, | ||
23 | { .name = "sched-smt", .has_arg = required_argument, .flag = NULL, .val = 's'}, | ||
24 | { }, | 22 | { }, |
25 | }; | 23 | }; |
26 | 24 | ||
@@ -38,13 +36,11 @@ int cmd_set(int argc, char **argv) | |||
38 | 36 | ||
39 | union { | 37 | union { |
40 | struct { | 38 | struct { |
41 | int sched_mc:1; | ||
42 | int sched_smt:1; | ||
43 | int perf_bias:1; | 39 | int perf_bias:1; |
44 | }; | 40 | }; |
45 | int params; | 41 | int params; |
46 | } params; | 42 | } params; |
47 | int sched_mc = 0, sched_smt = 0, perf_bias = 0; | 43 | int perf_bias = 0; |
48 | int ret = 0; | 44 | int ret = 0; |
49 | 45 | ||
50 | setlocale(LC_ALL, ""); | 46 | setlocale(LC_ALL, ""); |
@@ -52,7 +48,7 @@ int cmd_set(int argc, char **argv) | |||
52 | 48 | ||
53 | params.params = 0; | 49 | params.params = 0; |
54 | /* parameter parsing */ | 50 | /* parameter parsing */ |
55 | while ((ret = getopt_long(argc, argv, "m:s:b:", | 51 | while ((ret = getopt_long(argc, argv, "b:", |
56 | set_opts, NULL)) != -1) { | 52 | set_opts, NULL)) != -1) { |
57 | switch (ret) { | 53 | switch (ret) { |
58 | case 'b': | 54 | case 'b': |
@@ -66,28 +62,6 @@ int cmd_set(int argc, char **argv) | |||
66 | } | 62 | } |
67 | params.perf_bias = 1; | 63 | params.perf_bias = 1; |
68 | break; | 64 | break; |
69 | case 'm': | ||
70 | if (params.sched_mc) | ||
71 | print_wrong_arg_exit(); | ||
72 | sched_mc = atoi(optarg); | ||
73 | if (sched_mc < 0 || sched_mc > 2) { | ||
74 | printf(_("--sched-mc param out " | ||
75 | "of range [0-%d]\n"), 2); | ||
76 | print_wrong_arg_exit(); | ||
77 | } | ||
78 | params.sched_mc = 1; | ||
79 | break; | ||
80 | case 's': | ||
81 | if (params.sched_smt) | ||
82 | print_wrong_arg_exit(); | ||
83 | sched_smt = atoi(optarg); | ||
84 | if (sched_smt < 0 || sched_smt > 2) { | ||
85 | printf(_("--sched-smt param out " | ||
86 | "of range [0-%d]\n"), 2); | ||
87 | print_wrong_arg_exit(); | ||
88 | } | ||
89 | params.sched_smt = 1; | ||
90 | break; | ||
91 | default: | 65 | default: |
92 | print_wrong_arg_exit(); | 66 | print_wrong_arg_exit(); |
93 | } | 67 | } |
@@ -96,19 +70,6 @@ int cmd_set(int argc, char **argv) | |||
96 | if (!params.params) | 70 | if (!params.params) |
97 | print_wrong_arg_exit(); | 71 | print_wrong_arg_exit(); |
98 | 72 | ||
99 | if (params.sched_mc) { | ||
100 | ret = sysfs_set_sched("mc", sched_mc); | ||
101 | if (ret) | ||
102 | fprintf(stderr, _("Error setting sched-mc %s\n"), | ||
103 | (ret == -ENODEV) ? "not supported" : ""); | ||
104 | } | ||
105 | if (params.sched_smt) { | ||
106 | ret = sysfs_set_sched("smt", sched_smt); | ||
107 | if (ret) | ||
108 | fprintf(stderr, _("Error setting sched-smt %s\n"), | ||
109 | (ret == -ENODEV) ? "not supported" : ""); | ||
110 | } | ||
111 | |||
112 | /* Default is: set all CPUs */ | 73 | /* Default is: set all CPUs */ |
113 | if (bitmask_isallclear(cpus_chosen)) | 74 | if (bitmask_isallclear(cpus_chosen)) |
114 | bitmask_setall(cpus_chosen); | 75 | bitmask_setall(cpus_chosen); |
diff --git a/tools/power/cpupower/utils/cpupower.c b/tools/power/cpupower/utils/cpupower.c index 7efc570ffbaa..7cdcf88659c7 100644 --- a/tools/power/cpupower/utils/cpupower.c +++ b/tools/power/cpupower/utils/cpupower.c | |||
@@ -12,6 +12,9 @@ | |||
12 | #include <string.h> | 12 | #include <string.h> |
13 | #include <unistd.h> | 13 | #include <unistd.h> |
14 | #include <errno.h> | 14 | #include <errno.h> |
15 | #include <sys/types.h> | ||
16 | #include <sys/stat.h> | ||
17 | #include <sys/utsname.h> | ||
15 | 18 | ||
16 | #include "builtin.h" | 19 | #include "builtin.h" |
17 | #include "helpers/helpers.h" | 20 | #include "helpers/helpers.h" |
@@ -169,6 +172,8 @@ int main(int argc, const char *argv[]) | |||
169 | { | 172 | { |
170 | const char *cmd; | 173 | const char *cmd; |
171 | unsigned int i, ret; | 174 | unsigned int i, ret; |
175 | struct stat statbuf; | ||
176 | struct utsname uts; | ||
172 | 177 | ||
173 | cpus_chosen = bitmask_alloc(sysconf(_SC_NPROCESSORS_CONF)); | 178 | cpus_chosen = bitmask_alloc(sysconf(_SC_NPROCESSORS_CONF)); |
174 | 179 | ||
@@ -195,6 +200,15 @@ int main(int argc, const char *argv[]) | |||
195 | 200 | ||
196 | get_cpu_info(0, &cpupower_cpu_info); | 201 | get_cpu_info(0, &cpupower_cpu_info); |
197 | run_as_root = !getuid(); | 202 | run_as_root = !getuid(); |
203 | if (run_as_root) { | ||
204 | ret = uname(&uts); | ||
205 | if (!ret && !strcmp(uts.machine, "x86_64") && | ||
206 | stat("/dev/cpu/0/msr", &statbuf) != 0) { | ||
207 | if (system("modprobe msr") == -1) | ||
208 | fprintf(stderr, _("MSR access not available.\n")); | ||
209 | } | ||
210 | } | ||
211 | |||
198 | 212 | ||
199 | for (i = 0; i < ARRAY_SIZE(commands); i++) { | 213 | for (i = 0; i < ARRAY_SIZE(commands); i++) { |
200 | struct cmd_struct *p = commands + i; | 214 | struct cmd_struct *p = commands + i; |
diff --git a/tools/power/x86/turbostat/turbostat.c b/tools/power/x86/turbostat/turbostat.c index 7c9d8e71eb9e..d0396af99fa0 100644 --- a/tools/power/x86/turbostat/turbostat.c +++ b/tools/power/x86/turbostat/turbostat.c | |||
@@ -1971,13 +1971,13 @@ int set_temperature_target(struct thread_data *t, struct core_data *c, struct pk | |||
1971 | if (get_msr(0, MSR_IA32_TEMPERATURE_TARGET, &msr)) | 1971 | if (get_msr(0, MSR_IA32_TEMPERATURE_TARGET, &msr)) |
1972 | goto guess; | 1972 | goto guess; |
1973 | 1973 | ||
1974 | target_c_local = (msr >> 16) & 0x7F; | 1974 | target_c_local = (msr >> 16) & 0xFF; |
1975 | 1975 | ||
1976 | if (verbose) | 1976 | if (verbose) |
1977 | fprintf(stderr, "cpu%d: MSR_IA32_TEMPERATURE_TARGET: 0x%08llx (%d C)\n", | 1977 | fprintf(stderr, "cpu%d: MSR_IA32_TEMPERATURE_TARGET: 0x%08llx (%d C)\n", |
1978 | cpu, msr, target_c_local); | 1978 | cpu, msr, target_c_local); |
1979 | 1979 | ||
1980 | if (target_c_local < 85 || target_c_local > 127) | 1980 | if (!target_c_local) |
1981 | goto guess; | 1981 | goto guess; |
1982 | 1982 | ||
1983 | tcc_activation_temp = target_c_local; | 1983 | tcc_activation_temp = target_c_local; |