68
* ACPI 1.0 Fixed ACPI Description Table (FADT)
70
#define FACP_SIGNATURE 0x50434146 // FACP
71
struct fadt_descriptor_rev1
73
ACPI_TABLE_HEADER_DEF /* ACPI common table header */
74
u32 firmware_ctrl; /* Physical address of FACS */
75
u32 dsdt; /* Physical address of DSDT */
76
u8 model; /* System Interrupt Model */
77
u8 reserved1; /* Reserved */
78
u16 sci_int; /* System vector of SCI interrupt */
79
u32 smi_cmd; /* Port address of SMI command port */
80
u8 acpi_enable; /* Value to write to smi_cmd to enable ACPI */
81
u8 acpi_disable; /* Value to write to smi_cmd to disable ACPI */
82
u8 S4bios_req; /* Value to write to SMI CMD to enter S4BIOS state */
83
u8 reserved2; /* Reserved - must be zero */
84
u32 pm1a_evt_blk; /* Port address of Power Mgt 1a acpi_event Reg Blk */
85
u32 pm1b_evt_blk; /* Port address of Power Mgt 1b acpi_event Reg Blk */
86
u32 pm1a_cnt_blk; /* Port address of Power Mgt 1a Control Reg Blk */
87
u32 pm1b_cnt_blk; /* Port address of Power Mgt 1b Control Reg Blk */
88
u32 pm2_cnt_blk; /* Port address of Power Mgt 2 Control Reg Blk */
89
u32 pm_tmr_blk; /* Port address of Power Mgt Timer Ctrl Reg Blk */
90
u32 gpe0_blk; /* Port addr of General Purpose acpi_event 0 Reg Blk */
91
u32 gpe1_blk; /* Port addr of General Purpose acpi_event 1 Reg Blk */
92
u8 pm1_evt_len; /* Byte length of ports at pm1_x_evt_blk */
93
u8 pm1_cnt_len; /* Byte length of ports at pm1_x_cnt_blk */
94
u8 pm2_cnt_len; /* Byte Length of ports at pm2_cnt_blk */
95
u8 pm_tmr_len; /* Byte Length of ports at pm_tm_blk */
96
u8 gpe0_blk_len; /* Byte Length of ports at gpe0_blk */
97
u8 gpe1_blk_len; /* Byte Length of ports at gpe1_blk */
98
u8 gpe1_base; /* Offset in gpe model where gpe1 events start */
99
u8 reserved3; /* Reserved */
100
u16 plvl2_lat; /* Worst case HW latency to enter/exit C2 state */
101
u16 plvl3_lat; /* Worst case HW latency to enter/exit C3 state */
102
u16 flush_size; /* Size of area read to flush caches */
103
u16 flush_stride; /* Stride used in flushing caches */
104
u8 duty_offset; /* Bit location of duty cycle field in p_cnt reg */
105
u8 duty_width; /* Bit width of duty cycle field in p_cnt reg */
106
u8 day_alrm; /* Index to day-of-month alarm in RTC CMOS RAM */
107
u8 mon_alrm; /* Index to month-of-year alarm in RTC CMOS RAM */
108
u8 century; /* Index to century in RTC CMOS RAM */
109
u8 reserved4; /* Reserved */
110
u8 reserved4a; /* Reserved */
111
u8 reserved4b; /* Reserved */
113
u32 wb_invd : 1; /* The wbinvd instruction works properly */
114
u32 wb_invd_flush : 1; /* The wbinvd flushes but does not invalidate */
115
u32 proc_c1 : 1; /* All processors support C1 state */
116
u32 plvl2_up : 1; /* C2 state works on MP system */
117
u32 pwr_button : 1; /* Power button is handled as a generic feature */
118
u32 sleep_button : 1; /* Sleep button is handled as a generic feature, or not present */
119
u32 fixed_rTC : 1; /* RTC wakeup stat not in fixed register space */
120
u32 rtcs4 : 1; /* RTC wakeup stat not possible from S4 */
121
u32 tmr_val_ext : 1; /* The tmr_val width is 32 bits (0 = 24 bits) */
122
u32 reserved5 : 23; /* Reserved - must be zero */
129
57
* MADT values and structures
332
// Encode a hex value
333
static inline char getHex(u32 val) {
335
return (val <= 9) ? ('0' + val) : ('A' + val - 10);
338
// Encode a length in an SSDT.
340
encodeLen(u8 *ssdt_ptr, int length, int bytes)
344
case 4: ssdt_ptr[3] = ((length >> 20) & 0xff);
345
case 3: ssdt_ptr[2] = ((length >> 12) & 0xff);
346
case 2: ssdt_ptr[1] = ((length >> 4) & 0xff);
347
ssdt_ptr[0] = (((bytes-1) & 0x3) << 6) | (length & 0x0f);
349
case 1: ssdt_ptr[0] = length & 0x3f;
351
return ssdt_ptr + bytes;
354
// AML Processor() object. See src/ssdt-proc.dsl for info.
355
static unsigned char ssdt_proc[] = {
356
0x5b,0x83,0x42,0x05,0x43,0x50,0x41,0x41,
357
0xaa,0x10,0xb0,0x00,0x00,0x06,0x08,0x49,
358
0x44,0x5f,0x5f,0x0a,0xaa,0x08,0x5f,0x48,
359
0x49,0x44,0x0d,0x41,0x43,0x50,0x49,0x30,
360
0x30,0x30,0x37,0x00,0x14,0x0f,0x5f,0x4d,
361
0x41,0x54,0x00,0xa4,0x43,0x50,0x4d,0x41,
362
0x49,0x44,0x5f,0x5f,0x14,0x0f,0x5f,0x53,
363
0x54,0x41,0x00,0xa4,0x43,0x50,0x53,0x54,
364
0x49,0x44,0x5f,0x5f,0x14,0x0f,0x5f,0x45,
365
0x4a,0x30,0x01,0x43,0x50,0x45,0x4a,0x49,
368
#define SD_OFFSET_CPUHEX 6
369
#define SD_OFFSET_CPUID1 8
370
#define SD_OFFSET_CPUID2 20
409
372
#define SSDT_SIGNATURE 0x54445353 // SSDT
413
376
int acpi_cpus = MaxCountCPUs > 0xff ? 0xff : MaxCountCPUs;
414
// calculate the length of processor block and scope block
415
// excluding PkgLength
416
int cpu_length = 13 * acpi_cpus + 4;
418
int length = sizeof(struct acpi_table_header) + 3 + cpu_length;
419
u8 *ssdt = malloc_high(length);
377
// length = ScopeOp + procs + NTYF method + CPON package
378
int length = ((1+3+4)
379
+ (acpi_cpus * sizeof(ssdt_proc))
380
+ (1+2+5+(12*acpi_cpus))
381
+ (6+2+1+(1*acpi_cpus)));
382
u8 *ssdt = malloc_high(sizeof(struct acpi_table_header) + length);
426
ssdt_ptr[9] = 0; // checksum;
427
ssdt_ptr += sizeof(struct acpi_table_header);
429
// build processor scope header
387
u8 *ssdt_ptr = ssdt + sizeof(struct acpi_table_header);
389
// build Scope(_SB_) header
430
390
*(ssdt_ptr++) = 0x10; // ScopeOp
431
if (cpu_length <= 0x3e) {
432
/* Handle 1-4 CPUs with one byte encoding */
433
*(ssdt_ptr++) = cpu_length + 1;
435
/* Handle 5-314 CPUs with two byte encoding */
436
*(ssdt_ptr++) = 0x40 | ((cpu_length + 2) & 0xf);
437
*(ssdt_ptr++) = (cpu_length + 2) >> 4;
439
*(ssdt_ptr++) = '_'; // Name
391
ssdt_ptr = encodeLen(ssdt_ptr, length-1, 3);
397
// build Processor object for each processor
399
for (i=0; i<acpi_cpus; i++) {
400
memcpy(ssdt_ptr, ssdt_proc, sizeof(ssdt_proc));
401
ssdt_ptr[SD_OFFSET_CPUHEX] = getHex(i >> 4);
402
ssdt_ptr[SD_OFFSET_CPUHEX+1] = getHex(i);
403
ssdt_ptr[SD_OFFSET_CPUID1] = i;
404
ssdt_ptr[SD_OFFSET_CPUID2] = i;
405
ssdt_ptr += sizeof(ssdt_proc);
408
// build "Method(NTFY, 2) {If (LEqual(Arg0, 0x00)) {Notify(CP00, Arg1)} ...}"
409
*(ssdt_ptr++) = 0x14; // MethodOp
410
ssdt_ptr = encodeLen(ssdt_ptr, 2+5+(12*acpi_cpus), 2);
415
*(ssdt_ptr++) = 0x02;
416
for (i=0; i<acpi_cpus; i++) {
417
*(ssdt_ptr++) = 0xA0; // IfOp
418
ssdt_ptr = encodeLen(ssdt_ptr, 11, 1);
419
*(ssdt_ptr++) = 0x93; // LEqualOp
420
*(ssdt_ptr++) = 0x68; // Arg0Op
421
*(ssdt_ptr++) = 0x0A; // BytePrefix
423
*(ssdt_ptr++) = 0x86; // NotifyOp
426
*(ssdt_ptr++) = getHex(i >> 4);
427
*(ssdt_ptr++) = getHex(i);
428
*(ssdt_ptr++) = 0x69; // Arg1Op
431
// build "Name(CPON, Package() { One, One, ..., Zero, Zero, ... })"
432
*(ssdt_ptr++) = 0x08; // NameOp
440
434
*(ssdt_ptr++) = 'P';
444
// build object for each processor
446
for (i=0; i<acpi_cpus; i++) {
447
*(ssdt_ptr++) = 0x5B; // ProcessorOp
448
*(ssdt_ptr++) = 0x83;
449
*(ssdt_ptr++) = 0x0B; // Length
450
*(ssdt_ptr++) = 'C'; // Name (CPUxx)
453
*(ssdt_ptr++) = (i >> 4) < 0xa ? (i >> 4) + '0' : (i >> 4) + 'A' - 0xa;
456
*(ssdt_ptr++) = (i & 0xf) < 0xa ? (i & 0xf) + '0' : (i & 0xf) + 'A' - 0xa;
458
*(ssdt_ptr++) = 0x10; // Processor block address
459
*(ssdt_ptr++) = 0xb0;
462
*(ssdt_ptr++) = 6; // Processor block length
437
*(ssdt_ptr++) = 0x12; // PackageOp
438
ssdt_ptr = encodeLen(ssdt_ptr, 2+1+(1*acpi_cpus), 2);
439
*(ssdt_ptr++) = acpi_cpus;
440
for (i=0; i<acpi_cpus; i++)
441
*(ssdt_ptr++) = (i < CountCPUs) ? 0x01 : 0x00;
465
443
build_header((void*)ssdt, SSDT_SIGNATURE, ssdt_ptr - ssdt, 1);
445
//hexdump(ssdt, ssdt_ptr - ssdt);