|  | @@ -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 ) );
 |