1 #ifndef _IPXE_ACPI_H
2 #define _IPXE_ACPI_H
3
4 /** @file
5 *
6 * ACPI data structures
7 *
8 */
9
10 FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
11
12 #include <stdint.h>
13 #include <byteswap.h>
14 #include <ipxe/refcnt.h>
15 #include <ipxe/list.h>
16 #include <ipxe/interface.h>
17 #include <ipxe/uaccess.h>
18 #include <ipxe/tables.h>
19 #include <ipxe/api.h>
20 #include <config/general.h>
21
22 /** An ACPI small resource descriptor header */
23 struct acpi_small_resource {
24 /** Tag byte */
25 uint8_t tag;
26 } __attribute__ (( packed ));
27
28 /** ACPI small resource length mask */
29 #define ACPI_SMALL_LEN_MASK 0x03
30
31 /** An ACPI end resource descriptor */
32 #define ACPI_END_RESOURCE 0x78
33
34 /** An ACPI end resource descriptor */
35 struct acpi_end_resource {
36 /** Header */
37 struct acpi_small_resource hdr;
38 /** Checksum */
39 uint8_t checksum;
40 } __attribute__ (( packed ));
41
42 /** An ACPI large resource descriptor header */
43 struct acpi_large_resource {
44 /** Tag byte */
45 uint8_t tag;
46 /** Length of data items */
47 uint16_t len;
48 } __attribute__ (( packed ));
49
50 /** ACPI large resource flag */
51 #define ACPI_LARGE 0x80
52
53 /** An ACPI QWORD address space resource descriptor */
54 #define ACPI_QWORD_ADDRESS_SPACE_RESOURCE 0x8a
55
56 /** An ACPI QWORD address space resource descriptor */
57 struct acpi_qword_address_space_resource {
58 /** Header */
59 struct acpi_large_resource hdr;
60 /** Resource type */
61 uint8_t type;
62 /** General flags */
63 uint8_t general;
64 /** Type-specific flags */
65 uint8_t specific;
66 /** Granularity */
67 uint64_t granularity;
68 /** Minimum address */
69 uint64_t min;
70 /** Maximum address */
71 uint64_t max;
72 /** Translation offset */
73 uint64_t offset;
74 /** Length */
75 uint64_t len;
76 } __attribute__ (( packed ));
77
78 /** A memory address space type */
79 #define ACPI_ADDRESS_TYPE_MEM 0x00
80
81 /** A bus number address space type */
82 #define ACPI_ADDRESS_TYPE_BUS 0x02
83
84 /** An ACPI resource descriptor */
85 union acpi_resource {
86 /** Tag byte */
87 uint8_t tag;
88 /** Small resource descriptor */
89 struct acpi_small_resource small;
90 /** End resource descriptor */
91 struct acpi_end_resource end;
92 /** Large resource descriptor */
93 struct acpi_large_resource large;
94 /** QWORD address space resource descriptor */
95 struct acpi_qword_address_space_resource qword;
96 };
97
98 /**
99 * Get ACPI resource tag
100 *
101 * @v res ACPI resource descriptor
102 * @ret tag Resource tag
103 */
acpi_resource_tag(union acpi_resource * res)104 static inline unsigned int acpi_resource_tag ( union acpi_resource *res ) {
105
106 return ( ( res->tag & ACPI_LARGE ) ?
107 res->tag : ( res->tag & ~ACPI_SMALL_LEN_MASK ) );
108 }
109
110 /**
111 * Get length of ACPI small resource descriptor
112 *
113 * @v res Small resource descriptor
114 * @ret len Length of descriptor
115 */
acpi_small_len(struct acpi_small_resource * res)116 static inline size_t acpi_small_len ( struct acpi_small_resource *res ) {
117
118 return ( sizeof ( *res ) + ( res->tag & ACPI_SMALL_LEN_MASK ) );
119 }
120
121 /**
122 * Get length of ACPI large resource descriptor
123 *
124 * @v res Large resource descriptor
125 * @ret len Length of descriptor
126 */
acpi_large_len(struct acpi_large_resource * res)127 static inline size_t acpi_large_len ( struct acpi_large_resource *res ) {
128
129 return ( sizeof ( *res ) + le16_to_cpu ( res->len ) );
130 }
131
132 /**
133 * Get length of ACPI resource descriptor
134 *
135 * @v res ACPI resource descriptor
136 * @ret len Length of descriptor
137 */
acpi_resource_len(union acpi_resource * res)138 static inline size_t acpi_resource_len ( union acpi_resource *res ) {
139
140 return ( ( res->tag & ACPI_LARGE ) ?
141 acpi_large_len ( &res->large ) :
142 acpi_small_len ( &res->small ) );
143 }
144
145 /**
146 * Get next ACPI resource descriptor
147 *
148 * @v res ACPI resource descriptor
149 * @ret next Next ACPI resource descriptor
150 */
151 static inline union acpi_resource *
acpi_resource_next(union acpi_resource * res)152 acpi_resource_next ( union acpi_resource *res ) {
153
154 return ( ( ( void * ) res ) + acpi_resource_len ( res ) );
155 }
156
157 /**
158 * An ACPI description header
159 *
160 * This is the structure common to the start of all ACPI system
161 * description tables.
162 */
163 struct acpi_header {
164 /** ACPI signature (4 ASCII characters) */
165 uint32_t signature;
166 /** Length of table, in bytes, including header */
167 uint32_t length;
168 /** ACPI Specification minor version number */
169 uint8_t revision;
170 /** To make sum of entire table == 0 */
171 uint8_t checksum;
172 /** OEM identification */
173 char oem_id[6];
174 /** OEM table identification */
175 char oem_table_id[8];
176 /** OEM revision number */
177 uint32_t oem_revision;
178 /** ASL compiler vendor ID */
179 char asl_compiler_id[4];
180 /** ASL compiler revision number */
181 uint32_t asl_compiler_revision;
182 } __attribute__ (( packed ));
183
184 /**
185 * Transcribe ACPI table signature (for debugging)
186 *
187 * @v signature ACPI table signature
188 * @ret name ACPI table signature name
189 */
acpi_name(uint32_t signature)190 static inline const char * acpi_name ( uint32_t signature ) {
191 static union {
192 uint32_t signature;
193 char name[5];
194 } u;
195
196 u.signature = cpu_to_le32 ( signature );
197 return u.name;
198 }
199
200 /**
201 * Build ACPI signature
202 *
203 * @v a First character of ACPI signature
204 * @v b Second character of ACPI signature
205 * @v c Third character of ACPI signature
206 * @v d Fourth character of ACPI signature
207 * @ret signature ACPI signature
208 */
209 #define ACPI_SIGNATURE( a, b, c, d ) \
210 ( ( (a) << 0 ) | ( (b) << 8 ) | ( (c) << 16 ) | ( (d) << 24 ) )
211
212 /** Root System Description Pointer signature */
213 #define RSDP_SIGNATURE { 'R', 'S', 'D', ' ', 'P', 'T', 'R', ' ' }
214
215 /** Root System Description Pointer */
216 struct acpi_rsdp {
217 /** Signature */
218 char signature[8];
219 /** To make sum of entire table == 0 */
220 uint8_t checksum;
221 /** OEM identification */
222 char oem_id[6];
223 /** Revision */
224 uint8_t revision;
225 /** Physical address of RSDT */
226 uint32_t rsdt;
227 } __attribute__ (( packed ));
228
229 /** Root System Description Table (RSDT) signature */
230 #define RSDT_SIGNATURE ACPI_SIGNATURE ( 'R', 'S', 'D', 'T' )
231
232 /** ACPI Root System Description Table (RSDT) */
233 struct acpi_rsdt {
234 /** ACPI header */
235 struct acpi_header acpi;
236 /** ACPI table entries */
237 uint32_t entry[0];
238 } __attribute__ (( packed ));
239
240 /** Fixed ACPI Description Table (FADT) signature */
241 #define FADT_SIGNATURE ACPI_SIGNATURE ( 'F', 'A', 'C', 'P' )
242
243 /** Fixed ACPI Description Table (FADT) */
244 struct acpi_fadt {
245 /** ACPI header */
246 struct acpi_header acpi;
247 /** Physical address of FACS */
248 uint32_t facs;
249 /** Physical address of DSDT */
250 uint32_t dsdt;
251 /** Unused by iPXE */
252 uint8_t unused[20];
253 /** PM1a Control Register Block */
254 uint32_t pm1a_cnt_blk;
255 /** PM1b Control Register Block */
256 uint32_t pm1b_cnt_blk;
257 /** PM2 Control Register Block */
258 uint32_t pm2_cnt_blk;
259 /** PM Timer Control Register Block */
260 uint32_t pm_tmr_blk;
261 } __attribute__ (( packed ));
262
263 /** ACPI PM1 Control Register (within PM1a_CNT_BLK or PM1A_CNT_BLK) */
264 #define ACPI_PM1_CNT 0
265 #define ACPI_PM1_CNT_SLP_TYP(x) ( (x) << 10 ) /**< Sleep type */
266 #define ACPI_PM1_CNT_SLP_EN ( 1 << 13 ) /**< Sleep enable */
267
268 /** ACPI PM Timer Register (within PM_TMR_BLK) */
269 #define ACPI_PM_TMR 0
270
271 /** Differentiated System Description Table (DSDT) signature */
272 #define DSDT_SIGNATURE ACPI_SIGNATURE ( 'D', 'S', 'D', 'T' )
273
274 /** Secondary System Description Table (SSDT) signature */
275 #define SSDT_SIGNATURE ACPI_SIGNATURE ( 'S', 'S', 'D', 'T' )
276
277 /** An ACPI descriptor (used to construct ACPI tables) */
278 struct acpi_descriptor {
279 /** Reference count of containing object */
280 struct refcnt *refcnt;
281 /** Table model */
282 struct acpi_model *model;
283 /** List of ACPI descriptors for this model */
284 struct list_head list;
285 };
286
287 /**
288 * Initialise ACPI descriptor
289 *
290 * @v desc ACPI descriptor
291 * @v model Table model
292 * @v refcnt Reference count
293 */
294 static inline __attribute__ (( always_inline )) void
acpi_init(struct acpi_descriptor * desc,struct acpi_model * model,struct refcnt * refcnt)295 acpi_init ( struct acpi_descriptor *desc, struct acpi_model *model,
296 struct refcnt *refcnt ) {
297
298 desc->refcnt = refcnt;
299 desc->model = model;
300 INIT_LIST_HEAD ( &desc->list );
301 }
302
303 /** An ACPI table model */
304 struct acpi_model {
305 /** List of descriptors */
306 struct list_head descs;
307 /**
308 * Check if ACPI descriptor is complete
309 *
310 * @v desc ACPI descriptor
311 * @ret rc Return status code
312 */
313 int ( * complete ) ( struct acpi_descriptor *desc );
314 /**
315 * Install ACPI tables
316 *
317 * @v install Installation method
318 * @ret rc Return status code
319 */
320 int ( * install ) ( int ( * install ) ( struct acpi_header *acpi ) );
321 };
322
323 /** ACPI models */
324 #define ACPI_MODELS __table ( struct acpi_model, "acpi_models" )
325
326 /** Declare an ACPI model */
327 #define __acpi_model __table_entry ( ACPI_MODELS, 01 )
328
329 /**
330 * Calculate static inline ACPI API function name
331 *
332 * @v _prefix Subsystem prefix
333 * @v _api_func API function
334 * @ret _subsys_func Subsystem API function
335 */
336 #define ACPI_INLINE( _subsys, _api_func ) \
337 SINGLE_API_INLINE ( ACPI_PREFIX_ ## _subsys, _api_func )
338
339 /**
340 * Provide an ACPI API implementation
341 *
342 * @v _prefix Subsystem prefix
343 * @v _api_func API function
344 * @v _func Implementing function
345 */
346 #define PROVIDE_ACPI( _subsys, _api_func, _func ) \
347 PROVIDE_SINGLE_API ( ACPI_PREFIX_ ## _subsys, _api_func, _func )
348
349 /**
350 * Provide a static inline ACPI API implementation
351 *
352 * @v _prefix Subsystem prefix
353 * @v _api_func API function
354 */
355 #define PROVIDE_ACPI_INLINE( _subsys, _api_func ) \
356 PROVIDE_SINGLE_API_INLINE ( ACPI_PREFIX_ ## _subsys, _api_func )
357
358 extern userptr_t acpi_find_via_rsdt ( uint32_t signature, unsigned int index );
359
360 /* Include all architecture-independent ACPI API headers */
361 #include <ipxe/null_acpi.h>
362 #include <ipxe/efi/efi_acpi.h>
363 #include <ipxe/linux/linux_acpi.h>
364
365 /* Include all architecture-dependent ACPI API headers */
366 #include <bits/acpi.h>
367
368 /**
369 * Locate ACPI root system description table
370 *
371 * @ret rsdt ACPI root system description table, or UNULL
372 */
373 userptr_t acpi_find_rsdt ( void );
374
375 /**
376 * Locate ACPI table
377 *
378 * @v signature Requested table signature
379 * @v index Requested index of table with this signature
380 * @ret table Table, or UNULL if not found
381 */
382 userptr_t acpi_find ( uint32_t signature, unsigned int index );
383
384 extern struct acpi_descriptor *
385 acpi_describe ( struct interface *interface );
386 #define acpi_describe_TYPE( object_type ) \
387 typeof ( struct acpi_descriptor * ( object_type ) )
388
389 extern void acpi_fix_checksum ( struct acpi_header *acpi );
390 extern int acpi_extract ( uint32_t signature, void *data,
391 int ( * extract ) ( userptr_t zsdt, size_t len,
392 size_t offset, void *data ) );
393 extern void acpi_add ( struct acpi_descriptor *desc );
394 extern void acpi_del ( struct acpi_descriptor *desc );
395 extern int acpi_install ( int ( * install ) ( struct acpi_header *acpi ) );
396
397 #endif /* _IPXE_ACPI_H */
398