iPXE
Functions
acpi.c File Reference

ACPI support functions. More...

#include <errno.h>
#include <byteswap.h>
#include <ipxe/uaccess.h>
#include <ipxe/acpi.h>
#include <ipxe/interface.h>

Go to the source code of this file.

Functions

 FILE_LICENCE (GPL2_OR_LATER_OR_UBDL)
 
static uint8_t acpi_checksum (userptr_t table)
 Compute ACPI table checksum. More...
 
void acpi_fix_checksum (struct acpi_header *acpi)
 Fix up ACPI table checksum. More...
 
userptr_t acpi_find (uint32_t signature, unsigned int index)
 Locate ACPI table. More...
 
static int acpi_sx_zsdt (userptr_t zsdt, uint32_t signature)
 Extract _Sx value from DSDT/SSDT. More...
 
int acpi_sx (uint32_t signature)
 Extract _Sx value from DSDT/SSDT. More...
 
void acpi_add (struct acpi_descriptor *desc)
 Add ACPI descriptor. More...
 
void acpi_del (struct acpi_descriptor *desc)
 Remove ACPI descriptor. More...
 
struct acpi_descriptoracpi_describe (struct interface *intf)
 Get object's ACPI descriptor. More...
 
int acpi_install (int(*install)(struct acpi_header *acpi))
 Install ACPI tables. More...
 

Detailed Description

ACPI support functions.

Definition in file acpi.c.

Function Documentation

◆ FILE_LICENCE()

FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL  )

◆ acpi_checksum()

static uint8_t acpi_checksum ( userptr_t  table)
static

Compute ACPI table checksum.

Parameters
tableAny ACPI table
Return values
checksum0 if checksum is good

Definition at line 51 of file acpi.c.

51  {
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 }
uint16_t length
Length.
Definition: intel.h:14
#define le32_to_cpu(value)
Definition: byteswap.h:113
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
#define offsetof(type, field)
Get offset of a field within a structure.
Definition: stddef.h:24
static EFI_ACPI_TABLE_PROTOCOL * acpi
ACPI table protocol protocol.
Definition: efi_block.c:61
unsigned char uint8_t
Definition: stdint.h:10
An ACPI description header.
Definition: acpi.h:28
struct arbelprm_port_state_change_st data
Message.
Definition: arbel.h:12

References acpi, copy_from_user(), data, le32_to_cpu, length, and offsetof.

Referenced by acpi_find(), and acpi_fix_checksum().

◆ acpi_fix_checksum()

void acpi_fix_checksum ( struct acpi_header acpi)

Fix up ACPI table checksum.

Parameters
acpiACPI table header

Definition at line 76 of file acpi.c.

76  {
77 
78  /* Update checksum */
79  acpi->checksum -= acpi_checksum ( virt_to_user ( acpi ) );
80 }
static uint8_t acpi_checksum(userptr_t table)
Compute ACPI table checksum.
Definition: acpi.c:51
static EFI_ACPI_TABLE_PROTOCOL * acpi
ACPI table protocol protocol.
Definition: efi_block.c:61
userptr_t virt_to_user(volatile const void *addr)
Convert virtual address to user pointer.

References acpi, acpi_checksum(), and virt_to_user().

Referenced by efi_block_install(), and int13_install().

◆ acpi_find()

userptr_t acpi_find ( uint32_t  signature,
unsigned int  index 
)

Locate ACPI table.

Parameters
signatureRequested table signature
indexRequested index of table with this signature
Return values
tableTable, or UNULL if not found

Definition at line 89 of file acpi.c.

89  {
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 }
#define RSDT_SIGNATURE
Root System Description Table (RSDT) signature.
Definition: acpi.h:95
#define le32_to_cpu(value)
Definition: byteswap.h:113
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
userptr_t phys_to_user(unsigned long phys_addr)
Convert physical address to user pointer.
#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
u8 signature
Definition: CIB_PRM.h:35
#define DBGC_HDA(...)
Definition: compiler.h:506
static EFI_ACPI_TABLE_PROTOCOL * acpi
ACPI table protocol protocol.
Definition: efi_block.c:61
uint32_t entry[0]
ACPI table entries.
Definition: acpi.h:102
#define cpu_to_le32(value)
Definition: byteswap.h:107
union aes_table_entry entry[256]
Table entries, indexed by S(N)
Definition: aes.c:26
userptr_t acpi_find_rsdt(void)
Locate ACPI root system description table.
An ACPI description header.
Definition: acpi.h:28
struct acpi_header acpi
ACPI header.
Definition: acpi.h:100
#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
static const char * acpi_name(uint32_t signature)
Transcribe ACPI table signature (for debugging)
Definition: acpi.h:55
#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
unsigned long userptr_t
A pointer to a user buffer.
Definition: uaccess.h:33
if(natsemi->flags &NATSEMI_64BIT) return 1

