|
@@ -42,19 +42,41 @@ FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
|
42
|
42
|
******************************************************************************
|
43
|
43
|
*/
|
44
|
44
|
|
|
45
|
+/**
|
|
46
|
+ * Compute ACPI table checksum
|
|
47
|
+ *
|
|
48
|
+ * @v table Any ACPI table
|
|
49
|
+ * @ret checksum 0 if checksum is good
|
|
50
|
+ */
|
|
51
|
+static uint8_t acpi_checksum ( userptr_t table ) {
|
|
52
|
+ struct acpi_header acpi;
|
|
53
|
+ uint8_t sum = 0;
|
|
54
|
+ uint8_t data;
|
|
55
|
+ unsigned int i;
|
|
56
|
+
|
|
57
|
+ /* Read table length */
|
|
58
|
+ copy_from_user ( &acpi.length, table,
|
|
59
|
+ offsetof ( typeof ( acpi ), length ),
|
|
60
|
+ sizeof ( acpi.length ) );
|
|
61
|
+
|
|
62
|
+ /* Compute checksum */
|
|
63
|
+ for ( i = 0 ; i < le32_to_cpu ( acpi.length ) ; i++ ) {
|
|
64
|
+ copy_from_user ( &data, table, i, sizeof ( data ) );
|
|
65
|
+ sum += data;
|
|
66
|
+ }
|
|
67
|
+
|
|
68
|
+ return sum;
|
|
69
|
+}
|
|
70
|
+
|
45
|
71
|
/**
|
46
|
72
|
* Fix up ACPI table checksum
|
47
|
73
|
*
|
48
|
74
|
* @v acpi ACPI table header
|
49
|
75
|
*/
|
50
|
76
|
void acpi_fix_checksum ( struct acpi_header *acpi ) {
|
51
|
|
- unsigned int i = 0;
|
52
|
|
- uint8_t sum = 0;
|
53
|
77
|
|
54
|
|
- for ( i = 0 ; i < acpi->length ; i++ ) {
|
55
|
|
- sum += *( ( ( uint8_t * ) acpi ) + i );
|
56
|
|
- }
|
57
|
|
- acpi->checksum -= sum;
|
|
78
|
+ /* Update checksum */
|
|
79
|
+ acpi->checksum -= acpi_checksum ( virt_to_user ( acpi ) );
|
58
|
80
|
}
|
59
|
81
|
|
60
|
82
|
/**
|
|
@@ -123,6 +145,15 @@ userptr_t acpi_find ( uint32_t signature, unsigned int index ) {
|
123
|
145
|
if ( index-- )
|
124
|
146
|
continue;
|
125
|
147
|
|
|
148
|
+ /* Check table integrity */
|
|
149
|
+ if ( acpi_checksum ( table ) != 0 ) {
|
|
150
|
+ DBGC ( rsdt, "RSDT %#08lx found %s with bad checksum "
|
|
151
|
+ "at %08lx\n", user_to_phys ( rsdt, 0 ),
|
|
152
|
+ acpi_name ( signature ),
|
|
153
|
+ user_to_phys ( table, 0 ) );
|
|
154
|
+ break;
|
|
155
|
+ }
|
|
156
|
+
|
126
|
157
|
DBGC ( rsdt, "RSDT %#08lx found %s at %08lx\n",
|
127
|
158
|
user_to_phys ( rsdt, 0 ), acpi_name ( signature ),
|
128
|
159
|
user_to_phys ( table, 0 ) );
|