Переглянути джерело

[acpi] Add support for ACPI power off

Signed-off-by: Michael Brown <mcb30@ipxe.org>
tags/v1.20.1
Michael Brown 8 роки тому
джерело
коміт
e19c0a8fd2

+ 1
- 0
src/arch/x86/include/bios.h Переглянути файл

@@ -4,6 +4,7 @@
4 4
 FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
5 5
 
6 6
 #define BDA_SEG 0x0040
7
+#define BDA_EBDA 0x000e
7 8
 #define BDA_EQUIPMENT_WORD 0x0010
8 9
 #define BDA_FBMS 0x0013
9 10
 #define BDA_REBOOT 0x0072

+ 1
- 0
src/arch/x86/include/bits/errfile.h Переглянути файл

@@ -24,6 +24,7 @@ FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
24 24
 #define ERRFILE_int13con	( ERRFILE_ARCH | ERRFILE_CORE | 0x000d0000 )
25 25
 #define ERRFILE_gdbmach		( ERRFILE_ARCH | ERRFILE_CORE | 0x000e0000 )
26 26
 #define ERRFILE_rtc_entropy	( ERRFILE_ARCH | ERRFILE_CORE | 0x000f0000 )
27
+#define ERRFILE_acpipwr		( ERRFILE_ARCH | ERRFILE_CORE | 0x00100000 )
27 28
 
28 29
 #define ERRFILE_bootsector     ( ERRFILE_ARCH | ERRFILE_IMAGE | 0x00000000 )
29 30
 #define ERRFILE_bzimage	       ( ERRFILE_ARCH | ERRFILE_IMAGE | 0x00010000 )

+ 14
- 0
src/arch/x86/include/ipxe/acpipwr.h Переглянути файл

@@ -0,0 +1,14 @@
1
+#ifndef _IPXE_ACPIPWR_H
2
+#define _IPXE_ACPIPWR_H
3
+
4
+/** @file
5
+ *
6
+ * ACPI power off
7
+ *
8
+ */
9
+
10
+FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
11
+
12
+extern int acpi_poweroff ( void );
13
+
14
+#endif /* _IPXE_ACPIPWR_H */

+ 14
- 0
src/arch/x86/include/ipxe/apm.h Переглянути файл

@@ -0,0 +1,14 @@
1
+#ifndef _IPXE_APM_H
2
+#define _IPXE_APM_H
3
+
4
+/** @file
5
+ *
6
+ * Advanced Power Management
7
+ *
8
+ */
9
+
10
+FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
11
+
12
+extern int apm_poweroff ( void );
13
+
14
+#endif /* _IPXE_APM_H */

+ 116
- 0
src/arch/x86/interface/pcbios/acpipwr.c Переглянути файл

