Subversion Repositories Kolibri OS

Rev

Rev 1498 | Go to most recent revision | Details | Compare with Previous | Last modification | View Log | RSS feed

Rev Author Line No. Line
1498 serge 1
/******************************************************************************
2
 *
3
 * Module Name: tbfadt   - FADT table utilities
4
 *
5
 *****************************************************************************/
6
 
7
/******************************************************************************
8
 *
9
 * 1. Copyright Notice
10
 *
2216 Serge 11
 * Some or all of this work - Copyright (c) 1999 - 2011, Intel Corp.
1498 serge 12
 * All rights reserved.
13
 *
14
 * 2. License
15
 *
16
 * 2.1. This is your license from Intel Corp. under its intellectual property
17
 * rights.  You may have additional license terms from the party that provided
18
 * you this software, covering your right to use that party's intellectual
19
 * property rights.
20
 *
21
 * 2.2. Intel grants, free of charge, to any person ("Licensee") obtaining a
22
 * copy of the source code appearing in this file ("Covered Code") an
23
 * irrevocable, perpetual, worldwide license under Intel's copyrights in the
24
 * base code distributed originally by Intel ("Original Intel Code") to copy,
25
 * make derivatives, distribute, use and display any portion of the Covered
26
 * Code in any form, with the right to sublicense such rights; and
27
 *
28
 * 2.3. Intel grants Licensee a non-exclusive and non-transferable patent
29
 * license (with the right to sublicense), under only those claims of Intel
30
 * patents that are infringed by the Original Intel Code, to make, use, sell,
31
 * offer to sell, and import the Covered Code and derivative works thereof
32
 * solely to the minimum extent necessary to exercise the above copyright
33
 * license, and in no event shall the patent license extend to any additions
34
 * to or modifications of the Original Intel Code.  No other license or right
35
 * is granted directly or by implication, estoppel or otherwise;
36
 *
37
 * The above copyright and patent license is granted only if the following
38
 * conditions are met:
39
 *
40
 * 3. Conditions
41
 *
42
 * 3.1. Redistribution of Source with Rights to Further Distribute Source.
43
 * Redistribution of source code of any substantial portion of the Covered
44
 * Code or modification with rights to further distribute source must include
45
 * the above Copyright Notice, the above License, this list of Conditions,
46
 * and the following Disclaimer and Export Compliance provision.  In addition,
47
 * Licensee must cause all Covered Code to which Licensee contributes to
48
 * contain a file documenting the changes Licensee made to create that Covered
49
 * Code and the date of any change.  Licensee must include in that file the
50
 * documentation of any changes made by any predecessor Licensee.  Licensee
51
 * must include a prominent statement that the modification is derived,
52
 * directly or indirectly, from Original Intel Code.
53
 *
54
 * 3.2. Redistribution of Source with no Rights to Further Distribute Source.
55
 * Redistribution of source code of any substantial portion of the Covered
56
 * Code or modification without rights to further distribute source must
57
 * include the following Disclaimer and Export Compliance provision in the
58
 * documentation and/or other materials provided with distribution.  In
59
 * addition, Licensee may not authorize further sublicense of source of any
60
 * portion of the Covered Code, and must include terms to the effect that the
61
 * license from Licensee to its licensee is limited to the intellectual
62
 * property embodied in the software Licensee provides to its licensee, and
63
 * not to intellectual property embodied in modifications its licensee may
64
 * make.
65
 *
66
 * 3.3. Redistribution of Executable. Redistribution in executable form of any
67
 * substantial portion of the Covered Code or modification must reproduce the
68
 * above Copyright Notice, and the following Disclaimer and Export Compliance
69
 * provision in the documentation and/or other materials provided with the
70
 * distribution.
71
 *
72
 * 3.4. Intel retains all right, title, and interest in and to the Original
73
 * Intel Code.
74
 *
75
 * 3.5. Neither the name Intel nor any other trademark owned or controlled by
76
 * Intel shall be used in advertising or otherwise to promote the sale, use or
77
 * other dealings in products derived from or relating to the Covered Code
78
 * without prior written authorization from Intel.
79
 *
80
 * 4. Disclaimer and Export Compliance
81
 *
82
 * 4.1. INTEL MAKES NO WARRANTY OF ANY KIND REGARDING ANY SOFTWARE PROVIDED
83
 * HERE.  ANY SOFTWARE ORIGINATING FROM INTEL OR DERIVED FROM INTEL SOFTWARE
84
 * IS PROVIDED "AS IS," AND INTEL WILL NOT PROVIDE ANY SUPPORT,  ASSISTANCE,
85
 * INSTALLATION, TRAINING OR OTHER SERVICES.  INTEL WILL NOT PROVIDE ANY
86
 * UPDATES, ENHANCEMENTS OR EXTENSIONS.  INTEL SPECIFICALLY DISCLAIMS ANY
87
 * IMPLIED WARRANTIES OF MERCHANTABILITY, NONINFRINGEMENT AND FITNESS FOR A
88
 * PARTICULAR PURPOSE.
89
 *
90
 * 4.2. IN NO EVENT SHALL INTEL HAVE ANY LIABILITY TO LICENSEE, ITS LICENSEES
91
 * OR ANY OTHER THIRD PARTY, FOR ANY LOST PROFITS, LOST DATA, LOSS OF USE OR
92
 * COSTS OF PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, OR FOR ANY INDIRECT,
93
 * SPECIAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THIS AGREEMENT, UNDER ANY
94
 * CAUSE OF ACTION OR THEORY OF LIABILITY, AND IRRESPECTIVE OF WHETHER INTEL
95
 * HAS ADVANCE NOTICE OF THE POSSIBILITY OF SUCH DAMAGES.  THESE LIMITATIONS
96
 * SHALL APPLY NOTWITHSTANDING THE FAILURE OF THE ESSENTIAL PURPOSE OF ANY
97
 * LIMITED REMEDY.
98
 *
99
 * 4.3. Licensee shall not export, either directly or indirectly, any of this
100
 * software or system incorporating such software without first obtaining any
101
 * required license or other approval from the U. S. Department of Commerce or
102
 * any other agency or department of the United States Government.  In the
103
 * event Licensee exports any such software from the United States or
104
 * re-exports any such software from a foreign destination, Licensee shall
105
 * ensure that the distribution and export/re-export of the software is in
106
 * compliance with all laws, regulations, orders, or other restrictions of the
107
 * U.S. Export Administration Regulations. Licensee agrees that neither it nor
108
 * any of its subsidiaries will export/re-export any technical data, process,
109
 * software, or service, directly or indirectly, to any country for which the
110
 * United States government or any agency thereof requires an export license,
111
 * other governmental approval, or letter of assurance, without first obtaining
112
 * such license, approval or letter.
113
 *
114
 *****************************************************************************/
