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