summaryrefslogtreecommitdiffstats
path: root/src/core
diff options
context:
space:
mode:
authorLaurent Gourvénec2017-07-27 16:04:35 +0200
committerMichael Brown2017-07-28 18:05:33 +0200
commit041d362423bb8414b0bd1baf93023bac14e52f14 (patch)
tree20ce0f48cee25cb1fca35662bccc9497580e5a74 /src/core
parent[build] Fix ARM32 EFI builds with current EDK2 headers (diff)
downloadipxe-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.c43
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 ) );