@@ -0,0 +1,116 @@
1
+/*
2
+ * Copyright (C) 2016 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 <realmode.h>
29
+#include <bios.h>
30
+#include <ipxe/io.h>
31
+#include <ipxe/acpi.h>
32
+#include <ipxe/acpipwr.h>
33
+
34
+/** @file
35
+ *
36
+ * ACPI power off
37
+ *
38
+ */
39
+
40
+/** Colour for debug messages */
41
+#define colour FADT_SIGNATURE
42
+
43
+/** _S5_ signature */
44
+#define S5_SIGNATURE ACPI_SIGNATURE ( '_', 'S', '5', '_' )
45
+
46
+/**
47
+ * Power off the computer using ACPI
48
+ *
49
+ * @ret rc		Return status code
50
+ */
51
+int acpi_poweroff ( void ) {
52
+	struct acpi_fadt fadtab;
53
+	uint16_t ebda;
54
+	userptr_t rsdt;
55
+	userptr_t fadt;
56
+	unsigned int pm1a_cnt_blk;
57
+	unsigned int pm1b_cnt_blk;
58
+	unsigned int pm1a_cnt;
59
+	unsigned int pm1b_cnt;
60
+	unsigned int slp_typa;
61
+	unsigned int slp_typb;
62
+	int s5;
63
+	int rc;
64
+
65
+	/* Locate EBDA */
66
+	get_real ( ebda, BDA_SEG, BDA_EBDA );
67
+
68
+	/* Locate RSDT */
69
+	rsdt = acpi_find_rsdt ( real_to_user ( ebda, 0 ) );
70
+	if ( ! rsdt ) {
71
+		DBGC ( colour, "ACPI could not find RSDT (EBDA %04x)\n", ebda );
72
+		return -ENOENT;
73
+	}
74
+
75
+	/* Locate FADT */
76
+	fadt = acpi_find ( rsdt, FADT_SIGNATURE, 0 );
77
+	if ( ! fadt ) {
78
+		DBGC ( colour, "ACPI could not find FADT\n" );
79
+		return -ENOENT;
80
+	}
81
+
82
+	/* Read FADT */
83
+	copy_from_user ( &fadtab, fadt, 0, sizeof ( fadtab ) );
84
+	pm1a_cnt_blk = le32_to_cpu ( fadtab.pm1a_cnt_blk );
85
+	pm1b_cnt_blk = le32_to_cpu ( fadtab.pm1b_cnt_blk );
86
+	pm1a_cnt = ( pm1a_cnt_blk + ACPI_PM1_CNT );
87
+	pm1b_cnt = ( pm1b_cnt_blk + ACPI_PM1_CNT );
88
+
89
+	/* Extract \_S5 from DSDT or any SSDT */
90
+	s5 = acpi_sx ( rsdt, S5_SIGNATURE );
91
+	if ( s5 < 0 ) {
92
+		rc = s5;
93
+		DBGC ( colour, "ACPI could not extract \\_S5: %s\n",
94
+		       strerror ( rc ) );
95
+		return rc;
96
+	}
97
+
98
+	/* Power off system */
99
+	if ( pm1a_cnt_blk ) {
100
+		slp_typa = ( ( s5 >> 0 ) & 0xff );
101
+		DBGC ( colour, "ACPI PM1a sleep type %#x => %04x\n",
102
+		       slp_typa, pm1a_cnt );
103
+		outw ( ( ACPI_PM1_CNT_SLP_TYP ( slp_typa ) |
104
+			 ACPI_PM1_CNT_SLP_EN ), pm1a_cnt );
105
+	}
106
+	if ( pm1b_cnt_blk ) {
107
+		slp_typb = ( ( s5 >> 8 ) & 0xff );
108
+		DBGC ( colour, "ACPI PM1b sleep type %#x => %04x\n",
109
+		       slp_typb, pm1b_cnt );
110
+		outw ( ( ACPI_PM1_CNT_SLP_TYP ( slp_typb ) |
111
+			 ACPI_PM1_CNT_SLP_EN ), pm1b_cnt );
112
+	}
113
+
114
+	DBGC ( colour, "ACPI power off failed\n" );
115
+	return -EPROTO;
116
+}

+ 2
- 4
src/arch/x86/interface/pcbios/apm.c Переглянути файл

@@ -32,14 +32,14 @@ FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
32 32
 
33 33
 #include <errno.h>
34 34
 #include <realmode.h>
35
-#include <ipxe/reboot.h>
35
+#include <ipxe/apm.h>
36 36
 
37 37
 /**
38 38
  * Power off the computer using APM
39 39
  *
40 40
  * @ret rc		Return status code
41 41
  */
