diff options
author | Laurent Gourvénec | 2017-07-27 16:04:35 +0200 |
---|---|---|
committer | Michael Brown | 2017-07-28 18:05:33 +0200 |
commit | 041d362423bb8414b0bd1baf93023bac14e52f14 (patch) | |
tree | 20ce0f48cee25cb1fca35662bccc9497580e5a74 /src/core | |
parent | [build] Fix ARM32 EFI builds with current EDK2 headers (diff) | |
download | ipxe-041d362423bb8414b0bd1baf93023bac14e52f14.tar.gz ipxe-041d362423bb8414b0bd1baf93023bac14e52f14.tar.xz ipxe-041d362423bb8414b0bd1baf93023bac14e52f14.zip |
[acpi] Compute and check checksum for ACPI tables
Modified-by: Michael Brown <mcb30@ipxe.org>
Signed-off-by: Michael Brown <mcb30@ipxe.org>
Diffstat (limited to 'src/core')
-rw-r--r-- | src/core/acpi.c | 43 |
1 files 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 @@ -43,18 +43,40 @@ 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 ) ); |