1 /******************************************************************************
2 *
3 * Module Name: apfiles - File-related functions for acpidump utility
4 *
5 *****************************************************************************/
6
7 /*
8 * Copyright (C) 2000 - 2023, 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 MERCHANTABILITY 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
47 /* Local prototypes */
48
49 static int
50 ApIsExistingFile (
51 char *Pathname);
52
53
54 /******************************************************************************
55 *
56 * FUNCTION: ApIsExistingFile
57 *
58 * PARAMETERS: Pathname - Output filename
59 *
60 * RETURN: 0 on success
61 *
62 * DESCRIPTION: Query for file overwrite if it already exists.
63 *
64 ******************************************************************************/
65
66 static int
ApIsExistingFile(char * Pathname)67 ApIsExistingFile (
68 char *Pathname)
69 {
70 #if !defined(_GNU_EFI) && !defined(_EDK2_EFI)
71 struct stat StatInfo;
72 int InChar;
73
74
75 if (!stat (Pathname, &StatInfo))
76 {
77 fprintf (stderr, "Target path already exists, overwrite? [y|n] ");
78
79 InChar = fgetc (stdin);
80 if (InChar == '\n')
81 {
82 InChar = fgetc (stdin);
83 }
84
85 if (InChar != 'y' && InChar != 'Y')
86 {
87 return (-1);
88 }
89 }
90 #endif
91
92 return (0);
93 }
94
95
96 /******************************************************************************
97 *
98 * FUNCTION: ApOpenOutputFile
99 *
100 * PARAMETERS: Pathname - Output filename
101 *
102 * RETURN: Open file handle
103 *
104 * DESCRIPTION: Open a text output file for acpidump. Checks if file already
105 * exists.
106 *
107 ******************************************************************************/
108
109 int
ApOpenOutputFile(char * Pathname)110 ApOpenOutputFile (
111 char *Pathname)
112 {
113 ACPI_FILE File;
114
115
116 /* If file exists, prompt for overwrite */
117
118 if (ApIsExistingFile (Pathname) != 0)
119 {
120 return (-1);
121 }
122
123 /* Point stdout to the file */
124
125 File = fopen (Pathname, "w");
126 if (!File)
127 {
128 fprintf (stderr, "Could not open output file: %s\n", Pathname);
129 return (-1);
130 }
131
132 /* Save the file and path */
133
134 Gbl_OutputFile = File;
135 Gbl_OutputFilename = Pathname;
136 return (0);
137 }
138
139
140 /******************************************************************************
141 *
142 * FUNCTION: ApWriteToBinaryFile
143 *
144 * PARAMETERS: Table - ACPI table to be written
145 * Instance - ACPI table instance no. to be written
146 *
147 * RETURN: Status
148 *
149 * DESCRIPTION: Write an ACPI table to a binary file. Builds the output
150 * filename from the table signature.
151 *
152 ******************************************************************************/
153
154 int
ApWriteToBinaryFile(ACPI_TABLE_HEADER * Table,UINT32 Instance)155 ApWriteToBinaryFile (
156 ACPI_TABLE_HEADER *Table,
157 UINT32 Instance)
158 {
159 char Filename[ACPI_NAMESEG_SIZE + 16];
160 char InstanceStr [16];
161 ACPI_FILE File;
162 ACPI_SIZE Actual;
163 UINT32 TableLength;
164
165
166 /* Obtain table length */
167
168 TableLength = ApGetTableLength (Table);
169
170 /* Construct lower-case filename from the table local signature */
171
172 if (ACPI_VALIDATE_RSDP_SIG (Table->Signature))
173 {
174 ACPI_COPY_NAMESEG (Filename, ACPI_RSDP_NAME);
175 }
176 else
177 {
178 ACPI_COPY_NAMESEG (Filename, Table->Signature);
179 }
180
181 Filename[0] = (char) tolower ((int) Filename[0]);
182 Filename[1] = (char) tolower ((int) Filename[1]);
183 Filename[2] = (char) tolower ((int) Filename[2]);
184 Filename[3] = (char) tolower ((int) Filename[3]);
185 Filename[ACPI_NAMESEG_SIZE] = 0;
186
187 /* Handle multiple SSDTs - create different filenames for each */
188
189 if (Instance > 0)
190 {
191 snprintf (InstanceStr, sizeof (InstanceStr), "%u", Instance);
192 strcat (Filename, InstanceStr);
193 }
194
195 strcat (Filename, FILE_SUFFIX_BINARY_TABLE);
196
197 if (Gbl_VerboseMode)
198 {
199 fprintf (stderr,
200 "Writing [%4.4s] to binary file: %s 0x%X (%u) bytes\n",
201 Table->Signature, Filename, Table->Length, Table->Length);
202 }
203
204 /* Open the file and dump the entire table in binary mode */
205
206 File = fopen (Filename, "wb");
207 if (!File)
208 {
209 fprintf (stderr, "Could not open output file: %s\n", Filename);
210 return (-1);
211 }
212
213 Actual = fwrite (Table, 1, TableLength, File);
214 if (Actual != TableLength)
215 {
216 fprintf (stderr, "Error writing binary output file: %s\n", Filename);
217 fclose (File);
218 return (-1);
219 }
220
221 fclose (File);
222 return (0);
223 }
224
225
226 /******************************************************************************
227 *
228 * FUNCTION: ApGetTableFromFile
229 *
230 * PARAMETERS: Pathname - File containing the binary ACPI table
231 * OutFileSize - Where the file size is returned
232 *
233 * RETURN: Buffer containing the ACPI table. NULL on error.
234 *
235 * DESCRIPTION: Open a file and read it entirely into a new buffer
236 *
237 ******************************************************************************/
238
239 ACPI_TABLE_HEADER *
ApGetTableFromFile(char * Pathname,UINT32 * OutFileSize)240 ApGetTableFromFile (
241 char *Pathname,
242 UINT32 *OutFileSize)
243 {
244 ACPI_TABLE_HEADER *Buffer = NULL;
245 ACPI_FILE File;
246 UINT32 FileSize;
247 ACPI_SIZE Actual;
248
249
250 /* Must use binary mode */
251
252 File = fopen (Pathname, "rb");
253 if (!File)
254 {
255 fprintf (stderr, "Could not open input file: %s\n", Pathname);
256 return (NULL);
257 }
258
259 /* Need file size to allocate a buffer */
260
261 FileSize = CmGetFileSize (File);
262 if (FileSize == ACPI_UINT32_MAX)
263 {
264 fprintf (stderr,
265 "Could not get input file size: %s\n", Pathname);
266 goto Cleanup;
267 }
268
269 /* Allocate a buffer for the entire file */
270
271 Buffer = ACPI_ALLOCATE_ZEROED (FileSize);
272 if (!Buffer)
273 {
274 fprintf (stderr,
275 "Could not allocate file buffer of size: %u\n", FileSize);
276 goto Cleanup;
277 }
278
279 /* Read the entire file */
280
281 Actual = fread (Buffer, 1, FileSize, File);
282 if (Actual != FileSize)
283 {
284 fprintf (stderr, "Could not read input file: %s\n", Pathname);
285 ACPI_FREE (Buffer);
286 Buffer = NULL;
287 goto Cleanup;
288 }
289
290 *OutFileSize = FileSize;
291
292 Cleanup:
293 fclose (File);
294 return (Buffer);
295 }
296