References acpi, acpi_rsdt::acpi, acpi_checksum(), acpi_find_rsdt(), acpi_name(), copy_from_user(), count, cpu_to_le32, DBG, DBGC, DBGC_HDA, entry, acpi_rsdt::entry, index, le32_to_cpu, len, offsetof, phys_to_user(), RSDT_SIGNATURE, signature, UNULL, and user_to_phys().

Referenced by acpi_poweroff(), acpi_settings_fetch(), acpi_sx(), and acpi_timer_probe().

◆ acpi_sx_zsdt()

static int acpi_sx_zsdt ( userptr_t  zsdt,
uint32_t  signature 
)
static

Extract _Sx value from DSDT/SSDT.

Parameters
zsdtDSDT or SSDT
signatureSignature (e.g. "_S5_")
Return values
sx_Sx value, or negative error

In theory, extracting the _Sx value from the DSDT/SSDT requires a full ACPI parser plus some heuristics to work around the various broken encodings encountered in real ACPI implementations.

In practice, we can get the same result by scanning through the DSDT/SSDT for the signature (e.g. "_S5_"), extracting the first four bytes, removing any bytes with bit 3 set, and treating whatever is left as a little-endian value. This is one of the uglier hacks I have ever implemented, but it's still prettier than the ACPI specification itself.

Definition at line 186 of file acpi.c.

186  {
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 }
#define le32_to_cpu(value)
Definition: byteswap.h:113
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.
#define DBGC(...)
Definition: compiler.h:505
#define ENOENT
No such file or directory.
Definition: errno.h:514
u8 signature
Definition: CIB_PRM.h:35
static EFI_ACPI_TABLE_PROTOCOL * acpi
ACPI table protocol protocol.
Definition: efi_block.c:61
static userptr_t size_t offset
Offset of the first segment within the content.
Definition: deflate.h:259
#define cpu_to_le32(value)
Definition: byteswap.h:107
unsigned char uint8_t
Definition: stdint.h:10
An ACPI description header.
Definition: acpi.h:28
unsigned int uint32_t
Definition: stdint.h:12
unsigned char byte
Definition: smc9000.h:38
uint32_t len
Length.
Definition: ena.h:14
static const char * acpi_name(uint32_t signature)
Transcribe ACPI table signature (for debugging)
Definition: acpi.h:55
unsigned long int dword
Definition: smc9000.h:40

References acpi, acpi_name(), copy_from_user(), cpu_to_le32, DBGC, ENOENT, le32_to_cpu, len, offset, signature, and user_to_phys().

Referenced by acpi_sx().

◆ acpi_sx()

int acpi_sx ( uint32_t  signature)

Extract _Sx value from DSDT/SSDT.

Parameters
signatureSignature (e.g. "_S5_")
Return values
sx_Sx value, or negative error

Definition at line 257 of file acpi.c.

257  {
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 }
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.
#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.
u8 signature
Definition: CIB_PRM.h:35
Fixed ACPI Description Table (FADT)
Definition: acpi.h:109
#define FADT_SIGNATURE
Fixed ACPI Description Table (FADT) signature.
Definition: acpi.h:106
userptr_t acpi_find_rsdt(void)
Locate ACPI root system description table.
uint32_t dsdt
Physical address of DSDT.
Definition: acpi.h:115
static const char * acpi_name(uint32_t signature)
Transcribe ACPI table signature (for debugging)
Definition: acpi.h:55
userptr_t acpi_find(uint32_t signature, unsigned int index)
Locate ACPI table.
Definition: acpi.c:89
#define DBG(...)
Print a debugging message.
Definition: compiler.h:498
static int acpi_sx_zsdt(userptr_t zsdt, uint32_t signature)
Extract _Sx value from DSDT/SSDT.
Definition: acpi.c:186
unsigned long userptr_t
A pointer to a user buffer.
Definition: uaccess.h:33