115
 
116
#define __TBFADT_C__
117
 
118
#include "acpi.h"
119
#include "accommon.h"
120
#include "actables.h"
121
 
122
#define _COMPONENT          ACPI_TABLES
123
        ACPI_MODULE_NAME    ("tbfadt")
124
 
125
/* Local prototypes */
126
 
2216 Serge 127
static ACPI_INLINE void
1498 serge 128
AcpiTbInitGenericAddress (
129
    ACPI_GENERIC_ADDRESS    *GenericAddress,
130
    UINT8                   SpaceId,
131
    UINT8                   ByteWidth,
132
    UINT64                  Address);
133
 
134
static void
135
AcpiTbConvertFadt (
136
    void);
137
 
138
static void
139
AcpiTbValidateFadt (
140
    void);
141
 
142
static void
143
AcpiTbSetupFadtRegisters (
144
    void);
145
 
146
 
147
/* Table for conversion of FADT to common internal format and FADT validation */
148
 
149
typedef struct acpi_fadt_info
150
{
151
    char                    *Name;
152
    UINT8                   Address64;
153
    UINT8                   Address32;
154
    UINT8                   Length;
155
    UINT8                   DefaultLength;
156
    UINT8                   Type;
157
 
158
} ACPI_FADT_INFO;
159
 
160
#define ACPI_FADT_REQUIRED          1
161
#define ACPI_FADT_SEPARATE_LENGTH   2
162
 
