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