diff options
-rw-r--r-- | src/interface/linux/linux_acpi.c | 99 |
1 files changed, 21 insertions, 78 deletions
diff --git a/src/interface/linux/linux_acpi.c b/src/interface/linux/linux_acpi.c index 08833d6..851cc54 100644 --- a/src/interface/linux/linux_acpi.c +++ b/src/interface/linux/linux_acpi.c @@ -23,9 +23,11 @@ FILE_LICENCE ( GPL2_OR_LATER ); #include <stdio.h> #include <errno.h> #include <ipxe/linux_api.h> +#include <ipxe/linux_sysfs.h> #include <ipxe/linux.h> #include <ipxe/list.h> #include <ipxe/init.h> +#include <ipxe/umalloc.h> #include <ipxe/acpi.h> /** ACPI sysfs directory */ @@ -40,7 +42,7 @@ struct linux_acpi_table { /** Index */ unsigned int index; /** Cached data */ - void *data; + userptr_t data; }; /** List of cached ACPI tables */ @@ -55,7 +57,6 @@ static LIST_HEAD ( linux_acpi_tables ); */ static userptr_t linux_acpi_find ( uint32_t signature, unsigned int index ) { struct linux_acpi_table *table; - struct acpi_header header; union { uint32_t signature; char filename[5]; @@ -63,16 +64,14 @@ static userptr_t linux_acpi_find ( uint32_t signature, unsigned int index ) { static const char prefix[] = ACPI_SYSFS_PREFIX; char filename[ sizeof ( prefix ) - 1 /* NUL */ + 4 /* signature */ + 3 /* "999" */ + 1 /* NUL */ ]; - ssize_t rlen; - size_t len; - void *data; - int fd; + int len; + int rc; /* Check for existing table */ list_for_each_entry ( table, &linux_acpi_tables, list ) { if ( ( table->signature == signature ) && ( table->index == index ) ) - return virt_to_user ( table->data ); + return table->data; } /* Allocate a new table */ @@ -82,90 +81,34 @@ static userptr_t linux_acpi_find ( uint32_t signature, unsigned int index ) { table->signature = signature; table->index = index; - /* Construct filename */ + /* Construct filename (including numeric suffix) */ memset ( &u, 0, sizeof ( u ) ); u.signature = le32_to_cpu ( signature ); snprintf ( filename, sizeof ( filename ), "%s%s%d", prefix, u.filename, ( index + 1 ) ); - /* Open file */ - fd = linux_open ( filename, O_RDONLY ); - if ( ( fd < 0 ) && ( index == 0 ) ) { + /* Read file (with or without numeric suffix for index 0) */ + len = linux_sysfs_read ( filename, &table->data ); + if ( ( len < 0 ) && ( index == 0 ) ) { filename[ sizeof ( prefix ) - 1 /* NUL */ + 4 /* signature */ ] = '\0'; - fd = linux_open ( filename, O_RDONLY ); + len = linux_sysfs_read ( filename, &table->data ); } - if ( fd < 0 ) { - DBGC ( &linux_acpi_tables, "ACPI could not open %s: %s\n", - filename, linux_strerror ( linux_errno ) ); - goto err_open; + if ( len < 0 ) { + rc = len; + DBGC ( &linux_acpi_tables, "ACPI could not read %s: %s\n", + filename, strerror ( rc ) ); + goto err_read; } - /* Read header */ - rlen = linux_read ( fd, &header, sizeof ( header ) ); - if ( rlen < 0 ) { - DBGC ( &linux_acpi_tables, "ACPI could not read %s header: " - "%s\n", filename, linux_strerror ( linux_errno ) ); - goto err_header; - } - if ( ( ( size_t ) rlen ) != sizeof ( header ) ) { - DBGC ( &linux_acpi_tables, "ACPI underlength %s header\n", - filename ); - goto err_header_len; - } - - /* Parse header */ - len = le32_to_cpu ( header.length ); - if ( len < sizeof ( header ) ) { - DBGC ( &linux_acpi_tables, "ACPI malformed %s header\n", - filename ); - goto err_malformed; - } - - /* Allocate data */ - table->data = malloc ( len ); - if ( ! table->data ) - goto err_data; - - /* Read table */ - memcpy ( table->data, &header, sizeof ( header ) ); - data = ( table->data + sizeof ( header ) ); - len -= sizeof ( header ); - while ( len ) { - rlen = linux_read ( fd, data, len ); - if ( rlen < 0 ) { - DBGC ( &linux_acpi_tables, "ACPI could not read %s: " - "%s\n", filename, - linux_strerror ( linux_errno ) ); - goto err_body; - } - if ( rlen == 0 ) { - DBGC ( &linux_acpi_tables, "ACPI underlength %s\n", - filename ); - goto err_body_len; - } - data += rlen; - len -= rlen; - } - - /* Close file */ - linux_close ( fd ); - /* Add to list of tables */ list_add ( &table->list, &linux_acpi_tables ); DBGC ( &linux_acpi_tables, "ACPI cached %s\n", filename ); - return virt_to_user ( table->data ); - - err_body_len: - err_body: - free ( table->data ); - err_data: - err_malformed: - err_header_len: - err_header: - linux_close ( fd ); - err_open: + return table->data; + + ufree ( table->data ); + err_read: free ( table ); err_alloc: return UNULL; @@ -181,7 +124,7 @@ static void linux_acpi_shutdown ( int booting __unused ) { list_for_each_entry_safe ( table, tmp, &linux_acpi_tables, list ) { list_del ( &table->list ); - free ( table->data ); + ufree ( table->data ); free ( table ); } } |