163
static ACPI_FADT_INFO     FadtInfoTable[] =
164
{
165
    {"Pm1aEventBlock",
166
        ACPI_FADT_OFFSET (XPm1aEventBlock),
167
        ACPI_FADT_OFFSET (Pm1aEventBlock),
168
        ACPI_FADT_OFFSET (Pm1EventLength),
169
        ACPI_PM1_REGISTER_WIDTH * 2,        /* Enable + Status register */
170
        ACPI_FADT_REQUIRED},
171
 
172
    {"Pm1bEventBlock",
173
        ACPI_FADT_OFFSET (XPm1bEventBlock),
174
        ACPI_FADT_OFFSET (Pm1bEventBlock),
175
        ACPI_FADT_OFFSET (Pm1EventLength),
176
        ACPI_PM1_REGISTER_WIDTH * 2,        /* Enable + Status register */
177
        0},
178
 
179
    {"Pm1aControlBlock",
180
        ACPI_FADT_OFFSET (XPm1aControlBlock),
181
        ACPI_FADT_OFFSET (Pm1aControlBlock),
182
        ACPI_FADT_OFFSET (Pm1ControlLength),
183
        ACPI_PM1_REGISTER_WIDTH,
184
        ACPI_FADT_REQUIRED},
185
 
186
    {"Pm1bControlBlock",
187
        ACPI_FADT_OFFSET (XPm1bControlBlock),
188
        ACPI_FADT_OFFSET (Pm1bControlBlock),
189
        ACPI_FADT_OFFSET (Pm1ControlLength),
190
        ACPI_PM1_REGISTER_WIDTH,
191
        0},
192
 
193
    {"Pm2ControlBlock",
194
        ACPI_FADT_OFFSET (XPm2ControlBlock),
195
        ACPI_FADT_OFFSET (Pm2ControlBlock),
196
        ACPI_FADT_OFFSET (Pm2ControlLength),
197
        ACPI_PM2_REGISTER_WIDTH,
198
        ACPI_FADT_SEPARATE_LENGTH},
199
 
200
    {"PmTimerBlock",
201
        ACPI_FADT_OFFSET (XPmTimerBlock),
202
        ACPI_FADT_OFFSET (PmTimerBlock),
203
        ACPI_FADT_OFFSET (PmTimerLength),
204
        ACPI_PM_TIMER_WIDTH,
205
        ACPI_FADT_REQUIRED},
206
 
207
    {"Gpe0Block",
208
        ACPI_FADT_OFFSET (XGpe0Block),
209
        ACPI_FADT_OFFSET (Gpe0Block),
210
        ACPI_FADT_OFFSET (Gpe0BlockLength),
211
        0,
212
        ACPI_FADT_SEPARATE_LENGTH},
213
 
214
    {"Gpe1Block",
215
        ACPI_FADT_OFFSET (XGpe1Block),
216
        ACPI_FADT_OFFSET (Gpe1Block),
217
        ACPI_FADT_OFFSET (Gpe1BlockLength),
218
        0,
219
        ACPI_FADT_SEPARATE_LENGTH}
220
};
221
 
222
#define ACPI_FADT_INFO_ENTRIES \
223
            (sizeof (FadtInfoTable) / sizeof (ACPI_FADT_INFO))
224
 
225
 
226
/* Table used to split Event Blocks into separate status/enable registers */
227
 
228
typedef struct acpi_fadt_pm_info
229
{
230
    ACPI_GENERIC_ADDRESS    *Target;
231
    UINT8                   Source;
232
    UINT8                   RegisterNum;
233
 
234
} ACPI_FADT_PM_INFO;
235
 
236
static ACPI_FADT_PM_INFO    FadtPmInfoTable[] =
237
{
238
    {&AcpiGbl_XPm1aStatus,
239
        ACPI_FADT_OFFSET (XPm1aEventBlock),
240
        0},
241
 
242
    {&AcpiGbl_XPm1aEnable,
243
        ACPI_FADT_OFFSET (XPm1aEventBlock),
244
        1},
245
 
246
    {&AcpiGbl_XPm1bStatus,
247
        ACPI_FADT_OFFSET (XPm1bEventBlock),
248
        0},
249
 
250
    {&AcpiGbl_XPm1bEnable,
251
        ACPI_FADT_OFFSET (XPm1bEventBlock),
252
        1}
253
};
254
 
