From 041d362423bb8414b0bd1baf93023bac14e52f14 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Laurent=20Gourv=C3=A9nec?= Date: Thu, 27 Jul 2017 16:04:35 +0200 Subject: [PATCH] [acpi] Compute and check checksum for ACPI tables Modified-by: Michael Brown Signed-off-by: Michael Brown --- src/core/acpi.c | 43 +++++++++++++++++++++++++++++++++++++------ 1 file changed, 37 insertions(+), 6 deletions(-) diff --git a/src/core/acpi.c b/src/core/acpi.c index ff8875e1..07679153 100644 --- a/src/core/acpi.c +++ b/src/core/acpi.c @@ -42,19 +42,41 @@ FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL ); ****************************************************************************** */ +/** + * Compute ACPI table checksum + * + * @v table Any ACPI table + * @ret checksum 0 if checksum is good + */ +static uint8_t acpi_checksum ( userptr_t table ) { + struct acpi_header acpi; + uint8_t sum = 0; + uint8_t data; + unsigned int i; + + /* Read table length */ + copy_from_user ( &acpi.length, table, + offsetof ( typeof ( acpi ), length ), + sizeof ( acpi.length ) ); + + /* Compute checksum */ + for ( i = 0 ; i < le32_to_cpu ( acpi.length ) ; i++ ) { + copy_from_user ( &data, table, i, sizeof ( data ) ); + sum += data; + } + + return sum; +} + /** * Fix up ACPI table checksum * * @v acpi ACPI table header */ void acpi_fix_checksum ( struct acpi_header *acpi ) { - unsigned int i = 0; - uint8_t sum = 0; - for ( i = 0 ; i < acpi->length ; i++ ) { - sum += *( ( ( uint8_t * ) acpi ) + i ); - } - acpi->checksum -= sum; + /* Update checksum */ + acpi->checksum -= acpi_checksum ( virt_to_user ( acpi ) ); } /** @@ -123,6 +145,15 @@ userptr_t acpi_find ( uint32_t signature, unsigned int index ) { if ( index-- ) continue; + /* Check table integrity */ + if ( acpi_checksum ( table ) != 0 ) { + DBGC ( rsdt, "RSDT %#08lx found %s with bad checksum " + "at %08lx\n", user_to_phys ( rsdt, 0 ), + acpi_name ( signature ), + user_to_phys ( table, 0 ) ); + break; + } + DBGC ( rsdt, "RSDT %#08lx found %s at %08lx\n", user_to_phys ( rsdt, 0 ), acpi_name ( signature ), user_to_phys ( table, 0 ) );