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