255
#define ACPI_FADT_PM_INFO_ENTRIES \
256
            (sizeof (FadtPmInfoTable) / sizeof (ACPI_FADT_PM_INFO))
257
 
258
 
259
/*******************************************************************************
260
 *
261
 * FUNCTION:    AcpiTbInitGenericAddress
262
 *
263
 * PARAMETERS:  GenericAddress      - GAS struct to be initialized
264
 *              SpaceId             - ACPI Space ID for this register
265
 *              ByteWidth           - Width of this register, in bytes
266
 *              Address             - Address of the register
267
 *
268
 * RETURN:      None
269
 *
270
 * DESCRIPTION: Initialize a Generic Address Structure (GAS)
271
 *              See the ACPI specification for a full description and
272
 *              definition of this structure.
273
 *
274
 ******************************************************************************/
275
 
2216 Serge 276
static ACPI_INLINE void
1498 serge 277
AcpiTbInitGenericAddress (
278
    ACPI_GENERIC_ADDRESS    *GenericAddress,
279
    UINT8                   SpaceId,
280
    UINT8                   ByteWidth,
281
    UINT64                  Address)
282
{
283
 
284
    /*
285
     * The 64-bit Address field is non-aligned in the byte packed
286
     * GAS struct.
287
     */
288
    ACPI_MOVE_64_TO_64 (&GenericAddress->Address, &Address);
289
 
290
    /* All other fields are byte-wide */
291
 
292
    GenericAddress->SpaceId = SpaceId;
293
    GenericAddress->BitWidth = (UINT8) ACPI_MUL_8 (ByteWidth);
294
    GenericAddress->BitOffset = 0;
295
    GenericAddress->AccessWidth = 0; /* Access width ANY */
296
}
297
 
298
 
299
/*******************************************************************************
300
 *
301
 * FUNCTION:    AcpiTbParseFadt
302
 *
303
 * PARAMETERS:  TableIndex          - Index for the FADT
304
 *
305
 * RETURN:      None
306
 *
307
 * DESCRIPTION: Initialize the FADT, DSDT and FACS tables
308
 *              (FADT contains the addresses of the DSDT and FACS)
309
 *
310
 ******************************************************************************/
311
 
312
void
313
AcpiTbParseFadt (
314
    UINT32                  TableIndex)
315
{
316
    UINT32                  Length;
317
    ACPI_TABLE_HEADER       *Table;
318
 
319
 
320
    /*
321
     * The FADT has multiple versions with different lengths,
322
     * and it contains pointers to both the DSDT and FACS tables.
323
     *
324
     * Get a local copy of the FADT and convert it to a common format
325
     * Map entire FADT, assumed to be smaller than one page.
326
     */
327
    Length = AcpiGbl_RootTableList.Tables[TableIndex].Length;
328
 
329
    Table = AcpiOsMapMemory (
330
                AcpiGbl_RootTableList.Tables[TableIndex].Address, Length);
331
    if (!Table)
332
    {
333
        return;
334
    }
335
 
336
    /*
337
     * Validate the FADT checksum before we copy the table. Ignore
338
     * checksum error as we want to try to get the DSDT and FACS.
339
     */
340
    (void) AcpiTbVerifyChecksum (Table, Length);
341
 
342
    /* Create a local copy of the FADT in common ACPI 2.0+ format */
343
 
344
    AcpiTbCreateLocalFadt (Table, Length);
345
 
346
    /* All done with the real FADT, unmap it */
347
 
348
    AcpiOsUnmapMemory (Table, Length);
349
 
350
    /* Obtain the DSDT and FACS tables via their addresses within the FADT */
351
 
352
    AcpiTbInstallTable ((ACPI_PHYSICAL_ADDRESS) AcpiGbl_FADT.XDsdt,
353
        ACPI_SIG_DSDT, ACPI_TABLE_INDEX_DSDT);
354
 
355
    AcpiTbInstallTable ((ACPI_PHYSICAL_ADDRESS) AcpiGbl_FADT.XFacs,
356
        ACPI_SIG_FACS, ACPI_TABLE_INDEX_FACS);
357
}
358
 
359
 
