1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44#include <acpi/acpi.h>
45#include "accommon.h"
46#include "actables.h"
47
48#define _COMPONENT ACPI_TABLES
49ACPI_MODULE_NAME("tbfadt")
50
51
52static ACPI_INLINE void
53acpi_tb_init_generic_address(struct acpi_generic_address *generic_address,
54 u8 space_id, u8 byte_width, u64 address);
55
56static void acpi_tb_convert_fadt(void);
57
58static void acpi_tb_validate_fadt(void);
59
60static void acpi_tb_setup_fadt_registers(void);
61
62
63
64typedef struct acpi_fadt_info {
65 char *name;
66 u8 address64;
67 u8 address32;
68 u8 length;
69 u8 default_length;
70 u8 type;
71
72} acpi_fadt_info;
73
74#define ACPI_FADT_REQUIRED 1
75#define ACPI_FADT_SEPARATE_LENGTH 2
76
77static struct acpi_fadt_info fadt_info_table[] = {
78 {"Pm1aEventBlock",
79 ACPI_FADT_OFFSET(xpm1a_event_block),
80 ACPI_FADT_OFFSET(pm1a_event_block),
81 ACPI_FADT_OFFSET(pm1_event_length),
82 ACPI_PM1_REGISTER_WIDTH * 2,
83 ACPI_FADT_REQUIRED},
84
85 {"Pm1bEventBlock",
86 ACPI_FADT_OFFSET(xpm1b_event_block),
87 ACPI_FADT_OFFSET(pm1b_event_block),
88 ACPI_FADT_OFFSET(pm1_event_length),
89 ACPI_PM1_REGISTER_WIDTH * 2,
90 0},
91
92 {"Pm1aControlBlock",
93 ACPI_FADT_OFFSET(xpm1a_control_block),
94 ACPI_FADT_OFFSET(pm1a_control_block),
95 ACPI_FADT_OFFSET(pm1_control_length),
96 ACPI_PM1_REGISTER_WIDTH,
97 ACPI_FADT_REQUIRED},
98
99 {"Pm1bControlBlock",
100 ACPI_FADT_OFFSET(xpm1b_control_block),
101 ACPI_FADT_OFFSET(pm1b_control_block),
102 ACPI_FADT_OFFSET(pm1_control_length),
103 ACPI_PM1_REGISTER_WIDTH,
104 0},
105
106 {"Pm2ControlBlock",
107 ACPI_FADT_OFFSET(xpm2_control_block),
108 ACPI_FADT_OFFSET(pm2_control_block),
109 ACPI_FADT_OFFSET(pm2_control_length),
110 ACPI_PM2_REGISTER_WIDTH,
111 ACPI_FADT_SEPARATE_LENGTH},
112
113 {"PmTimerBlock",
114 ACPI_FADT_OFFSET(xpm_timer_block),
115 ACPI_FADT_OFFSET(pm_timer_block),
116 ACPI_FADT_OFFSET(pm_timer_length),
117 ACPI_PM_TIMER_WIDTH,
118 ACPI_FADT_REQUIRED},
119
120 {"Gpe0Block",
121 ACPI_FADT_OFFSET(xgpe0_block),
122 ACPI_FADT_OFFSET(gpe0_block),
123 ACPI_FADT_OFFSET(gpe0_block_length),
124 0,
125 ACPI_FADT_SEPARATE_LENGTH},
126
127 {"Gpe1Block",
128 ACPI_FADT_OFFSET(xgpe1_block),
129 ACPI_FADT_OFFSET(gpe1_block),
130 ACPI_FADT_OFFSET(gpe1_block_length),
131 0,
132 ACPI_FADT_SEPARATE_LENGTH}
133};
134
135#define ACPI_FADT_INFO_ENTRIES \
136 (sizeof (fadt_info_table) / sizeof (struct acpi_fadt_info))
137
138
139
140typedef struct acpi_fadt_pm_info {
141 struct acpi_generic_address *target;
142 u8 source;
143 u8 register_num;
144
145} acpi_fadt_pm_info;
146
147static struct acpi_fadt_pm_info fadt_pm_info_table[] = {
148 {&acpi_gbl_xpm1a_status,
149 ACPI_FADT_OFFSET(xpm1a_event_block),
150 0},
151
152 {&acpi_gbl_xpm1a_enable,
153 ACPI_FADT_OFFSET(xpm1a_event_block),
154 1},
155
156 {&acpi_gbl_xpm1b_status,
157 ACPI_FADT_OFFSET(xpm1b_event_block),
158 0},
159
160 {&acpi_gbl_xpm1b_enable,
161 ACPI_FADT_OFFSET(xpm1b_event_block),
162 1}
163};
164
165#define ACPI_FADT_PM_INFO_ENTRIES \
166 (sizeof (fadt_pm_info_table) / sizeof (struct acpi_fadt_pm_info))
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184static ACPI_INLINE void
185acpi_tb_init_generic_address(struct acpi_generic_address *generic_address,
186 u8 space_id, u8 byte_width, u64 address)
187{
188
189
190
191
192
193 ACPI_MOVE_64_TO_64(&generic_address->address, &address);
194
195
196
197 generic_address->space_id = space_id;
198 generic_address->bit_width = (u8)ACPI_MUL_8(byte_width);
199 generic_address->bit_offset = 0;
200 generic_address->access_width = 0;
201}
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216void acpi_tb_parse_fadt(u32 table_index)
217{
218 u32 length;
219 struct acpi_table_header *table;
220
221
222
223
224
225
226
227
228 length = acpi_gbl_root_table_list.tables[table_index].length;
229
230 table =
231 acpi_os_map_memory(acpi_gbl_root_table_list.tables[table_index].
232 address, length);
233 if (!table) {
234 return;
235 }
236
237
238
239
240
241 (void)acpi_tb_verify_checksum(table, length);
242
243
244
245 acpi_tb_create_local_fadt(table, length);
246
247
248
249 acpi_os_unmap_memory(table, length);
250
251
252
253 acpi_tb_install_table((acpi_physical_address) acpi_gbl_FADT.Xdsdt,
254 ACPI_SIG_DSDT, ACPI_TABLE_INDEX_DSDT);
255
256 acpi_tb_install_table((acpi_physical_address) acpi_gbl_FADT.Xfacs,
257 ACPI_SIG_FACS, ACPI_TABLE_INDEX_FACS);
258}
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276void acpi_tb_create_local_fadt(struct acpi_table_header *table, u32 length)
277{
278
279
280
281
282
283 if (length > sizeof(struct acpi_table_fadt)) {
284 ACPI_WARNING((AE_INFO,
285 "FADT (revision %u) is longer than ACPI 2.0 version, "
286 "truncating length %u to %u",
287 table->revision, length,
288 (u32)sizeof(struct acpi_table_fadt)));
289 }
290
291
292
293 ACPI_MEMSET(&acpi_gbl_FADT, 0, sizeof(struct acpi_table_fadt));
294
295
296
297 ACPI_MEMCPY(&acpi_gbl_FADT, table,
298 ACPI_MIN(length, sizeof(struct acpi_table_fadt)));
299
300
301
302 acpi_tb_convert_fadt();
303
304
305
306 acpi_tb_validate_fadt();
307
308
309
310 acpi_tb_setup_fadt_registers();
311}
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347static void acpi_tb_convert_fadt(void)
348{
349 struct acpi_generic_address *address64;
350 u32 address32;
351 u32 i;
352
353
354
355 acpi_gbl_FADT.header.length = sizeof(struct acpi_table_fadt);
356
357
358
359
360
361
362
363
364 if (!acpi_gbl_FADT.Xfacs) {
365 acpi_gbl_FADT.Xfacs = (u64) acpi_gbl_FADT.facs;
366 } else if (acpi_gbl_FADT.facs &&
367 (acpi_gbl_FADT.Xfacs != (u64) acpi_gbl_FADT.facs)) {
368 ACPI_WARNING((AE_INFO,
369 "32/64 FACS address mismatch in FADT - two FACS tables!"));
370 }
371
372 if (!acpi_gbl_FADT.Xdsdt) {
373 acpi_gbl_FADT.Xdsdt = (u64) acpi_gbl_FADT.dsdt;
374 } else if (acpi_gbl_FADT.dsdt &&
375 (acpi_gbl_FADT.Xdsdt != (u64) acpi_gbl_FADT.dsdt)) {
376 ACPI_WARNING((AE_INFO,
377 "32/64 DSDT address mismatch in FADT - two DSDT tables!"));
378 }
379
380
381
382
383
384
385
386
387
388 if (acpi_gbl_FADT.header.revision < FADT2_REVISION_ID) {
389 acpi_gbl_FADT.preferred_profile = 0;
390 acpi_gbl_FADT.pstate_control = 0;
391 acpi_gbl_FADT.cst_control = 0;
392 acpi_gbl_FADT.boot_flags = 0;
393 }
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409 for (i = 0; i < ACPI_FADT_INFO_ENTRIES; i++) {
410 address32 = *ACPI_ADD_PTR(u32,
411 &acpi_gbl_FADT,
412 fadt_info_table[i].address32);
413
414 address64 = ACPI_ADD_PTR(struct acpi_generic_address,
415 &acpi_gbl_FADT,
416 fadt_info_table[i].address64);
417
418
419
420
421
422 if (address64->address && address32 &&
423 (address64->address != (u64) address32)) {
424 ACPI_ERROR((AE_INFO,
425 "32/64X address mismatch in %s: 0x%8.8X/0x%8.8X%8.8X, using 32",
426 fadt_info_table[i].name, address32,
427 ACPI_FORMAT_UINT64(address64->address)));
428 }
429
430
431
432 if (address32) {
433
434
435
436
437 acpi_tb_init_generic_address(address64,
438 ACPI_ADR_SPACE_SYSTEM_IO,
439 *ACPI_ADD_PTR(u8,
440 &acpi_gbl_FADT,
441 fadt_info_table
442 [i].length),
443 (u64) address32);
444 }
445 }
446}
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468static void acpi_tb_validate_fadt(void)
469{
470 char *name;
471 struct acpi_generic_address *address64;
472 u8 length;
473 u32 i;
474
475
476
477
478
479
480 if (acpi_gbl_FADT.facs &&
481 (acpi_gbl_FADT.Xfacs != (u64) acpi_gbl_FADT.facs)) {
482 ACPI_WARNING((AE_INFO,
483 "32/64X FACS address mismatch in FADT - "
484 "0x%8.8X/0x%8.8X%8.8X, using 32",
485 acpi_gbl_FADT.facs,
486 ACPI_FORMAT_UINT64(acpi_gbl_FADT.Xfacs)));
487
488 acpi_gbl_FADT.Xfacs = (u64) acpi_gbl_FADT.facs;
489 }
490
491 if (acpi_gbl_FADT.dsdt &&
492 (acpi_gbl_FADT.Xdsdt != (u64) acpi_gbl_FADT.dsdt)) {
493 ACPI_WARNING((AE_INFO,
494 "32/64X DSDT address mismatch in FADT - "
495 "0x%8.8X/0x%8.8X%8.8X, using 32",
496 acpi_gbl_FADT.dsdt,
497 ACPI_FORMAT_UINT64(acpi_gbl_FADT.Xdsdt)));
498
499 acpi_gbl_FADT.Xdsdt = (u64) acpi_gbl_FADT.dsdt;
500 }
501
502
503
504 for (i = 0; i < ACPI_FADT_INFO_ENTRIES; i++) {
505
506
507
508
509 address64 = ACPI_ADD_PTR(struct acpi_generic_address,
510 &acpi_gbl_FADT,
511 fadt_info_table[i].address64);
512 length =
513 *ACPI_ADD_PTR(u8, &acpi_gbl_FADT,
514 fadt_info_table[i].length);
515 name = fadt_info_table[i].name;
516
517
518
519
520
521 if (address64->address &&
522 (address64->bit_width != ACPI_MUL_8(length))) {
523 ACPI_WARNING((AE_INFO,
524 "32/64X length mismatch in %s: %u/%u",
525 name, ACPI_MUL_8(length),
526 address64->bit_width));
527 }
528
529 if (fadt_info_table[i].type & ACPI_FADT_REQUIRED) {
530
531
532
533
534 if (!address64->address || !length) {
535 ACPI_ERROR((AE_INFO,
536 "Required field %s has zero address and/or length:"
537 " 0x%8.8X%8.8X/0x%X",
538 name,
539 ACPI_FORMAT_UINT64(address64->
540 address),
541 length));
542 }
543 } else if (fadt_info_table[i].type & ACPI_FADT_SEPARATE_LENGTH) {
544
545
546
547
548
549 if ((address64->address && !length) ||
550 (!address64->address && length)) {
551 ACPI_WARNING((AE_INFO,
552 "Optional field %s has zero address or length: "
553 "0x%8.8X%8.8X/0x%X",
554 name,
555 ACPI_FORMAT_UINT64(address64->
556 address),
557 length));
558 }
559 }
560 }
561}
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576static void acpi_tb_setup_fadt_registers(void)
577{
578 struct acpi_generic_address *target64;
579 struct acpi_generic_address *source64;
580 u8 pm1_register_byte_width;
581 u32 i;
582
583
584
585
586
587 if (acpi_gbl_use_default_register_widths) {
588 for (i = 0; i < ACPI_FADT_INFO_ENTRIES; i++) {
589 target64 =
590 ACPI_ADD_PTR(struct acpi_generic_address,
591 &acpi_gbl_FADT,
592 fadt_info_table[i].address64);
593
594
595
596
597
598 if ((target64->address) &&
599 (fadt_info_table[i].default_length > 0) &&
600 (fadt_info_table[i].default_length !=
601 target64->bit_width)) {
602 ACPI_WARNING((AE_INFO,
603 "Invalid length for %s: %u, using default %u",
604 fadt_info_table[i].name,
605 target64->bit_width,
606 fadt_info_table[i].
607 default_length));
608
609
610
611 target64->bit_width =
612 fadt_info_table[i].default_length;
613 }
614 }
615 }
616
617
618
619
620
621
622 pm1_register_byte_width = (u8)
623 ACPI_DIV_16(acpi_gbl_FADT.xpm1a_event_block.bit_width);
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639 for (i = 0; i < ACPI_FADT_PM_INFO_ENTRIES; i++) {
640 source64 =
641 ACPI_ADD_PTR(struct acpi_generic_address, &acpi_gbl_FADT,
642 fadt_pm_info_table[i].source);
643
644 if (source64->address) {
645 acpi_tb_init_generic_address(fadt_pm_info_table[i].
646 target, source64->space_id,
647 pm1_register_byte_width,
648 source64->address +
649 (fadt_pm_info_table[i].
650 register_num *
651 pm1_register_byte_width));
652 }
653 }
654}
655