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
24FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
25FILE_SECBOOT ( PERMITTED );
26
27#include <string.h>
28#include <errno.h>
29#include <byteswap.h>
30#include <ipxe/uaccess.h>
31#include <ipxe/iomap.h>
32#include <ipxe/acpi.h>
33#include <ipxe/interface.h>
34
35/** @file
36 *
37 * ACPI support functions
38 *
39 */
40
41/** Colour for debug messages */
42#define colour FADT_SIGNATURE
43
44/** ACPI table finder
45 *
46 * May be overridden at link time to inject tables for testing.
47 */
49
50/******************************************************************************
51 *
52 * Utility functions
53 *
54 ******************************************************************************
55 */
56
57/**
58 * Compute ACPI table checksum
59 *
60 * @v acpi Any ACPI table header
61 * @ret checksum 0 if checksum is good
62 */
63static uint8_t acpi_checksum ( const struct acpi_header *acpi ) {
64 const uint8_t *byte = ( ( const void * ) acpi );
65 size_t len = le32_to_cpu ( acpi->length );
66 uint8_t sum = 0;
67
68 /* Compute checksum */
69 while ( len-- )
70 sum += *(byte++);
71
72 return sum;
73}
74
75/**
76 * Fix up ACPI table checksum
77 *
78 * @v acpi ACPI table header
79 */
81
82 /* Update checksum */
83 acpi->checksum -= acpi_checksum ( acpi );
84}
85
86/**
87 * Locate ACPI table
88 *
89 * @v signature Requested table signature
90 * @v index Requested index of table with this signature
91 * @ret table Table, or NULL if not found
92 */
94 unsigned int index ) {
95
96 return ( *acpi_finder ) ( signature, index );
97}
98
99/**
100 * Locate ACPI table via RSDT
101 *
102 * @v signature Requested table signature
103 * @v index Requested index of table with this signature
104 * @ret table Table, or NULL if not found
105 */
107 unsigned int index ) {
108 const struct acpi_rsdt *rsdt;
109 const struct acpi_header *table;
110 size_t len;
111 unsigned int count;
112 unsigned int i;
113
114 /* Locate RSDT */
115 rsdt = acpi_find_rsdt();
116 if ( ! rsdt ) {
117 DBG ( "RSDT not found\n" );
118 return NULL;
119 }
120
121 /* Read RSDT header */
122 if ( rsdt->acpi.signature != cpu_to_le32 ( RSDT_SIGNATURE ) ) {
123 DBGC ( colour, "RSDT %#08lx has invalid signature:\n",
124 virt_to_phys ( rsdt ) );
125 DBGC_HDA ( colour, virt_to_phys ( rsdt ), &rsdt->acpi,
126 sizeof ( rsdt->acpi ) );
127 return NULL;
128 }
129 len = le32_to_cpu ( rsdt->acpi.length );
130 if ( len < sizeof ( rsdt->acpi ) ) {
131 DBGC ( colour, "RSDT %#08lx has invalid length:\n",
132 virt_to_phys ( rsdt ) );
133 DBGC_HDA ( colour, virt_to_phys ( rsdt ), &rsdt->acpi,
134 sizeof ( rsdt->acpi ) );
135 return NULL;
136 }
137
138 /* Calculate number of entries */
139 count = ( ( len - sizeof ( rsdt->acpi ) ) /
140 sizeof ( rsdt->entry[0] ) );
141
142 /* Search through entries */
143 for ( i = 0 ; i < count ; i++ ) {
144
145 /* Read table header */
146 table = phys_to_virt ( rsdt->entry[i] );
147
148 /* Check table signature */
149 if ( table->signature != cpu_to_le32 ( signature ) )
150 continue;
151
152 /* Check index */
153 if ( index-- )
154 continue;
155
156 /* Check table integrity */
157 if ( acpi_checksum ( table ) != 0 ) {
158 DBGC ( colour, "RSDT %#08lx found %s with bad "
159 "checksum at %#08lx\n", virt_to_phys ( rsdt ),
161 virt_to_phys ( table ) );
162 break;
163 }
164
165 DBGC ( colour, "RSDT %#08lx found %s at %#08lx\n",
166 virt_to_phys ( rsdt ), acpi_name ( signature ),
167 virt_to_phys ( table ) );
168 return table;
169 }
170
171 DBGC ( colour, "RSDT %#08lx could not find %s\n",
172 virt_to_phys ( rsdt ), acpi_name ( signature ) );
173 return NULL;
174}
175
176/**
177 * Extract value from DSDT/SSDT
178 *
179 * @v zsdt DSDT or SSDT
180 * @v signature Signature (e.g. "_S5_")
181 * @v data Data buffer
182 * @v extract Extraction method
183 * @ret rc Return status code
184 */
185static int acpi_zsdt ( const struct acpi_header *zsdt,
186 uint32_t signature, void *data,
187 int ( * extract ) ( const struct acpi_header *zsdt,
188 size_t len, size_t offset,
189 void *data ) ) {
190 uint32_t buf;
191 size_t offset;
192 size_t len;
193 int rc;
194
195 /* Read table header */
196 len = le32_to_cpu ( zsdt->length );
197
198 /* Locate signature */
199 for ( offset = sizeof ( *zsdt ) ;
200 ( ( offset + sizeof ( buf ) /* signature */ ) < len ) ;
201 offset++ ) {
202
203 /* Check signature */
204 memcpy ( &buf, ( ( ( const void * ) zsdt ) + offset ),
205 sizeof ( buf ) );
206 if ( buf != cpu_to_le32 ( signature ) )
207 continue;
208 DBGC ( zsdt, "DSDT/SSDT %#08lx found %s at offset %#zx\n",
209 virt_to_phys ( zsdt ), acpi_name ( signature ),
210 offset );
211
212 /* Attempt to extract data */
213 if ( ( rc = extract ( zsdt, len, offset, data ) ) == 0 )
214 return 0;
215 }
216
217 return -ENOENT;
218}
219
220/**
221 * Extract value from DSDT/SSDT
222 *
223 * @v signature Signature (e.g. "_S5_")
224 * @v data Data buffer
225 * @v extract Extraction method
226 * @ret rc Return status code
227 */
229 int ( * extract ) ( const struct acpi_header *zsdt,
230 size_t len, size_t offset,
231 void *data ) ) {
232 const struct acpi_fadt *fadt;
233 const struct acpi_header *dsdt;
234 const struct acpi_header *ssdt;
235 unsigned int i;
236 int rc;
237
238 /* Try DSDT first */
239 fadt = container_of ( acpi_table ( FADT_SIGNATURE, 0 ),
240 struct acpi_fadt, acpi );
241 if ( fadt ) {
242 dsdt = phys_to_virt ( fadt->dsdt );
243 if ( ( rc = acpi_zsdt ( dsdt, signature, data,
244 extract ) ) == 0 )
245 return 0;
246 }
247
248 /* Try all SSDTs */
249 for ( i = 0 ; ; i++ ) {
250 ssdt = acpi_table ( SSDT_SIGNATURE, i );
251 if ( ! ssdt )
252 break;
253 if ( ( rc = acpi_zsdt ( ssdt, signature, data,
254 extract ) ) == 0 )
255 return 0;
256 }
257
258 DBGC ( colour, "ACPI could not find \"%s\"\n",
259 acpi_name ( signature ) );
260 return -ENOENT;
261}
262
263/**
264 * Map an ACPI generic address
265 *
266 * @v address Generic address
267 * @v len Length of region
268 * @ret io_addr I/O address, or NULL on error
269 */
270void * acpi_ioremap ( struct acpi_address *address, size_t len ) {
271 physaddr_t base = le64_to_cpu ( address->address );
272
273 switch ( address->type ) {
275 return ioremap ( base, len );
277 return ( ( void * ) base );
278 default:
279 return NULL;
280 }
281}
282
283/******************************************************************************
284 *
285 * Descriptors
286 *
287 ******************************************************************************
288 */
289
290/**
291 * Add ACPI descriptor
292 *
293 * @v desc ACPI descriptor
294 */
295void acpi_add ( struct acpi_descriptor *desc ) {
296
297 /* Add to list of descriptors */
298 ref_get ( desc->refcnt );
299 list_add_tail ( &desc->list, &desc->model->descs );
300}
301
302/**
303 * Remove ACPI descriptor
304 *
305 * @v desc ACPI descriptor
306 */
307void acpi_del ( struct acpi_descriptor *desc ) {
308
309 /* Remove from list of descriptors */
310 list_check_contains_entry ( desc, &desc->model->descs, list );
311 list_del ( &desc->list );
312 ref_put ( desc->refcnt );
313}
314
315/**
316 * Get object's ACPI descriptor
317 *
318 * @v intf Interface
319 * @ret desc ACPI descriptor, or NULL
320 */
321struct acpi_descriptor * acpi_describe ( struct interface *intf ) {
322 struct interface *dest;
323 acpi_describe_TYPE ( void * ) *op =
325 void *object = intf_object ( dest );
326 struct acpi_descriptor *desc;
327
328 if ( op ) {
329 desc = op ( object );
330 } else {
331 desc = NULL;
332 }
333
334 intf_put ( dest );
335 return desc;
336}
337
338/**
339 * Install ACPI tables
340 *
341 * @v install Table installation method
342 * @ret rc Return status code
343 */
344int acpi_install ( int ( * install ) ( struct acpi_header *acpi ) ){
345 struct acpi_model *model;
346 int rc;
347
349 if ( ( rc = model->install ( install ) ) != 0 )
350 return rc;
351 }
352
353 return 0;
354}
#define NULL
NULL pointer (VOID *)
Definition Base.h:322
u8 signature
CPU signature.
Definition CIB_PRM.h:7
const struct acpi_header * acpi_table(uint32_t signature, unsigned int index)
Locate ACPI table.
Definition acpi.c:93
#define colour
Colour for debug messages.
Definition acpi.c:42
void acpi_del(struct acpi_descriptor *desc)
Remove ACPI descriptor.
Definition acpi.c:307
int acpi_install(int(*install)(struct acpi_header *acpi))
Install ACPI tables.
Definition acpi.c:344
void acpi_add(struct acpi_descriptor *desc)
Add ACPI descriptor.
Definition acpi.c:295
void acpi_fix_checksum(struct acpi_header *acpi)
Fix up ACPI table checksum.
Definition acpi.c:80
const struct acpi_header * acpi_find_via_rsdt(uint32_t signature, unsigned int index)
Locate ACPI table via RSDT.
Definition acpi.c:106
static int acpi_zsdt(const struct acpi_header *zsdt, uint32_t signature, void *data, int(*extract)(const struct acpi_header *zsdt, size_t len, size_t offset, void *data))
Extract value from DSDT/SSDT.
Definition acpi.c:185
typeof(acpi_finder=acpi_find)
ACPI table finder.
Definition acpi.c:48
int acpi_extract(uint32_t signature, void *data, int(*extract)(const struct acpi_header *zsdt, size_t len, size_t offset, void *data))
Extract value from DSDT/SSDT.
Definition acpi.c:228
void * acpi_ioremap(struct acpi_address *address, size_t len)
Map an ACPI generic address.
Definition acpi.c:270
struct acpi_descriptor * acpi_describe(struct interface *intf)
Get object's ACPI descriptor.
Definition acpi.c:321
struct arbelprm_rc_send_wqe rc
Definition arbel.h:3
unsigned int uint32_t
Definition stdint.h:12
unsigned long physaddr_t
Definition stdint.h:20
unsigned char uint8_t
Definition stdint.h:10
long index
Definition bigint.h:65
if(len >=6 *4) __asm__ __volatile__("movsl" if(len >=5 *4) __asm__ __volatile__("movsl" if(len >=4 *4) __asm__ __volatile__("movsl" if(len >=3 *4) __asm__ __volatile__("movsl" if(len >=2 *4) __asm__ __volatile__("movsl" if(len >=1 *4) __asm__ __volatile__("movsl" if((len % 4) >=2) __asm__ __volatile__("movsw" if((len % 2) >=1) __asm__ __volatile__("movsb" retur dest)
Definition string.h:151
uint16_t offset
Offset to command line.
Definition bzimage.h:3
ring len
Length.
Definition dwmac.h:226
static EFI_ACPI_TABLE_PROTOCOL * acpi
ACPI table protocol protocol.
Definition efi_block.c:67
uint8_t data[48]
Additional event data.
Definition ena.h:11
uint64_t address
Base address.
Definition ena.h:13
struct ena_llq_option desc
Descriptor counts.
Definition ena.h:9
Error codes.
#define DBGC(...)
Definition compiler.h:505
#define DBG(...)
Print a debugging message.
Definition compiler.h:498
#define DBGC_HDA(...)
Definition compiler.h:506
static unsigned int count
Number of entries.
Definition dwmac.h:220
#define FILE_LICENCE(_licence)
Declare a particular licence as applying to a file.
Definition compiler.h:896
#define ENOENT
No such file or directory.
Definition errno.h:515
#define FILE_SECBOOT(_status)
Declare a file's UEFI Secure Boot permission status.
Definition compiler.h:926
#define le64_to_cpu(value)
Definition byteswap.h:115
#define le32_to_cpu(value)
Definition byteswap.h:114
#define cpu_to_le32(value)
Definition byteswap.h:108
#define __attribute__(x)
Definition compiler.h:10
ACPI data structures.
#define acpi_describe_TYPE(object_type)
Definition acpi.h:405
#define ACPI_MODELS
ACPI models.
Definition acpi.h:341
static const char * acpi_name(uint32_t signature)
Transcribe ACPI table signature (for debugging)
Definition acpi.h:207
#define FADT_SIGNATURE
Fixed ACPI Description Table (FADT) signature.
Definition acpi.h:258
#define RSDT_SIGNATURE
Root System Description Table (RSDT) signature.
Definition acpi.h:247
const struct acpi_rsdt * acpi_find_rsdt(void)
Locate ACPI root system description table.
#define ACPI_ADDRESS_TYPE_MEM
A memory address space type.
Definition acpi.h:37
#define ACPI_ADDRESS_TYPE_IO
An I/O address space type.
Definition acpi.h:40
const struct acpi_header *(* acpi_finder)(uint32_t signature, unsigned int index)
#define SSDT_SIGNATURE
Secondary System Description Table (SSDT) signature.
Definition acpi.h:292
iPXE I/O mapping API
void * ioremap(unsigned long bus_addr, size_t len)
Map bus address as an I/O address.
String functions.
void * memcpy(void *dest, const void *src, size_t len) __nonnull
void * intf_object(struct interface *intf)
Get pointer to object containing object interface.
Definition interface.c:160
void intf_put(struct interface *intf)
Decrement reference count on an object interface.
Definition interface.c:150
Object interfaces.
#define intf_get_dest_op(intf, type, dest)
Get object interface destination and operation method.
Definition interface.h:270
Access to external ("user") memory.
uint32_t base
Base.
Definition librm.h:3
#define list_add_tail(new, head)
Add a new entry to the tail of a list.
Definition list.h:94
#define list_del(list)
Delete an entry from a list.
Definition list.h:120
#define list_check_contains_entry(entry, head, member)
Check list contains a specified entry.
Definition list.h:550
static uint16_t struct vmbus_xfer_pages_operations * op
Definition netvsc.h:327
#define ref_get(refcnt)
Get additional reference to object.
Definition refcnt.h:93
#define ref_put(refcnt)
Drop reference to object.
Definition refcnt.h:107
static acpi_find(uint32_t signature, unsigned int index)
Locate ACPI table.
Definition rsdp.h:27
#define container_of(ptr, type, field)
Get containing structure.
Definition stddef.h:36
An ACPI generic address structure.
Definition acpi.h:23
An ACPI descriptor (used to construct ACPI tables)
Definition acpi.h:295
Fixed ACPI Description Table (FADT)
Definition acpi.h:261
uint32_t dsdt
Physical address of DSDT.
Definition acpi.h:267
An ACPI description header.
Definition acpi.h:180
uint32_t signature
ACPI signature (4 ASCII characters)
Definition acpi.h:182
uint32_t length
Length of table, in bytes, including header.
Definition acpi.h:184
An ACPI table model.
Definition acpi.h:321
int(* install)(int(*install)(struct acpi_header *acpi))
Install ACPI tables.
Definition acpi.h:337
ACPI Root System Description Table (RSDT)
Definition acpi.h:250
struct acpi_header acpi
ACPI header.
Definition acpi.h:252
uint32_t entry[0]
ACPI table entries.
Definition acpi.h:254
An object interface.
Definition interface.h:125
struct interface * intf
Original interface.
Definition interface.h:159
#define for_each_table_entry(pointer, table)
Iterate through all entries within a linker table.
Definition tables.h:386