360
/*******************************************************************************
361
 *
362
 * FUNCTION:    AcpiTbCreateLocalFadt
363
 *
364
 * PARAMETERS:  Table               - Pointer to BIOS FADT
365
 *              Length              - Length of the table
366
 *
367
 * RETURN:      None
368
 *
369
 * DESCRIPTION: Get a local copy of the FADT and convert it to a common format.
370
 *              Performs validation on some important FADT fields.
371
 *
372
 * NOTE:        We create a local copy of the FADT regardless of the version.
373
 *
374
 ******************************************************************************/
375
 
376
void
377
AcpiTbCreateLocalFadt (
378
    ACPI_TABLE_HEADER       *Table,
379
    UINT32                  Length)
380
{
381
 
382
    /*
383
     * Check if the FADT is larger than the largest table that we expect
384
     * (the ACPI 2.0/3.0 version). If so, truncate the table, and issue
385
     * a warning.
386
     */
387
    if (Length > sizeof (ACPI_TABLE_FADT))
388
    {
389
        ACPI_WARNING ((AE_INFO,
390
            "FADT (revision %u) is longer than ACPI 2.0 version, "
391
            "truncating length %u to %u",
392
            Table->Revision, Length, (UINT32) sizeof (ACPI_TABLE_FADT)));
393
    }
394
 
395
    /* Clear the entire local FADT */
396
 
397
    ACPI_MEMSET (&AcpiGbl_FADT, 0, sizeof (ACPI_TABLE_FADT));
398
 
399
    /* Copy the original FADT, up to sizeof (ACPI_TABLE_FADT) */
400
 
401
    ACPI_MEMCPY (&AcpiGbl_FADT, Table,
402
        ACPI_MIN (Length, sizeof (ACPI_TABLE_FADT)));
403
 
404
    /* Convert the local copy of the FADT to the common internal format */
405
 
406
    AcpiTbConvertFadt ();
407
 
408
    /* Validate FADT values now, before we make any changes */
409
 
410
    AcpiTbValidateFadt ();
411
 
412
    /* Initialize the global ACPI register structures */
413
 
414
    AcpiTbSetupFadtRegisters ();
415
}
416
 
417
 
418
/*******************************************************************************
419
 *
420
 * FUNCTION:    AcpiTbConvertFadt
421
 *
422
 * PARAMETERS:  None, uses AcpiGbl_FADT
423
 *
424
 * RETURN:      None
425
 *
426
 * DESCRIPTION: Converts all versions of the FADT to a common internal format.
427
 *              Expand 32-bit addresses to 64-bit as necessary.
428
 *
429
 * NOTE:        AcpiGbl_FADT must be of size (ACPI_TABLE_FADT),
430
 *              and must contain a copy of the actual FADT.
431
 *
432
 * Notes on 64-bit register addresses:
433
 *
434
 * After this FADT conversion, later ACPICA code will only use the 64-bit "X"
435
 * fields of the FADT for all ACPI register addresses.
436
 *
437
 * The 64-bit "X" fields are optional extensions to the original 32-bit FADT
438
 * V1.0 fields. Even if they are present in the FADT, they are optional and
439
 * are unused if the BIOS sets them to zero. Therefore, we must copy/expand
440
 * 32-bit V1.0 fields if the corresponding X field is zero.
441
 *
442
 * For ACPI 1.0 FADTs, all 32-bit address fields are expanded to the
443
 * corresponding "X" fields in the internal FADT.
444
 *
445
 * For ACPI 2.0+ FADTs, all valid (non-zero) 32-bit address fields are expanded
446
 * to the corresponding 64-bit X fields. For compatibility with other ACPI
447
 * implementations, we ignore the 64-bit field if the 32-bit field is valid,
448
 * regardless of whether the host OS is 32-bit or 64-bit.
449
 *
450
 ******************************************************************************/
451
 
452
static void
453
AcpiTbConvertFadt (
454
    void)
