diff options
author | Bob Moore <robert.moore@intel.com> | 2007-02-02 11:48:20 -0500 |
---|---|---|
committer | Len Brown <len.brown@intel.com> | 2007-02-02 21:14:25 -0500 |
commit | ea5d8ebcbb7ca3bcb35a2133805571295f3f06e8 (patch) | |
tree | f29ca361fe3e9592898730fcd5e42d9fdff84429 /drivers/acpi/tables/tbfadt.c | |
parent | 775d85b6aa33116da8aacad4168c540ce86a1803 (diff) |
ACPICA: FADT verification is now table driven.
Disassembler now verifies an input
Signed-off-by: Alexey Starikovskiy <alexey.y.starikovskiy@intel.com>
Signed-off-by: Len Brown <len.brown@intel.com>
Diffstat (limited to 'drivers/acpi/tables/tbfadt.c')
-rw-r--r-- | drivers/acpi/tables/tbfadt.c | 289 |
1 files changed, 153 insertions, 136 deletions
diff --git a/drivers/acpi/tables/tbfadt.c b/drivers/acpi/tables/tbfadt.c index 62485d32fcd6..8816bab0fe0e 100644 --- a/drivers/acpi/tables/tbfadt.c +++ b/drivers/acpi/tables/tbfadt.c | |||
@@ -49,74 +49,92 @@ ACPI_MODULE_NAME("tbfadt") | |||
49 | 49 | ||
50 | /* Local prototypes */ | 50 | /* Local prototypes */ |
51 | static void inline | 51 | static void inline |
52 | acpi_tb_init_generic_address(struct acpi_generic_address *new_gas_struct, | 52 | acpi_tb_init_generic_address(struct acpi_generic_address *generic_address, |
53 | u8 bit_width, u64 address); | 53 | u8 bit_width, u64 address); |
54 | 54 | ||
55 | static void acpi_tb_fadt_register_error(char *register_name, u32 value); | 55 | /* Table for conversion of FADT to common internal format and FADT validation */ |
56 | 56 | ||
57 | static void acpi_tb_convert_fadt(void); | 57 | typedef struct acpi_fadt_info { |
58 | 58 | char *name; | |
59 | static void acpi_tb_validate_fadt(void); | ||
60 | |||
61 | /* Table used for conversion of FADT to common format */ | ||
62 | |||
63 | typedef struct acpi_fadt_conversion { | ||
64 | u8 target; | 59 | u8 target; |
65 | u8 source; | 60 | u8 source; |
66 | u8 length; | 61 | u8 length; |
62 | u8 type; | ||
67 | 63 | ||
68 | } acpi_fadt_conversion; | 64 | } acpi_fadt_info; |
69 | 65 | ||
70 | static struct acpi_fadt_conversion fadt_conversion_table[] = { | 66 | #define ACPI_FADT_REQUIRED 1 |
71 | {ACPI_FADT_OFFSET(xpm1a_event_block), | 67 | #define ACPI_FADT_SEPARATE_LENGTH 2 |
68 | |||
69 | static struct acpi_fadt_info fadt_info_table[] = { | ||
70 | {"Pm1aEventBlock", ACPI_FADT_OFFSET(xpm1a_event_block), | ||
72 | ACPI_FADT_OFFSET(pm1a_event_block), | 71 | ACPI_FADT_OFFSET(pm1a_event_block), |
73 | ACPI_FADT_OFFSET(pm1_event_length)}, | 72 | ACPI_FADT_OFFSET(pm1_event_length), ACPI_FADT_REQUIRED}, |
74 | {ACPI_FADT_OFFSET(xpm1b_event_block), | 73 | |
74 | {"Pm1bEventBlock", ACPI_FADT_OFFSET(xpm1b_event_block), | ||
75 | ACPI_FADT_OFFSET(pm1b_event_block), | 75 | ACPI_FADT_OFFSET(pm1b_event_block), |
76 | ACPI_FADT_OFFSET(pm1_event_length)}, | 76 | ACPI_FADT_OFFSET(pm1_event_length), 0}, |
77 | {ACPI_FADT_OFFSET(xpm1a_control_block), | 77 | |
78 | {"Pm1aControlBlock", ACPI_FADT_OFFSET(xpm1a_control_block), | ||
78 | ACPI_FADT_OFFSET(pm1a_control_block), | 79 | ACPI_FADT_OFFSET(pm1a_control_block), |
79 | ACPI_FADT_OFFSET(pm1_control_length)}, | 80 | ACPI_FADT_OFFSET(pm1_control_length), ACPI_FADT_REQUIRED}, |
80 | {ACPI_FADT_OFFSET(xpm1b_control_block), | 81 | |
82 | {"Pm1bControlBlock", ACPI_FADT_OFFSET(xpm1b_control_block), | ||
81 | ACPI_FADT_OFFSET(pm1b_control_block), | 83 | ACPI_FADT_OFFSET(pm1b_control_block), |
82 | ACPI_FADT_OFFSET(pm1_control_length)}, | 84 | ACPI_FADT_OFFSET(pm1_control_length), 0}, |
83 | {ACPI_FADT_OFFSET(xpm2_control_block), | 85 | |
86 | {"Pm2ControlBlock", ACPI_FADT_OFFSET(xpm2_control_block), | ||
84 | ACPI_FADT_OFFSET(pm2_control_block), | 87 | ACPI_FADT_OFFSET(pm2_control_block), |
85 | ACPI_FADT_OFFSET(pm2_control_length)}, | 88 | ACPI_FADT_OFFSET(pm2_control_length), ACPI_FADT_SEPARATE_LENGTH}, |
86 | {ACPI_FADT_OFFSET(xpm_timer_block), ACPI_FADT_OFFSET(pm_timer_block), | 89 | |
87 | ACPI_FADT_OFFSET(pm_timer_length)}, | 90 | {"PmTimerBlock", ACPI_FADT_OFFSET(xpm_timer_block), |
88 | {ACPI_FADT_OFFSET(xgpe0_block), ACPI_FADT_OFFSET(gpe0_block), | 91 | ACPI_FADT_OFFSET(pm_timer_block), |
89 | ACPI_FADT_OFFSET(gpe0_block_length)}, | 92 | ACPI_FADT_OFFSET(pm_timer_length), ACPI_FADT_REQUIRED}, |
90 | {ACPI_FADT_OFFSET(xgpe1_block), ACPI_FADT_OFFSET(gpe1_block), | 93 | |
91 | ACPI_FADT_OFFSET(gpe1_block_length)} | 94 | {"Gpe0Block", ACPI_FADT_OFFSET(xgpe0_block), |
95 | ACPI_FADT_OFFSET(gpe0_block), | ||
96 | ACPI_FADT_OFFSET(gpe0_block_length), ACPI_FADT_SEPARATE_LENGTH}, | ||
97 | |||
98 | {"Gpe1Block", ACPI_FADT_OFFSET(xgpe1_block), | ||
99 | ACPI_FADT_OFFSET(gpe1_block), | ||
100 | ACPI_FADT_OFFSET(gpe1_block_length), ACPI_FADT_SEPARATE_LENGTH} | ||
92 | }; | 101 | }; |
93 | 102 | ||
94 | #define ACPI_FADT_CONVERSION_ENTRIES (sizeof (fadt_conversion_table) / sizeof (struct acpi_fadt_conversion)) | 103 | #define ACPI_FADT_INFO_ENTRIES (sizeof (fadt_info_table) / sizeof (struct acpi_fadt_info)) |
95 | 104 | ||
96 | /******************************************************************************* | 105 | /******************************************************************************* |
97 | * | 106 | * |
98 | * FUNCTION: acpi_tb_init_generic_address | 107 | * FUNCTION: acpi_tb_init_generic_address |
99 | * | 108 | * |
100 | * PARAMETERS: new_gas_struct - GAS struct to be initialized | 109 | * PARAMETERS: generic_address - GAS struct to be initialized |
101 | * bit_width - Width of this register | 110 | * bit_width - Width of this register |
102 | * Address - Address of the register | 111 | * Address - Address of the register |
103 | * | 112 | * |
104 | * RETURN: None | 113 | * RETURN: None |
105 | * | 114 | * |
106 | * DESCRIPTION: Initialize a GAS structure. | 115 | * DESCRIPTION: Initialize a Generic Address Structure (GAS) |
116 | * See the ACPI specification for a full description and | ||
117 | * definition of this structure. | ||
107 | * | 118 | * |
108 | ******************************************************************************/ | 119 | ******************************************************************************/ |
109 | 120 | ||
110 | static void inline | 121 | static void inline |
111 | acpi_tb_init_generic_address(struct acpi_generic_address *new_gas_struct, | 122 | acpi_tb_init_generic_address(struct acpi_generic_address *generic_address, |
112 | u8 bit_width, u64 address) | 123 | u8 bit_width, u64 address) |
113 | { | 124 | { |
114 | 125 | ||
115 | ACPI_MOVE_64_TO_64(&new_gas_struct->address, &address); | 126 | /* |
116 | new_gas_struct->space_id = ACPI_ADR_SPACE_SYSTEM_IO; | 127 | * The 64-bit Address field is non-aligned in the byte packed |
117 | new_gas_struct->bit_width = bit_width; | 128 | * GAS struct. |
118 | new_gas_struct->bit_offset = 0; | 129 | */ |
119 | new_gas_struct->access_width = 0; | 130 | ACPI_MOVE_64_TO_64(&generic_address->address, &address); |
131 | |||
132 | /* All other fields are byte-wide */ | ||
133 | |||
134 | generic_address->space_id = ACPI_ADR_SPACE_SYSTEM_IO; | ||
135 | generic_address->bit_width = bit_width; | ||
136 | generic_address->bit_offset = 0; | ||
137 | generic_address->access_width = 0; | ||
120 | } | 138 | } |
121 | 139 | ||
122 | /******************************************************************************* | 140 | /******************************************************************************* |
@@ -139,8 +157,8 @@ void acpi_tb_parse_fadt(acpi_native_uint table_index, u8 flags) | |||
139 | struct acpi_table_header *table; | 157 | struct acpi_table_header *table; |
140 | 158 | ||
141 | /* | 159 | /* |
142 | * Special case for the FADT because of multiple versions and the fact | 160 | * The FADT has multiple versions with different lengths, |
143 | * that it contains pointers to both the DSDT and FACS tables. | 161 | * and it contains pointers to both the DSDT and FACS tables. |
144 | * | 162 | * |
145 | * Get a local copy of the FADT and convert it to a common format | 163 | * Get a local copy of the FADT and convert it to a common format |
146 | * Map entire FADT, assumed to be smaller than one page. | 164 | * Map entire FADT, assumed to be smaller than one page. |
@@ -160,29 +178,41 @@ void acpi_tb_parse_fadt(acpi_native_uint table_index, u8 flags) | |||
160 | */ | 178 | */ |
161 | (void)acpi_tb_verify_checksum(table, length); | 179 | (void)acpi_tb_verify_checksum(table, length); |
162 | 180 | ||
163 | /* Copy the entire FADT locally */ | 181 | /* |
182 | * If the FADT is larger than what we know about, we have a problem. | ||
183 | * Truncate the table, but make some noise. | ||
184 | */ | ||
185 | if (length > sizeof(struct acpi_table_fadt)) { | ||
186 | ACPI_WARNING((AE_INFO, | ||
187 | "FADT (revision %u) is too large, truncating length 0x%X to 0x%X", | ||
188 | table->revision, length, | ||
189 | sizeof(struct acpi_table_fadt))); | ||
190 | } | ||
164 | 191 | ||
165 | ACPI_MEMSET(&acpi_gbl_FADT, 0, sizeof(struct acpi_table_fadt)); | 192 | /* Copy the entire FADT locally. Zero first for tb_convert_fadt */ |
166 | 193 | ||
194 | ACPI_MEMSET(&acpi_gbl_FADT, 0, sizeof(struct acpi_table_fadt)); | ||
167 | ACPI_MEMCPY(&acpi_gbl_FADT, table, | 195 | ACPI_MEMCPY(&acpi_gbl_FADT, table, |
168 | ACPI_MIN(length, sizeof(struct acpi_table_fadt))); | 196 | ACPI_MIN(length, sizeof(struct acpi_table_fadt))); |
169 | acpi_os_unmap_memory(table, length); | ||
170 | 197 | ||
171 | /* Convert local FADT to the common internal format */ | 198 | /* All done with the real FADT, unmap it */ |
199 | |||
200 | acpi_os_unmap_memory(table, length); | ||
172 | 201 | ||
202 | /* | ||
203 | * 1) Convert the local copy of the FADT to the common internal format | ||
204 | * 2) Validate some of the important values within the FADT | ||
205 | */ | ||
173 | acpi_tb_convert_fadt(); | 206 | acpi_tb_convert_fadt(); |
207 | acpi_tb_validate_fadt(&acpi_gbl_FADT); | ||
174 | 208 | ||
175 | /* Extract the DSDT and FACS tables from the FADT */ | 209 | /* Obtain the DSDT and FACS tables via their addresses within the FADT */ |
176 | 210 | ||
177 | acpi_tb_install_table((acpi_physical_address) acpi_gbl_FADT.Xdsdt, | 211 | acpi_tb_install_table((acpi_physical_address) acpi_gbl_FADT.Xdsdt, |
178 | flags, ACPI_SIG_DSDT, ACPI_TABLE_INDEX_DSDT); | 212 | flags, ACPI_SIG_DSDT, ACPI_TABLE_INDEX_DSDT); |
179 | 213 | ||
180 | acpi_tb_install_table((acpi_physical_address) acpi_gbl_FADT.Xfacs, | 214 | acpi_tb_install_table((acpi_physical_address) acpi_gbl_FADT.Xfacs, |
181 | flags, ACPI_SIG_FACS, ACPI_TABLE_INDEX_FACS); | 215 | flags, ACPI_SIG_FACS, ACPI_TABLE_INDEX_FACS); |
182 | |||
183 | /* Validate important FADT values */ | ||
184 | |||
185 | acpi_tb_validate_fadt(); | ||
186 | } | 216 | } |
187 | 217 | ||
188 | /******************************************************************************* | 218 | /******************************************************************************* |
@@ -194,6 +224,7 @@ void acpi_tb_parse_fadt(acpi_native_uint table_index, u8 flags) | |||
194 | * RETURN: None | 224 | * RETURN: None |
195 | * | 225 | * |
196 | * DESCRIPTION: Converts all versions of the FADT to a common internal format. | 226 | * DESCRIPTION: Converts all versions of the FADT to a common internal format. |
227 | * -> Expand all 32-bit addresses to 64-bit. | ||
197 | * | 228 | * |
198 | * NOTE: acpi_gbl_FADT must be of size (struct acpi_table_fadt), | 229 | * NOTE: acpi_gbl_FADT must be of size (struct acpi_table_fadt), |
199 | * and must contain a copy of the actual FADT. | 230 | * and must contain a copy of the actual FADT. |
@@ -213,13 +244,17 @@ void acpi_tb_parse_fadt(acpi_native_uint table_index, u8 flags) | |||
213 | * | 244 | * |
214 | ******************************************************************************/ | 245 | ******************************************************************************/ |
215 | 246 | ||
216 | static void acpi_tb_convert_fadt(void) | 247 | void acpi_tb_convert_fadt(void) |
217 | { | 248 | { |
218 | u8 pm1_register_length; | 249 | u8 pm1_register_length; |
219 | struct acpi_generic_address *target; | 250 | struct acpi_generic_address *target; |
220 | acpi_native_uint i; | 251 | acpi_native_uint i; |
221 | 252 | ||
222 | /* Expand the FACS and DSDT addresses as necessary */ | 253 | /* Update the local FADT table header length */ |
254 | |||
255 | acpi_gbl_FADT.header.length = sizeof(struct acpi_table_fadt); | ||
256 | |||
257 | /* Expand the 32-bit FACS and DSDT addresses to 64-bit as necessary */ | ||
223 | 258 | ||
224 | if (!acpi_gbl_FADT.Xfacs) { | 259 | if (!acpi_gbl_FADT.Xfacs) { |
225 | acpi_gbl_FADT.Xfacs = (u64) acpi_gbl_FADT.facs; | 260 | acpi_gbl_FADT.Xfacs = (u64) acpi_gbl_FADT.facs; |
@@ -233,10 +268,10 @@ static void acpi_tb_convert_fadt(void) | |||
233 | * Expand the 32-bit V1.0 addresses to the 64-bit "X" generic address | 268 | * Expand the 32-bit V1.0 addresses to the 64-bit "X" generic address |
234 | * structures as necessary. | 269 | * structures as necessary. |
235 | */ | 270 | */ |
236 | for (i = 0; i < ACPI_FADT_CONVERSION_ENTRIES; i++) { | 271 | for (i = 0; i < ACPI_FADT_INFO_ENTRIES; i++) { |
237 | target = | 272 | target = |
238 | ACPI_ADD_PTR(struct acpi_generic_address, &acpi_gbl_FADT, | 273 | ACPI_ADD_PTR(struct acpi_generic_address, &acpi_gbl_FADT, |
239 | fadt_conversion_table[i].target); | 274 | fadt_info_table[i].target); |
240 | 275 | ||
241 | /* Expand only if the X target is null */ | 276 | /* Expand only if the X target is null */ |
242 | 277 | ||
@@ -244,11 +279,11 @@ static void acpi_tb_convert_fadt(void) | |||
244 | acpi_tb_init_generic_address(target, | 279 | acpi_tb_init_generic_address(target, |
245 | *ACPI_ADD_PTR(u8, | 280 | *ACPI_ADD_PTR(u8, |
246 | &acpi_gbl_FADT, | 281 | &acpi_gbl_FADT, |
247 | fadt_conversion_table | 282 | fadt_info_table |
248 | [i].length), | 283 | [i].length), |
249 | (u64) * ACPI_ADD_PTR(u32, | 284 | (u64) * ACPI_ADD_PTR(u32, |
250 | &acpi_gbl_FADT, | 285 | &acpi_gbl_FADT, |
251 | fadt_conversion_table | 286 | fadt_info_table |
252 | [i]. | 287 | [i]. |
253 | source)); | 288 | source)); |
254 | } | 289 | } |
@@ -265,14 +300,14 @@ static void acpi_tb_convert_fadt(void) | |||
265 | */ | 300 | */ |
266 | pm1_register_length = (u8) ACPI_DIV_2(acpi_gbl_FADT.pm1_event_length); | 301 | pm1_register_length = (u8) ACPI_DIV_2(acpi_gbl_FADT.pm1_event_length); |
267 | 302 | ||
268 | /* PM1A is required */ | 303 | /* The PM1A register block is required */ |
269 | 304 | ||
270 | acpi_tb_init_generic_address(&acpi_gbl_xpm1a_enable, | 305 | acpi_tb_init_generic_address(&acpi_gbl_xpm1a_enable, |
271 | pm1_register_length, | 306 | pm1_register_length, |
272 | (acpi_gbl_FADT.xpm1a_event_block.address + | 307 | (acpi_gbl_FADT.xpm1a_event_block.address + |
273 | pm1_register_length)); | 308 | pm1_register_length)); |
274 | 309 | ||
275 | /* PM1B is optional; leave null if not present */ | 310 | /* The PM1B register block is optional, ignore if not present */ |
276 | 311 | ||
277 | if (acpi_gbl_FADT.xpm1b_event_block.address) { | 312 | if (acpi_gbl_FADT.xpm1b_event_block.address) { |
278 | acpi_tb_init_generic_address(&acpi_gbl_xpm1b_enable, | 313 | acpi_tb_init_generic_address(&acpi_gbl_xpm1b_enable, |
@@ -280,102 +315,84 @@ static void acpi_tb_convert_fadt(void) | |||
280 | (acpi_gbl_FADT.xpm1b_event_block. | 315 | (acpi_gbl_FADT.xpm1b_event_block. |
281 | address + pm1_register_length)); | 316 | address + pm1_register_length)); |
282 | } | 317 | } |
283 | |||
284 | /* Global FADT is the new common V2.0 FADT */ | ||
285 | |||
286 | acpi_gbl_FADT.header.length = sizeof(struct acpi_table_fadt); | ||
287 | } | 318 | } |
288 | 319 | ||
289 | /****************************************************************************** | 320 | /****************************************************************************** |
290 | * | 321 | * |
291 | * FUNCTION: acpi_tb_validate_fadt | 322 | * FUNCTION: acpi_tb_validate_fadt |
292 | * | 323 | * |
293 | * PARAMETERS: None | 324 | * PARAMETERS: Table - Pointer to the FADT to be validated |
294 | * | 325 | * |
295 | * RETURN: None | 326 | * RETURN: None |
296 | * | 327 | * |
297 | * DESCRIPTION: Validate various ACPI registers in the FADT. For problems, | 328 | * DESCRIPTION: Validate various important fields within the FADT. If a problem |
298 | * issue a message, but no status is returned. | 329 | * is found, issue a message, but no status is returned. |
330 | * Used by both the table manager and the disassembler. | ||
331 | * | ||
332 | * Possible additional checks: | ||
333 | * (acpi_gbl_FADT.pm1_event_length >= 4) | ||
334 | * (acpi_gbl_FADT.pm1_control_length >= 2) | ||
335 | * (acpi_gbl_FADT.pm_timer_length >= 4) | ||
336 | * Gpe block lengths must be multiple of 2 | ||
299 | * | 337 | * |
300 | ******************************************************************************/ | 338 | ******************************************************************************/ |
301 | 339 | ||
302 | static void acpi_tb_validate_fadt(void) | 340 | void acpi_tb_validate_fadt(struct acpi_table_fadt *table) |
303 | { | 341 | { |
342 | u32 *address32; | ||
343 | struct acpi_generic_address *address64; | ||
344 | u8 length; | ||
345 | acpi_native_uint i; | ||
304 | 346 | ||
305 | /* These length fields have a minimum value */ | 347 | /* Examine all of the 64-bit extended address fields (X fields) */ |
306 | 348 | ||
307 | if (acpi_gbl_FADT.pm1_event_length < 4) { | 349 | for (i = 0; i < ACPI_FADT_INFO_ENTRIES; i++) { |
308 | acpi_tb_fadt_register_error("Pm1EventLength", | 350 | |
309 | (u32) acpi_gbl_FADT. | 351 | /* Generate pointers to the 32-bit and 64-bit addresses and get the length */ |
310 | pm1_event_length); | 352 | |
311 | } | 353 | address64 = |
312 | 354 | ACPI_ADD_PTR(struct acpi_generic_address, table, | |
313 | if (acpi_gbl_FADT.pm_timer_length < 4) { | 355 | fadt_info_table[i].target); |
314 | acpi_tb_fadt_register_error("PmTimerLength", | 356 | address32 = ACPI_ADD_PTR(u32, table, fadt_info_table[i].source); |
315 | (u32) acpi_gbl_FADT. | 357 | length = *ACPI_ADD_PTR(u8, table, fadt_info_table[i].length); |
316 | pm_timer_length); | 358 | |
317 | } | 359 | if (fadt_info_table[i].type & ACPI_FADT_REQUIRED) { |
318 | 360 | /* | |
319 | /* These length and address fields must be non-zero */ | 361 | * Field is required (Pm1a_event, Pm1a_control, pm_timer). |
320 | 362 | * Both the address and length must be non-zero. | |
321 | if (!acpi_gbl_FADT.pm1_control_length) { | 363 | */ |
322 | acpi_tb_fadt_register_error("Pm1ControlLength", 0); | 364 | if (!address64->address || !length) { |
323 | } | 365 | ACPI_ERROR((AE_INFO, |
324 | 366 | "Required field \"%s\" has zero address and/or length: %8.8X%8.8X/%X", | |
325 | if (!acpi_gbl_FADT.xpm1a_event_block.address) { | 367 | fadt_info_table[i].name, |
326 | acpi_tb_fadt_register_error("XPm1aEventBlock.Address", 0); | 368 | ACPI_FORMAT_UINT64(address64-> |
327 | } | 369 | address), |
328 | 370 | length)); | |
329 | if (!acpi_gbl_FADT.xpm1a_control_block.address) { | 371 | } |
330 | acpi_tb_fadt_register_error("XPm1aControlBlock.Address", 0); | 372 | } else if (fadt_info_table[i].type & ACPI_FADT_SEPARATE_LENGTH) { |
331 | } | 373 | /* |
332 | 374 | * Field is optional (PM2Control, GPE0, GPE1) AND has its own | |
333 | if (!acpi_gbl_FADT.xpm_timer_block.address) { | 375 | * length field. If present, both the address and length must be valid. |
334 | acpi_tb_fadt_register_error("XPmTimerBlock.Address", 0); | 376 | */ |
335 | } | 377 | if ((address64->address && !length) |
336 | 378 | || (!address64->address && length)) { | |
337 | /* If PM2 block is present, must have non-zero length */ | 379 | ACPI_WARNING((AE_INFO, |
338 | 380 | "Optional field \"%s\" has zero address or length: %8.8X%8.8X/%X", | |
339 | if ((acpi_gbl_FADT.xpm2_control_block.address && | 381 | fadt_info_table[i].name, |
340 | !acpi_gbl_FADT.pm2_control_length)) { | 382 | ACPI_FORMAT_UINT64(address64-> |
341 | acpi_tb_fadt_register_error("Pm2ControlLength", | 383 | address), |
342 | (u32) acpi_gbl_FADT. | 384 | length)); |
343 | pm2_control_length); | 385 | } |
344 | } | 386 | } |
345 | |||
346 | /* Length of any valid GPE blocks must be a multiple of 2 */ | ||
347 | 387 | ||
348 | if (acpi_gbl_FADT.xgpe0_block.address && | 388 | /* If both 32- and 64-bit addresses are valid (non-zero), they must match */ |
349 | (acpi_gbl_FADT.gpe0_block_length & 1)) { | ||
350 | acpi_tb_fadt_register_error("Gpe0BlockLength", | ||
351 | (u32) acpi_gbl_FADT. | ||
352 | gpe0_block_length); | ||
353 | } | ||
354 | 389 | ||
355 | if (acpi_gbl_FADT.xgpe1_block.address && | 390 | if (address64->address && *address32 && |
356 | (acpi_gbl_FADT.gpe1_block_length & 1)) { | 391 | (address64->address != (u64) * address32)) { |
357 | acpi_tb_fadt_register_error("Gpe1BlockLength", | 392 | ACPI_ERROR((AE_INFO, |
358 | (u32) acpi_gbl_FADT. | 393 | "32/64X address mismatch in \"%s\": [%8.8X] [%8.8X%8.8X], using 64X", |
359 | gpe1_block_length); | 394 | fadt_info_table[i].name, *address32, |
395 | ACPI_FORMAT_UINT64(address64->address))); | ||
396 | } | ||
360 | } | 397 | } |
361 | } | 398 | } |
362 | |||
363 | /******************************************************************************* | ||
364 | * | ||
365 | * FUNCTION: acpi_tb_fadt_register_error | ||
366 | * | ||
367 | * PARAMETERS: register_name - Pointer to string identifying register | ||
368 | * Value - Actual register contents value | ||
369 | * | ||
370 | * RETURN: None | ||
371 | * | ||
372 | * DESCRIPTION: Display FADT warning message | ||
373 | * | ||
374 | ******************************************************************************/ | ||
375 | |||
376 | static void acpi_tb_fadt_register_error(char *register_name, u32 value) | ||
377 | { | ||
378 | |||
379 | ACPI_WARNING((AE_INFO, "Invalid FADT value in field \"%s\" = %X", | ||
380 | register_name, value)); | ||
381 | } | ||