iPXE
acpi.c
Go to the documentation of this file.
1 /*
2  * Copyright (C) 2006 Michael Brown <mbrown@fensystems.co.uk>.
3  *
4  * This program is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU General Public License as
6  * published by the Free Software Foundation; either version 2 of the
7  * License, or any later version.
8  *
9  * This program is distributed in the hope that it will be useful, but
10  * WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12  * General Public License for more details.
13  *
14  * You should have received a copy of the GNU General Public License
15  * along with this program; if not, write to the Free Software
16  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
17  * 02110-1301, USA.
18  *
19  * You can also choose to distribute this program under the terms of
20  * the Unmodified Binary Distribution Licence (as given in the file
21  * COPYING.UBDL), provided that you have satisfied its requirements.
22  */
23 
24 FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
25 
26 #include <errno.h>
27 #include <byteswap.h>
28 #include <ipxe/uaccess.h>
29 #include <ipxe/acpi.h>
30 #include <ipxe/interface.h>
31 
32 /** @file
33  *
34  * ACPI support functions
35  *
36  */
37 
38 /******************************************************************************
39  *
40  * Utility functions
41  *
42  ******************************************************************************
43  */
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 = 0;
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 
71 /**
72  * Fix up ACPI table checksum
73  *
74  * @v acpi ACPI table header
75  */
77 
78  /* Update checksum */
79  acpi->checksum -= acpi_checksum ( virt_to_user ( acpi ) );
80 }
81 
82 /**
83  * Locate ACPI table
84  *
85  * @v signature Requested table signature
86  * @v index Requested index of table with this signature
87  * @ret table Table, or UNULL if not found
88  */
90  struct acpi_header acpi;
91  struct acpi_rsdt *rsdtab;
92  typeof ( rsdtab->entry[0] ) entry;
93  userptr_t rsdt;
94  userptr_t table;
95  size_t len;
96  unsigned int count;
97  unsigned int i;
98 
99  /* Locate RSDT */
100  rsdt = acpi_find_rsdt();
101  if ( ! rsdt ) {
102  DBG ( "RSDT not found\n" );
103  return UNULL;
104  }
105 
106  /* Read RSDT header */
107  copy_from_user ( &acpi, rsdt, 0, sizeof ( acpi ) );
108  if ( acpi.signature != cpu_to_le32 ( RSDT_SIGNATURE ) ) {
109  DBGC ( rsdt, "RSDT %#08lx has invalid signature:\n",
110  user_to_phys ( rsdt, 0 ) );
111  DBGC_HDA ( rsdt, user_to_phys ( rsdt, 0 ), &acpi,
112  sizeof ( acpi ) );
113  return UNULL;
114  }
115  len = le32_to_cpu ( acpi.length );
116  if ( len < sizeof ( rsdtab->acpi ) ) {
117  DBGC ( rsdt, "RSDT %#08lx has invalid length:\n",
118  user_to_phys ( rsdt, 0 ) );
119  DBGC_HDA ( rsdt, user_to_phys ( rsdt, 0 ), &acpi,
120  sizeof ( acpi ) );
121  return UNULL;
122  }
123 
124  /* Calculate number of entries */
125  count = ( ( len - sizeof ( rsdtab->acpi ) ) / sizeof ( entry ) );
126 
127  /* Search through entries */
128  for ( i = 0 ; i < count ; i++ ) {
129 
130  /* Get table address */
131  copy_from_user ( &entry, rsdt,
132  offsetof ( typeof ( *rsdtab ), entry[i] ),
133  sizeof ( entry ) );
134 
135  /* Read table header */
136  table = phys_to_user ( entry );
137  copy_from_user ( &acpi.signature, table, 0,
138  sizeof ( acpi.signature ) );
139 
140  /* Check table signature */
141  if ( acpi.signature != cpu_to_le32 ( signature ) )
142  continue;
143 
144  /* Check index */
145  if ( index-- )
146  continue;
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 
157  DBGC ( rsdt, "RSDT %#08lx found %s at %08lx\n",
158  user_to_phys ( rsdt, 0 ), acpi_name ( signature ),
159  user_to_phys ( table, 0 ) );
160  return table;
161  }
162 
163  DBGC ( rsdt, "RSDT %#08lx could not find %s\n",
164  user_to_phys ( rsdt, 0 ), acpi_name ( signature ) );
165  return UNULL;
166 }
167 
168 /**
169  * Extract \_Sx value from DSDT/SSDT
170  *
171  * @v zsdt DSDT or SSDT
172  * @v signature Signature (e.g. "_S5_")
173  * @ret sx \_Sx value, or negative error
174  *
175  * In theory, extracting the \_Sx value from the DSDT/SSDT requires a
176  * full ACPI parser plus some heuristics to work around the various
177  * broken encodings encountered in real ACPI implementations.
178  *
179  * In practice, we can get the same result by scanning through the
180  * DSDT/SSDT for the signature (e.g. "_S5_"), extracting the first
181  * four bytes, removing any bytes with bit 3 set, and treating
182  * whatever is left as a little-endian value. This is one of the
183  * uglier hacks I have ever implemented, but it's still prettier than
184  * the ACPI specification itself.
185  */
186 static int acpi_sx_zsdt ( userptr_t zsdt, uint32_t signature ) {
187  struct acpi_header acpi;
188  union {
189  uint32_t dword;
190  uint8_t byte[4];
191  } buf;
192  size_t offset;
193  size_t len;
194  unsigned int sx;
195  uint8_t *byte;
196 
197  /* Read table header */
198  copy_from_user ( &acpi, zsdt, 0, sizeof ( acpi ) );
199  len = le32_to_cpu ( acpi.length );
200 
201  /* Locate signature */
202  for ( offset = sizeof ( acpi ) ;
203  ( ( offset + sizeof ( buf ) /* signature */ + 3 /* pkg header */
204  + sizeof ( buf ) /* value */ ) < len ) ;
205  offset++ ) {
206 
207  /* Check signature */
208  copy_from_user ( &buf, zsdt, offset, sizeof ( buf ) );
209  if ( buf.dword != cpu_to_le32 ( signature ) )
210  continue;
211  DBGC ( zsdt, "DSDT/SSDT %#08lx found %s at offset %#zx\n",
212  user_to_phys ( zsdt, 0 ), acpi_name ( signature ),
213  offset );
214  offset += sizeof ( buf );
215 
216  /* Read first four bytes of value */
217  copy_from_user ( &buf, zsdt, ( offset + 3 /* pkg header */ ),
218  sizeof ( buf ) );
219  DBGC ( zsdt, "DSDT/SSDT %#08lx found %s containing "
220  "%02x:%02x:%02x:%02x\n", user_to_phys ( zsdt, 0 ),
221  acpi_name ( signature ), buf.byte[0], buf.byte[1],
222  buf.byte[2], buf.byte[3] );
223 
224  /* Extract \Sx value. There are three potential
225  * encodings that we might encounter:
226  *
227  * - SLP_TYPa, SLP_TYPb, rsvd, rsvd
228  *
229  * - <byteprefix>, SLP_TYPa, <byteprefix>, SLP_TYPb, ...
230  *
231  * - <dwordprefix>, SLP_TYPa, SLP_TYPb, 0, 0
232  *
233  * Since <byteprefix> and <dwordprefix> both have bit
234  * 3 set, and valid SLP_TYPx must have bit 3 clear
235  * (since SLP_TYPx is a 3-bit field), we can just skip
236  * any bytes with bit 3 set.
237  */
238  byte = &buf.byte[0];
239  if ( *byte & 0x08 )
240  byte++;
241  sx = *(byte++);
242  if ( *byte & 0x08 )
243  byte++;
244  sx |= ( *byte << 8 );
245  return sx;
246  }
247 
248  return -ENOENT;
249 }
250 
251 /**
252  * Extract \_Sx value from DSDT/SSDT
253  *
254  * @v signature Signature (e.g. "_S5_")
255  * @ret sx \_Sx value, or negative error
256  */
258  struct acpi_fadt fadtab;
259  userptr_t rsdt;
260  userptr_t fadt;
261  userptr_t dsdt;
262  userptr_t ssdt;
263  unsigned int i;
264  int sx;
265 
266  /* Locate RSDT */
267  rsdt = acpi_find_rsdt();
268  if ( ! rsdt ) {
269  DBG ( "RSDT not found\n" );
270  return -ENOENT;
271  }
272 
273  /* Try DSDT first */
274  fadt = acpi_find ( FADT_SIGNATURE, 0 );
275  if ( fadt ) {
276  copy_from_user ( &fadtab, fadt, 0, sizeof ( fadtab ) );
277  dsdt = phys_to_user ( fadtab.dsdt );
278  if ( ( sx = acpi_sx_zsdt ( dsdt, signature ) ) >= 0 )
279  return sx;
280  }
281 
282  /* Try all SSDTs */
283  for ( i = 0 ; ; i++ ) {
284  ssdt = acpi_find ( SSDT_SIGNATURE, i );
285  if ( ! ssdt )
286  break;
287  if ( ( sx = acpi_sx_zsdt ( ssdt, signature ) ) >= 0 )
288  return sx;
289  }
290 
291  DBGC ( rsdt, "RSDT %#08lx could not find \\_Sx \"%s\"\n",
292  user_to_phys ( rsdt, 0 ), acpi_name ( signature ) );
293  return -ENOENT;
294 }
295 
296 /******************************************************************************
297  *
298  * Descriptors
299  *
300  ******************************************************************************
301  */
302 
303 /**
304  * Add ACPI descriptor
305  *
306  * @v desc ACPI descriptor
307  */
308 void acpi_add ( struct acpi_descriptor *desc ) {
309 
310  /* Add to list of descriptors */
311  ref_get ( desc->refcnt );
312  list_add_tail ( &desc->list, &desc->model->descs );
313 }
314 
315 /**
316  * Remove ACPI descriptor
317  *
318  * @v desc ACPI descriptor
319  */
320 void acpi_del ( struct acpi_descriptor *desc ) {
321 
322  /* Remove from list of descriptors */
323  list_check_contains_entry ( desc, &desc->model->descs, list );
324  list_del ( &desc->list );
325  ref_put ( desc->refcnt );
326 }
327 
328 /**
329  * Get object's ACPI descriptor
330  *
331  * @v intf Interface
332  * @ret desc ACPI descriptor, or NULL
333  */
334 struct acpi_descriptor * acpi_describe ( struct interface *intf ) {
335  struct interface *dest;
336  acpi_describe_TYPE ( void * ) *op =
337  intf_get_dest_op ( intf, acpi_describe, &dest );
338  void *object = intf_object ( dest );
339  struct acpi_descriptor *desc;
340 
341  if ( op ) {
342  desc = op ( object );
343  } else {
344  desc = NULL;
345  }
346 
347  intf_put ( dest );
348  return desc;
349 }
350 
351 /**
352  * Install ACPI tables
353  *
354  * @v install Table installation method
355  * @ret rc Return status code
356  */
357 int acpi_install ( int ( * install ) ( struct acpi_header *acpi ) ){
358  struct acpi_model *model;
359  int rc;
360 
361  for_each_table_entry ( model, ACPI_MODELS ) {
362  if ( ( rc = model->install ( install ) ) != 0 )
363  return rc;
364  }
365 
366  return 0;
367 }
uint16_t length
Length.
Definition: intel.h:14
#define RSDT_SIGNATURE
Root System Description Table (RSDT) signature.
Definition: acpi.h:95
struct arbelprm_rc_send_wqe rc
Definition: arbel.h:14
#define le32_to_cpu(value)
Definition: byteswap.h:113
Error codes.
struct list_head descs
List of descriptors.
Definition: acpi.h:171
static __always_inline void copy_from_user(void *dest, userptr_t src, off_t src_off, size_t len)
Copy data from user buffer.
Definition: uaccess.h:337
unsigned long user_to_phys(userptr_t userptr, off_t offset)
Convert user pointer to physical address.
static uint8_t acpi_checksum(userptr_t table)
Compute ACPI table checksum.
Definition: acpi.c:51
#define DBGC(...)
Definition: compiler.h:505
#define SSDT_SIGNATURE
Secondary System Description Table (SSDT) signature.
Definition: acpi.h:140
#define ENOENT
No such file or directory.
Definition: errno.h:514
userptr_t phys_to_user(unsigned long phys_addr)
Convert physical address to user pointer.
FILE_LICENCE(GPL2_OR_LATER_OR_UBDL)
int(* install)(int(*install)(struct acpi_header *acpi))
Install ACPI tables.
Definition: acpi.h:185
#define offsetof(type, field)
Get offset of a field within a structure.
Definition: stddef.h:24
ACPI Root System Description Table (RSDT)
Definition: acpi.h:98
Access to external ("user") memory.
void * intf_object(struct interface *intf)
Get pointer to object containing object interface.
Definition: interface.c:154
struct acpi_model * model
Table model.
Definition: acpi.h:147
void acpi_del(struct acpi_descriptor *desc)
Remove ACPI descriptor.
Definition: acpi.c:320
u8 signature
Definition: CIB_PRM.h:35
#define list_del(list)
Delete an entry from a list.
Definition: list.h:119
An object interface.
Definition: interface.h:109
Fixed ACPI Description Table (FADT)
Definition: acpi.h:109
An ACPI table model.
Definition: acpi.h:169
#define DBGC_HDA(...)
Definition: compiler.h:506
Object interfaces.
#define list_add_tail(new, head)
Add a new entry to the tail of a list.
Definition: list.h:93
static EFI_ACPI_TABLE_PROTOCOL * acpi
ACPI table protocol protocol.
Definition: efi_block.c:61
struct list_head list
List of ACPI descriptors for this model.
Definition: acpi.h:149
uint32_t entry[0]
ACPI table entries.
Definition: acpi.h:102
static userptr_t size_t offset
Offset of the first segment within the content.
Definition: deflate.h:259
#define FADT_SIGNATURE
Fixed ACPI Description Table (FADT) signature.
Definition: acpi.h:106
void acpi_fix_checksum(struct acpi_header *acpi)
Fix up ACPI table checksum.
Definition: acpi.c:76
static void * dest
Definition: strings.h:176
#define cpu_to_le32(value)
Definition: byteswap.h:107
int acpi_install(int(*install)(struct acpi_header *acpi))
Install ACPI tables.
Definition: acpi.c:357
ACPI data structures.
union aes_table_entry entry[256]
Table entries, indexed by S(N)
Definition: aes.c:26
#define ref_get(refcnt)
Get additional reference to object.
Definition: refcnt.h:92
#define for_each_table_entry(pointer, table)
Iterate through all entries within a linker table.
Definition: tables.h:358
unsigned char uint8_t
Definition: stdint.h:10
userptr_t acpi_find_rsdt(void)
Locate ACPI root system description table.
An ACPI description header.
Definition: acpi.h:28
unsigned int uint32_t
Definition: stdint.h:12
struct acpi_descriptor * acpi_describe(struct interface *intf)
Get object's ACPI descriptor.
Definition: acpi.c:334
#define acpi_describe_TYPE(object_type)
Definition: acpi.h:239
unsigned char byte
Definition: smc9000.h:38
struct acpi_header acpi
ACPI header.
Definition: acpi.h:100
static uint16_t struct vmbus_xfer_pages_operations * op
Definition: netvsc.h:327
An ACPI descriptor (used to construct ACPI tables)
Definition: acpi.h:143
uint32_t dsdt
Physical address of DSDT.
Definition: acpi.h:115
#define UNULL
Equivalent of NULL for user pointers.
Definition: uaccess.h:36
uint32_t len
Length.
Definition: ena.h:14
uint16_t count
Number of entries.
Definition: ena.h:22
void intf_put(struct interface *intf)
Decrement reference count on an object interface.
Definition: interface.c:144
static const char * acpi_name(uint32_t signature)
Transcribe ACPI table signature (for debugging)
Definition: acpi.h:55
userptr_t virt_to_user(volatile const void *addr)
Convert virtual address to user pointer.
#define ACPI_MODELS
ACPI models.
Definition: acpi.h:189
userptr_t acpi_find(uint32_t signature, unsigned int index)
Locate ACPI table.
Definition: acpi.c:89
struct refcnt * refcnt
Reference count of containing object.
Definition: acpi.h:145
struct arbelprm_port_state_change_st data
Message.
Definition: arbel.h:12
#define DBG(...)
Print a debugging message.
Definition: compiler.h:498
uint64_t index
Index of the first segment within the content.
Definition: pccrc.h:21
#define list_check_contains_entry(entry, head, member)
Check list contains a specified entry.
Definition: list.h:522
static int acpi_sx_zsdt(userptr_t zsdt, uint32_t signature)
Extract _Sx value from DSDT/SSDT.
Definition: acpi.c:186
void acpi_add(struct acpi_descriptor *desc)
Add ACPI descriptor.
Definition: acpi.c:308
#define NULL
NULL pointer (VOID *)
Definition: Base.h:362
#define intf_get_dest_op(intf, type, dest)
Get object interface destination and operation method.
Definition: interface.h:214
unsigned long int dword
Definition: smc9000.h:40
int acpi_sx(uint32_t signature)
Extract _Sx value from DSDT/SSDT.
Definition: acpi.c:257
#define ref_put(refcnt)
Drop reference to object.
Definition: refcnt.h:106
unsigned long userptr_t
A pointer to a user buffer.
Definition: uaccess.h:33