aboutsummaryrefslogtreecommitdiffstats
path: root/tools
diff options
context:
space:
mode:
authorRafael J. Wysocki <rafael.j.wysocki@intel.com>2014-04-28 06:12:57 -0400
committerRafael J. Wysocki <rafael.j.wysocki@intel.com>2014-04-28 06:12:57 -0400
commitfd0c940522c5c5b281b7a4fe3497fabf74bd8911 (patch)
tree9905a60f65d2eb051cb05a95a1052fb35c24c37c /tools
parent6273f00e6ecbd60494a979033b7e5271a29a0436 (diff)
parent35476c75efa04a5fdb01074e54135dcc126c25f7 (diff)
Merge back earlier ACPICA material.
Diffstat (limited to 'tools')
-rw-r--r--tools/power/acpi/Makefile26
-rw-r--r--tools/power/acpi/common/cmfsize.c101
-rw-r--r--tools/power/acpi/common/getopt.c239
-rw-r--r--tools/power/acpi/man/acpidump.885
-rw-r--r--tools/power/acpi/os_specific/service_layers/oslinuxtbl.c1275
-rw-r--r--tools/power/acpi/os_specific/service_layers/osunixdir.c204
-rw-r--r--tools/power/acpi/os_specific/service_layers/osunixmap.c151
-rw-r--r--tools/power/acpi/tools/acpidump/acpidump.c559
-rw-r--r--tools/power/acpi/tools/acpidump/acpidump.h131
-rw-r--r--tools/power/acpi/tools/acpidump/apdump.c451
-rw-r--r--tools/power/acpi/tools/acpidump/apfiles.c228
-rw-r--r--tools/power/acpi/tools/acpidump/apmain.c340
12 files changed, 3216 insertions, 574 deletions
diff --git a/tools/power/acpi/Makefile b/tools/power/acpi/Makefile
index d9186a2fdf06..98625fa2baf1 100644
--- a/tools/power/acpi/Makefile
+++ b/tools/power/acpi/Makefile
@@ -68,7 +68,8 @@ WARNINGS += $(call cc-supports,-Wstrict-prototypes)
68WARNINGS += $(call cc-supports,-Wdeclaration-after-statement) 68WARNINGS += $(call cc-supports,-Wdeclaration-after-statement)
69 69
70KERNEL_INCLUDE := ../../../include 70KERNEL_INCLUDE := ../../../include
71CFLAGS += -D_LINUX -DDEFINE_ALTERNATE_TYPES -I$(KERNEL_INCLUDE) 71ACPICA_INCLUDE := ../../../drivers/acpi/acpica
72CFLAGS += -D_LINUX -I$(KERNEL_INCLUDE) -I$(ACPICA_INCLUDE)
72CFLAGS += $(WARNINGS) 73CFLAGS += $(WARNINGS)
73 74
74ifeq ($(strip $(V)),false) 75ifeq ($(strip $(V)),false)
@@ -101,10 +102,29 @@ endif
101# --- ACPIDUMP BEGIN --- 102# --- ACPIDUMP BEGIN ---
102 103
103vpath %.c \ 104vpath %.c \
104 tools/acpidump 105 ../../../drivers/acpi/acpica\
106 tools/acpidump\
107 common\
108 os_specific/service_layers
109
110CFLAGS += -DACPI_DUMP_APP -Itools/acpidump
105 111
106DUMP_OBJS = \ 112DUMP_OBJS = \
107 acpidump.o 113 apdump.o\
114 apfiles.o\
115 apmain.o\
116 osunixdir.o\
117 osunixmap.o\
118 tbprint.o\
119 tbxfroot.o\
120 utbuffer.o\
121 utexcep.o\
122 utmath.o\
123 utstring.o\
124 utxferror.o\
125 oslinuxtbl.o\
126 cmfsize.o\
127 getopt.o
108 128
109DUMP_OBJS := $(addprefix $(OUTPUT)tools/acpidump/,$(DUMP_OBJS)) 129DUMP_OBJS := $(addprefix $(OUTPUT)tools/acpidump/,$(DUMP_OBJS))
110 130
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
50ACPI_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 ******************************************************************************/
65u32 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
94offset_error:
95 perror("Could not get file offset");
96 return (ACPI_UINT32_MAX);
97
98seek_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
63int acpi_gbl_opterr = 1;
64int acpi_gbl_optind = 1;
65int acpi_gbl_sub_opt_char = 0;
66char *acpi_gbl_optarg;
67
68static 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
88int 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
122int 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
3acpidump \- Dump system's ACPI tables to an ASCII file. 3acpidump \- 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
9appropriate for attaching to a bug report. 12dumps the systems ACPI tables to an ASCII file appropriate for
13attaching to a bug report.
10 14
11Subsequently, they can be processed by utilities in the ACPICA package. 15Subsequently, they can be processed by utilities in the ACPICA package.
12.SS Options 16
13no options worth worrying about. 17.SH OPTIONS
14.PP 18acpidump options are as follow:
15.SH EXAMPLE 19.TP
20.B Options
21.TP
22.B \-b
23Dump tables to binary files
24.TP
25.B \-c
26Dump customized tables
27.TP
28.B \-h \-?
29This help message
30.TP
31.B \-o <File>
32Redirect output to file
33.TP
34.B \-r <Address>
35Dump tables from specified RSDP
36.TP
37.B \-s
38Print table summaries only
39.TP
40.B \-v
41Display version information
42.TP
43.B \-z
44Verbose mode
45.TP
46.B Table Options
47.TP
48.B \-a <Address>
49Get table via a physical address
50.TP
51.B \-f <BinaryFile>
52Get table via a binary file
53.TP
54.B \-n <Signature>
55Get table via a name/signature
56.TP
57Invocation without parameters dumps all available tables
58.TP
59Multiple 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
59Written by Len Brown <len.brown@intel.com> 106Original by:
107 Len Brown <len.brown@intel.com>
108.TP
109Written by:
110 Chao Guan <chao.guan@intel.com>
111.TP
112Updated 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
120COPYRIGHT (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..e975aa90016a
--- /dev/null
+++ b/tools/power/acpi/os_specific/service_layers/oslinuxtbl.c
@@ -0,0 +1,1275 @@
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
47ACPI_MODULE_NAME("oslinuxtbl")
48
49#ifndef PATH_MAX
50#define PATH_MAX 256
51#endif
52/* List of information about obtained ACPI tables */
53typedef 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
62static acpi_status osl_table_initialize(void);
63
64static acpi_status
65osl_table_name_from_file(char *filename, char *signature, u32 *instance);
66
67static acpi_status osl_add_table_to_list(char *signature, u32 instance);
68
69static acpi_status
70osl_read_table_from_file(char *filename,
71 acpi_size file_offset,
72 char *signature, struct acpi_table_header **table);
73
74static acpi_status
75osl_map_table(acpi_size address,
76 char *signature, struct acpi_table_header **table);
77
78static void osl_unmap_table(struct acpi_table_header *table);
79
80static acpi_physical_address osl_find_rsdp_via_efi(void);
81
82static acpi_status osl_load_rsdp(void);
83
84static acpi_status osl_list_customized_tables(char *directory);
85
86static acpi_status
87osl_get_customized_table(char *pathname,
88 char *signature,
89 u32 instance,
90 struct acpi_table_header **table,
91 acpi_physical_address * address);
92
93static acpi_status osl_list_bios_tables(void);
94
95static acpi_status
96osl_get_bios_table(char *signature,
97 u32 instance,
98 struct acpi_table_header **table,
99 acpi_physical_address * address);
100
101static 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
111u8 gbl_dump_dynamic_tables = TRUE;
112
113/* Initialization flags */
114
115u8 gbl_table_list_initialized = FALSE;
116
117/* Local copies of main ACPI tables */
118
119struct acpi_table_rsdp gbl_rsdp;
120struct acpi_table_fadt *gbl_fadt = NULL;
121struct acpi_table_rsdt *gbl_rsdt = NULL;
122struct acpi_table_xsdt *gbl_xsdt = NULL;
123
124/* Table addresses */
125
126acpi_physical_address gbl_fadt_address = 0;
127acpi_physical_address gbl_rsdp_address = 0;
128
129/* Revision of RSD PTR */
130
131u8 gbl_revision = 0;
132
133struct osl_table_info *gbl_table_list_head = NULL;
134u32 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
148static 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
185acpi_status
186acpi_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
224exit:
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
249acpi_status
250acpi_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
308static 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
378acpi_status
379acpi_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
430static 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
461static 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_table_initialize
509 *
510 * PARAMETERS: None
511 *
512 * RETURN: Status
513 *
514 * DESCRIPTION: Initialize ACPI table data. Get and store main ACPI tables to
515 * local variables. Main ACPI tables include RSDT, FADT, RSDT,
516 * and/or XSDT.
517 *
518 *****************************************************************************/
519
520static acpi_status osl_table_initialize(void)
521{
522 acpi_status status;
523 acpi_physical_address address;
524
525 if (gbl_table_list_initialized) {
526 return (AE_OK);
527 }
528
529 /* Get RSDP from memory */
530
531 status = osl_load_rsdp();
532 if (ACPI_FAILURE(status)) {
533 return (status);
534 }
535
536 /* Get XSDT from memory */
537
538 if (gbl_rsdp.revision) {
539 if (gbl_xsdt) {
540 free(gbl_xsdt);
541 gbl_xsdt = NULL;
542 }
543
544 gbl_revision = 2;
545 status = osl_get_bios_table(ACPI_SIG_XSDT, 0,
546 ACPI_CAST_PTR(struct
547 acpi_table_header *,
548 &gbl_xsdt), &address);
549 if (ACPI_FAILURE(status)) {
550 return (status);
551 }
552 }
553
554 /* Get RSDT from memory */
555
556 if (gbl_rsdp.rsdt_physical_address) {
557 if (gbl_rsdt) {
558 free(gbl_rsdt);
559 gbl_rsdt = NULL;
560 }
561
562 status = osl_get_bios_table(ACPI_SIG_RSDT, 0,
563 ACPI_CAST_PTR(struct
564 acpi_table_header *,
565 &gbl_rsdt), &address);
566 if (ACPI_FAILURE(status)) {
567 return (status);
568 }
569 }
570
571 /* Get FADT from memory */
572
573 if (gbl_fadt) {
574 free(gbl_fadt);
575 gbl_fadt = NULL;
576 }
577
578 status = osl_get_bios_table(ACPI_SIG_FADT, 0,
579 ACPI_CAST_PTR(struct acpi_table_header *,
580 &gbl_fadt),
581 &gbl_fadt_address);
582 if (ACPI_FAILURE(status)) {
583 return (status);
584 }
585
586 if (!gbl_dump_customized_tables) {
587
588 /* Add mandatory tables to global table list first */
589
590 status = osl_add_table_to_list(ACPI_RSDP_NAME, 0);
591 if (ACPI_FAILURE(status)) {
592 return (status);
593 }
594
595 status = osl_add_table_to_list(ACPI_SIG_RSDT, 0);
596 if (ACPI_FAILURE(status)) {
597 return (status);
598 }
599
600 if (gbl_revision == 2) {
601 status = osl_add_table_to_list(ACPI_SIG_XSDT, 0);
602 if (ACPI_FAILURE(status)) {
603 return (status);
604 }
605 }
606
607 status = osl_add_table_to_list(ACPI_SIG_DSDT, 0);
608 if (ACPI_FAILURE(status)) {
609 return (status);
610 }
611
612 status = osl_add_table_to_list(ACPI_SIG_FACS, 0);
613 if (ACPI_FAILURE(status)) {
614 return (status);
615 }
616
617 /* Add all tables found in the memory */
618
619 status = osl_list_bios_tables();
620 if (ACPI_FAILURE(status)) {
621 return (status);
622 }
623 } else {
624 /* Add all tables found in the static directory */
625
626 status = osl_list_customized_tables(STATIC_TABLE_DIR);
627 if (ACPI_FAILURE(status)) {
628 return (status);
629 }
630 }
631
632 if (gbl_dump_dynamic_tables) {
633
634 /* Add all dynamically loaded tables in the dynamic directory */
635
636 status = osl_list_customized_tables(DYNAMIC_TABLE_DIR);
637 if (ACPI_FAILURE(status)) {
638 return (status);
639 }
640 }
641
642 gbl_table_list_initialized = TRUE;
643 return (AE_OK);
644}
645
646/******************************************************************************
647 *
648 * FUNCTION: osl_list_bios_tables
649 *
650 * PARAMETERS: None
651 *
652 * RETURN: Status; Table list is initialized if AE_OK.
653 *
654 * DESCRIPTION: Add ACPI tables to the table list from memory.
655 *
656 * NOTE: This works on Linux as table customization does not modify the
657 * addresses stored in RSDP/RSDT/XSDT/FADT.
658 *
659 *****************************************************************************/
660
661static acpi_status osl_list_bios_tables(void)
662{
663 struct acpi_table_header *mapped_table = NULL;
664 u8 *table_data;
665 u8 number_of_tables;
666 u8 item_size;
667 acpi_physical_address table_address = 0;
668 acpi_status status = AE_OK;
669 u32 i;
670
671 if (gbl_revision) {
672 item_size = sizeof(u64);
673 table_data =
674 ACPI_CAST8(gbl_xsdt) + sizeof(struct acpi_table_header);
675 number_of_tables =
676 (u8)((gbl_xsdt->header.length -
677 sizeof(struct acpi_table_header))
678 / item_size);
679 } else { /* Use RSDT if XSDT is not available */
680
681 item_size = sizeof(u32);
682 table_data =
683 ACPI_CAST8(gbl_rsdt) + sizeof(struct acpi_table_header);
684 number_of_tables =
685 (u8)((gbl_rsdt->header.length -
686 sizeof(struct acpi_table_header))
687 / item_size);
688 }
689
690 /* Search RSDT/XSDT for the requested table */
691
692 for (i = 0; i < number_of_tables; ++i, table_data += item_size) {
693 if (gbl_revision) {
694 table_address =
695 (acpi_physical_address) (*ACPI_CAST64(table_data));
696 } else {
697 table_address =
698 (acpi_physical_address) (*ACPI_CAST32(table_data));
699 }
700
701 status = osl_map_table(table_address, NULL, &mapped_table);
702 if (ACPI_FAILURE(status)) {
703 return (status);
704 }
705
706 osl_add_table_to_list(mapped_table->signature, 0);
707 osl_unmap_table(mapped_table);
708 }
709
710 return (AE_OK);
711}
712
713/******************************************************************************
714 *
715 * FUNCTION: osl_get_bios_table
716 *
717 * PARAMETERS: signature - ACPI Signature for common table. Must be
718 * a null terminated 4-character string.
719 * instance - Multiple table support for SSDT/UEFI (0...n)
720 * Must be 0 for other tables.
721 * table - Where a pointer to the table is returned
722 * address - Where the table physical address is returned
723 *
724 * RETURN: Status; Table buffer and physical address returned if AE_OK.
725 * AE_LIMIT: Instance is beyond valid limit
726 * AE_NOT_FOUND: A table with the signature was not found
727 *
728 * DESCRIPTION: Get a BIOS provided ACPI table
729 *
730 * NOTE: Assumes the input signature is uppercase.
731 *
732 *****************************************************************************/
733
734static acpi_status
735osl_get_bios_table(char *signature,
736 u32 instance,
737 struct acpi_table_header **table,
738 acpi_physical_address * address)
739{
740 struct acpi_table_header *local_table = NULL;
741 struct acpi_table_header *mapped_table = NULL;
742 u8 *table_data;
743 u8 number_of_tables;
744 u8 item_size;
745 u32 current_instance = 0;
746 acpi_physical_address table_address = 0;
747 u32 table_length = 0;
748 acpi_status status = AE_OK;
749 u32 i;
750
751 /* Handle special tables whose addresses are not in RSDT/XSDT */
752
753 if (ACPI_COMPARE_NAME(signature, ACPI_RSDP_NAME) ||
754 ACPI_COMPARE_NAME(signature, ACPI_SIG_RSDT) ||
755 ACPI_COMPARE_NAME(signature, ACPI_SIG_XSDT) ||
756 ACPI_COMPARE_NAME(signature, ACPI_SIG_DSDT) ||
757 ACPI_COMPARE_NAME(signature, ACPI_SIG_FACS)) {
758 /*
759 * Get the appropriate address, either 32-bit or 64-bit. Be very
760 * careful about the FADT length and validate table addresses.
761 * Note: The 64-bit addresses have priority.
762 */
763 if (ACPI_COMPARE_NAME(signature, ACPI_SIG_DSDT)) {
764 if ((gbl_fadt->header.length >= MIN_FADT_FOR_XDSDT) &&
765 gbl_fadt->Xdsdt) {
766 table_address =
767 (acpi_physical_address) gbl_fadt->Xdsdt;
768 } else
769 if ((gbl_fadt->header.length >= MIN_FADT_FOR_DSDT)
770 && gbl_fadt->dsdt) {
771 table_address =
772 (acpi_physical_address) gbl_fadt->dsdt;
773 }
774 } else if (ACPI_COMPARE_NAME(signature, ACPI_SIG_FACS)) {
775 if ((gbl_fadt->header.length >= MIN_FADT_FOR_XFACS) &&
776 gbl_fadt->Xfacs) {
777 table_address =
778 (acpi_physical_address) gbl_fadt->Xfacs;
779 } else
780 if ((gbl_fadt->header.length >= MIN_FADT_FOR_FACS)
781 && gbl_fadt->facs) {
782 table_address =
783 (acpi_physical_address) gbl_fadt->facs;
784 }
785 } else if (ACPI_COMPARE_NAME(signature, ACPI_SIG_XSDT)) {
786 if (!gbl_revision) {
787 return (AE_BAD_SIGNATURE);
788 }
789 table_address =
790 (acpi_physical_address) gbl_rsdp.
791 xsdt_physical_address;
792 } else if (ACPI_COMPARE_NAME(signature, ACPI_SIG_RSDT)) {
793 table_address =
794 (acpi_physical_address) gbl_rsdp.
795 rsdt_physical_address;
796 } else {
797 table_address =
798 (acpi_physical_address) gbl_rsdp_address;
799 signature = ACPI_SIG_RSDP;
800 }
801
802 /* Now we can get the requested special table */
803
804 status = osl_map_table(table_address, signature, &mapped_table);
805 if (ACPI_FAILURE(status)) {
806 return (status);
807 }
808
809 table_length = ap_get_table_length(mapped_table);
810 } else { /* Case for a normal ACPI table */
811
812 if (gbl_revision) {
813 item_size = sizeof(u64);
814 table_data =
815 ACPI_CAST8(gbl_xsdt) +
816 sizeof(struct acpi_table_header);
817 number_of_tables =
818 (u8)((gbl_xsdt->header.length -
819 sizeof(struct acpi_table_header))
820 / item_size);
821 } else { /* Use RSDT if XSDT is not available */
822
823 item_size = sizeof(u32);
824 table_data =
825 ACPI_CAST8(gbl_rsdt) +
826 sizeof(struct acpi_table_header);
827 number_of_tables =
828 (u8)((gbl_rsdt->header.length -
829 sizeof(struct acpi_table_header))
830 / item_size);
831 }
832
833 /* Search RSDT/XSDT for the requested table */
834
835 for (i = 0; i < number_of_tables; ++i, table_data += item_size) {
836 if (gbl_revision) {
837 table_address =
838 (acpi_physical_address) (*ACPI_CAST64
839 (table_data));
840 } else {
841 table_address =
842 (acpi_physical_address) (*ACPI_CAST32
843 (table_data));
844 }
845
846 status =
847 osl_map_table(table_address, NULL, &mapped_table);
848 if (ACPI_FAILURE(status)) {
849 return (status);
850 }
851 table_length = mapped_table->length;
852
853 /* Does this table match the requested signature? */
854
855 if (!ACPI_COMPARE_NAME
856 (mapped_table->signature, signature)) {
857 osl_unmap_table(mapped_table);
858 mapped_table = NULL;
859 continue;
860 }
861
862 /* Match table instance (for SSDT/UEFI tables) */
863
864 if (current_instance != instance) {
865 osl_unmap_table(mapped_table);
866 mapped_table = NULL;
867 current_instance++;
868 continue;
869 }
870
871 break;
872 }
873 }
874
875 if (!mapped_table) {
876 return (AE_LIMIT);
877 }
878
879 if (table_length == 0) {
880 status = AE_BAD_HEADER;
881 goto exit;
882 }
883
884 /* Copy table to local buffer and return it */
885
886 local_table = calloc(1, table_length);
887 if (!local_table) {
888 status = AE_NO_MEMORY;
889 goto exit;
890 }
891
892 ACPI_MEMCPY(local_table, mapped_table, table_length);
893 *address = table_address;
894 *table = local_table;
895
896exit:
897 osl_unmap_table(mapped_table);
898 return (status);
899}
900
901/******************************************************************************
902 *
903 * FUNCTION: osl_list_customized_tables
904 *
905 * PARAMETERS: directory - Directory that contains the tables
906 *
907 * RETURN: Status; Table list is initialized if AE_OK.
908 *
909 * DESCRIPTION: Add ACPI tables to the table list from a directory.
910 *
911 *****************************************************************************/
912
913static acpi_status osl_list_customized_tables(char *directory)
914{
915 void *table_dir;
916 u32 instance;
917 char temp_name[ACPI_NAME_SIZE];
918 char *filename;
919 acpi_status status = AE_OK;
920
921 /* Open the requested directory */
922
923 table_dir = acpi_os_open_directory(directory, "*", REQUEST_FILE_ONLY);
924 if (!table_dir) {
925 return (osl_get_last_status(AE_NOT_FOUND));
926 }
927
928 /* Examine all entries in this directory */
929
930 while ((filename = acpi_os_get_next_filename(table_dir))) {
931
932 /* Extract table name and instance number */
933
934 status =
935 osl_table_name_from_file(filename, temp_name, &instance);
936
937 /* Ignore meaningless files */
938
939 if (ACPI_FAILURE(status)) {
940 continue;
941 }
942
943 /* Add new info node to global table list */
944
945 status = osl_add_table_to_list(temp_name, instance);
946 if (ACPI_FAILURE(status)) {
947 break;
948 }
949 }
950
951 acpi_os_close_directory(table_dir);
952 return (status);
953}
954
955/******************************************************************************
956 *
957 * FUNCTION: osl_map_table
958 *
959 * PARAMETERS: address - Address of the table in memory
960 * signature - Optional ACPI Signature for desired table.
961 * Null terminated 4-character string.
962 * table - Where a pointer to the mapped table is
963 * returned
964 *
965 * RETURN: Status; Mapped table is returned if AE_OK.
966 * AE_NOT_FOUND: A valid table was not found at the address
967 *
968 * DESCRIPTION: Map entire ACPI table into caller's address space.
969 *
970 *****************************************************************************/
971
972static acpi_status
973osl_map_table(acpi_size address,
974 char *signature, struct acpi_table_header **table)
975{
976 struct acpi_table_header *mapped_table;
977 u32 length;
978
979 if (!address) {
980 return (AE_BAD_ADDRESS);
981 }
982
983 /*
984 * Map the header so we can get the table length.
985 * Use sizeof (struct acpi_table_header) as:
986 * 1. it is bigger than 24 to include RSDP->Length
987 * 2. it is smaller than sizeof (struct acpi_table_rsdp)
988 */
989 mapped_table =
990 acpi_os_map_memory(address, sizeof(struct acpi_table_header));
991 if (!mapped_table) {
992 fprintf(stderr, "Could not map table header at 0x%8.8X%8.8X\n",
993 ACPI_FORMAT_UINT64(address));
994 return (osl_get_last_status(AE_BAD_ADDRESS));
995 }
996
997 /* If specified, signature must match */
998
999 if (signature && !ACPI_COMPARE_NAME(signature, mapped_table->signature)) {
1000 acpi_os_unmap_memory(mapped_table,
1001 sizeof(struct acpi_table_header));
1002 return (AE_BAD_SIGNATURE);
1003 }
1004
1005 /* Map the entire table */
1006
1007 length = ap_get_table_length(mapped_table);
1008 acpi_os_unmap_memory(mapped_table, sizeof(struct acpi_table_header));
1009 if (length == 0) {
1010 return (AE_BAD_HEADER);
1011 }
1012
1013 mapped_table = acpi_os_map_memory(address, length);
1014 if (!mapped_table) {
1015 fprintf(stderr,
1016 "Could not map table at 0x%8.8X%8.8X length %8.8X\n",
1017 ACPI_FORMAT_UINT64(address), length);
1018 return (osl_get_last_status(AE_INVALID_TABLE_LENGTH));
1019 }
1020
1021 (void)ap_is_valid_checksum(mapped_table);
1022
1023 *table = mapped_table;
1024 return (AE_OK);
1025}
1026
1027/******************************************************************************
1028 *
1029 * FUNCTION: osl_unmap_table
1030 *
1031 * PARAMETERS: table - A pointer to the mapped table
1032 *
1033 * RETURN: None
1034 *
1035 * DESCRIPTION: Unmap entire ACPI table.
1036 *
1037 *****************************************************************************/
1038
1039static void osl_unmap_table(struct acpi_table_header *table)
1040{
1041 if (table) {
1042 acpi_os_unmap_memory(table, ap_get_table_length(table));
1043 }
1044}
1045
1046/******************************************************************************
1047 *
1048 * FUNCTION: osl_table_name_from_file
1049 *
1050 * PARAMETERS: filename - File that contains the desired table
1051 * signature - Pointer to 4-character buffer to store
1052 * extracted table signature.
1053 * instance - Pointer to integer to store extracted
1054 * table instance number.
1055 *
1056 * RETURN: Status; Table name is extracted if AE_OK.
1057 *
1058 * DESCRIPTION: Extract table signature and instance number from a table file
1059 * name.
1060 *
1061 *****************************************************************************/
1062
1063static acpi_status
1064osl_table_name_from_file(char *filename, char *signature, u32 *instance)
1065{
1066
1067 /* Ignore meaningless files */
1068
1069 if (strlen(filename) < ACPI_NAME_SIZE) {
1070 return (AE_BAD_SIGNATURE);
1071 }
1072
1073 /* Extract instance number */
1074
1075 if (isdigit((int)filename[ACPI_NAME_SIZE])) {
1076 sscanf(&filename[ACPI_NAME_SIZE], "%d", instance);
1077 } else if (strlen(filename) != ACPI_NAME_SIZE) {
1078 return (AE_BAD_SIGNATURE);
1079 } else {
1080 *instance = 0;
1081 }
1082
1083 /* Extract signature */
1084
1085 ACPI_MOVE_NAME(signature, filename);
1086 return (AE_OK);
1087}
1088
1089/******************************************************************************
1090 *
1091 * FUNCTION: osl_read_table_from_file
1092 *
1093 * PARAMETERS: filename - File that contains the desired table
1094 * file_offset - Offset of the table in file
1095 * signature - Optional ACPI Signature for desired table.
1096 * A null terminated 4-character string.
1097 * table - Where a pointer to the table is returned
1098 *
1099 * RETURN: Status; Table buffer is returned if AE_OK.
1100 *
1101 * DESCRIPTION: Read a ACPI table from a file.
1102 *
1103 *****************************************************************************/
1104
1105static acpi_status
1106osl_read_table_from_file(char *filename,
1107 acpi_size file_offset,
1108 char *signature, struct acpi_table_header **table)
1109{
1110 FILE *table_file;
1111 struct acpi_table_header header;
1112 struct acpi_table_header *local_table = NULL;
1113 u32 table_length;
1114 s32 count;
1115 u32 total = 0;
1116 acpi_status status = AE_OK;
1117
1118 /* Open the file */
1119
1120 table_file = fopen(filename, "rb");
1121 if (table_file == NULL) {
1122 fprintf(stderr, "Could not open table file: %s\n", filename);
1123 return (osl_get_last_status(AE_NOT_FOUND));
1124 }
1125
1126 fseek(table_file, file_offset, SEEK_SET);
1127
1128 /* Read the Table header to get the table length */
1129
1130 count = fread(&header, 1, sizeof(struct acpi_table_header), table_file);
1131 if (count != sizeof(struct acpi_table_header)) {
1132 fprintf(stderr, "Could not read table header: %s\n", filename);
1133 status = AE_BAD_HEADER;
1134 goto exit;
1135 }
1136
1137 /* If signature is specified, it must match the table */
1138
1139 if (signature && !ACPI_COMPARE_NAME(signature, header.signature)) {
1140 fprintf(stderr,
1141 "Incorrect signature: Expecting %4.4s, found %4.4s\n",
1142 signature, header.signature);
1143 status = AE_BAD_SIGNATURE;
1144 goto exit;
1145 }
1146
1147 table_length = ap_get_table_length(&header);
1148 if (table_length == 0) {
1149 status = AE_BAD_HEADER;
1150 goto exit;
1151 }
1152
1153 /* Read the entire table into a local buffer */
1154
1155 local_table = calloc(1, table_length);
1156 if (!local_table) {
1157 fprintf(stderr,
1158 "%4.4s: Could not allocate buffer for table of length %X\n",
1159 header.signature, table_length);
1160 status = AE_NO_MEMORY;
1161 goto exit;
1162 }
1163
1164 fseek(table_file, file_offset, SEEK_SET);
1165
1166 while (!feof(table_file) && total < table_length) {
1167 count = fread(local_table + total, 1, table_length - total, table_file);
1168 if (count < 0) {
1169 fprintf(stderr, "%4.4s: Could not read table content\n",
1170 header.signature);
1171 status = AE_INVALID_TABLE_LENGTH;
1172 goto exit;
1173 }
1174
1175 total += count;
1176 }
1177
1178 /* Validate checksum */
1179
1180 (void)ap_is_valid_checksum(local_table);
1181
1182exit:
1183 fclose(table_file);
1184 *table = local_table;
1185 return (status);
1186}
1187
1188/******************************************************************************
1189 *
1190 * FUNCTION: osl_get_customized_table
1191 *
1192 * PARAMETERS: pathname - Directory to find Linux customized table
1193 * signature - ACPI Signature for desired table. Must be
1194 * a null terminated 4-character string.
1195 * instance - Multiple table support for SSDT/UEFI (0...n)
1196 * Must be 0 for other tables.
1197 * table - Where a pointer to the table is returned
1198 * address - Where the table physical address is returned
1199 *
1200 * RETURN: Status; Table buffer is returned if AE_OK.
1201 * AE_LIMIT: Instance is beyond valid limit
1202 * AE_NOT_FOUND: A table with the signature was not found
1203 *
1204 * DESCRIPTION: Get an OS customized table.
1205 *
1206 *****************************************************************************/
1207
1208static acpi_status
1209osl_get_customized_table(char *pathname,
1210 char *signature,
1211 u32 instance,
1212 struct acpi_table_header **table,
1213 acpi_physical_address * address)
1214{
1215 void *table_dir;
1216 u32 current_instance = 0;
1217 char temp_name[ACPI_NAME_SIZE];
1218 char table_filename[PATH_MAX];
1219 char *filename;
1220 acpi_status status;
1221
1222 /* Open the directory for customized tables */
1223
1224 table_dir = acpi_os_open_directory(pathname, "*", REQUEST_FILE_ONLY);
1225 if (!table_dir) {
1226 return (osl_get_last_status(AE_NOT_FOUND));
1227 }
1228
1229 /* Attempt to find the table in the directory */
1230
1231 while ((filename = acpi_os_get_next_filename(table_dir))) {
1232
1233 /* Ignore meaningless files */
1234
1235 if (!ACPI_COMPARE_NAME(filename, signature)) {
1236 continue;
1237 }
1238
1239 /* Extract table name and instance number */
1240
1241 status =
1242 osl_table_name_from_file(filename, temp_name,
1243 &current_instance);
1244
1245 /* Ignore meaningless files */
1246
1247 if (ACPI_FAILURE(status) || current_instance != instance) {
1248 continue;
1249 }
1250
1251 /* Create the table pathname */
1252
1253 if (instance != 0) {
1254 sprintf(table_filename, "%s/%4.4s%d", pathname,
1255 temp_name, instance);
1256 } else {
1257 sprintf(table_filename, "%s/%4.4s", pathname,
1258 temp_name);
1259 }
1260 break;
1261 }
1262
1263 acpi_os_close_directory(table_dir);
1264
1265 if (!filename) {
1266 return (AE_LIMIT);
1267 }
1268
1269 /* There is no physical address saved for customized tables, use zero */
1270
1271 *address = 0;
1272 status = osl_read_table_from_file(table_filename, 0, NULL, table);
1273
1274 return (status);
1275}
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 */
57typedef 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
80void *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
124char *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
196void 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
52ACPI_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 ******************************************************************************/
74static 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
97void *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
143void 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
48typedef int s32;
49typedef unsigned char u8;
50typedef unsigned short u16;
51typedef unsigned int u32;
52typedef unsigned long long u64;
53typedef 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
72static 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
80static unsigned long psz, addr, length;
81static int print, connect, skip;
82static u8 select_sig[4];
83
84static 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
99static 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
116static 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
122static 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
133static void acpi_unmap_table(struct acpi_table_header *tbl)
134{
135 acpi_unmap_memory((u8 *)tbl, tbl->length);
136}
137
138static 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 */
161static 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 */
189static 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
199static 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
222static 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);
252no_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);
272no_facs:
273 write_table(fd, (struct acpi_table_header *)&x, xaddr);
274}
275
276static 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
336static 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
395static 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
411static 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};
421int 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;
553not_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..3361b9e04d9c
--- /dev/null
+++ b/tools/power/acpi/tools/acpidump/acpidump.h
@@ -0,0 +1,131 @@
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#include <acpi/acpi.h>
45#include "accommon.h"
46#include "actables.h"
47
48#include <stdio.h>
49#include <fcntl.h>
50#include <errno.h>
51#include <sys/stat.h>
52
53/*
54 * Global variables. Defined in main.c only, externed in all other files
55 */
56#ifdef _DECLARE_GLOBALS
57#define EXTERN
58#define INIT_GLOBAL(a,b) a=b
59#else
60#define EXTERN extern
61#define INIT_GLOBAL(a,b) a
62#endif
63
64/* Globals */
65
66EXTERN u8 INIT_GLOBAL(gbl_summary_mode, FALSE);
67EXTERN u8 INIT_GLOBAL(gbl_verbose_mode, FALSE);
68EXTERN u8 INIT_GLOBAL(gbl_binary_mode, FALSE);
69EXTERN u8 INIT_GLOBAL(gbl_dump_customized_tables, FALSE);
70EXTERN FILE INIT_GLOBAL(*gbl_output_file, NULL);
71EXTERN char INIT_GLOBAL(*gbl_output_filename, NULL);
72EXTERN u64 INIT_GLOBAL(gbl_rsdp_base, 0);
73
74/* Globals required for use with ACPICA modules */
75
76#ifdef _DECLARE_GLOBALS
77u8 acpi_gbl_enable_interpreter_slack = FALSE;
78u8 acpi_gbl_integer_byte_width = 8;
79u32 acpi_dbg_level = 0;
80u32 acpi_dbg_layer = 0;
81#endif
82
83/* Action table used to defer requested options */
84
85struct ap_dump_action {
86 char *argument;
87 u32 to_be_done;
88};
89
90#define AP_MAX_ACTIONS 32
91
92#define AP_DUMP_ALL_TABLES 0
93#define AP_DUMP_TABLE_BY_ADDRESS 1
94#define AP_DUMP_TABLE_BY_NAME 2
95#define AP_DUMP_TABLE_BY_FILE 3
96
97#define AP_MAX_ACPI_FILES 256 /* Prevent infinite loops */
98
99/* Minimum FADT sizes for various table addresses */
100
101#define MIN_FADT_FOR_DSDT (ACPI_FADT_OFFSET (dsdt) + sizeof (u32))
102#define MIN_FADT_FOR_FACS (ACPI_FADT_OFFSET (facs) + sizeof (u32))
103#define MIN_FADT_FOR_XDSDT (ACPI_FADT_OFFSET (Xdsdt) + sizeof (u64))
104#define MIN_FADT_FOR_XFACS (ACPI_FADT_OFFSET (Xfacs) + sizeof (u64))
105
106/*
107 * apdump - Table get/dump routines
108 */
109int ap_dump_table_from_file(char *pathname);
110
111int ap_dump_table_by_name(char *signature);
112
113int ap_dump_table_by_address(char *ascii_address);
114
115int ap_dump_all_tables(void);
116
117u8 ap_is_valid_header(struct acpi_table_header *table);
118
119u8 ap_is_valid_checksum(struct acpi_table_header *table);
120
121u32 ap_get_table_length(struct acpi_table_header *table);
122
123/*
124 * apfiles - File I/O utilities
125 */
126int ap_open_output_file(char *pathname);
127
128int ap_write_to_binary_file(struct acpi_table_header *table, u32 instance);
129
130struct acpi_table_header *ap_get_table_from_file(char *pathname,
131 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
48static int
49ap_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
64u8 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
102u8 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
138u32 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
173static int
174ap_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
221int 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
279int 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
323int 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
396int 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
426exit:
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
439void 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
448void 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
60int 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
105int 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
178struct 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
225cleanup:
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..70d71ec687a5
--- /dev/null
+++ b/tools/power/acpi/tools/acpidump/apmain.c
@@ -0,0 +1,340 @@
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
71static void ap_display_usage(void);
72
73static int ap_do_options(int argc, char **argv);
74
75static void ap_insert_action(char *argument, u32 to_be_done);
76
77/* Table for deferred actions from command line options */
78
79struct ap_dump_action action_table[AP_MAX_ACTIONS];
80u32 current_action = 0;
81
82#define AP_UTILITY_NAME "ACPI Binary Table Dump Utility"
83#define AP_SUPPORTED_OPTIONS "?a:bcf:hn:o:r:svz"
84
85/******************************************************************************
86 *
87 * FUNCTION: ap_display_usage
88 *
89 * DESCRIPTION: Usage message for the acpi_dump utility
90 *
91 ******************************************************************************/
92
93static 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
113 printf("\n"
114 "Invocation without parameters dumps all available tables\n"
115 "Multiple mixed instances of -a, -f, and -n are supported\n\n");
116}
117
118/******************************************************************************
119 *
120 * FUNCTION: ap_insert_action
121 *
122 * PARAMETERS: argument - Pointer to the argument for this action
123 * to_be_done - What to do to process this action
124 *
125 * RETURN: None. Exits program if action table becomes full.
126 *
127 * DESCRIPTION: Add an action item to the action table
128 *
129 ******************************************************************************/
130
131static void ap_insert_action(char *argument, u32 to_be_done)
132{
133
134 /* Insert action and check for table overflow */
135
136 action_table[current_action].argument = argument;
137 action_table[current_action].to_be_done = to_be_done;
138
139 current_action++;
140 if (current_action > AP_MAX_ACTIONS) {
141 fprintf(stderr, "Too many table options (max %u)\n",
142 AP_MAX_ACTIONS);
143 exit(-1);
144 }
145}
146
147/******************************************************************************
148 *
149 * FUNCTION: ap_do_options
150 *
151 * PARAMETERS: argc/argv - Standard argc/argv
152 *
153 * RETURN: Status
154 *
155 * DESCRIPTION: Command line option processing. The main actions for getting
156 * and dumping tables are deferred via the action table.
157 *
158 *****************************************************************************/
159
160static int ap_do_options(int argc, char **argv)
161{
162 int j;
163 acpi_status status;
164
165 /* Command line options */
166
167 while ((j = acpi_getopt(argc, argv, AP_SUPPORTED_OPTIONS)) != EOF)
168 switch (j) {
169 /*
170 * Global options
171 */
172 case 'b': /* Dump all input tables to binary files */
173
174 gbl_binary_mode = TRUE;
175 continue;
176
177 case 'c': /* Dump customized tables */
178
179 gbl_dump_customized_tables = TRUE;
180 continue;
181
182 case 'h':
183 case '?':
184
185 ap_display_usage();
186 exit(0);
187
188 case 'o': /* Redirect output to a single file */
189
190 if (ap_open_output_file(acpi_gbl_optarg)) {
191 exit(-1);
192 }
193 continue;
194
195 case 'r': /* Dump tables from specified RSDP */
196
197 status =
198 acpi_ut_strtoul64(acpi_gbl_optarg, 0,
199 &gbl_rsdp_base);
200 if (ACPI_FAILURE(status)) {
201 fprintf(stderr,
202 "%s: Could not convert to a physical address\n",
203 acpi_gbl_optarg);
204 exit(-1);
205 }
206 continue;
207
208 case 's': /* Print table summaries only */
209
210 gbl_summary_mode = TRUE;
211 continue;
212
213 case 'v': /* Revision/version */
214
215 printf(ACPI_COMMON_SIGNON(AP_UTILITY_NAME));
216 exit(0);
217
218 case 'z': /* Verbose mode */
219
220 gbl_verbose_mode = TRUE;
221 fprintf(stderr, ACPI_COMMON_SIGNON(AP_UTILITY_NAME));
222 continue;
223
224 /*
225 * Table options
226 */
227 case 'a': /* Get table by physical address */
228
229 ap_insert_action(acpi_gbl_optarg,
230 AP_DUMP_TABLE_BY_ADDRESS);
231 break;
232
233 case 'f': /* Get table from a file */
234
235 ap_insert_action(acpi_gbl_optarg,
236 AP_DUMP_TABLE_BY_FILE);
237 break;
238
239 case 'n': /* Get table by input name (signature) */
240
241 ap_insert_action(acpi_gbl_optarg,
242 AP_DUMP_TABLE_BY_NAME);
243 break;
244
245 default:
246
247 ap_display_usage();
248 exit(-1);
249 }
250
251 /* If there are no actions, this means "get/dump all tables" */
252
253 if (current_action == 0) {
254 ap_insert_action(NULL, AP_DUMP_ALL_TABLES);
255 }
256
257 return (0);
258}
259
260/******************************************************************************
261 *
262 * FUNCTION: main
263 *
264 * PARAMETERS: argc/argv - Standard argc/argv
265 *
266 * RETURN: Status
267 *
268 * DESCRIPTION: C main function for acpidump utility
269 *
270 ******************************************************************************/
271
272int ACPI_SYSTEM_XFACE main(int argc, char *argv[])
273{
274 int status = 0;
275 struct ap_dump_action *action;
276 u32 file_size;
277 u32 i;
278
279 ACPI_DEBUG_INITIALIZE(); /* For debug version only */
280
281 /* Process command line options */
282
283 if (ap_do_options(argc, argv)) {
284 return (-1);
285 }
286
287 /* Get/dump ACPI table(s) as requested */
288
289 for (i = 0; i < current_action; i++) {
290 action = &action_table[i];
291 switch (action->to_be_done) {
292 case AP_DUMP_ALL_TABLES:
293
294 status = ap_dump_all_tables();
295 break;
296
297 case AP_DUMP_TABLE_BY_ADDRESS:
298
299 status = ap_dump_table_by_address(action->argument);
300 break;
301
302 case AP_DUMP_TABLE_BY_NAME:
303
304 status = ap_dump_table_by_name(action->argument);
305 break;
306
307 case AP_DUMP_TABLE_BY_FILE:
308
309 status = ap_dump_table_from_file(action->argument);
310 break;
311
312 default:
313
314 fprintf(stderr,
315 "Internal error, invalid action: 0x%X\n",
316 action->to_be_done);
317 return (-1);
318 }
319
320 if (status) {
321 return (status);
322 }
323 }
324
325 if (gbl_output_file) {
326 if (gbl_verbose_mode) {
327
328 /* Summary for the output file */
329
330 file_size = cm_get_file_size(gbl_output_file);
331 fprintf(stderr,
332 "Output file %s contains 0x%X (%u) bytes\n\n",
333 gbl_output_filename, file_size, file_size);
334 }
335
336 fclose(gbl_output_file);
337 }
338
339 return (status);
340}