apfiles.c revision 1.6
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
50static int
51ApIsExistingFile (
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
67static int
68ApIsExistingFile (
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
103int
104ApOpenOutputFile (
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
148int
149ApWriteToBinaryFile (
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
234ACPI_TABLE_HEADER *
235ApGetTableFromFile (
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
288Cleanup:
289    AcpiOsCloseFile (File);
290    return (Buffer);
291}
292