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 49static int 50ApIsExistingFile ( 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 66static int 67ApIsExistingFile ( 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 109int 110ApOpenOutputFile ( 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 154int 155ApWriteToBinaryFile ( 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 239ACPI_TABLE_HEADER * 240ApGetTableFromFile ( 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 292Cleanup: 293 fclose (File); 294 return (Buffer); 295} 296