]> git.ipfire.org Git - thirdparty/ipxe.git/commitdiff
[linux] Use generic sysfs mechanism to read ACPI tables
authorMichael Brown <mcb30@ipxe.org>
Tue, 2 Mar 2021 23:42:36 +0000 (23:42 +0000)
committerMichael Brown <mcb30@ipxe.org>
Tue, 2 Mar 2021 23:59:46 +0000 (23:59 +0000)
Signed-off-by: Michael Brown <mcb30@ipxe.org>
src/interface/linux/linux_acpi.c

index 08833d61d373498da06f45f48370d309e026321a..851cc54e6540d21a87b0d64a061242f859fe7ec4 100644 (file)
@@ -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 );
        }
 }