455
{
456
    ACPI_GENERIC_ADDRESS    *Address64;
457
    UINT32                  Address32;
458
    UINT32                  i;
459
 
460
 
461
    /* Update the local FADT table header length */
462
 
463
    AcpiGbl_FADT.Header.Length = sizeof (ACPI_TABLE_FADT);
464
 
465
    /*
466
     * Expand the 32-bit FACS and DSDT addresses to 64-bit as necessary.
467
     * Later code will always use the X 64-bit field.
468
     */
469
    if (!AcpiGbl_FADT.XFacs)
470
    {
471
        AcpiGbl_FADT.XFacs = (UINT64) AcpiGbl_FADT.Facs;
472
    }
473
    if (!AcpiGbl_FADT.XDsdt)
474
    {
475
        AcpiGbl_FADT.XDsdt = (UINT64) AcpiGbl_FADT.Dsdt;
476
    }
477
 
478
    /*
479
     * For ACPI 1.0 FADTs (revision 1 or 2), ensure that reserved fields which
480
     * should be zero are indeed zero. This will workaround BIOSs that
481
     * inadvertently place values in these fields.
482
     *
483
     * The ACPI 1.0 reserved fields that will be zeroed are the bytes located
484
     * at offset 45, 55, 95, and the word located at offset 109, 110.
2216 Serge 485
     *
486
     * Note: The FADT revision value is unreliable. Only the length can be
487
     * trusted.
1498 serge 488
     */
2216 Serge 489
    if (AcpiGbl_FADT.Header.Length <= ACPI_FADT_V2_SIZE)
1498 serge 490
    {
491
        AcpiGbl_FADT.PreferredProfile = 0;
492
        AcpiGbl_FADT.PstateControl = 0;
493
        AcpiGbl_FADT.CstControl = 0;
494
        AcpiGbl_FADT.BootFlags = 0;
495
    }
496
 
497
    /*
498
     * Expand the ACPI 1.0 32-bit addresses to the ACPI 2.0 64-bit "X"
499
     * generic address structures as necessary. Later code will always use
500
     * the 64-bit address structures.
501
     *
502
     * March 2009:
503
     * We now always use the 32-bit address if it is valid (non-null). This
504
     * is not in accordance with the ACPI specification which states that
505
     * the 64-bit address supersedes the 32-bit version, but we do this for
506
     * compatibility with other ACPI implementations. Most notably, in the
507
     * case where both the 32 and 64 versions are non-null, we use the 32-bit
508
     * version. This is the only address that is guaranteed to have been
509
     * tested by the BIOS manufacturer.
510
     */
511
    for (i = 0; i < ACPI_FADT_INFO_ENTRIES; i++)
512
    {
513
        Address32 = *ACPI_ADD_PTR (UINT32,
514
            &AcpiGbl_FADT, FadtInfoTable[i].Address32);
515
 
516
        Address64 = ACPI_ADD_PTR (ACPI_GENERIC_ADDRESS,
517
            &AcpiGbl_FADT, FadtInfoTable[i].Address64);
518
 
519
        /*
520
         * If both 32- and 64-bit addresses are valid (non-zero),
521
         * they must match.
522
         */
523
        if (Address64->Address && Address32 &&
524
           (Address64->Address != (UINT64) Address32))
525
        {
526
            ACPI_ERROR ((AE_INFO,
527
                "32/64X address mismatch in %s: 0x%8.8X/0x%8.8X%8.8X, using 32",
528
                FadtInfoTable[i].Name, Address32,
529
                ACPI_FORMAT_UINT64 (Address64->Address)));
530
        }
531
 
532
        /* Always use 32-bit address if it is valid (non-null) */
533
 
534
        if (Address32)
535
        {
536
            /*
537
             * Copy the 32-bit address to the 64-bit GAS structure. The
538
             * Space ID is always I/O for 32-bit legacy address fields
539
             */
540
            AcpiTbInitGenericAddress (Address64, ACPI_ADR_SPACE_SYSTEM_IO,
541
                *ACPI_ADD_PTR (UINT8, &AcpiGbl_FADT, FadtInfoTable[i].Length),
542
                (UINT64) Address32);
543
        }
544
    }
545
}
546
 
547
 
548
/*******************************************************************************
549
 *
550
 * FUNCTION:    AcpiTbValidateFadt
551
 *
552
 * PARAMETERS:  Table           - Pointer to the FADT to be validated
553
 *
554
 * RETURN:      None
555
 *
556
 * DESCRIPTION: Validate various important fields within the FADT. If a problem
557
 *              is found, issue a message, but no status is returned.
558
 *              Used by both the table manager and the disassembler.
559
 *
560
 * Possible additional checks:
561
 * (AcpiGbl_FADT.Pm1EventLength >= 4)
562
 * (AcpiGbl_FADT.Pm1ControlLength >= 2)
563
 * (AcpiGbl_FADT.PmTimerLength >= 4)
564
 * Gpe block lengths must be multiple of 2
565
 *
566
 ******************************************************************************/