42
-static int apm_poweroff ( void ) {
42
+int apm_poweroff ( void ) {
43 43
 	uint16_t apm_version;
44 44
 	uint16_t apm_signature;
45 45
 	uint16_t apm_flags;
@@ -108,5 +108,3 @@ static int apm_poweroff ( void ) {
108 108
 	/* Should never happen */
109 109
 	return -ECANCELED;
110 110
 }
111
-
112
-PROVIDE_REBOOT ( pcbios, poweroff, apm_poweroff );

+ 22
- 0
src/arch/x86/interface/pcbios/bios_reboot.c Переглянути файл

@@ -32,6 +32,8 @@ FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
32 32
 #include <ipxe/reboot.h>
33 33
 #include <realmode.h>
34 34
 #include <bios.h>
35
+#include <ipxe/apm.h>
36
+#include <ipxe/acpipwr.h>
35 37
 
36 38
 /**
37 39
  * Reboot system
@@ -49,4 +51,24 @@ static void bios_reboot ( int warm ) {
49 51
 	__asm__ __volatile__ ( REAL_CODE ( "ljmp $0xf000, $0xfff0" ) );
50 52
 }
51 53
 
54
+/**
55
+ * Power off system
56
+ *
57
+ * @ret rc		Return status code
58
+ */
59
+static int bios_poweroff ( void ) {
60
+	int rc;
61
+
62
+	/* Try APM */
63
+	if ( ( rc = apm_poweroff() ) != 0 )
64
+		DBG ( "APM power off failed: %s\n", strerror ( rc ) );
65
+
66
+	/* Try ACPI */
67
+	if ( ( rc = acpi_poweroff() ) != 0 )
68
+		DBG ( "ACPI power off failed: %s\n", strerror ( rc ) );
69
+
70
+	return rc;
71
+}
72
+
52 73
 PROVIDE_REBOOT ( pcbios, reboot, bios_reboot );
74
+PROVIDE_REBOOT ( pcbios, poweroff, bios_poweroff );

+ 274
- 0
src/core/acpi.c Переглянути файл

@@ -24,6 +24,8 @@
24 24
 FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
25 25
 
26 26
 #include <errno.h>
27
+#include <byteswap.h>
28
+#include <ipxe/uaccess.h>
27 29
 #include <ipxe/acpi.h>
28 30
 #include <ipxe/interface.h>
29 31
 
@@ -40,6 +42,22 @@ FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
40 42
  ******************************************************************************
41 43
  */
42 44
 
45
+/**
46
+ * Transcribe ACPI table signature (for debugging)
47
+ *
48
+ * @v signature		ACPI table signature
49
+ * @ret name		ACPI table signature name
50
+ */
51
+static const char * acpi_name ( uint32_t signature ) {
52
+	static union {
53
+		uint32_t signature;
54
+		char name[5];
55
+	} u;
56
+
57
+	u.signature = cpu_to_le32 ( signature );
58
+	return u.name;
59
+}
60
+
43 61
 /**
44 62
  * Fix up ACPI table checksum
45 63
  *
@@ -55,6 +73,262 @@ void acpi_fix_checksum ( struct acpi_description_header *acpi ) {
55 73
 	acpi->checksum -= sum;
56 74
 }
57 75
 
76
+/**
77
+ * Locate ACPI root system description table within a memory range
78
+ *
79
+ * @v start		Start address to search
80
+ * @v len		Length to search
81
+ * @ret rsdt		ACPI root system description table, or UNULL
82
+ */
83
+static userptr_t acpi_find_rsdt_range ( userptr_t start, size_t len ) {
84
+	static const char signature[8] = RSDP_SIGNATURE;
85
+	struct acpi_rsdp rsdp;
86
+	userptr_t rsdt;
87
+	size_t offset;
88
+	uint8_t sum;
89
+	unsigned int i;
90
+
91
+	/* Search for RSDP */
92
+	for ( offset = 0 ; ( ( offset + sizeof ( rsdp ) ) < len ) ;
93
+	      offset += RSDP_STRIDE ) {
94
+
95
+		/* Check signature and checksum */
96
+		copy_from_user ( &rsdp, start, offset, sizeof ( rsdp ) );
97
+		if ( memcmp ( rsdp.signature, signature,
98
+			      sizeof ( signature ) ) != 0 )
99
+			continue;
100
+		for ( sum = 0, i = 0 ; i < sizeof ( rsdp ) ; i++ )
101
+			sum += *( ( ( uint8_t * ) &rsdp ) + i );
102
+		if ( sum != 0 )
103
+			continue;
104
+
105
+		/* Extract RSDT */
106
+		rsdt = phys_to_user ( le32_to_cpu ( rsdp.rsdt ) );
107
+		DBGC ( rsdt, "RSDT %#08lx found via RSDP %#08lx\n",
108
+		       user_to_phys ( rsdt, 0 ),
109
+		       user_to_phys ( start, offset ) );
110
+		return rsdt;
111
+	}
112
+
113
+	return UNULL;
114
+}
115
+
116
+/**
117
+ * Locate ACPI root system description table
118
+ *
119
+ * @v ebda		Extended BIOS data area, or UNULL
120
+ * @ret rsdt		ACPI root system description table, or UNULL
121
+ */
122
+userptr_t acpi_find_rsdt ( userptr_t ebda ) {
123
+	userptr_t rsdt;
124
+
125
+	/* Search EBDA, if applicable */
126
+	if ( ebda ) {
127
+		rsdt = acpi_find_rsdt_range ( ebda, RSDP_EBDA_LEN );
128
+		if ( rsdt )
129
+			return rsdt;
130
+	}
131
+
132
+	/* Search fixed BIOS area */
133
+	rsdt = acpi_find_rsdt_range ( phys_to_user ( RSDP_BIOS_START ),
134
+				      RSDP_BIOS_LEN );
135
+	if ( rsdt )
136
+		return rsdt;
137
+
138
+	return UNULL;
139
+}
140
+
141
+/**
142
+ * Locate ACPI table
143
+ *
144
+ * @v rsdt		ACPI root system description table
145
+ * @v signature		Requested table signature
146
+ * @v index		Requested index of table with this signature
147
+ * @ret table		Table, or UNULL if not found
148
+ */
149
+userptr_t acpi_find ( userptr_t rsdt, uint32_t signature, unsigned int index ) {
150
+	struct acpi_description_header acpi;
151
+	struct acpi_rsdt *rsdtab;
152
+	typeof ( rsdtab->entry[0] ) entry;
153
+	userptr_t table;
154
+	size_t len;
155
+	unsigned int count;
156
+	unsigned int i;
157
+
158
+	/* Read RSDT header */
159
+	copy_from_user ( &acpi, rsdt, 0, sizeof ( acpi ) );
160
+	if ( acpi.signature != cpu_to_le32 ( RSDT_SIGNATURE ) ) {
161
+		DBGC ( rsdt, "RSDT %#08lx has invalid signature:\n",
162
+		       user_to_phys ( rsdt, 0 ) );
163
+		DBGC_HDA ( rsdt, user_to_phys ( rsdt, 0 ), &acpi,
164
+			   sizeof ( acpi ) );
165
+		return UNULL;
166
+	}
167
+	len = le32_to_cpu ( acpi.length );
168
+	if ( len < sizeof ( rsdtab->acpi ) ) {
169
+		DBGC ( rsdt, "RSDT %#08lx has invalid length:\n",
170
+		       user_to_phys ( rsdt, 0 ) );
171
+		DBGC_HDA ( rsdt, user_to_phys ( rsdt, 0 ), &acpi,
172
+			   sizeof ( acpi ) );
173
+		return UNULL;
174
+	}
175
+
176
+	/* Calculate number of entries */
177
+	count = ( ( len - sizeof ( rsdtab->acpi ) ) / sizeof ( entry ) );
178
+
179
+	/* Search through entries */
180
+	for ( i = 0 ; i < count ; i++ ) {
181
+
182
+		/* Get table address */
183
+		copy_from_user ( &entry, rsdt,
184
+				 offsetof ( typeof ( *rsdtab ), entry[i] ),
185
+				 sizeof ( entry ) );
186
+
187
+		/* Read table header */
188
+		table = phys_to_user ( entry );
189
+		copy_from_user ( &acpi.signature, table, 0,
190
+				 sizeof ( acpi.signature ) );
191
+
192
+		/* Check table signature */
193
+		if ( acpi.signature != cpu_to_le32 ( signature ) )
194
+			continue;
195
+
196
+		/* Check index */
197
+		if ( index-- )
198
+			continue;
199
+
200
+		DBGC ( rsdt, "RSDT %#08lx found %s at %08lx\n",
201
+		       user_to_phys ( rsdt, 0 ), acpi_name ( signature ),
202
+		       user_to_phys ( table, 0 ) );
203
+		return table;
204
+	}
205
+
206
+	DBGC ( rsdt, "RSDT %#08lx could not find %s\n",
207
+	       user_to_phys ( rsdt, 0 ), acpi_name ( signature ) );
208
+	return UNULL;
209
+}
210
+
211
+/**
212
+ * Extract \_Sx value from DSDT/SSDT
213
+ *
214
+ * @v zsdt		DSDT or SSDT
215
+ * @v signature		Signature (e.g. "_S5_")
216
+ * @ret sx		\_Sx value, or negative error
217
+ *
218
+ * In theory, extracting the \_Sx value from the DSDT/SSDT requires a
219
+ * full ACPI parser plus some heuristics to work around the various
220
+ * broken encodings encountered in real ACPI implementations.
221
+ *
222
+ * In practice, we can get the same result by scanning through the
223
+ * DSDT/SSDT for the signature (e.g. "_S5_"), extracting the first
224
+ * four bytes, removing any bytes with bit 3 set, and treating
225
+ * whatever is left as a little-endian value.  This is one of the
226
+ * uglier hacks I have ever implemented, but it's still prettier than
227
+ * the ACPI specification itself.
228
+ */
229
+static int acpi_sx_zsdt ( userptr_t zsdt, uint32_t signature ) {
230
+	struct acpi_description_header acpi;
231
+	union {
232
+		uint32_t dword;
233
+		uint8_t byte[4];
234
+	} buf;
235
+	size_t offset;
236
+	size_t len;
237
+	unsigned int sx;
238
+	uint8_t *byte;
239
+
240
+	/* Read table header */
241
+	copy_from_user ( &acpi, zsdt, 0, sizeof ( acpi ) );
242
+	len = le32_to_cpu ( acpi.length );
243
+
244
+	/* Locate signature */
245
+	for ( offset = sizeof ( acpi ) ;
246
+	      ( ( offset + sizeof ( buf ) /* signature */ + 3 /* pkg header */
247
+		  + sizeof ( buf ) /* value */ ) < len ) ;
248
+	      offset++ ) {
249
+
250
+		/* Check signature */
251
+		copy_from_user ( &buf, zsdt, offset, sizeof ( buf ) );
252
+		if ( buf.dword != cpu_to_le32 ( signature ) )
253
+			continue;
254
+		DBGC ( zsdt, "DSDT/SSDT %#08lx found %s at offset %#zx\n",
255
+		       user_to_phys ( zsdt, 0 ), acpi_name ( signature ),
256
+		       offset );
257
+		offset += sizeof ( buf );
258
+
259
+		/* Read first four bytes of value */
260
+		copy_from_user ( &buf, zsdt, ( offset + 3 /* pkg header */ ),
261
+				 sizeof ( buf ) );
262
+		DBGC ( zsdt, "DSDT/SSDT %#08lx found %s containing "
263
+		       "%02x:%02x:%02x:%02x\n", user_to_phys ( zsdt, 0 ),
264
+		       acpi_name ( signature ), buf.byte[0], buf.byte[1],
265
+		       buf.byte[2], buf.byte[3] );
266
+
267
+		/* Extract \Sx value.  There are three potential
268
+		 * encodings that we might encounter:
269
+		 *
270
+		 * - SLP_TYPa, SLP_TYPb, rsvd, rsvd
271
+		 *
272
+		 * - <byteprefix>, SLP_TYPa, <byteprefix>, SLP_TYPb, ...
273
+		 *
274
+		 * - <dwordprefix>, SLP_TYPa, SLP_TYPb, 0, 0
275
+		 *
276
+		 * Since <byteprefix> and <dwordprefix> both have bit
277
+		 * 3 set, and valid SLP_TYPx must have bit 3 clear
278
+		 * (since SLP_TYPx is a 3-bit field), we can just skip
279
+		 * any bytes with bit 3 set.
280
+		 */
281
+		byte = &buf.byte[0];
282
+		if ( *byte & 0x08 )
283
+			byte++;
284
+		sx = *(byte++);
285
+		if ( *byte & 0x08 )
286
+			byte++;
287
+		sx |= ( *byte << 8 );
288
+		return sx;
289
+	}
290
+
291
+	return -ENOENT;
292
+}
293
+
294
+/**
295
+ * Extract \_Sx value from DSDT/SSDT
296
+ *
297
+ * @v rsdt		ACPI root system description table
298
+ * @v signature		Signature (e.g. "_S5_")
299
+ * @ret sx		\_Sx value, or negative error
300
+ */
301
+int acpi_sx ( userptr_t rsdt, uint32_t signature ) {
302
+	struct acpi_fadt fadtab;
303
+	userptr_t fadt;
304
+	userptr_t dsdt;
305
+	userptr_t ssdt;
306
+	unsigned int i;
307
+	int sx;
308
+
309
+	/* Try DSDT first */
310
+	fadt = acpi_find ( rsdt, FADT_SIGNATURE, 0 );
311
+	if ( fadt ) {
312
+		copy_from_user ( &fadtab, fadt, 0, sizeof ( fadtab ) );
313
+		dsdt = phys_to_user ( fadtab.dsdt );
314
+		if ( ( sx = acpi_sx_zsdt ( dsdt, signature ) ) >= 0 )
315
+			return sx;
316
+	}
317
+
318
+	/* Try all SSDTs */
319
+	for ( i = 0 ; ; i++ ) {
320
+		ssdt = acpi_find ( rsdt, SSDT_SIGNATURE, i );
321
+		if ( ! ssdt )
322
+			break;
323
+		if ( ( sx = acpi_sx_zsdt ( ssdt, signature ) ) >= 0 )
324
+			return sx;
325
+	}
326
+
327
+	DBGC ( rsdt, "RSDT %#08lx could not find \\_Sx \"%s\"\n",
328
+	       user_to_phys ( rsdt, 0 ), acpi_name ( signature ) );
329
+	return -ENOENT;
330
+}
331
+
58 332
 /******************************************************************************
59 333
  *
60 334
  * Interface methods

+ 75
- 0
src/include/ipxe/acpi.h Переглянути файл

@@ -11,6 +11,7 @@ FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
11 11
 
12 12
 #include <stdint.h>
13 13
 #include <ipxe/interface.h>
14
+#include <ipxe/uaccess.h>
14 15
 
15 16
 /**
16 17
  * An ACPI description header
@@ -51,6 +52,76 @@ struct acpi_description_header {
51 52
 #define ACPI_SIGNATURE( a, b, c, d ) \
52 53
 	( ( (a) << 0 ) | ( (b) << 8 ) | ( (c) << 16 ) | ( (d) << 24 ) )
53 54
 
55
+/** Root System Description Pointer signature */
56
+#define RSDP_SIGNATURE { 'R', 'S', 'D', ' ', 'P', 'T', 'R', ' ' }
57
+
58
+/** Root System Description Pointer */
59
+struct acpi_rsdp {
60
+	/** Signature */
61
+	char signature[8];
62
+	/** To make sum of entire table == 0 */
63
+	uint8_t checksum;
64
+	/** OEM identification */
65
+	char oem_id[6];
66
+	/** Revision */
67
+	uint8_t revision;
68
+	/** Physical address of RSDT */
69
+	uint32_t rsdt;
70
+} __attribute__ (( packed ));
71
+
72
+/** EBDA RSDP length */
73
+#define RSDP_EBDA_LEN 0x400
74
+
75
+/** Fixed BIOS area RSDP start address */
76
+#define RSDP_BIOS_START 0xe0000
77
+
78
+/** Fixed BIOS area RSDP length */
79
+#define RSDP_BIOS_LEN 0x20000
80
+
81
+/** Stride at which to search for RSDP */
82
+#define RSDP_STRIDE 16
83
+
84
+/** Root System Description Table (RSDT) signature */
85
+#define RSDT_SIGNATURE ACPI_SIGNATURE ( 'R', 'S', 'D', 'T' )
86
+
87
+/** ACPI Root System Description Table (RSDT) */
88
+struct acpi_rsdt {
89
+	/** ACPI header */
90
+	struct acpi_description_header acpi;
91
+	/** ACPI table entries */
92
+	uint32_t entry[0];
93
+} __attribute__ (( packed ));
94
+
95
+/** Fixed ACPI Description Table (FADT) signature */
96
+#define FADT_SIGNATURE ACPI_SIGNATURE ( 'F', 'A', 'C', 'P' )
97
+
98
+/** Fixed ACPI Description Table (FADT) */
99
+struct acpi_fadt {
100
+	/** ACPI header */
101
+	struct acpi_description_header acpi;
102
+	/** Physical address of FACS */
103
+	uint32_t facs;
104
+	/** Physical address of DSDT */
105
+	uint32_t dsdt;
106
+	/** Unused by iPXE */
107
+	uint8_t unused[20];
108
+	/** PM1a Control Register Block */
109
+	uint32_t pm1a_cnt_blk;
110
+	/** PM1b Control Register Block */
111
+	uint32_t pm1b_cnt_blk;
112
+} __attribute__ (( packed ));
113
+
114
+/** ACPI PM1 Control Register (within PM1a_CNT_BLK or PM1A_CNT_BLK) */
115
+#define ACPI_PM1_CNT 0
116
+#define ACPI_PM1_CNT_SLP_TYP(x) ( (x) << 10 )	/**< Sleep type */
117
+#define ACPI_PM1_CNT_SLP_EN ( 1 << 13 )		/**< Sleep enable */
118
+
119
+/** Differentiated System Description Table (DSDT) signature */
120
+#define DSDT_SIGNATURE ACPI_SIGNATURE ( 'D', 'S', 'D', 'T' )
121
+
122
+/** Secondary System Description Table (SSDT) signature */
123
+#define SSDT_SIGNATURE ACPI_SIGNATURE ( 'S', 'S', 'D', 'T' )
124
+
54 125
 extern int acpi_describe ( struct interface *interface,
55 126
 			   struct acpi_description_header *acpi, size_t len );
56 127
 #define acpi_describe_TYPE( object_type )				\
@@ -59,5 +130,9 @@ extern int acpi_describe ( struct interface *interface,
59 130
 		       size_t len ) )
60 131
 
61 132
 extern void acpi_fix_checksum ( struct acpi_description_header *acpi );
133
+extern userptr_t acpi_find_rsdt ( userptr_t ebda );
134
+extern userptr_t acpi_find ( userptr_t rsdt, uint32_t signature,
135
+			     unsigned int index );
136
+extern int acpi_sx ( userptr_t rsdt, uint32_t signature );
62 137
 
63 138
 #endif /* _IPXE_ACPI_H */

Завантаження…
Відмінити
Зберегти