References acpi_find(), acpi_find_rsdt(), acpi_name(), acpi_sx_zsdt(), copy_from_user(), DBG, DBGC, acpi_fadt::dsdt, ENOENT, FADT_SIGNATURE, phys_to_user(), signature, SSDT_SIGNATURE, and user_to_phys().

Referenced by acpi_poweroff().

◆ acpi_add()

void acpi_add ( struct acpi_descriptor desc)

Add ACPI descriptor.

Parameters
descACPI descriptor

Definition at line 308 of file acpi.c.

308  {
309 
310  /* Add to list of descriptors */
311  ref_get ( desc->refcnt );
312  list_add_tail ( &desc->list, &desc->model->descs );
313 }
struct list_head descs
List of descriptors.
Definition: acpi.h:171
struct acpi_model * model
Table model.
Definition: acpi.h:147
#define list_add_tail(new, head)
Add a new entry to the tail of a list.
Definition: list.h:93
struct list_head list
List of ACPI descriptors for this model.
Definition: acpi.h:149
#define ref_get(refcnt)
Get additional reference to object.
Definition: refcnt.h:92
struct refcnt * refcnt
Reference count of containing object.
Definition: acpi.h:145

References acpi_model::descs, acpi_descriptor::list, list_add_tail, acpi_descriptor::model, ref_get, and acpi_descriptor::refcnt.

Referenced by sanpath_open().

◆ acpi_del()

void acpi_del ( struct acpi_descriptor desc)

Remove ACPI descriptor.

Parameters
descACPI descriptor

Definition at line 320 of file acpi.c.

320  {
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 }
struct list_head descs
List of descriptors.
Definition: acpi.h:171
struct acpi_model * model
Table model.
Definition: acpi.h:147
#define list_del(list)
Delete an entry from a list.
Definition: list.h:119
struct list_head list
List of ACPI descriptors for this model.
Definition: acpi.h:149
struct refcnt * refcnt
Reference count of containing object.
Definition: acpi.h:145
#define list_check_contains_entry(entry, head, member)
Check list contains a specified entry.
Definition: list.h:522
#define ref_put(refcnt)
Drop reference to object.
Definition: refcnt.h:106

References acpi_model::descs, acpi_descriptor::list, list_check_contains_entry, list_del, acpi_descriptor::model, ref_put, and acpi_descriptor::refcnt.

Referenced by sandev_undescribe(), and sanpath_open().

◆ acpi_describe()

struct acpi_descriptor* acpi_describe ( struct interface intf)

Get object's ACPI descriptor.

Parameters
intfInterface
Return values
descACPI descriptor, or NULL

Definition at line 334 of file acpi.c.

334  {
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 }
void * intf_object(struct interface *intf)
Get pointer to object containing object interface.
Definition: interface.c:154
An object interface.
Definition: interface.h:109
static void * dest
Definition: strings.h:176
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
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
void intf_put(struct interface *intf)
Decrement reference count on an object interface.
Definition: interface.c:144
#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

References acpi_describe(), acpi_describe_TYPE, dest, intf_get_dest_op, intf_object(), intf_put(), NULL, and op.

Referenced by acpi_describe(), and sanpath_open().

◆ acpi_install()

int acpi_install ( int(*)(struct acpi_header *acpi install)

Install ACPI tables.

Parameters
installTable installation method
Return values
rcReturn status code

Definition at line 357 of file acpi.c.

357  {
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 }
struct arbelprm_rc_send_wqe rc
Definition: arbel.h:14
int(* install)(int(*install)(struct acpi_header *acpi))
Install ACPI tables.
Definition: acpi.h:185
An ACPI table model.
Definition: acpi.h:169
#define for_each_table_entry(pointer, table)
Iterate through all entries within a linker table.
Definition: tables.h:358
#define ACPI_MODELS
ACPI models.
Definition: acpi.h:189

References ACPI_MODELS, for_each_table_entry, acpi_model::install, and rc.

Referenced by dummy_san_describe(), efi_block_describe(), and int13_describe().