]> git.proxmox.com Git - mirror_ubuntu-zesty-kernel.git/blame - drivers/acpi/tables/tbconvrt.c
ACPICA 20050617-0624 from Bob Moore <robert.moore@intel.com>
[mirror_ubuntu-zesty-kernel.git] / drivers / acpi / tables / tbconvrt.c
CommitLineData
1da177e4
LT
1/******************************************************************************
2 *
3 * Module Name: tbconvrt - ACPI Table conversion utilities
4 *
5 *****************************************************************************/
6
7/*
8 * Copyright (C) 2000 - 2005, R. Byron Moore
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#include <linux/module.h>
45
46#include <acpi/acpi.h>
47#include <acpi/actables.h>
48
49
50#define _COMPONENT ACPI_TABLES
51 ACPI_MODULE_NAME ("tbconvrt")
52
44f6c012
RM
53/* Local prototypes */
54
55static void
56acpi_tb_init_generic_address (
57 struct acpi_generic_address *new_gas_struct,
58 u8 register_bit_width,
59 acpi_physical_address address);
60
61static void
62acpi_tb_convert_fadt1 (
63 struct fadt_descriptor_rev2 *local_fadt,
64 struct fadt_descriptor_rev1 *original_fadt);
65
66static void
67acpi_tb_convert_fadt2 (
68 struct fadt_descriptor_rev2 *local_fadt,
69 struct fadt_descriptor_rev2 *original_fadt);
70
1da177e4
LT
71
72u8 acpi_fadt_is_v1;
73EXPORT_SYMBOL(acpi_fadt_is_v1);
74
75/*******************************************************************************
76 *
77 * FUNCTION: acpi_tb_get_table_count
78 *
79 * PARAMETERS: RSDP - Pointer to the RSDP
80 * RSDT - Pointer to the RSDT/XSDT
81 *
82 * RETURN: The number of tables pointed to by the RSDT or XSDT.
83 *
84 * DESCRIPTION: Calculate the number of tables. Automatically handles either
85 * an RSDT or XSDT.
86 *
87 ******************************************************************************/
88
89u32
90acpi_tb_get_table_count (
91 struct rsdp_descriptor *RSDP,
92 struct acpi_table_header *RSDT)
93{
94 u32 pointer_size;
95
96
97 ACPI_FUNCTION_ENTRY ();
98
99
73459f73
RM
100 /* RSDT pointers are 32 bits, XSDT pointers are 64 bits */
101
102 if (acpi_gbl_root_table_type == ACPI_TABLE_TYPE_RSDT) {
1da177e4
LT
103 pointer_size = sizeof (u32);
104 }
105 else {
106 pointer_size = sizeof (u64);
107 }
108
109 /*
110 * Determine the number of tables pointed to by the RSDT/XSDT.
111 * This is defined by the ACPI Specification to be the number of
112 * pointers contained within the RSDT/XSDT. The size of the pointers
113 * is architecture-dependent.
114 */
115 return ((RSDT->length - sizeof (struct acpi_table_header)) / pointer_size);
116}
117
118
119/*******************************************************************************
120 *
121 * FUNCTION: acpi_tb_convert_to_xsdt
122 *
123 * PARAMETERS: table_info - Info about the RSDT
124 *
125 * RETURN: Status
126 *
127 * DESCRIPTION: Convert an RSDT to an XSDT (internal common format)
128 *
129 ******************************************************************************/
130
131acpi_status
132acpi_tb_convert_to_xsdt (
133 struct acpi_table_desc *table_info)
134{
135 acpi_size table_size;
136 u32 i;
137 XSDT_DESCRIPTOR *new_table;
138
139
140 ACPI_FUNCTION_ENTRY ();
141
142
143 /* Compute size of the converted XSDT */
144
145 table_size = ((acpi_size) acpi_gbl_rsdt_table_count * sizeof (u64)) +
146 sizeof (struct acpi_table_header);
147
148 /* Allocate an XSDT */
149
150 new_table = ACPI_MEM_CALLOCATE (table_size);
151 if (!new_table) {
152 return (AE_NO_MEMORY);
153 }
154
155 /* Copy the header and set the length */
156
157 ACPI_MEMCPY (new_table, table_info->pointer, sizeof (struct acpi_table_header));
158 new_table->length = (u32) table_size;
159
160 /* Copy the table pointers */
161
162 for (i = 0; i < acpi_gbl_rsdt_table_count; i++) {
73459f73
RM
163 /* RSDT pointers are 32 bits, XSDT pointers are 64 bits */
164
165 if (acpi_gbl_root_table_type == ACPI_TABLE_TYPE_RSDT) {
1da177e4 166 ACPI_STORE_ADDRESS (new_table->table_offset_entry[i],
44f6c012
RM
167 (ACPI_CAST_PTR (struct rsdt_descriptor_rev1,
168 table_info->pointer))->table_offset_entry[i]);
1da177e4
LT
169 }
170 else {
171 new_table->table_offset_entry[i] =
44f6c012
RM
172 (ACPI_CAST_PTR (XSDT_DESCRIPTOR,
173 table_info->pointer))->table_offset_entry[i];
1da177e4
LT
174 }
175 }
176
177 /* Delete the original table (either mapped or in a buffer) */
178
179 acpi_tb_delete_single_table (table_info);
180
181 /* Point the table descriptor to the new table */
182
183 table_info->pointer = ACPI_CAST_PTR (struct acpi_table_header, new_table);
184 table_info->length = table_size;
185 table_info->allocation = ACPI_MEM_ALLOCATED;
186
187 return (AE_OK);
188}
189
190
44f6c012 191/*******************************************************************************
1da177e4
LT
192 *
193 * FUNCTION: acpi_tb_init_generic_address
194 *
195 * PARAMETERS: new_gas_struct - GAS struct to be initialized
196 * register_bit_width - Width of this register
197 * Address - Address of the register
198 *
199 * RETURN: None
200 *
201 * DESCRIPTION: Initialize a GAS structure.
202 *
203 ******************************************************************************/
204
205static void
206acpi_tb_init_generic_address (
207 struct acpi_generic_address *new_gas_struct,
208 u8 register_bit_width,
209 acpi_physical_address address)
210{
211
212 ACPI_STORE_ADDRESS (new_gas_struct->address, address);
213
214 new_gas_struct->address_space_id = ACPI_ADR_SPACE_SYSTEM_IO;
215 new_gas_struct->register_bit_width = register_bit_width;
216 new_gas_struct->register_bit_offset = 0;
217 new_gas_struct->access_width = 0;
218}
219
220
221/*******************************************************************************
222 *
223 * FUNCTION: acpi_tb_convert_fadt1
224 *
225 * PARAMETERS: local_fadt - Pointer to new FADT
226 * original_fadt - Pointer to old FADT
227 *
44f6c012 228 * RETURN: None, populates local_fadt
1da177e4
LT
229 *
230 * DESCRIPTION: Convert an ACPI 1.0 FADT to common internal format
231 *
232 ******************************************************************************/
233
234static void
235acpi_tb_convert_fadt1 (
236 struct fadt_descriptor_rev2 *local_fadt,
237 struct fadt_descriptor_rev1 *original_fadt)
238{
239
1da177e4
LT
240 /* ACPI 1.0 FACS */
241 /* The BIOS stored FADT should agree with Revision 1.0 */
242 acpi_fadt_is_v1 = 1;
243
244 /*
245 * Copy the table header and the common part of the tables.
246 *
247 * The 2.0 table is an extension of the 1.0 table, so the entire 1.0
248 * table can be copied first, then expand some fields to 64 bits.
249 */
250 ACPI_MEMCPY (local_fadt, original_fadt, sizeof (struct fadt_descriptor_rev1));
251
252 /* Convert table pointers to 64-bit fields */
253
254 ACPI_STORE_ADDRESS (local_fadt->xfirmware_ctrl, local_fadt->V1_firmware_ctrl);
255 ACPI_STORE_ADDRESS (local_fadt->Xdsdt, local_fadt->V1_dsdt);
256
257 /*
44f6c012
RM
258 * System Interrupt Model isn't used in ACPI 2.0
259 * (local_fadt->Reserved1 = 0;)
1da177e4
LT
260 */
261
262 /*
263 * This field is set by the OEM to convey the preferred power management
264 * profile to OSPM. It doesn't have any 1.0 equivalence. Since we don't
265 * know what kind of 32-bit system this is, we will use "unspecified".
266 */
267 local_fadt->prefer_PM_profile = PM_UNSPECIFIED;
268
269 /*
270 * Processor Performance State Control. This is the value OSPM writes to
271 * the SMI_CMD register to assume processor performance state control
272 * responsibility. There isn't any equivalence in 1.0, but as many 1.x
273 * ACPI tables contain _PCT and _PSS we also keep this value, unless
274 * acpi_strict is set.
275 */
276 if (acpi_strict)
277 local_fadt->pstate_cnt = 0;
278
279 /*
280 * Support for the _CST object and C States change notification.
281 * This data item hasn't any 1.0 equivalence so leave it zero.
282 */
283 local_fadt->cst_cnt = 0;
284
285 /*
286 * FADT Rev 2 was an interim FADT released between ACPI 1.0 and ACPI 2.0.
287 * It primarily adds the FADT reset mechanism.
288 */
289 if ((original_fadt->revision == 2) &&
290 (original_fadt->length == sizeof (struct fadt_descriptor_rev2_minus))) {
291 /*
292 * Grab the entire generic address struct, plus the 1-byte reset value
293 * that immediately follows.
294 */
295 ACPI_MEMCPY (&local_fadt->reset_register,
44f6c012
RM
296 &(ACPI_CAST_PTR (struct fadt_descriptor_rev2_minus,
297 original_fadt))->reset_register,
1da177e4
LT
298 sizeof (struct acpi_generic_address) + 1);
299 }
300 else {
301 /*
302 * Since there isn't any equivalence in 1.0 and since it is highly
303 * likely that a 1.0 system has legacy support.
304 */
305 local_fadt->iapc_boot_arch = BAF_LEGACY_DEVICES;
306 }
307
308 /*
309 * Convert the V1.0 block addresses to V2.0 GAS structures
310 */
311 acpi_tb_init_generic_address (&local_fadt->xpm1a_evt_blk, local_fadt->pm1_evt_len,
312 (acpi_physical_address) local_fadt->V1_pm1a_evt_blk);
313 acpi_tb_init_generic_address (&local_fadt->xpm1b_evt_blk, local_fadt->pm1_evt_len,
314 (acpi_physical_address) local_fadt->V1_pm1b_evt_blk);
315 acpi_tb_init_generic_address (&local_fadt->xpm1a_cnt_blk, local_fadt->pm1_cnt_len,
316 (acpi_physical_address) local_fadt->V1_pm1a_cnt_blk);
317 acpi_tb_init_generic_address (&local_fadt->xpm1b_cnt_blk, local_fadt->pm1_cnt_len,
318 (acpi_physical_address) local_fadt->V1_pm1b_cnt_blk);
319 acpi_tb_init_generic_address (&local_fadt->xpm2_cnt_blk, local_fadt->pm2_cnt_len,
320 (acpi_physical_address) local_fadt->V1_pm2_cnt_blk);
321 acpi_tb_init_generic_address (&local_fadt->xpm_tmr_blk, local_fadt->pm_tm_len,
322 (acpi_physical_address) local_fadt->V1_pm_tmr_blk);
323 acpi_tb_init_generic_address (&local_fadt->xgpe0_blk, 0,
324 (acpi_physical_address) local_fadt->V1_gpe0_blk);
325 acpi_tb_init_generic_address (&local_fadt->xgpe1_blk, 0,
326 (acpi_physical_address) local_fadt->V1_gpe1_blk);
327
328 /* Create separate GAS structs for the PM1 Enable registers */
329
330 acpi_tb_init_generic_address (&acpi_gbl_xpm1a_enable,
331 (u8) ACPI_DIV_2 (acpi_gbl_FADT->pm1_evt_len),
44f6c012
RM
332 (acpi_physical_address)
333 (local_fadt->xpm1a_evt_blk.address +
1da177e4
LT
334 ACPI_DIV_2 (acpi_gbl_FADT->pm1_evt_len)));
335
336 /* PM1B is optional; leave null if not present */
337
338 if (local_fadt->xpm1b_evt_blk.address) {
339 acpi_tb_init_generic_address (&acpi_gbl_xpm1b_enable,
340 (u8) ACPI_DIV_2 (acpi_gbl_FADT->pm1_evt_len),
44f6c012
RM
341 (acpi_physical_address)
342 (local_fadt->xpm1b_evt_blk.address +
1da177e4
LT
343 ACPI_DIV_2 (acpi_gbl_FADT->pm1_evt_len)));
344 }
345}
346
347
348/*******************************************************************************
349 *
350 * FUNCTION: acpi_tb_convert_fadt2
351 *
352 * PARAMETERS: local_fadt - Pointer to new FADT
353 * original_fadt - Pointer to old FADT
354 *
44f6c012 355 * RETURN: None, populates local_fadt
1da177e4
LT
356 *
357 * DESCRIPTION: Convert an ACPI 2.0 FADT to common internal format.
358 * Handles optional "X" fields.
359 *
360 ******************************************************************************/
361
362static void
363acpi_tb_convert_fadt2 (
364 struct fadt_descriptor_rev2 *local_fadt,
365 struct fadt_descriptor_rev2 *original_fadt)
366{
367
368 /* We have an ACPI 2.0 FADT but we must copy it to our local buffer */
369
370 ACPI_MEMCPY (local_fadt, original_fadt, sizeof (struct fadt_descriptor_rev2));
371
372 /*
373 * "X" fields are optional extensions to the original V1.0 fields, so
374 * we must selectively expand V1.0 fields if the corresponding X field
375 * is zero.
376 */
377 if (!(local_fadt->xfirmware_ctrl)) {
44f6c012
RM
378 ACPI_STORE_ADDRESS (local_fadt->xfirmware_ctrl,
379 local_fadt->V1_firmware_ctrl);
1da177e4
LT
380 }
381
382 if (!(local_fadt->Xdsdt)) {
383 ACPI_STORE_ADDRESS (local_fadt->Xdsdt, local_fadt->V1_dsdt);
384 }
385
386 if (!(local_fadt->xpm1a_evt_blk.address)) {
387 acpi_tb_init_generic_address (&local_fadt->xpm1a_evt_blk,
44f6c012
RM
388 local_fadt->pm1_evt_len,
389 (acpi_physical_address) local_fadt->V1_pm1a_evt_blk);
1da177e4
LT
390 }
391
392 if (!(local_fadt->xpm1b_evt_blk.address)) {
393 acpi_tb_init_generic_address (&local_fadt->xpm1b_evt_blk,
44f6c012
RM
394 local_fadt->pm1_evt_len,
395 (acpi_physical_address) local_fadt->V1_pm1b_evt_blk);
1da177e4
LT
396 }
397
398 if (!(local_fadt->xpm1a_cnt_blk.address)) {
399 acpi_tb_init_generic_address (&local_fadt->xpm1a_cnt_blk,
44f6c012
RM
400 local_fadt->pm1_cnt_len,
401 (acpi_physical_address) local_fadt->V1_pm1a_cnt_blk);
1da177e4
LT
402 }
403
404 if (!(local_fadt->xpm1b_cnt_blk.address)) {
405 acpi_tb_init_generic_address (&local_fadt->xpm1b_cnt_blk,
44f6c012
RM
406 local_fadt->pm1_cnt_len,
407 (acpi_physical_address) local_fadt->V1_pm1b_cnt_blk);
1da177e4
LT
408 }
409
410 if (!(local_fadt->xpm2_cnt_blk.address)) {
411 acpi_tb_init_generic_address (&local_fadt->xpm2_cnt_blk,
44f6c012
RM
412 local_fadt->pm2_cnt_len,
413 (acpi_physical_address) local_fadt->V1_pm2_cnt_blk);
1da177e4
LT
414 }
415
416 if (!(local_fadt->xpm_tmr_blk.address)) {
417 acpi_tb_init_generic_address (&local_fadt->xpm_tmr_blk,
44f6c012
RM
418 local_fadt->pm_tm_len,
419 (acpi_physical_address) local_fadt->V1_pm_tmr_blk);
1da177e4
LT
420 }
421
422 if (!(local_fadt->xgpe0_blk.address)) {
423 acpi_tb_init_generic_address (&local_fadt->xgpe0_blk,
424 0, (acpi_physical_address) local_fadt->V1_gpe0_blk);
425 }
426
427 if (!(local_fadt->xgpe1_blk.address)) {
428 acpi_tb_init_generic_address (&local_fadt->xgpe1_blk,
429 0, (acpi_physical_address) local_fadt->V1_gpe1_blk);
430 }
431
432 /* Create separate GAS structs for the PM1 Enable registers */
433
434 acpi_tb_init_generic_address (&acpi_gbl_xpm1a_enable,
435 (u8) ACPI_DIV_2 (acpi_gbl_FADT->pm1_evt_len),
44f6c012
RM
436 (acpi_physical_address)
437 (local_fadt->xpm1a_evt_blk.address +
1da177e4 438 ACPI_DIV_2 (acpi_gbl_FADT->pm1_evt_len)));
44f6c012
RM
439
440 acpi_gbl_xpm1a_enable.address_space_id =
441 local_fadt->xpm1a_evt_blk.address_space_id;
1da177e4
LT
442
443 /* PM1B is optional; leave null if not present */
444
445 if (local_fadt->xpm1b_evt_blk.address) {
446 acpi_tb_init_generic_address (&acpi_gbl_xpm1b_enable,
447 (u8) ACPI_DIV_2 (acpi_gbl_FADT->pm1_evt_len),
44f6c012
RM
448 (acpi_physical_address)
449 (local_fadt->xpm1b_evt_blk.address +
1da177e4 450 ACPI_DIV_2 (acpi_gbl_FADT->pm1_evt_len)));
44f6c012
RM
451
452 acpi_gbl_xpm1b_enable.address_space_id =
453 local_fadt->xpm1b_evt_blk.address_space_id;
1da177e4
LT
454 }
455}
456
457
458/*******************************************************************************
459 *
460 * FUNCTION: acpi_tb_convert_table_fadt
461 *
462 * PARAMETERS: None
463 *
464 * RETURN: Status
465 *
466 * DESCRIPTION: Converts a BIOS supplied ACPI 1.0 FADT to a local
467 * ACPI 2.0 FADT. If the BIOS supplied a 2.0 FADT then it is simply
468 * copied to the local FADT. The ACPI CA software uses this
469 * local FADT. Thus a significant amount of special #ifdef
470 * type codeing is saved.
471 *
472 ******************************************************************************/
473
474acpi_status
44f6c012
RM
475acpi_tb_convert_table_fadt (
476 void)
1da177e4
LT
477{
478 struct fadt_descriptor_rev2 *local_fadt;
479 struct acpi_table_desc *table_desc;
480
481
482 ACPI_FUNCTION_TRACE ("tb_convert_table_fadt");
483
484
485 /*
486 * acpi_gbl_FADT is valid. Validate the FADT length. The table must be
487 * at least as long as the version 1.0 FADT
488 */
489 if (acpi_gbl_FADT->length < sizeof (struct fadt_descriptor_rev1)) {
44f6c012
RM
490 ACPI_REPORT_ERROR (("FADT is invalid, too short: 0x%X\n",
491 acpi_gbl_FADT->length));
1da177e4
LT
492 return_ACPI_STATUS (AE_INVALID_TABLE_LENGTH);
493 }
494
495 /* Allocate buffer for the ACPI 2.0(+) FADT */
496
497 local_fadt = ACPI_MEM_CALLOCATE (sizeof (struct fadt_descriptor_rev2));
498 if (!local_fadt) {
499 return_ACPI_STATUS (AE_NO_MEMORY);
500 }
501
502 if (acpi_gbl_FADT->revision >= FADT2_REVISION_ID) {
503 if (acpi_gbl_FADT->length < sizeof (struct fadt_descriptor_rev2)) {
504 /* Length is too short to be a V2.0 table */
505
44f6c012
RM
506 ACPI_REPORT_WARNING ((
507 "Inconsistent FADT length (0x%X) and revision (0x%X), using FADT V1.0 portion of table\n",
508 acpi_gbl_FADT->length, acpi_gbl_FADT->revision));
1da177e4
LT
509
510 acpi_tb_convert_fadt1 (local_fadt, (void *) acpi_gbl_FADT);
511 }
512 else {
513 /* Valid V2.0 table */
514
515 acpi_tb_convert_fadt2 (local_fadt, acpi_gbl_FADT);
516 }
517 }
518 else {
519 /* Valid V1.0 table */
520
521 acpi_tb_convert_fadt1 (local_fadt, (void *) acpi_gbl_FADT);
522 }
523
44f6c012
RM
524 /* Global FADT pointer will point to the new common V2.0 FADT */
525
1da177e4
LT
526 acpi_gbl_FADT = local_fadt;
527 acpi_gbl_FADT->length = sizeof (FADT_DESCRIPTOR);
528
529 /* Free the original table */
530
531 table_desc = acpi_gbl_table_lists[ACPI_TABLE_FADT].next;
532 acpi_tb_delete_single_table (table_desc);
533
534 /* Install the new table */
535
536 table_desc->pointer = ACPI_CAST_PTR (struct acpi_table_header, acpi_gbl_FADT);
537 table_desc->allocation = ACPI_MEM_ALLOCATED;
538 table_desc->length = sizeof (struct fadt_descriptor_rev2);
539
540 /* Dump the entire FADT */
541
542 ACPI_DEBUG_PRINT ((ACPI_DB_TABLES,
543 "Hex dump of common internal FADT, size %d (%X)\n",
544 acpi_gbl_FADT->length, acpi_gbl_FADT->length));
545 ACPI_DUMP_BUFFER ((u8 *) (acpi_gbl_FADT), acpi_gbl_FADT->length);
546
547 return_ACPI_STATUS (AE_OK);
548}
549
550
551/*******************************************************************************
552 *
44f6c012 553 * FUNCTION: acpi_tb_build_common_facs
1da177e4
LT
554 *
555 * PARAMETERS: table_info - Info for currently installed FACS
556 *
557 * RETURN: Status
558 *
559 * DESCRIPTION: Convert ACPI 1.0 and ACPI 2.0 FACS to a common internal
560 * table format.
561 *
562 ******************************************************************************/
563
564acpi_status
565acpi_tb_build_common_facs (
566 struct acpi_table_desc *table_info)
567{
568
569 ACPI_FUNCTION_TRACE ("tb_build_common_facs");
570
571
572 /* Absolute minimum length is 24, but the ACPI spec says 64 */
573
574 if (acpi_gbl_FACS->length < 24) {
44f6c012
RM
575 ACPI_REPORT_ERROR (("Invalid FACS table length: 0x%X\n",
576 acpi_gbl_FACS->length));
1da177e4
LT
577 return_ACPI_STATUS (AE_INVALID_TABLE_LENGTH);
578 }
579
580 if (acpi_gbl_FACS->length < 64) {
44f6c012
RM
581 ACPI_REPORT_WARNING ((
582 "FACS is shorter than the ACPI specification allows: 0x%X, using anyway\n",
1da177e4
LT
583 acpi_gbl_FACS->length));
584 }
585
586 /* Copy fields to the new FACS */
587
588 acpi_gbl_common_fACS.global_lock = &(acpi_gbl_FACS->global_lock);
589
590 if ((acpi_gbl_RSDP->revision < 2) ||
591 (acpi_gbl_FACS->length < 32) ||
592 (!(acpi_gbl_FACS->xfirmware_waking_vector))) {
593 /* ACPI 1.0 FACS or short table or optional X_ field is zero */
594
44f6c012
RM
595 acpi_gbl_common_fACS.firmware_waking_vector = ACPI_CAST_PTR (u64,
596 &(acpi_gbl_FACS->firmware_waking_vector));
1da177e4
LT
597 acpi_gbl_common_fACS.vector_width = 32;
598 }
599 else {
600 /* ACPI 2.0 FACS with valid X_ field */
601
602 acpi_gbl_common_fACS.firmware_waking_vector = &acpi_gbl_FACS->xfirmware_waking_vector;
603 acpi_gbl_common_fACS.vector_width = 64;
604 }
605
606 return_ACPI_STATUS (AE_OK);
607}
608
609