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