|  | @@ -24,6 +24,8 @@
 | 
		
	
		
			
			| 24 | 24 |  FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
 | 
		
	
		
			
			| 25 | 25 |  
 | 
		
	
		
			
			| 26 | 26 |  #include <errno.h>
 | 
		
	
		
			
			|  | 27 | +#include <byteswap.h>
 | 
		
	
		
			
			|  | 28 | +#include <ipxe/uaccess.h>
 | 
		
	
		
			
			| 27 | 29 |  #include <ipxe/acpi.h>
 | 
		
	
		
			
			| 28 | 30 |  #include <ipxe/interface.h>
 | 
		
	
		
			
			| 29 | 31 |  
 | 
		
	
	
		
			
			|  | @@ -40,6 +42,22 @@ FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
 | 
		
	
		
			
			| 40 | 42 |   ******************************************************************************
 | 
		
	
		
			
			| 41 | 43 |   */
 | 
		
	
		
			
			| 42 | 44 |  
 | 
		
	
		
			
			|  | 45 | +/**
 | 
		
	
		
			
			|  | 46 | + * Transcribe ACPI table signature (for debugging)
 | 
		
	
		
			
			|  | 47 | + *
 | 
		
	
		
			
			|  | 48 | + * @v signature		ACPI table signature
 | 
		
	
		
			
			|  | 49 | + * @ret name		ACPI table signature name
 | 
		
	
		
			
			|  | 50 | + */
 | 
		
	
		
			
			|  | 51 | +static const char * acpi_name ( uint32_t signature ) {
 | 
		
	
		
			
			|  | 52 | +	static union {
 | 
		
	
		
			
			|  | 53 | +		uint32_t signature;
 | 
		
	
		
			
			|  | 54 | +		char name[5];
 | 
		
	
		
			
			|  | 55 | +	} u;
 | 
		
	
		
			
			|  | 56 | +
 | 
		
	
		
			
			|  | 57 | +	u.signature = cpu_to_le32 ( signature );
 | 
		
	
		
			
			|  | 58 | +	return u.name;
 | 
		
	
		
			
			|  | 59 | +}
 | 
		
	
		
			
			|  | 60 | +
 | 
		
	
		
			
			| 43 | 61 |  /**
 | 
		
	
		
			
			| 44 | 62 |   * Fix up ACPI table checksum
 | 
		
	
		
			
			| 45 | 63 |   *
 | 
		
	
	
		
			
			|  | @@ -55,6 +73,262 @@ void acpi_fix_checksum ( struct acpi_description_header *acpi ) {
 | 
		
	
		
			
			| 55 | 73 |  	acpi->checksum -= sum;
 | 
		
	
		
			
			| 56 | 74 |  }
 | 
		
	
		
			
			| 57 | 75 |  
 | 
		
	
		
			
			|  | 76 | +/**
 | 
		
	
		
			
			|  | 77 | + * Locate ACPI root system description table within a memory range
 | 
		
	
		
			
			|  | 78 | + *
 | 
		
	
		
			
			|  | 79 | + * @v start		Start address to search
 | 
		
	
		
			
			|  | 80 | + * @v len		Length to search
 | 
		
	
		
			
			|  | 81 | + * @ret rsdt		ACPI root system description table, or UNULL
 | 
		
	
		
			
			|  | 82 | + */
 | 
		
	
		
			
			|  | 83 | +static userptr_t acpi_find_rsdt_range ( userptr_t start, size_t len ) {
 | 
		
	
		
			
			|  | 84 | +	static const char signature[8] = RSDP_SIGNATURE;
 | 
		
	
		
			
			|  | 85 | +	struct acpi_rsdp rsdp;
 | 
		
	
		
			
			|  | 86 | +	userptr_t rsdt;
 | 
		
	
		
			
			|  | 87 | +	size_t offset;
 | 
		
	
		
			
			|  | 88 | +	uint8_t sum;
 | 
		
	
		
			
			|  | 89 | +	unsigned int i;
 | 
		
	
		
			
			|  | 90 | +
 | 
		
	
		
			
			|  | 91 | +	/* Search for RSDP */
 | 
		
	
		
			
			|  | 92 | +	for ( offset = 0 ; ( ( offset + sizeof ( rsdp ) ) < len ) ;
 | 
		
	
		
			
			|  | 93 | +	      offset += RSDP_STRIDE ) {
 | 
		
	
		
			
			|  | 94 | +
 | 
		
	
		
			
			|  | 95 | +		/* Check signature and checksum */
 | 
		
	
		
			
			|  | 96 | +		copy_from_user ( &rsdp, start, offset, sizeof ( rsdp ) );
 | 
		
	
		
			
			|  | 97 | +		if ( memcmp ( rsdp.signature, signature,
 | 
		
	
		
			
			|  | 98 | +			      sizeof ( signature ) ) != 0 )
 | 
		
	
		
			
			|  | 99 | +			continue;
 | 
		
	
		
			
			|  | 100 | +		for ( sum = 0, i = 0 ; i < sizeof ( rsdp ) ; i++ )
 | 
		
	
		
			
			|  | 101 | +			sum += *( ( ( uint8_t * ) &rsdp ) + i );
 | 
		
	
		
			
			|  | 102 | +		if ( sum != 0 )
 | 
		
	
		
			
			|  | 103 | +			continue;
 | 
		
	
		
			
			|  | 104 | +
 | 
		
	
		
			
			|  | 105 | +		/* Extract RSDT */
 | 
		
	
		
			
			|  | 106 | +		rsdt = phys_to_user ( le32_to_cpu ( rsdp.rsdt ) );
 | 
		
	
		
			
			|  | 107 | +		DBGC ( rsdt, "RSDT %#08lx found via RSDP %#08lx\n",
 | 
		
	
		
			
			|  | 108 | +		       user_to_phys ( rsdt, 0 ),
 | 
		
	
		
			
			|  | 109 | +		       user_to_phys ( start, offset ) );
 | 
		
	
		
			
			|  | 110 | +		return rsdt;
 | 
		
	
		
			
			|  | 111 | +	}
 | 
		
	
		
			
			|  | 112 | +
 | 
		
	
		
			
			|  | 113 | +	return UNULL;
 | 
		
	
		
			
			|  | 114 | +}
 | 
		
	
		
			
			|  | 115 | +
 | 
		
	
		
			
			|  | 116 | +/**
 | 
		
	
		
			
			|  | 117 | + * Locate ACPI root system description table
 | 
		
	
		
			
			|  | 118 | + *
 | 
		
	
		
			
			|  | 119 | + * @v ebda		Extended BIOS data area, or UNULL
 | 
		
	
		
			
			|  | 120 | + * @ret rsdt		ACPI root system description table, or UNULL
 | 
		
	
		
			
			|  | 121 | + */
 | 
		
	
		
			
			|  | 122 | +userptr_t acpi_find_rsdt ( userptr_t ebda ) {
 | 
		
	
		
			
			|  | 123 | +	userptr_t rsdt;
 | 
		
	
		
			
			|  | 124 | +
 | 
		
	
		
			
			|  | 125 | +	/* Search EBDA, if applicable */
 | 
		
	
		
			
			|  | 126 | +	if ( ebda ) {
 | 
		
	
		
			
			|  | 127 | +		rsdt = acpi_find_rsdt_range ( ebda, RSDP_EBDA_LEN );
 | 
		
	
		
			
			|  | 128 | +		if ( rsdt )
 | 
		
	
		
			
			|  | 129 | +			return rsdt;
 | 
		
	
		
			
			|  | 130 | +	}
 | 
		
	
		
			
			|  | 131 | +
 | 
		
	
		
			
			|  | 132 | +	/* Search fixed BIOS area */
 | 
		
	
		
			
			|  | 133 | +	rsdt = acpi_find_rsdt_range ( phys_to_user ( RSDP_BIOS_START ),
 | 
		
	
		
			
			|  | 134 | +				      RSDP_BIOS_LEN );
 | 
		
	
		
			
			|  | 135 | +	if ( rsdt )
 | 
		
	
		
			
			|  | 136 | +		return rsdt;
 | 
		
	
		
			
			|  | 137 | +
 | 
		
	
		
			
			|  | 138 | +	return UNULL;
 | 
		
	
		
			
			|  | 139 | +}
 | 
		
	
		
			
			|  | 140 | +
 | 
		
	
		
			
			|  | 141 | +/**
 | 
		
	
		
			
			|  | 142 | + * Locate ACPI table
 | 
		
	
		
			
			|  | 143 | + *
 | 
		
	
		
			
			|  | 144 | + * @v rsdt		ACPI root system description table
 | 
		
	
		
			
			|  | 145 | + * @v signature		Requested table signature
 | 
		
	
		
			
			|  | 146 | + * @v index		Requested index of table with this signature
 | 
		
	
		
			
			|  | 147 | + * @ret table		Table, or UNULL if not found
 | 
		
	
		
			
			|  | 148 | + */
 | 
		
	
		
			
			|  | 149 | +userptr_t acpi_find ( userptr_t rsdt, uint32_t signature, unsigned int index ) {
 | 
		
	
		
			
			|  | 150 | +	struct acpi_description_header acpi;
 | 
		
	
		
			
			|  | 151 | +	struct acpi_rsdt *rsdtab;
 | 
		
	
		
			
			|  | 152 | +	typeof ( rsdtab->entry[0] ) entry;
 | 
		
	
		
			
			|  | 153 | +	userptr_t table;
 | 
		
	
		
			
			|  | 154 | +	size_t len;
 | 
		
	
		
			
			|  | 155 | +	unsigned int count;
 | 
		
	
		
			
			|  | 156 | +	unsigned int i;
 | 
		
	
		
			
			|  | 157 | +
 | 
		
	
		
			
			|  | 158 | +	/* Read RSDT header */
 | 
		
	
		
			
			|  | 159 | +	copy_from_user ( &acpi, rsdt, 0, sizeof ( acpi ) );
 | 
		
	
		
			
			|  | 160 | +	if ( acpi.signature != cpu_to_le32 ( RSDT_SIGNATURE ) ) {
 | 
		
	
		
			
			|  | 161 | +		DBGC ( rsdt, "RSDT %#08lx has invalid signature:\n",
 | 
		
	
		
			
			|  | 162 | +		       user_to_phys ( rsdt, 0 ) );
 | 
		
	
		
			
			|  | 163 | +		DBGC_HDA ( rsdt, user_to_phys ( rsdt, 0 ), &acpi,
 | 
		
	
		
			
			|  | 164 | +			   sizeof ( acpi ) );
 | 
		
	
		
			
			|  | 165 | +		return UNULL;
 | 
		
	
		
			
			|  | 166 | +	}
 | 
		
	
		
			
			|  | 167 | +	len = le32_to_cpu ( acpi.length );
 | 
		
	
		
			
			|  | 168 | +	if ( len < sizeof ( rsdtab->acpi ) ) {
 | 
		
	
		
			
			|  | 169 | +		DBGC ( rsdt, "RSDT %#08lx has invalid length:\n",
 | 
		
	
		
			
			|  | 170 | +		       user_to_phys ( rsdt, 0 ) );
 | 
		
	
		
			
			|  | 171 | +		DBGC_HDA ( rsdt, user_to_phys ( rsdt, 0 ), &acpi,
 | 
		
	
		
			
			|  | 172 | +			   sizeof ( acpi ) );
 | 
		
	
		
			
			|  | 173 | +		return UNULL;
 | 
		
	
		
			
			|  | 174 | +	}
 | 
		
	
		
			
			|  | 175 | +
 | 
		
	
		
			
			|  | 176 | +	/* Calculate number of entries */
 | 
		
	
		
			
			|  | 177 | +	count = ( ( len - sizeof ( rsdtab->acpi ) ) / sizeof ( entry ) );
 | 
		
	
		
			
			|  | 178 | +
 | 
		
	
		
			
			|  | 179 | +	/* Search through entries */
 | 
		
	
		
			
			|  | 180 | +	for ( i = 0 ; i < count ; i++ ) {
 | 
		
	
		
			
			|  | 181 | +
 | 
		
	
		
			
			|  | 182 | +		/* Get table address */
 | 
		
	
		
			
			|  | 183 | +		copy_from_user ( &entry, rsdt,
 | 
		
	
		
			
			|  | 184 | +				 offsetof ( typeof ( *rsdtab ), entry[i] ),
 | 
		
	
		
			
			|  | 185 | +				 sizeof ( entry ) );
 | 
		
	
		
			
			|  | 186 | +
 | 
		
	
		
			
			|  | 187 | +		/* Read table header */
 | 
		
	
		
			
			|  | 188 | +		table = phys_to_user ( entry );
 | 
		
	
		
			
			|  | 189 | +		copy_from_user ( &acpi.signature, table, 0,
 | 
		
	
		
			
			|  | 190 | +				 sizeof ( acpi.signature ) );
 | 
		
	
		
			
			|  | 191 | +
 | 
		
	
		
			
			|  | 192 | +		/* Check table signature */
 | 
		
	
		
			
			|  | 193 | +		if ( acpi.signature != cpu_to_le32 ( signature ) )
 | 
		
	
		
			
			|  | 194 | +			continue;
 | 
		
	
		
			
			|  | 195 | +
 | 
		
	
		
			
			|  | 196 | +		/* Check index */
 | 
		
	
		
			
			|  | 197 | +		if ( index-- )
 | 
		
	
		
			
			|  | 198 | +			continue;
 | 
		
	
		
			
			|  | 199 | +
 | 
		
	
		
			
			|  | 200 | +		DBGC ( rsdt, "RSDT %#08lx found %s at %08lx\n",
 | 
		
	
		
			
			|  | 201 | +		       user_to_phys ( rsdt, 0 ), acpi_name ( signature ),
 | 
		
	
		
			
			|  | 202 | +		       user_to_phys ( table, 0 ) );
 | 
		
	
		
			
			|  | 203 | +		return table;
 | 
		
	
		
			
			|  | 204 | +	}
 | 
		
	
		
			
			|  | 205 | +
 | 
		
	
		
			
			|  | 206 | +	DBGC ( rsdt, "RSDT %#08lx could not find %s\n",
 | 
		
	
		
			
			|  | 207 | +	       user_to_phys ( rsdt, 0 ), acpi_name ( signature ) );
 | 
		
	
		
			
			|  | 208 | +	return UNULL;
 | 
		
	
		
			
			|  | 209 | +}
 | 
		
	
		
			
			|  | 210 | +
 | 
		
	
		
			
			|  | 211 | +/**
 | 
		
	
		
			
			|  | 212 | + * Extract \_Sx value from DSDT/SSDT
 | 
		
	
		
			
			|  | 213 | + *
 | 
		
	
		
			
			|  | 214 | + * @v zsdt		DSDT or SSDT
 | 
		
	
		
			
			|  | 215 | + * @v signature		Signature (e.g. "_S5_")
 | 
		
	
		
			
			|  | 216 | + * @ret sx		\_Sx value, or negative error
 | 
		
	
		
			
			|  | 217 | + *
 | 
		
	
		
			
			|  | 218 | + * In theory, extracting the \_Sx value from the DSDT/SSDT requires a
 | 
		
	
		
			
			|  | 219 | + * full ACPI parser plus some heuristics to work around the various
 | 
		
	
		
			
			|  | 220 | + * broken encodings encountered in real ACPI implementations.
 | 
		
	
		
			
			|  | 221 | + *
 | 
		
	
		
			
			|  | 222 | + * In practice, we can get the same result by scanning through the
 | 
		
	
		
			
			|  | 223 | + * DSDT/SSDT for the signature (e.g. "_S5_"), extracting the first
 | 
		
	
		
			
			|  | 224 | + * four bytes, removing any bytes with bit 3 set, and treating
 | 
		
	
		
			
			|  | 225 | + * whatever is left as a little-endian value.  This is one of the
 | 
		
	
		
			
			|  | 226 | + * uglier hacks I have ever implemented, but it's still prettier than
 | 
		
	
		
			
			|  | 227 | + * the ACPI specification itself.
 | 
		
	
		
			
			|  | 228 | + */
 | 
		
	
		
			
			|  | 229 | +static int acpi_sx_zsdt ( userptr_t zsdt, uint32_t signature ) {
 | 
		
	
		
			
			|  | 230 | +	struct acpi_description_header acpi;
 | 
		
	
		
			
			|  | 231 | +	union {
 | 
		
	
		
			
			|  | 232 | +		uint32_t dword;
 | 
		
	
		
			
			|  | 233 | +		uint8_t byte[4];
 | 
		
	
		
			
			|  | 234 | +	} buf;
 | 
		
	
		
			
			|  | 235 | +	size_t offset;
 | 
		
	
		
			
			|  | 236 | +	size_t len;
 | 
		
	
		
			
			|  | 237 | +	unsigned int sx;
 | 
		
	
		
			
			|  | 238 | +	uint8_t *byte;
 | 
		
	
		
			
			|  | 239 | +
 | 
		
	
		
			
			|  | 240 | +	/* Read table header */
 | 
		
	
		
			
			|  | 241 | +	copy_from_user ( &acpi, zsdt, 0, sizeof ( acpi ) );
 | 
		
	
		
			
			|  | 242 | +	len = le32_to_cpu ( acpi.length );
 | 
		
	
		
			
			|  | 243 | +
 | 
		
	
		
			
			|  | 244 | +	/* Locate signature */
 | 
		
	
		
			
			|  | 245 | +	for ( offset = sizeof ( acpi ) ;
 | 
		
	
		
			
			|  | 246 | +	      ( ( offset + sizeof ( buf ) /* signature */ + 3 /* pkg header */
 | 
		
	
		
			
			|  | 247 | +		  + sizeof ( buf ) /* value */ ) < len ) ;
 | 
		
	
		
			
			|  | 248 | +	      offset++ ) {
 | 
		
	
		
			
			|  | 249 | +
 | 
		
	
		
			
			|  | 250 | +		/* Check signature */
 | 
		
	
		
			
			|  | 251 | +		copy_from_user ( &buf, zsdt, offset, sizeof ( buf ) );
 | 
		
	
		
			
			|  | 252 | +		if ( buf.dword != cpu_to_le32 ( signature ) )
 | 
		
	
		
			
			|  | 253 | +			continue;
 | 
		
	
		
			
			|  | 254 | +		DBGC ( zsdt, "DSDT/SSDT %#08lx found %s at offset %#zx\n",
 | 
		
	
		
			
			|  | 255 | +		       user_to_phys ( zsdt, 0 ), acpi_name ( signature ),
 | 
		
	
		
			
			|  | 256 | +		       offset );
 | 
		
	
		
			
			|  | 257 | +		offset += sizeof ( buf );
 | 
		
	
		
			
			|  | 258 | +
 | 
		
	
		
			
			|  | 259 | +		/* Read first four bytes of value */
 | 
		
	
		
			
			|  | 260 | +		copy_from_user ( &buf, zsdt, ( offset + 3 /* pkg header */ ),
 | 
		
	
		
			
			|  | 261 | +				 sizeof ( buf ) );
 | 
		
	
		
			
			|  | 262 | +		DBGC ( zsdt, "DSDT/SSDT %#08lx found %s containing "
 | 
		
	
		
			
			|  | 263 | +		       "%02x:%02x:%02x:%02x\n", user_to_phys ( zsdt, 0 ),
 | 
		
	
		
			
			|  | 264 | +		       acpi_name ( signature ), buf.byte[0], buf.byte[1],
 | 
		
	
		
			
			|  | 265 | +		       buf.byte[2], buf.byte[3] );
 | 
		
	
		
			
			|  | 266 | +
 | 
		
	
		
			
			|  | 267 | +		/* Extract \Sx value.  There are three potential
 | 
		
	
		
			
			|  | 268 | +		 * encodings that we might encounter:
 | 
		
	
		
			
			|  | 269 | +		 *
 | 
		
	
		
			
			|  | 270 | +		 * - SLP_TYPa, SLP_TYPb, rsvd, rsvd
 | 
		
	
		
			
			|  | 271 | +		 *
 | 
		
	
		
			
			|  | 272 | +		 * - <byteprefix>, SLP_TYPa, <byteprefix>, SLP_TYPb, ...
 | 
		
	
		
			
			|  | 273 | +		 *
 | 
		
	
		
			
			|  | 274 | +		 * - <dwordprefix>, SLP_TYPa, SLP_TYPb, 0, 0
 | 
		
	
		
			
			|  | 275 | +		 *
 | 
		
	
		
			
			|  | 276 | +		 * Since <byteprefix> and <dwordprefix> both have bit
 | 
		
	
		
			
			|  | 277 | +		 * 3 set, and valid SLP_TYPx must have bit 3 clear
 | 
		
	
		
			
			|  | 278 | +		 * (since SLP_TYPx is a 3-bit field), we can just skip
 | 
		
	
		
			
			|  | 279 | +		 * any bytes with bit 3 set.
 | 
		
	
		
			
			|  | 280 | +		 */
 | 
		
	
		
			
			|  | 281 | +		byte = &buf.byte[0];
 | 
		
	
		
			
			|  | 282 | +		if ( *byte & 0x08 )
 | 
		
	
		
			
			|  | 283 | +			byte++;
 | 
		
	
		
			
			|  | 284 | +		sx = *(byte++);
 | 
		
	
		
			
			|  | 285 | +		if ( *byte & 0x08 )
 | 
		
	
		
			
			|  | 286 | +			byte++;
 | 
		
	
		
			
			|  | 287 | +		sx |= ( *byte << 8 );
 | 
		
	
		
			
			|  | 288 | +		return sx;
 | 
		
	
		
			
			|  | 289 | +	}
 | 
		
	
		
			
			|  | 290 | +
 | 
		
	
		
			
			|  | 291 | +	return -ENOENT;
 | 
		
	
		
			
			|  | 292 | +}
 | 
		
	
		
			
			|  | 293 | +
 | 
		
	
		
			
			|  | 294 | +/**
 | 
		
	
		
			
			|  | 295 | + * Extract \_Sx value from DSDT/SSDT
 | 
		
	
		
			
			|  | 296 | + *
 | 
		
	
		
			
			|  | 297 | + * @v rsdt		ACPI root system description table
 | 
		
	
		
			
			|  | 298 | + * @v signature		Signature (e.g. "_S5_")
 | 
		
	
		
			
			|  | 299 | + * @ret sx		\_Sx value, or negative error
 | 
		
	
		
			
			|  | 300 | + */
 | 
		
	
		
			
			|  | 301 | +int acpi_sx ( userptr_t rsdt, uint32_t signature ) {
 | 
		
	
		
			
			|  | 302 | +	struct acpi_fadt fadtab;
 | 
		
	
		
			
			|  | 303 | +	userptr_t fadt;
 | 
		
	
		
			
			|  | 304 | +	userptr_t dsdt;
 | 
		
	
		
			
			|  | 305 | +	userptr_t ssdt;
 | 
		
	
		
			
			|  | 306 | +	unsigned int i;
 | 
		
	
		
			
			|  | 307 | +	int sx;
 | 
		
	
		
			
			|  | 308 | +
 | 
		
	
		
			
			|  | 309 | +	/* Try DSDT first */
 | 
		
	
		
			
			|  | 310 | +	fadt = acpi_find ( rsdt, FADT_SIGNATURE, 0 );
 | 
		
	
		
			
			|  | 311 | +	if ( fadt ) {
 | 
		
	
		
			
			|  | 312 | +		copy_from_user ( &fadtab, fadt, 0, sizeof ( fadtab ) );
 | 
		
	
		
			
			|  | 313 | +		dsdt = phys_to_user ( fadtab.dsdt );
 | 
		
	
		
			
			|  | 314 | +		if ( ( sx = acpi_sx_zsdt ( dsdt, signature ) ) >= 0 )
 | 
		
	
		
			
			|  | 315 | +			return sx;
 | 
		
	
		
			
			|  | 316 | +	}
 | 
		
	
		
			
			|  | 317 | +
 | 
		
	
		
			
			|  | 318 | +	/* Try all SSDTs */
 | 
		
	
		
			
			|  | 319 | +	for ( i = 0 ; ; i++ ) {
 | 
		
	
		
			
			|  | 320 | +		ssdt = acpi_find ( rsdt, SSDT_SIGNATURE, i );
 | 
		
	
		
			
			|  | 321 | +		if ( ! ssdt )
 | 
		
	
		
			
			|  | 322 | +			break;
 | 
		
	
		
			
			|  | 323 | +		if ( ( sx = acpi_sx_zsdt ( ssdt, signature ) ) >= 0 )
 | 
		
	
		
			
			|  | 324 | +			return sx;
 | 
		
	
		
			
			|  | 325 | +	}
 | 
		
	
		
			
			|  | 326 | +
 | 
		
	
		
			
			|  | 327 | +	DBGC ( rsdt, "RSDT %#08lx could not find \\_Sx \"%s\"\n",
 | 
		
	
		
			
			|  | 328 | +	       user_to_phys ( rsdt, 0 ), acpi_name ( signature ) );
 | 
		
	
		
			
			|  | 329 | +	return -ENOENT;
 | 
		
	
		
			
			|  | 330 | +}
 | 
		
	
		
			
			|  | 331 | +
 | 
		
	
		
			
			| 58 | 332 |  /******************************************************************************
 | 
		
	
		
			
			| 59 | 333 |   *
 | 
		
	
		
			
			| 60 | 334 |   * Interface methods
 |