567
 
568
static void
569
AcpiTbValidateFadt (
570
    void)
571
{
572
    char                    *Name;
573
    ACPI_GENERIC_ADDRESS    *Address64;
574
    UINT8                   Length;
575
    UINT32                  i;
576
 
577
 
578
    /*
579
     * Check for FACS and DSDT address mismatches. An address mismatch between
580
     * the 32-bit and 64-bit address fields (FIRMWARE_CTRL/X_FIRMWARE_CTRL and
581
     * DSDT/X_DSDT) would indicate the presence of two FACS or two DSDT tables.
582
     */
583
    if (AcpiGbl_FADT.Facs &&
584
        (AcpiGbl_FADT.XFacs != (UINT64) AcpiGbl_FADT.Facs))
585
    {
586
        ACPI_WARNING ((AE_INFO,
587
            "32/64X FACS address mismatch in FADT - "
588
            "0x%8.8X/0x%8.8X%8.8X, using 32",
589
            AcpiGbl_FADT.Facs, ACPI_FORMAT_UINT64 (AcpiGbl_FADT.XFacs)));
590
 
591
        AcpiGbl_FADT.XFacs = (UINT64) AcpiGbl_FADT.Facs;
592
    }
593
 
594
    if (AcpiGbl_FADT.Dsdt &&
595
        (AcpiGbl_FADT.XDsdt != (UINT64) AcpiGbl_FADT.Dsdt))
596
    {
597
        ACPI_WARNING ((AE_INFO,
598
            "32/64X DSDT address mismatch in FADT - "
599
            "0x%8.8X/0x%8.8X%8.8X, using 32",
600
            AcpiGbl_FADT.Dsdt, ACPI_FORMAT_UINT64 (AcpiGbl_FADT.XDsdt)));
601
 
602
        AcpiGbl_FADT.XDsdt = (UINT64) AcpiGbl_FADT.Dsdt;
603
    }
604
 
605
    /* Examine all of the 64-bit extended address fields (X fields) */
606
 
607
    for (i = 0; i < ACPI_FADT_INFO_ENTRIES; i++)
608
    {
609
        /*
610
         * Generate pointer to the 64-bit address, get the register
611
         * length (width) and the register name
612
         */
613
        Address64 = ACPI_ADD_PTR (ACPI_GENERIC_ADDRESS,
614
                        &AcpiGbl_FADT, FadtInfoTable[i].Address64);
615
        Length = *ACPI_ADD_PTR (UINT8,
616
                        &AcpiGbl_FADT, FadtInfoTable[i].Length);
617
        Name = FadtInfoTable[i].Name;
618
 
619
        /*
620
         * For each extended field, check for length mismatch between the
621
         * legacy length field and the corresponding 64-bit X length field.
622
         */
623
        if (Address64->Address &&
624
           (Address64->BitWidth != ACPI_MUL_8 (Length)))
625
        {
626
            ACPI_WARNING ((AE_INFO,
627
                "32/64X length mismatch in %s: %u/%u",
628
                Name, ACPI_MUL_8 (Length), Address64->BitWidth));
629
        }
630
 
631
        if (FadtInfoTable[i].Type & ACPI_FADT_REQUIRED)
632
        {
633
            /*
634
             * Field is required (PM1aEvent, PM1aControl, PmTimer).
635
             * Both the address and length must be non-zero.
636
             */
637
            if (!Address64->Address || !Length)
638
            {
639
                ACPI_ERROR ((AE_INFO,
640
                    "Required field %s has zero address and/or length:"
641
                    " 0x%8.8X%8.8X/0x%X",
642
                    Name, ACPI_FORMAT_UINT64 (Address64->Address), Length));
643
            }
644
        }
645
        else if (FadtInfoTable[i].Type & ACPI_FADT_SEPARATE_LENGTH)
646
        {
647
            /*
648
             * Field is optional (PM2Control, GPE0, GPE1) AND has its own
649
             * length field. If present, both the address and length must
650
             * be valid.
651
             */
652
            if ((Address64->Address && !Length) ||
653
                (!Address64->Address && Length))
654
            {
655
                ACPI_WARNING ((AE_INFO,
656
                    "Optional field %s has zero address or length: "
657
                    "0x%8.8X%8.8X/0x%X",
658
                    Name, ACPI_FORMAT_UINT64 (Address64->Address), Length));
659
            }
660
        }
661
    }
662
}
663
 
