Deleted Added
full compact
tbfadt.c (233250) tbfadt.c (235945)
1/******************************************************************************
2 *
3 * Module Name: tbfadt - FADT table utilities
4 *
5 *****************************************************************************/
6
7/*
8 * Copyright (C) 2000 - 2012, Intel Corp.
9 * All rights reserved.
10 *
11 * Redistribution and use in source and binary forms, with or without
12 * modification, are permitted provided that the following conditions
13 * are met:
14 * 1. Redistributions of source code must retain the above copyright
15 * notice, this list of conditions, and the following disclaimer,
16 * without modification.
17 * 2. Redistributions in binary form must reproduce at minimum a disclaimer
18 * substantially similar to the "NO WARRANTY" disclaimer below
19 * ("Disclaimer") and any redistribution must be conditioned upon
20 * including a substantially similar Disclaimer requirement for further
21 * binary redistribution.
22 * 3. Neither the names of the above-listed copyright holders nor the names
23 * of any contributors may be used to endorse or promote products derived
24 * from this software without specific prior written permission.
25 *
26 * Alternatively, this software may be distributed under the terms of the
27 * GNU General Public License ("GPL") version 2 as published by the Free
28 * Software Foundation.
29 *
30 * NO WARRANTY
31 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
32 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
33 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR
34 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
35 * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
36 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
37 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
38 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
39 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
40 * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
41 * POSSIBILITY OF SUCH DAMAGES.
42 */
43
44#define __TBFADT_C__
45
46#include <contrib/dev/acpica/include/acpi.h>
47#include <contrib/dev/acpica/include/accommon.h>
48#include <contrib/dev/acpica/include/actables.h>
49
50#define _COMPONENT ACPI_TABLES
51 ACPI_MODULE_NAME ("tbfadt")
52
53/* Local prototypes */
54
1/******************************************************************************
2 *
3 * Module Name: tbfadt - FADT table utilities
4 *
5 *****************************************************************************/
6
7/*
8 * Copyright (C) 2000 - 2012, Intel Corp.
9 * All rights reserved.
10 *
11 * Redistribution and use in source and binary forms, with or without
12 * modification, are permitted provided that the following conditions
13 * are met:
14 * 1. Redistributions of source code must retain the above copyright
15 * notice, this list of conditions, and the following disclaimer,
16 * without modification.
17 * 2. Redistributions in binary form must reproduce at minimum a disclaimer
18 * substantially similar to the "NO WARRANTY" disclaimer below
19 * ("Disclaimer") and any redistribution must be conditioned upon
20 * including a substantially similar Disclaimer requirement for further
21 * binary redistribution.
22 * 3. Neither the names of the above-listed copyright holders nor the names
23 * of any contributors may be used to endorse or promote products derived
24 * from this software without specific prior written permission.
25 *
26 * Alternatively, this software may be distributed under the terms of the
27 * GNU General Public License ("GPL") version 2 as published by the Free
28 * Software Foundation.
29 *
30 * NO WARRANTY
31 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
32 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
33 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR
34 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
35 * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
36 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
37 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
38 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
39 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
40 * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
41 * POSSIBILITY OF SUCH DAMAGES.
42 */
43
44#define __TBFADT_C__
45
46#include <contrib/dev/acpica/include/acpi.h>
47#include <contrib/dev/acpica/include/accommon.h>
48#include <contrib/dev/acpica/include/actables.h>
49
50#define _COMPONENT ACPI_TABLES
51 ACPI_MODULE_NAME ("tbfadt")
52
53/* Local prototypes */
54
55static ACPI_INLINE void
55static void
56AcpiTbInitGenericAddress (
57 ACPI_GENERIC_ADDRESS *GenericAddress,
58 UINT8 SpaceId,
59 UINT8 ByteWidth,
56AcpiTbInitGenericAddress (
57 ACPI_GENERIC_ADDRESS *GenericAddress,
58 UINT8 SpaceId,
59 UINT8 ByteWidth,
60 UINT64 Address);
60 UINT64 Address,
61 char *RegisterName);
61
62static void
63AcpiTbConvertFadt (
64 void);
65
66static void
67AcpiTbValidateFadt (
68 void);
69
70static void
71AcpiTbSetupFadtRegisters (
72 void);
73
74
75/* Table for conversion of FADT to common internal format and FADT validation */
76
77typedef struct acpi_fadt_info
78{
79 char *Name;
80 UINT16 Address64;
81 UINT16 Address32;
82 UINT16 Length;
83 UINT8 DefaultLength;
84 UINT8 Type;
85
86} ACPI_FADT_INFO;
87
88#define ACPI_FADT_OPTIONAL 0
89#define ACPI_FADT_REQUIRED 1
90#define ACPI_FADT_SEPARATE_LENGTH 2
91
92static ACPI_FADT_INFO FadtInfoTable[] =
93{
94 {"Pm1aEventBlock",
95 ACPI_FADT_OFFSET (XPm1aEventBlock),
96 ACPI_FADT_OFFSET (Pm1aEventBlock),
97 ACPI_FADT_OFFSET (Pm1EventLength),
98 ACPI_PM1_REGISTER_WIDTH * 2, /* Enable + Status register */
99 ACPI_FADT_REQUIRED},
100
101 {"Pm1bEventBlock",
102 ACPI_FADT_OFFSET (XPm1bEventBlock),
103 ACPI_FADT_OFFSET (Pm1bEventBlock),
104 ACPI_FADT_OFFSET (Pm1EventLength),
105 ACPI_PM1_REGISTER_WIDTH * 2, /* Enable + Status register */
106 ACPI_FADT_OPTIONAL},
107
108 {"Pm1aControlBlock",
109 ACPI_FADT_OFFSET (XPm1aControlBlock),
110 ACPI_FADT_OFFSET (Pm1aControlBlock),
111 ACPI_FADT_OFFSET (Pm1ControlLength),
112 ACPI_PM1_REGISTER_WIDTH,
113 ACPI_FADT_REQUIRED},
114
115 {"Pm1bControlBlock",
116 ACPI_FADT_OFFSET (XPm1bControlBlock),
117 ACPI_FADT_OFFSET (Pm1bControlBlock),
118 ACPI_FADT_OFFSET (Pm1ControlLength),
119 ACPI_PM1_REGISTER_WIDTH,
120 ACPI_FADT_OPTIONAL},
121
122 {"Pm2ControlBlock",
123 ACPI_FADT_OFFSET (XPm2ControlBlock),
124 ACPI_FADT_OFFSET (Pm2ControlBlock),
125 ACPI_FADT_OFFSET (Pm2ControlLength),
126 ACPI_PM2_REGISTER_WIDTH,
127 ACPI_FADT_SEPARATE_LENGTH},
128
129 {"PmTimerBlock",
130 ACPI_FADT_OFFSET (XPmTimerBlock),
131 ACPI_FADT_OFFSET (PmTimerBlock),
132 ACPI_FADT_OFFSET (PmTimerLength),
133 ACPI_PM_TIMER_WIDTH,
134 ACPI_FADT_REQUIRED},
135
136 {"Gpe0Block",
137 ACPI_FADT_OFFSET (XGpe0Block),
138 ACPI_FADT_OFFSET (Gpe0Block),
139 ACPI_FADT_OFFSET (Gpe0BlockLength),
140 0,
141 ACPI_FADT_SEPARATE_LENGTH},
142
143 {"Gpe1Block",
144 ACPI_FADT_OFFSET (XGpe1Block),
145 ACPI_FADT_OFFSET (Gpe1Block),
146 ACPI_FADT_OFFSET (Gpe1BlockLength),
147 0,
148 ACPI_FADT_SEPARATE_LENGTH}
149};
150
151#define ACPI_FADT_INFO_ENTRIES \
152 (sizeof (FadtInfoTable) / sizeof (ACPI_FADT_INFO))
153
154
155/* Table used to split Event Blocks into separate status/enable registers */
156
157typedef struct acpi_fadt_pm_info
158{
159 ACPI_GENERIC_ADDRESS *Target;
160 UINT16 Source;
161 UINT8 RegisterNum;
162
163} ACPI_FADT_PM_INFO;
164
165static ACPI_FADT_PM_INFO FadtPmInfoTable[] =
166{
167 {&AcpiGbl_XPm1aStatus,
168 ACPI_FADT_OFFSET (XPm1aEventBlock),
169 0},
170
171 {&AcpiGbl_XPm1aEnable,
172 ACPI_FADT_OFFSET (XPm1aEventBlock),
173 1},
174
175 {&AcpiGbl_XPm1bStatus,
176 ACPI_FADT_OFFSET (XPm1bEventBlock),
177 0},
178
179 {&AcpiGbl_XPm1bEnable,
180 ACPI_FADT_OFFSET (XPm1bEventBlock),
181 1}
182};
183
184#define ACPI_FADT_PM_INFO_ENTRIES \
185 (sizeof (FadtPmInfoTable) / sizeof (ACPI_FADT_PM_INFO))
186
187
188/*******************************************************************************
189 *
190 * FUNCTION: AcpiTbInitGenericAddress
191 *
192 * PARAMETERS: GenericAddress - GAS struct to be initialized
193 * SpaceId - ACPI Space ID for this register
194 * ByteWidth - Width of this register, in bytes
195 * Address - Address of the register
196 *
197 * RETURN: None
198 *
199 * DESCRIPTION: Initialize a Generic Address Structure (GAS)
200 * See the ACPI specification for a full description and
201 * definition of this structure.
202 *
203 ******************************************************************************/
204
62
63static void
64AcpiTbConvertFadt (
65 void);
66
67static void
68AcpiTbValidateFadt (
69 void);
70
71static void
72AcpiTbSetupFadtRegisters (
73 void);
74
75
76/* Table for conversion of FADT to common internal format and FADT validation */
77
78typedef struct acpi_fadt_info
79{
80 char *Name;
81 UINT16 Address64;
82 UINT16 Address32;
83 UINT16 Length;
84 UINT8 DefaultLength;
85 UINT8 Type;
86
87} ACPI_FADT_INFO;
88
89#define ACPI_FADT_OPTIONAL 0
90#define ACPI_FADT_REQUIRED 1
91#define ACPI_FADT_SEPARATE_LENGTH 2
92
93static ACPI_FADT_INFO FadtInfoTable[] =
94{
95 {"Pm1aEventBlock",
96 ACPI_FADT_OFFSET (XPm1aEventBlock),
97 ACPI_FADT_OFFSET (Pm1aEventBlock),
98 ACPI_FADT_OFFSET (Pm1EventLength),
99 ACPI_PM1_REGISTER_WIDTH * 2, /* Enable + Status register */
100 ACPI_FADT_REQUIRED},
101
102 {"Pm1bEventBlock",
103 ACPI_FADT_OFFSET (XPm1bEventBlock),
104 ACPI_FADT_OFFSET (Pm1bEventBlock),
105 ACPI_FADT_OFFSET (Pm1EventLength),
106 ACPI_PM1_REGISTER_WIDTH * 2, /* Enable + Status register */
107 ACPI_FADT_OPTIONAL},
108
109 {"Pm1aControlBlock",
110 ACPI_FADT_OFFSET (XPm1aControlBlock),
111 ACPI_FADT_OFFSET (Pm1aControlBlock),
112 ACPI_FADT_OFFSET (Pm1ControlLength),
113 ACPI_PM1_REGISTER_WIDTH,
114 ACPI_FADT_REQUIRED},
115
116 {"Pm1bControlBlock",
117 ACPI_FADT_OFFSET (XPm1bControlBlock),
118 ACPI_FADT_OFFSET (Pm1bControlBlock),
119 ACPI_FADT_OFFSET (Pm1ControlLength),
120 ACPI_PM1_REGISTER_WIDTH,
121 ACPI_FADT_OPTIONAL},
122
123 {"Pm2ControlBlock",
124 ACPI_FADT_OFFSET (XPm2ControlBlock),
125 ACPI_FADT_OFFSET (Pm2ControlBlock),
126 ACPI_FADT_OFFSET (Pm2ControlLength),
127 ACPI_PM2_REGISTER_WIDTH,
128 ACPI_FADT_SEPARATE_LENGTH},
129
130 {"PmTimerBlock",
131 ACPI_FADT_OFFSET (XPmTimerBlock),
132 ACPI_FADT_OFFSET (PmTimerBlock),
133 ACPI_FADT_OFFSET (PmTimerLength),
134 ACPI_PM_TIMER_WIDTH,
135 ACPI_FADT_REQUIRED},
136
137 {"Gpe0Block",
138 ACPI_FADT_OFFSET (XGpe0Block),
139 ACPI_FADT_OFFSET (Gpe0Block),
140 ACPI_FADT_OFFSET (Gpe0BlockLength),
141 0,
142 ACPI_FADT_SEPARATE_LENGTH},
143
144 {"Gpe1Block",
145 ACPI_FADT_OFFSET (XGpe1Block),
146 ACPI_FADT_OFFSET (Gpe1Block),
147 ACPI_FADT_OFFSET (Gpe1BlockLength),
148 0,
149 ACPI_FADT_SEPARATE_LENGTH}
150};
151
152#define ACPI_FADT_INFO_ENTRIES \
153 (sizeof (FadtInfoTable) / sizeof (ACPI_FADT_INFO))
154
155
156/* Table used to split Event Blocks into separate status/enable registers */
157
158typedef struct acpi_fadt_pm_info
159{
160 ACPI_GENERIC_ADDRESS *Target;
161 UINT16 Source;
162 UINT8 RegisterNum;
163
164} ACPI_FADT_PM_INFO;
165
166static ACPI_FADT_PM_INFO FadtPmInfoTable[] =
167{
168 {&AcpiGbl_XPm1aStatus,
169 ACPI_FADT_OFFSET (XPm1aEventBlock),
170 0},
171
172 {&AcpiGbl_XPm1aEnable,
173 ACPI_FADT_OFFSET (XPm1aEventBlock),
174 1},
175
176 {&AcpiGbl_XPm1bStatus,
177 ACPI_FADT_OFFSET (XPm1bEventBlock),
178 0},
179
180 {&AcpiGbl_XPm1bEnable,
181 ACPI_FADT_OFFSET (XPm1bEventBlock),
182 1}
183};
184
185#define ACPI_FADT_PM_INFO_ENTRIES \
186 (sizeof (FadtPmInfoTable) / sizeof (ACPI_FADT_PM_INFO))
187
188
189/*******************************************************************************
190 *
191 * FUNCTION: AcpiTbInitGenericAddress
192 *
193 * PARAMETERS: GenericAddress - GAS struct to be initialized
194 * SpaceId - ACPI Space ID for this register
195 * ByteWidth - Width of this register, in bytes
196 * Address - Address of the register
197 *
198 * RETURN: None
199 *
200 * DESCRIPTION: Initialize a Generic Address Structure (GAS)
201 * See the ACPI specification for a full description and
202 * definition of this structure.
203 *
204 ******************************************************************************/
205
205static ACPI_INLINE void
206static void
206AcpiTbInitGenericAddress (
207 ACPI_GENERIC_ADDRESS *GenericAddress,
208 UINT8 SpaceId,
209 UINT8 ByteWidth,
207AcpiTbInitGenericAddress (
208 ACPI_GENERIC_ADDRESS *GenericAddress,
209 UINT8 SpaceId,
210 UINT8 ByteWidth,
210 UINT64 Address)
211 UINT64 Address,
212 char *RegisterName)
211{
213{
214 UINT8 BitWidth;
212
215
216
217 /* Bit width field in the GAS is only one byte long, 255 max */
218
219 BitWidth = (UINT8) (ByteWidth * 8);
220
221 if (ByteWidth > 31) /* (31*8)=248 */
222 {
223 ACPI_ERROR ((AE_INFO,
224 "%s - 32-bit FADT register is too long (%u bytes, %u bits) "
225 "to convert to GAS struct - 255 bits max, truncating",
226 RegisterName, ByteWidth, (ByteWidth * 8)));
227
228 BitWidth = 255;
229 }
230
213 /*
214 * The 64-bit Address field is non-aligned in the byte packed
215 * GAS struct.
216 */
217 ACPI_MOVE_64_TO_64 (&GenericAddress->Address, &Address);
218
219 /* All other fields are byte-wide */
220
221 GenericAddress->SpaceId = SpaceId;
231 /*
232 * The 64-bit Address field is non-aligned in the byte packed
233 * GAS struct.
234 */
235 ACPI_MOVE_64_TO_64 (&GenericAddress->Address, &Address);
236
237 /* All other fields are byte-wide */
238
239 GenericAddress->SpaceId = SpaceId;
222 GenericAddress->BitWidth = (UINT8) ACPI_MUL_8 (ByteWidth);
240 GenericAddress->BitWidth = BitWidth;
223 GenericAddress->BitOffset = 0;
224 GenericAddress->AccessWidth = 0; /* Access width ANY */
225}
226
227
228/*******************************************************************************
229 *
230 * FUNCTION: AcpiTbParseFadt
231 *
232 * PARAMETERS: TableIndex - Index for the FADT
233 *
234 * RETURN: None
235 *
236 * DESCRIPTION: Initialize the FADT, DSDT and FACS tables
237 * (FADT contains the addresses of the DSDT and FACS)
238 *
239 ******************************************************************************/
240
241void
242AcpiTbParseFadt (
243 UINT32 TableIndex)
244{
245 UINT32 Length;
246 ACPI_TABLE_HEADER *Table;
247
248
249 /*
250 * The FADT has multiple versions with different lengths,
251 * and it contains pointers to both the DSDT and FACS tables.
252 *
253 * Get a local copy of the FADT and convert it to a common format
254 * Map entire FADT, assumed to be smaller than one page.
255 */
256 Length = AcpiGbl_RootTableList.Tables[TableIndex].Length;
257
258 Table = AcpiOsMapMemory (
259 AcpiGbl_RootTableList.Tables[TableIndex].Address, Length);
260 if (!Table)
261 {
262 return;
263 }
264
265 /*
266 * Validate the FADT checksum before we copy the table. Ignore
267 * checksum error as we want to try to get the DSDT and FACS.
268 */
269 (void) AcpiTbVerifyChecksum (Table, Length);
270
271 /* Create a local copy of the FADT in common ACPI 2.0+ format */
272
273 AcpiTbCreateLocalFadt (Table, Length);
274
275 /* All done with the real FADT, unmap it */
276
277 AcpiOsUnmapMemory (Table, Length);
278
279 /* Obtain the DSDT and FACS tables via their addresses within the FADT */
280
281 AcpiTbInstallTable ((ACPI_PHYSICAL_ADDRESS) AcpiGbl_FADT.XDsdt,
282 ACPI_SIG_DSDT, ACPI_TABLE_INDEX_DSDT);
283
284 /* If Hardware Reduced flag is set, there is no FACS */
285
286 if (!AcpiGbl_ReducedHardware)
287 {
288 AcpiTbInstallTable ((ACPI_PHYSICAL_ADDRESS) AcpiGbl_FADT.XFacs,
289 ACPI_SIG_FACS, ACPI_TABLE_INDEX_FACS);
290 }
291}
292
293
294/*******************************************************************************
295 *
296 * FUNCTION: AcpiTbCreateLocalFadt
297 *
298 * PARAMETERS: Table - Pointer to BIOS FADT
299 * Length - Length of the table
300 *
301 * RETURN: None
302 *
303 * DESCRIPTION: Get a local copy of the FADT and convert it to a common format.
304 * Performs validation on some important FADT fields.
305 *
306 * NOTE: We create a local copy of the FADT regardless of the version.
307 *
308 ******************************************************************************/
309
310void
311AcpiTbCreateLocalFadt (
312 ACPI_TABLE_HEADER *Table,
313 UINT32 Length)
314{
315
316 /*
317 * Check if the FADT is larger than the largest table that we expect
318 * (the ACPI 5.0 version). If so, truncate the table, and issue
319 * a warning.
320 */
321 if (Length > sizeof (ACPI_TABLE_FADT))
322 {
323 ACPI_WARNING ((AE_INFO,
324 "FADT (revision %u) is longer than ACPI 5.0 version, "
325 "truncating length %u to %u",
326 Table->Revision, Length, (UINT32) sizeof (ACPI_TABLE_FADT)));
327 }
328
329 /* Clear the entire local FADT */
330
331 ACPI_MEMSET (&AcpiGbl_FADT, 0, sizeof (ACPI_TABLE_FADT));
332
333 /* Copy the original FADT, up to sizeof (ACPI_TABLE_FADT) */
334
335 ACPI_MEMCPY (&AcpiGbl_FADT, Table,
336 ACPI_MIN (Length, sizeof (ACPI_TABLE_FADT)));
337
338 /* Take a copy of the Hardware Reduced flag */
339
340 AcpiGbl_ReducedHardware = FALSE;
341 if (AcpiGbl_FADT.Flags & ACPI_FADT_HW_REDUCED)
342 {
343 AcpiGbl_ReducedHardware = TRUE;
344 }
345
346 /* Convert the local copy of the FADT to the common internal format */
347
348 AcpiTbConvertFadt ();
349
350 /* Validate FADT values now, before we make any changes */
351
352 AcpiTbValidateFadt ();
353
354 /* Initialize the global ACPI register structures */
355
356 AcpiTbSetupFadtRegisters ();
357}
358
359
360/*******************************************************************************
361 *
362 * FUNCTION: AcpiTbConvertFadt
363 *
364 * PARAMETERS: None, uses AcpiGbl_FADT
365 *
366 * RETURN: None
367 *
368 * DESCRIPTION: Converts all versions of the FADT to a common internal format.
369 * Expand 32-bit addresses to 64-bit as necessary.
370 *
371 * NOTE: AcpiGbl_FADT must be of size (ACPI_TABLE_FADT),
372 * and must contain a copy of the actual FADT.
373 *
374 * Notes on 64-bit register addresses:
375 *
376 * After this FADT conversion, later ACPICA code will only use the 64-bit "X"
377 * fields of the FADT for all ACPI register addresses.
378 *
379 * The 64-bit "X" fields are optional extensions to the original 32-bit FADT
380 * V1.0 fields. Even if they are present in the FADT, they are optional and
381 * are unused if the BIOS sets them to zero. Therefore, we must copy/expand
382 * 32-bit V1.0 fields if the corresponding X field is zero.
383 *
384 * For ACPI 1.0 FADTs, all 32-bit address fields are expanded to the
385 * corresponding "X" fields in the internal FADT.
386 *
387 * For ACPI 2.0+ FADTs, all valid (non-zero) 32-bit address fields are expanded
388 * to the corresponding 64-bit X fields. For compatibility with other ACPI
389 * implementations, we ignore the 64-bit field if the 32-bit field is valid,
390 * regardless of whether the host OS is 32-bit or 64-bit.
391 *
392 ******************************************************************************/
393
394static void
395AcpiTbConvertFadt (
396 void)
397{
398 ACPI_GENERIC_ADDRESS *Address64;
399 UINT32 Address32;
400 UINT32 i;
401
402
403 /*
404 * Expand the 32-bit FACS and DSDT addresses to 64-bit as necessary.
405 * Later code will always use the X 64-bit field.
406 */
407 if (!AcpiGbl_FADT.XFacs)
408 {
409 AcpiGbl_FADT.XFacs = (UINT64) AcpiGbl_FADT.Facs;
410 }
411 if (!AcpiGbl_FADT.XDsdt)
412 {
413 AcpiGbl_FADT.XDsdt = (UINT64) AcpiGbl_FADT.Dsdt;
414 }
415
416 /*
417 * For ACPI 1.0 FADTs (revision 1 or 2), ensure that reserved fields which
418 * should be zero are indeed zero. This will workaround BIOSs that
419 * inadvertently place values in these fields.
420 *
421 * The ACPI 1.0 reserved fields that will be zeroed are the bytes located
422 * at offset 45, 55, 95, and the word located at offset 109, 110.
423 *
424 * Note: The FADT revision value is unreliable. Only the length can be
425 * trusted.
426 */
427 if (AcpiGbl_FADT.Header.Length <= ACPI_FADT_V2_SIZE)
428 {
429 AcpiGbl_FADT.PreferredProfile = 0;
430 AcpiGbl_FADT.PstateControl = 0;
431 AcpiGbl_FADT.CstControl = 0;
432 AcpiGbl_FADT.BootFlags = 0;
433 }
434
435 /*
436 * Now we can update the local FADT length to the length of the
437 * current FADT version as defined by the ACPI specification.
438 * Thus, we will have a common FADT internally.
439 */
440 AcpiGbl_FADT.Header.Length = sizeof (ACPI_TABLE_FADT);
441
442 /*
443 * Expand the ACPI 1.0 32-bit addresses to the ACPI 2.0 64-bit "X"
444 * generic address structures as necessary. Later code will always use
445 * the 64-bit address structures.
446 *
447 * March 2009:
448 * We now always use the 32-bit address if it is valid (non-null). This
449 * is not in accordance with the ACPI specification which states that
450 * the 64-bit address supersedes the 32-bit version, but we do this for
451 * compatibility with other ACPI implementations. Most notably, in the
452 * case where both the 32 and 64 versions are non-null, we use the 32-bit
453 * version. This is the only address that is guaranteed to have been
454 * tested by the BIOS manufacturer.
455 */
456 for (i = 0; i < ACPI_FADT_INFO_ENTRIES; i++)
457 {
458 Address32 = *ACPI_ADD_PTR (UINT32,
459 &AcpiGbl_FADT, FadtInfoTable[i].Address32);
460
461 Address64 = ACPI_ADD_PTR (ACPI_GENERIC_ADDRESS,
462 &AcpiGbl_FADT, FadtInfoTable[i].Address64);
463
464 /*
465 * If both 32- and 64-bit addresses are valid (non-zero),
466 * they must match.
467 */
468 if (Address64->Address && Address32 &&
469 (Address64->Address != (UINT64) Address32))
470 {
471 ACPI_ERROR ((AE_INFO,
472 "32/64X address mismatch in %s: 0x%8.8X/0x%8.8X%8.8X, using 32",
473 FadtInfoTable[i].Name, Address32,
474 ACPI_FORMAT_UINT64 (Address64->Address)));
475 }
476
477 /* Always use 32-bit address if it is valid (non-null) */
478
479 if (Address32)
480 {
481 /*
482 * Copy the 32-bit address to the 64-bit GAS structure. The
483 * Space ID is always I/O for 32-bit legacy address fields
484 */
485 AcpiTbInitGenericAddress (Address64, ACPI_ADR_SPACE_SYSTEM_IO,
486 *ACPI_ADD_PTR (UINT8, &AcpiGbl_FADT, FadtInfoTable[i].Length),
241 GenericAddress->BitOffset = 0;
242 GenericAddress->AccessWidth = 0; /* Access width ANY */
243}
244
245
246/*******************************************************************************
247 *
248 * FUNCTION: AcpiTbParseFadt
249 *
250 * PARAMETERS: TableIndex - Index for the FADT
251 *
252 * RETURN: None
253 *
254 * DESCRIPTION: Initialize the FADT, DSDT and FACS tables
255 * (FADT contains the addresses of the DSDT and FACS)
256 *
257 ******************************************************************************/
258
259void
260AcpiTbParseFadt (
261 UINT32 TableIndex)
262{
263 UINT32 Length;
264 ACPI_TABLE_HEADER *Table;
265
266
267 /*
268 * The FADT has multiple versions with different lengths,
269 * and it contains pointers to both the DSDT and FACS tables.
270 *
271 * Get a local copy of the FADT and convert it to a common format
272 * Map entire FADT, assumed to be smaller than one page.
273 */
274 Length = AcpiGbl_RootTableList.Tables[TableIndex].Length;
275
276 Table = AcpiOsMapMemory (
277 AcpiGbl_RootTableList.Tables[TableIndex].Address, Length);
278 if (!Table)
279 {
280 return;
281 }
282
283 /*
284 * Validate the FADT checksum before we copy the table. Ignore
285 * checksum error as we want to try to get the DSDT and FACS.
286 */
287 (void) AcpiTbVerifyChecksum (Table, Length);
288
289 /* Create a local copy of the FADT in common ACPI 2.0+ format */
290
291 AcpiTbCreateLocalFadt (Table, Length);
292
293 /* All done with the real FADT, unmap it */
294
295 AcpiOsUnmapMemory (Table, Length);
296
297 /* Obtain the DSDT and FACS tables via their addresses within the FADT */
298
299 AcpiTbInstallTable ((ACPI_PHYSICAL_ADDRESS) AcpiGbl_FADT.XDsdt,
300 ACPI_SIG_DSDT, ACPI_TABLE_INDEX_DSDT);
301
302 /* If Hardware Reduced flag is set, there is no FACS */
303
304 if (!AcpiGbl_ReducedHardware)
305 {
306 AcpiTbInstallTable ((ACPI_PHYSICAL_ADDRESS) AcpiGbl_FADT.XFacs,
307 ACPI_SIG_FACS, ACPI_TABLE_INDEX_FACS);
308 }
309}
310
311
312/*******************************************************************************
313 *
314 * FUNCTION: AcpiTbCreateLocalFadt
315 *
316 * PARAMETERS: Table - Pointer to BIOS FADT
317 * Length - Length of the table
318 *
319 * RETURN: None
320 *
321 * DESCRIPTION: Get a local copy of the FADT and convert it to a common format.
322 * Performs validation on some important FADT fields.
323 *
324 * NOTE: We create a local copy of the FADT regardless of the version.
325 *
326 ******************************************************************************/
327
328void
329AcpiTbCreateLocalFadt (
330 ACPI_TABLE_HEADER *Table,
331 UINT32 Length)
332{
333
334 /*
335 * Check if the FADT is larger than the largest table that we expect
336 * (the ACPI 5.0 version). If so, truncate the table, and issue
337 * a warning.
338 */
339 if (Length > sizeof (ACPI_TABLE_FADT))
340 {
341 ACPI_WARNING ((AE_INFO,
342 "FADT (revision %u) is longer than ACPI 5.0 version, "
343 "truncating length %u to %u",
344 Table->Revision, Length, (UINT32) sizeof (ACPI_TABLE_FADT)));
345 }
346
347 /* Clear the entire local FADT */
348
349 ACPI_MEMSET (&AcpiGbl_FADT, 0, sizeof (ACPI_TABLE_FADT));
350
351 /* Copy the original FADT, up to sizeof (ACPI_TABLE_FADT) */
352
353 ACPI_MEMCPY (&AcpiGbl_FADT, Table,
354 ACPI_MIN (Length, sizeof (ACPI_TABLE_FADT)));
355
356 /* Take a copy of the Hardware Reduced flag */
357
358 AcpiGbl_ReducedHardware = FALSE;
359 if (AcpiGbl_FADT.Flags & ACPI_FADT_HW_REDUCED)
360 {
361 AcpiGbl_ReducedHardware = TRUE;
362 }
363
364 /* Convert the local copy of the FADT to the common internal format */
365
366 AcpiTbConvertFadt ();
367
368 /* Validate FADT values now, before we make any changes */
369
370 AcpiTbValidateFadt ();
371
372 /* Initialize the global ACPI register structures */
373
374 AcpiTbSetupFadtRegisters ();
375}
376
377
378/*******************************************************************************
379 *
380 * FUNCTION: AcpiTbConvertFadt
381 *
382 * PARAMETERS: None, uses AcpiGbl_FADT
383 *
384 * RETURN: None
385 *
386 * DESCRIPTION: Converts all versions of the FADT to a common internal format.
387 * Expand 32-bit addresses to 64-bit as necessary.
388 *
389 * NOTE: AcpiGbl_FADT must be of size (ACPI_TABLE_FADT),
390 * and must contain a copy of the actual FADT.
391 *
392 * Notes on 64-bit register addresses:
393 *
394 * After this FADT conversion, later ACPICA code will only use the 64-bit "X"
395 * fields of the FADT for all ACPI register addresses.
396 *
397 * The 64-bit "X" fields are optional extensions to the original 32-bit FADT
398 * V1.0 fields. Even if they are present in the FADT, they are optional and
399 * are unused if the BIOS sets them to zero. Therefore, we must copy/expand
400 * 32-bit V1.0 fields if the corresponding X field is zero.
401 *
402 * For ACPI 1.0 FADTs, all 32-bit address fields are expanded to the
403 * corresponding "X" fields in the internal FADT.
404 *
405 * For ACPI 2.0+ FADTs, all valid (non-zero) 32-bit address fields are expanded
406 * to the corresponding 64-bit X fields. For compatibility with other ACPI
407 * implementations, we ignore the 64-bit field if the 32-bit field is valid,
408 * regardless of whether the host OS is 32-bit or 64-bit.
409 *
410 ******************************************************************************/
411
412static void
413AcpiTbConvertFadt (
414 void)
415{
416 ACPI_GENERIC_ADDRESS *Address64;
417 UINT32 Address32;
418 UINT32 i;
419
420
421 /*
422 * Expand the 32-bit FACS and DSDT addresses to 64-bit as necessary.
423 * Later code will always use the X 64-bit field.
424 */
425 if (!AcpiGbl_FADT.XFacs)
426 {
427 AcpiGbl_FADT.XFacs = (UINT64) AcpiGbl_FADT.Facs;
428 }
429 if (!AcpiGbl_FADT.XDsdt)
430 {
431 AcpiGbl_FADT.XDsdt = (UINT64) AcpiGbl_FADT.Dsdt;
432 }
433
434 /*
435 * For ACPI 1.0 FADTs (revision 1 or 2), ensure that reserved fields which
436 * should be zero are indeed zero. This will workaround BIOSs that
437 * inadvertently place values in these fields.
438 *
439 * The ACPI 1.0 reserved fields that will be zeroed are the bytes located
440 * at offset 45, 55, 95, and the word located at offset 109, 110.
441 *
442 * Note: The FADT revision value is unreliable. Only the length can be
443 * trusted.
444 */
445 if (AcpiGbl_FADT.Header.Length <= ACPI_FADT_V2_SIZE)
446 {
447 AcpiGbl_FADT.PreferredProfile = 0;
448 AcpiGbl_FADT.PstateControl = 0;
449 AcpiGbl_FADT.CstControl = 0;
450 AcpiGbl_FADT.BootFlags = 0;
451 }
452
453 /*
454 * Now we can update the local FADT length to the length of the
455 * current FADT version as defined by the ACPI specification.
456 * Thus, we will have a common FADT internally.
457 */
458 AcpiGbl_FADT.Header.Length = sizeof (ACPI_TABLE_FADT);
459
460 /*
461 * Expand the ACPI 1.0 32-bit addresses to the ACPI 2.0 64-bit "X"
462 * generic address structures as necessary. Later code will always use
463 * the 64-bit address structures.
464 *
465 * March 2009:
466 * We now always use the 32-bit address if it is valid (non-null). This
467 * is not in accordance with the ACPI specification which states that
468 * the 64-bit address supersedes the 32-bit version, but we do this for
469 * compatibility with other ACPI implementations. Most notably, in the
470 * case where both the 32 and 64 versions are non-null, we use the 32-bit
471 * version. This is the only address that is guaranteed to have been
472 * tested by the BIOS manufacturer.
473 */
474 for (i = 0; i < ACPI_FADT_INFO_ENTRIES; i++)
475 {
476 Address32 = *ACPI_ADD_PTR (UINT32,
477 &AcpiGbl_FADT, FadtInfoTable[i].Address32);
478
479 Address64 = ACPI_ADD_PTR (ACPI_GENERIC_ADDRESS,
480 &AcpiGbl_FADT, FadtInfoTable[i].Address64);
481
482 /*
483 * If both 32- and 64-bit addresses are valid (non-zero),
484 * they must match.
485 */
486 if (Address64->Address && Address32 &&
487 (Address64->Address != (UINT64) Address32))
488 {
489 ACPI_ERROR ((AE_INFO,
490 "32/64X address mismatch in %s: 0x%8.8X/0x%8.8X%8.8X, using 32",
491 FadtInfoTable[i].Name, Address32,
492 ACPI_FORMAT_UINT64 (Address64->Address)));
493 }
494
495 /* Always use 32-bit address if it is valid (non-null) */
496
497 if (Address32)
498 {
499 /*
500 * Copy the 32-bit address to the 64-bit GAS structure. The
501 * Space ID is always I/O for 32-bit legacy address fields
502 */
503 AcpiTbInitGenericAddress (Address64, ACPI_ADR_SPACE_SYSTEM_IO,
504 *ACPI_ADD_PTR (UINT8, &AcpiGbl_FADT, FadtInfoTable[i].Length),
487 (UINT64) Address32);
505 (UINT64) Address32, FadtInfoTable[i].Name);
488 }
489 }
490}
491
492
493/*******************************************************************************
494 *
495 * FUNCTION: AcpiTbValidateFadt
496 *
497 * PARAMETERS: Table - Pointer to the FADT to be validated
498 *
499 * RETURN: None
500 *
501 * DESCRIPTION: Validate various important fields within the FADT. If a problem
502 * is found, issue a message, but no status is returned.
503 * Used by both the table manager and the disassembler.
504 *
505 * Possible additional checks:
506 * (AcpiGbl_FADT.Pm1EventLength >= 4)
507 * (AcpiGbl_FADT.Pm1ControlLength >= 2)
508 * (AcpiGbl_FADT.PmTimerLength >= 4)
509 * Gpe block lengths must be multiple of 2
510 *
511 ******************************************************************************/
512
513static void
514AcpiTbValidateFadt (
515 void)
516{
517 char *Name;
518 ACPI_GENERIC_ADDRESS *Address64;
519 UINT8 Length;
520 UINT32 i;
521
522
523 /*
524 * Check for FACS and DSDT address mismatches. An address mismatch between
525 * the 32-bit and 64-bit address fields (FIRMWARE_CTRL/X_FIRMWARE_CTRL and
526 * DSDT/X_DSDT) would indicate the presence of two FACS or two DSDT tables.
527 */
528 if (AcpiGbl_FADT.Facs &&
529 (AcpiGbl_FADT.XFacs != (UINT64) AcpiGbl_FADT.Facs))
530 {
531 ACPI_WARNING ((AE_INFO,
532 "32/64X FACS address mismatch in FADT - "
533 "0x%8.8X/0x%8.8X%8.8X, using 32",
534 AcpiGbl_FADT.Facs, ACPI_FORMAT_UINT64 (AcpiGbl_FADT.XFacs)));
535
536 AcpiGbl_FADT.XFacs = (UINT64) AcpiGbl_FADT.Facs;
537 }
538
539 if (AcpiGbl_FADT.Dsdt &&
540 (AcpiGbl_FADT.XDsdt != (UINT64) AcpiGbl_FADT.Dsdt))
541 {
542 ACPI_WARNING ((AE_INFO,
543 "32/64X DSDT address mismatch in FADT - "
544 "0x%8.8X/0x%8.8X%8.8X, using 32",
545 AcpiGbl_FADT.Dsdt, ACPI_FORMAT_UINT64 (AcpiGbl_FADT.XDsdt)));
546
547 AcpiGbl_FADT.XDsdt = (UINT64) AcpiGbl_FADT.Dsdt;
548 }
549
550 /* If Hardware Reduced flag is set, we are all done */
551
552 if (AcpiGbl_ReducedHardware)
553 {
554 return;
555 }
556
557 /* Examine all of the 64-bit extended address fields (X fields) */
558
559 for (i = 0; i < ACPI_FADT_INFO_ENTRIES; i++)
560 {
561 /*
562 * Generate pointer to the 64-bit address, get the register
563 * length (width) and the register name
564 */
565 Address64 = ACPI_ADD_PTR (ACPI_GENERIC_ADDRESS,
566 &AcpiGbl_FADT, FadtInfoTable[i].Address64);
567 Length = *ACPI_ADD_PTR (UINT8,
568 &AcpiGbl_FADT, FadtInfoTable[i].Length);
569 Name = FadtInfoTable[i].Name;
570
571 /*
572 * For each extended field, check for length mismatch between the
573 * legacy length field and the corresponding 64-bit X length field.
574 */
575 if (Address64->Address &&
576 (Address64->BitWidth != ACPI_MUL_8 (Length)))
577 {
578 ACPI_WARNING ((AE_INFO,
579 "32/64X length mismatch in %s: %u/%u",
580 Name, ACPI_MUL_8 (Length), Address64->BitWidth));
581 }
582
583 if (FadtInfoTable[i].Type & ACPI_FADT_REQUIRED)
584 {
585 /*
586 * Field is required (PM1aEvent, PM1aControl, PmTimer).
587 * Both the address and length must be non-zero.
588 */
589 if (!Address64->Address || !Length)
590 {
591 ACPI_ERROR ((AE_INFO,
592 "Required field %s has zero address and/or length:"
593 " 0x%8.8X%8.8X/0x%X",
594 Name, ACPI_FORMAT_UINT64 (Address64->Address), Length));
595 }
596 }
597 else if (FadtInfoTable[i].Type & ACPI_FADT_SEPARATE_LENGTH)
598 {
599 /*
600 * Field is optional (PM2Control, GPE0, GPE1) AND has its own
601 * length field. If present, both the address and length must
602 * be valid.
603 */
604 if ((Address64->Address && !Length) ||
605 (!Address64->Address && Length))
606 {
607 ACPI_WARNING ((AE_INFO,
608 "Optional field %s has zero address or length: "
609 "0x%8.8X%8.8X/0x%X",
610 Name, ACPI_FORMAT_UINT64 (Address64->Address), Length));
611 }
612 }
613 }
614}
615
616
617/*******************************************************************************
618 *
619 * FUNCTION: AcpiTbSetupFadtRegisters
620 *
621 * PARAMETERS: None, uses AcpiGbl_FADT.
622 *
623 * RETURN: None
624 *
625 * DESCRIPTION: Initialize global ACPI PM1 register definitions. Optionally,
626 * force FADT register definitions to their default lengths.
627 *
628 ******************************************************************************/
629
630static void
631AcpiTbSetupFadtRegisters (
632 void)
633{
634 ACPI_GENERIC_ADDRESS *Target64;
635 ACPI_GENERIC_ADDRESS *Source64;
636 UINT8 Pm1RegisterByteWidth;
637 UINT32 i;
638
639
640 /*
641 * Optionally check all register lengths against the default values and
642 * update them if they are incorrect.
643 */
644 if (AcpiGbl_UseDefaultRegisterWidths)
645 {
646 for (i = 0; i < ACPI_FADT_INFO_ENTRIES; i++)
647 {
648 Target64 = ACPI_ADD_PTR (ACPI_GENERIC_ADDRESS, &AcpiGbl_FADT,
649 FadtInfoTable[i].Address64);
650
651 /*
652 * If a valid register (Address != 0) and the (DefaultLength > 0)
653 * (Not a GPE register), then check the width against the default.
654 */
655 if ((Target64->Address) &&
656 (FadtInfoTable[i].DefaultLength > 0) &&
657 (FadtInfoTable[i].DefaultLength != Target64->BitWidth))
658 {
659 ACPI_WARNING ((AE_INFO,
660 "Invalid length for %s: %u, using default %u",
661 FadtInfoTable[i].Name, Target64->BitWidth,
662 FadtInfoTable[i].DefaultLength));
663
664 /* Incorrect size, set width to the default */
665
666 Target64->BitWidth = FadtInfoTable[i].DefaultLength;
667 }
668 }
669 }
670
671 /*
672 * Get the length of the individual PM1 registers (enable and status).
673 * Each register is defined to be (event block length / 2). Extra divide
674 * by 8 converts bits to bytes.
675 */
676 Pm1RegisterByteWidth = (UINT8)
677 ACPI_DIV_16 (AcpiGbl_FADT.XPm1aEventBlock.BitWidth);
678
679 /*
680 * Calculate separate GAS structs for the PM1x (A/B) Status and Enable
681 * registers. These addresses do not appear (directly) in the FADT, so it
682 * is useful to pre-calculate them from the PM1 Event Block definitions.
683 *
684 * The PM event blocks are split into two register blocks, first is the
685 * PM Status Register block, followed immediately by the PM Enable
686 * Register block. Each is of length (Pm1EventLength/2)
687 *
688 * Note: The PM1A event block is required by the ACPI specification.
689 * However, the PM1B event block is optional and is rarely, if ever,
690 * used.
691 */
692
693 for (i = 0; i < ACPI_FADT_PM_INFO_ENTRIES; i++)
694 {
695 Source64 = ACPI_ADD_PTR (ACPI_GENERIC_ADDRESS, &AcpiGbl_FADT,
696 FadtPmInfoTable[i].Source);
697
698 if (Source64->Address)
699 {
700 AcpiTbInitGenericAddress (FadtPmInfoTable[i].Target,
701 Source64->SpaceId, Pm1RegisterByteWidth,
702 Source64->Address +
506 }
507 }
508}
509
510
511/*******************************************************************************
512 *
513 * FUNCTION: AcpiTbValidateFadt
514 *
515 * PARAMETERS: Table - Pointer to the FADT to be validated
516 *
517 * RETURN: None
518 *
519 * DESCRIPTION: Validate various important fields within the FADT. If a problem
520 * is found, issue a message, but no status is returned.
521 * Used by both the table manager and the disassembler.
522 *
523 * Possible additional checks:
524 * (AcpiGbl_FADT.Pm1EventLength >= 4)
525 * (AcpiGbl_FADT.Pm1ControlLength >= 2)
526 * (AcpiGbl_FADT.PmTimerLength >= 4)
527 * Gpe block lengths must be multiple of 2
528 *
529 ******************************************************************************/
530
531static void
532AcpiTbValidateFadt (
533 void)
534{
535 char *Name;
536 ACPI_GENERIC_ADDRESS *Address64;
537 UINT8 Length;
538 UINT32 i;
539
540
541 /*
542 * Check for FACS and DSDT address mismatches. An address mismatch between
543 * the 32-bit and 64-bit address fields (FIRMWARE_CTRL/X_FIRMWARE_CTRL and
544 * DSDT/X_DSDT) would indicate the presence of two FACS or two DSDT tables.
545 */
546 if (AcpiGbl_FADT.Facs &&
547 (AcpiGbl_FADT.XFacs != (UINT64) AcpiGbl_FADT.Facs))
548 {
549 ACPI_WARNING ((AE_INFO,
550 "32/64X FACS address mismatch in FADT - "
551 "0x%8.8X/0x%8.8X%8.8X, using 32",
552 AcpiGbl_FADT.Facs, ACPI_FORMAT_UINT64 (AcpiGbl_FADT.XFacs)));
553
554 AcpiGbl_FADT.XFacs = (UINT64) AcpiGbl_FADT.Facs;
555 }
556
557 if (AcpiGbl_FADT.Dsdt &&
558 (AcpiGbl_FADT.XDsdt != (UINT64) AcpiGbl_FADT.Dsdt))
559 {
560 ACPI_WARNING ((AE_INFO,
561 "32/64X DSDT address mismatch in FADT - "
562 "0x%8.8X/0x%8.8X%8.8X, using 32",
563 AcpiGbl_FADT.Dsdt, ACPI_FORMAT_UINT64 (AcpiGbl_FADT.XDsdt)));
564
565 AcpiGbl_FADT.XDsdt = (UINT64) AcpiGbl_FADT.Dsdt;
566 }
567
568 /* If Hardware Reduced flag is set, we are all done */
569
570 if (AcpiGbl_ReducedHardware)
571 {
572 return;
573 }
574
575 /* Examine all of the 64-bit extended address fields (X fields) */
576
577 for (i = 0; i < ACPI_FADT_INFO_ENTRIES; i++)
578 {
579 /*
580 * Generate pointer to the 64-bit address, get the register
581 * length (width) and the register name
582 */
583 Address64 = ACPI_ADD_PTR (ACPI_GENERIC_ADDRESS,
584 &AcpiGbl_FADT, FadtInfoTable[i].Address64);
585 Length = *ACPI_ADD_PTR (UINT8,
586 &AcpiGbl_FADT, FadtInfoTable[i].Length);
587 Name = FadtInfoTable[i].Name;
588
589 /*
590 * For each extended field, check for length mismatch between the
591 * legacy length field and the corresponding 64-bit X length field.
592 */
593 if (Address64->Address &&
594 (Address64->BitWidth != ACPI_MUL_8 (Length)))
595 {
596 ACPI_WARNING ((AE_INFO,
597 "32/64X length mismatch in %s: %u/%u",
598 Name, ACPI_MUL_8 (Length), Address64->BitWidth));
599 }
600
601 if (FadtInfoTable[i].Type & ACPI_FADT_REQUIRED)
602 {
603 /*
604 * Field is required (PM1aEvent, PM1aControl, PmTimer).
605 * Both the address and length must be non-zero.
606 */
607 if (!Address64->Address || !Length)
608 {
609 ACPI_ERROR ((AE_INFO,
610 "Required field %s has zero address and/or length:"
611 " 0x%8.8X%8.8X/0x%X",
612 Name, ACPI_FORMAT_UINT64 (Address64->Address), Length));
613 }
614 }
615 else if (FadtInfoTable[i].Type & ACPI_FADT_SEPARATE_LENGTH)
616 {
617 /*
618 * Field is optional (PM2Control, GPE0, GPE1) AND has its own
619 * length field. If present, both the address and length must
620 * be valid.
621 */
622 if ((Address64->Address && !Length) ||
623 (!Address64->Address && Length))
624 {
625 ACPI_WARNING ((AE_INFO,
626 "Optional field %s has zero address or length: "
627 "0x%8.8X%8.8X/0x%X",
628 Name, ACPI_FORMAT_UINT64 (Address64->Address), Length));
629 }
630 }
631 }
632}
633
634
635/*******************************************************************************
636 *
637 * FUNCTION: AcpiTbSetupFadtRegisters
638 *
639 * PARAMETERS: None, uses AcpiGbl_FADT.
640 *
641 * RETURN: None
642 *
643 * DESCRIPTION: Initialize global ACPI PM1 register definitions. Optionally,
644 * force FADT register definitions to their default lengths.
645 *
646 ******************************************************************************/
647
648static void
649AcpiTbSetupFadtRegisters (
650 void)
651{
652 ACPI_GENERIC_ADDRESS *Target64;
653 ACPI_GENERIC_ADDRESS *Source64;
654 UINT8 Pm1RegisterByteWidth;
655 UINT32 i;
656
657
658 /*
659 * Optionally check all register lengths against the default values and
660 * update them if they are incorrect.
661 */
662 if (AcpiGbl_UseDefaultRegisterWidths)
663 {
664 for (i = 0; i < ACPI_FADT_INFO_ENTRIES; i++)
665 {
666 Target64 = ACPI_ADD_PTR (ACPI_GENERIC_ADDRESS, &AcpiGbl_FADT,
667 FadtInfoTable[i].Address64);
668
669 /*
670 * If a valid register (Address != 0) and the (DefaultLength > 0)
671 * (Not a GPE register), then check the width against the default.
672 */
673 if ((Target64->Address) &&
674 (FadtInfoTable[i].DefaultLength > 0) &&
675 (FadtInfoTable[i].DefaultLength != Target64->BitWidth))
676 {
677 ACPI_WARNING ((AE_INFO,
678 "Invalid length for %s: %u, using default %u",
679 FadtInfoTable[i].Name, Target64->BitWidth,
680 FadtInfoTable[i].DefaultLength));
681
682 /* Incorrect size, set width to the default */
683
684 Target64->BitWidth = FadtInfoTable[i].DefaultLength;
685 }
686 }
687 }
688
689 /*
690 * Get the length of the individual PM1 registers (enable and status).
691 * Each register is defined to be (event block length / 2). Extra divide
692 * by 8 converts bits to bytes.
693 */
694 Pm1RegisterByteWidth = (UINT8)
695 ACPI_DIV_16 (AcpiGbl_FADT.XPm1aEventBlock.BitWidth);
696
697 /*
698 * Calculate separate GAS structs for the PM1x (A/B) Status and Enable
699 * registers. These addresses do not appear (directly) in the FADT, so it
700 * is useful to pre-calculate them from the PM1 Event Block definitions.
701 *
702 * The PM event blocks are split into two register blocks, first is the
703 * PM Status Register block, followed immediately by the PM Enable
704 * Register block. Each is of length (Pm1EventLength/2)
705 *
706 * Note: The PM1A event block is required by the ACPI specification.
707 * However, the PM1B event block is optional and is rarely, if ever,
708 * used.
709 */
710
711 for (i = 0; i < ACPI_FADT_PM_INFO_ENTRIES; i++)
712 {
713 Source64 = ACPI_ADD_PTR (ACPI_GENERIC_ADDRESS, &AcpiGbl_FADT,
714 FadtPmInfoTable[i].Source);
715
716 if (Source64->Address)
717 {
718 AcpiTbInitGenericAddress (FadtPmInfoTable[i].Target,
719 Source64->SpaceId, Pm1RegisterByteWidth,
720 Source64->Address +
703 (FadtPmInfoTable[i].RegisterNum * Pm1RegisterByteWidth));
721 (FadtPmInfoTable[i].RegisterNum * Pm1RegisterByteWidth),
722 "PmRegisters");
704 }
705 }
706}
707
723 }
724 }
725}
726