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