664
 
665
/*******************************************************************************
666
 *
667
 * FUNCTION:    AcpiTbSetupFadtRegisters
668
 *
669
 * PARAMETERS:  None, uses AcpiGbl_FADT.
670
 *
671
 * RETURN:      None
672
 *
673
 * DESCRIPTION: Initialize global ACPI PM1 register definitions. Optionally,
674
 *              force FADT register definitions to their default lengths.
675
 *
676
 ******************************************************************************/
677
 
678
static void
679
AcpiTbSetupFadtRegisters (
680
    void)
681
{
682
    ACPI_GENERIC_ADDRESS    *Target64;
683
    ACPI_GENERIC_ADDRESS    *Source64;
684
    UINT8                   Pm1RegisterByteWidth;
685
    UINT32                  i;
686
 
687
 
688
    /*
689
     * Optionally check all register lengths against the default values and
690
     * update them if they are incorrect.
691
     */
692
    if (AcpiGbl_UseDefaultRegisterWidths)
693
    {
694
        for (i = 0; i < ACPI_FADT_INFO_ENTRIES; i++)
695
        {
696
            Target64 = ACPI_ADD_PTR (ACPI_GENERIC_ADDRESS, &AcpiGbl_FADT,
697
                FadtInfoTable[i].Address64);
698
 
699
            /*
700
             * If a valid register (Address != 0) and the (DefaultLength > 0)
701
             * (Not a GPE register), then check the width against the default.
702
             */
703
            if ((Target64->Address) &&
704
                (FadtInfoTable[i].DefaultLength > 0) &&
705
                (FadtInfoTable[i].DefaultLength != Target64->BitWidth))
706
            {
707
                ACPI_WARNING ((AE_INFO,
708
                    "Invalid length for %s: %u, using default %u",
709
                    FadtInfoTable[i].Name, Target64->BitWidth,
710
                    FadtInfoTable[i].DefaultLength));
711
 
712
                /* Incorrect size, set width to the default */
713
 
714
                Target64->BitWidth = FadtInfoTable[i].DefaultLength;
715
            }
716
        }
717
    }
718
 
719
    /*
720
     * Get the length of the individual PM1 registers (enable and status).
721
     * Each register is defined to be (event block length / 2). Extra divide
722
     * by 8 converts bits to bytes.
723
     */
724
    Pm1RegisterByteWidth = (UINT8)
725
        ACPI_DIV_16 (AcpiGbl_FADT.XPm1aEventBlock.BitWidth);
726
 
727
    /*
728
     * Calculate separate GAS structs for the PM1x (A/B) Status and Enable
729
     * registers. These addresses do not appear (directly) in the FADT, so it
730
     * is useful to pre-calculate them from the PM1 Event Block definitions.
731
     *
732
     * The PM event blocks are split into two register blocks, first is the
733
     * PM Status Register block, followed immediately by the PM Enable
734
     * Register block. Each is of length (Pm1EventLength/2)
735
     *
736
     * Note: The PM1A event block is required by the ACPI specification.
737
     * However, the PM1B event block is optional and is rarely, if ever,
738
     * used.
739
     */
740
 
741
    for (i = 0; i < ACPI_FADT_PM_INFO_ENTRIES; i++)
742
    {
743
        Source64 = ACPI_ADD_PTR (ACPI_GENERIC_ADDRESS, &AcpiGbl_FADT,
744
            FadtPmInfoTable[i].Source);
745
 
746
        if (Source64->Address)
747
        {
748
            AcpiTbInitGenericAddress (FadtPmInfoTable[i].Target,
749
                Source64->SpaceId, Pm1RegisterByteWidth,
750
                Source64->Address +
751
                    (FadtPmInfoTable[i].RegisterNum * Pm1RegisterByteWidth));
752
        }
753
    }
754
}
755