diff options
Diffstat (limited to 'tools/power/acpi/tools/acpidump/apfiles.c')
-rw-r--r-- | tools/power/acpi/tools/acpidump/apfiles.c | 229 |
1 files changed, 229 insertions, 0 deletions
diff --git a/tools/power/acpi/tools/acpidump/apfiles.c b/tools/power/acpi/tools/acpidump/apfiles.c new file mode 100644 index 000000000..a682bae4e --- /dev/null +++ b/tools/power/acpi/tools/acpidump/apfiles.c @@ -0,0 +1,229 @@ +// SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0 +/****************************************************************************** + * + * Module Name: apfiles - File-related functions for acpidump utility + * + * Copyright (C) 2000 - 2020, Intel Corp. + * + *****************************************************************************/ + +#include "acpidump.h" + +/* Local prototypes */ + +static int ap_is_existing_file(char *pathname); + +/****************************************************************************** + * + * FUNCTION: ap_is_existing_file + * + * PARAMETERS: pathname - Output filename + * + * RETURN: 0 on success + * + * DESCRIPTION: Query for file overwrite if it already exists. + * + ******************************************************************************/ + +static int ap_is_existing_file(char *pathname) +{ +#if !defined(_GNU_EFI) && !defined(_EDK2_EFI) + struct stat stat_info; + int in_char; + + if (!stat(pathname, &stat_info)) { + fprintf(stderr, + "Target path already exists, overwrite? [y|n] "); + + in_char = fgetc(stdin); + if (in_char == '\n') { + in_char = fgetc(stdin); + } + + if (in_char != 'y' && in_char != 'Y') { + return (-1); + } + } +#endif + + return (0); +} + +/****************************************************************************** + * + * FUNCTION: ap_open_output_file + * + * PARAMETERS: pathname - Output filename + * + * RETURN: Open file handle + * + * DESCRIPTION: Open a text output file for acpidump. Checks if file already + * exists. + * + ******************************************************************************/ + +int ap_open_output_file(char *pathname) +{ + ACPI_FILE file; + + /* If file exists, prompt for overwrite */ + + if (ap_is_existing_file(pathname) != 0) { + return (-1); + } + + /* Point stdout to the file */ + + file = fopen(pathname, "w"); + if (!file) { + fprintf(stderr, "Could not open output file: %s\n", pathname); + return (-1); + } + + /* Save the file and path */ + + gbl_output_file = file; + gbl_output_filename = pathname; + return (0); +} + +/****************************************************************************** + * + * FUNCTION: ap_write_to_binary_file + * + * PARAMETERS: table - ACPI table to be written + * instance - ACPI table instance no. to be written + * + * RETURN: Status + * + * DESCRIPTION: Write an ACPI table to a binary file. Builds the output + * filename from the table signature. + * + ******************************************************************************/ + +int ap_write_to_binary_file(struct acpi_table_header *table, u32 instance) +{ + char filename[ACPI_NAMESEG_SIZE + 16]; + char instance_str[16]; + ACPI_FILE file; + acpi_size actual; + u32 table_length; + + /* Obtain table length */ + + table_length = ap_get_table_length(table); + + /* Construct lower-case filename from the table local signature */ + + if (ACPI_VALIDATE_RSDP_SIG(table->signature)) { + ACPI_COPY_NAMESEG(filename, ACPI_RSDP_NAME); + } else { + ACPI_COPY_NAMESEG(filename, table->signature); + } + + filename[0] = (char)tolower((int)filename[0]); + filename[1] = (char)tolower((int)filename[1]); + filename[2] = (char)tolower((int)filename[2]); + filename[3] = (char)tolower((int)filename[3]); + filename[ACPI_NAMESEG_SIZE] = 0; + + /* Handle multiple SSDts - create different filenames for each */ + + if (instance > 0) { + snprintf(instance_str, sizeof(instance_str), "%u", instance); + strcat(filename, instance_str); + } + + strcat(filename, FILE_SUFFIX_BINARY_TABLE); + + if (gbl_verbose_mode) { + fprintf(stderr, + "Writing [%4.4s] to binary file: %s 0x%X (%u) bytes\n", + table->signature, filename, table->length, + table->length); + } + + /* Open the file and dump the entire table in binary mode */ + + file = fopen(filename, "wb"); + if (!file) { + fprintf(stderr, "Could not open output file: %s\n", filename); + return (-1); + } + + actual = fwrite(table, 1, table_length, file); + if (actual != table_length) { + fprintf(stderr, "Error writing binary output file: %s\n", + filename); + fclose(file); + return (-1); + } + + fclose(file); + return (0); +} + +/****************************************************************************** + * + * FUNCTION: ap_get_table_from_file + * + * PARAMETERS: pathname - File containing the binary ACPI table + * out_file_size - Where the file size is returned + * + * RETURN: Buffer containing the ACPI table. NULL on error. + * + * DESCRIPTION: Open a file and read it entirely into a new buffer + * + ******************************************************************************/ + +struct acpi_table_header *ap_get_table_from_file(char *pathname, + u32 *out_file_size) +{ + struct acpi_table_header *buffer = NULL; + ACPI_FILE file; + u32 file_size; + acpi_size actual; + + /* Must use binary mode */ + + file = fopen(pathname, "rb"); + if (!file) { + fprintf(stderr, "Could not open input file: %s\n", pathname); + return (NULL); + } + + /* Need file size to allocate a buffer */ + + file_size = cm_get_file_size(file); + if (file_size == ACPI_UINT32_MAX) { + fprintf(stderr, + "Could not get input file size: %s\n", pathname); + goto cleanup; + } + + /* Allocate a buffer for the entire file */ + + buffer = ACPI_ALLOCATE_ZEROED(file_size); + if (!buffer) { + fprintf(stderr, + "Could not allocate file buffer of size: %u\n", + file_size); + goto cleanup; + } + + /* Read the entire file */ + + actual = fread(buffer, 1, file_size, file); + if (actual != file_size) { + fprintf(stderr, "Could not read input file: %s\n", pathname); + ACPI_FREE(buffer); + buffer = NULL; + goto cleanup; + } + + *out_file_size = file_size; + +cleanup: + fclose(file); + return (buffer); +} |