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