Merge tag 'acpi-5.1-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/rafael...
[sfrench/cifs-2.6.git] / tools / power / acpi / tools / acpidump / apfiles.c
1 // SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0
2 /******************************************************************************
3  *
4  * Module Name: apfiles - File-related functions for acpidump utility
5  *
6  * Copyright (C) 2000 - 2019, Intel Corp.
7  *
8  *****************************************************************************/
9
10 #include "acpidump.h"
11
12 /* Local prototypes */
13
14 static int ap_is_existing_file(char *pathname);
15
16 /******************************************************************************
17  *
18  * FUNCTION:    ap_is_existing_file
19  *
20  * PARAMETERS:  pathname            - Output filename
21  *
22  * RETURN:      0 on success
23  *
24  * DESCRIPTION: Query for file overwrite if it already exists.
25  *
26  ******************************************************************************/
27
28 static int ap_is_existing_file(char *pathname)
29 {
30 #if !defined(_GNU_EFI) && !defined(_EDK2_EFI)
31         struct stat stat_info;
32
33         if (!stat(pathname, &stat_info)) {
34                 fprintf(stderr,
35                         "Target path already exists, overwrite? [y|n] ");
36
37                 if (getchar() != 'y') {
38                         return (-1);
39                 }
40         }
41 #endif
42
43         return 0;
44 }
45
46 /******************************************************************************
47  *
48  * FUNCTION:    ap_open_output_file
49  *
50  * PARAMETERS:  pathname            - Output filename
51  *
52  * RETURN:      Open file handle
53  *
54  * DESCRIPTION: Open a text output file for acpidump. Checks if file already
55  *              exists.
56  *
57  ******************************************************************************/
58
59 int ap_open_output_file(char *pathname)
60 {
61         ACPI_FILE file;
62
63         /* If file exists, prompt for overwrite */
64
65         if (ap_is_existing_file(pathname) != 0) {
66                 return (-1);
67         }
68
69         /* Point stdout to the file */
70
71         file = fopen(pathname, "w");
72         if (!file) {
73                 fprintf(stderr, "Could not open output file: %s\n", pathname);
74                 return (-1);
75         }
76
77         /* Save the file and path */
78
79         gbl_output_file = file;
80         gbl_output_filename = pathname;
81         return (0);
82 }
83
84 /******************************************************************************
85  *
86  * FUNCTION:    ap_write_to_binary_file
87  *
88  * PARAMETERS:  table               - ACPI table to be written
89  *              instance            - ACPI table instance no. to be written
90  *
91  * RETURN:      Status
92  *
93  * DESCRIPTION: Write an ACPI table to a binary file. Builds the output
94  *              filename from the table signature.
95  *
96  ******************************************************************************/
97
98 int ap_write_to_binary_file(struct acpi_table_header *table, u32 instance)
99 {
100         char filename[ACPI_NAME_SIZE + 16];
101         char instance_str[16];
102         ACPI_FILE file;
103         acpi_size actual;
104         u32 table_length;
105
106         /* Obtain table length */
107
108         table_length = ap_get_table_length(table);
109
110         /* Construct lower-case filename from the table local signature */
111
112         if (ACPI_VALIDATE_RSDP_SIG(table->signature)) {
113                 ACPI_MOVE_NAME(filename, ACPI_RSDP_NAME);
114         } else {
115                 ACPI_MOVE_NAME(filename, table->signature);
116         }
117
118         filename[0] = (char)tolower((int)filename[0]);
119         filename[1] = (char)tolower((int)filename[1]);
120         filename[2] = (char)tolower((int)filename[2]);
121         filename[3] = (char)tolower((int)filename[3]);
122         filename[ACPI_NAME_SIZE] = 0;
123
124         /* Handle multiple SSDts - create different filenames for each */
125
126         if (instance > 0) {
127                 snprintf(instance_str, sizeof(instance_str), "%u", instance);
128                 strcat(filename, instance_str);
129         }
130
131         strcat(filename, FILE_SUFFIX_BINARY_TABLE);
132
133         if (gbl_verbose_mode) {
134                 fprintf(stderr,
135                         "Writing [%4.4s] to binary file: %s 0x%X (%u) bytes\n",
136                         table->signature, filename, table->length,
137                         table->length);
138         }
139
140         /* Open the file and dump the entire table in binary mode */
141
142         file = fopen(filename, "wb");
143         if (!file) {
144                 fprintf(stderr, "Could not open output file: %s\n", filename);
145                 return (-1);
146         }
147
148         actual = fwrite(table, 1, table_length, file);
149         if (actual != table_length) {
150                 fprintf(stderr, "Error writing binary output file: %s\n",
151                         filename);
152                 fclose(file);
153                 return (-1);
154         }
155
156         fclose(file);
157         return (0);
158 }
159
160 /******************************************************************************
161  *
162  * FUNCTION:    ap_get_table_from_file
163  *
164  * PARAMETERS:  pathname            - File containing the binary ACPI table
165  *              out_file_size       - Where the file size is returned
166  *
167  * RETURN:      Buffer containing the ACPI table. NULL on error.
168  *
169  * DESCRIPTION: Open a file and read it entirely into a new buffer
170  *
171  ******************************************************************************/
172
173 struct acpi_table_header *ap_get_table_from_file(char *pathname,
174                                                  u32 *out_file_size)
175 {
176         struct acpi_table_header *buffer = NULL;
177         ACPI_FILE file;
178         u32 file_size;
179         acpi_size actual;
180
181         /* Must use binary mode */
182
183         file = fopen(pathname, "rb");
184         if (!file) {
185                 fprintf(stderr, "Could not open input file: %s\n", pathname);
186                 return (NULL);
187         }
188
189         /* Need file size to allocate a buffer */
190
191         file_size = cm_get_file_size(file);
192         if (file_size == ACPI_UINT32_MAX) {
193                 fprintf(stderr,
194                         "Could not get input file size: %s\n", pathname);
195                 goto cleanup;
196         }
197
198         /* Allocate a buffer for the entire file */
199
200         buffer = ACPI_ALLOCATE_ZEROED(file_size);
201         if (!buffer) {
202                 fprintf(stderr,
203                         "Could not allocate file buffer of size: %u\n",
204                         file_size);
205                 goto cleanup;
206         }
207
208         /* Read the entire file */
209
210         actual = fread(buffer, 1, file_size, file);
211         if (actual != file_size) {
212                 fprintf(stderr, "Could not read input file: %s\n", pathname);
213                 ACPI_FREE(buffer);
214                 buffer = NULL;
215                 goto cleanup;
216         }
217
218         *out_file_size = file_size;
219
220 cleanup:
221         fclose(file);
222         return (buffer);
223 }