~pmdj/ubuntu/trusty/qemu/2.9+applesmc+fadtv3

« back to all changes in this revision

Viewing changes to roms/seabios/src/fw/acpi.c

  • Committer: Phil Dennis-Jordan
  • Date: 2017-07-21 08:03:43 UTC
  • mfrom: (1.1.1)
  • Revision ID: phil@philjordan.eu-20170721080343-2yr2vdj7713czahv
New upstream release 2.9.0.

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
// Support for generating ACPI tables (on emulators)
 
2
// DO NOT ADD NEW FEATURES HERE.  (See paravirt.c / biostables.c instead.)
 
3
//
 
4
// Copyright (C) 2008-2010  Kevin O'Connor <kevin@koconnor.net>
 
5
// Copyright (C) 2006 Fabrice Bellard
 
6
//
 
7
// This file may be distributed under the terms of the GNU LGPLv3 license.
 
8
 
 
9
#include "byteorder.h" // cpu_to_le16
 
10
#include "config.h" // CONFIG_*
 
11
#include "dev-q35.h"
 
12
#include "dev-piix.h"
 
13
#include "hw/pcidevice.h" // pci_find_init_device
 
14
#include "hw/pci_ids.h" // PCI_VENDOR_ID_INTEL
 
15
#include "hw/pci_regs.h" // PCI_INTERRUPT_LINE
 
16
#include "malloc.h" // free
 
17
#include "output.h" // dprintf
 
18
#include "paravirt.h" // RamSize
 
19
#include "romfile.h" // romfile_loadint
 
20
#include "std/acpi.h" // struct rsdp_descriptor
 
21
#include "string.h" // memset
 
22
#include "util.h" // MaxCountCPUs
 
23
#include "x86.h" // readl
 
24
 
 
25
#include "fw/acpi-dsdt.hex"
 
26
 
 
27
static void
 
28
build_header(struct acpi_table_header *h, u32 sig, int len, u8 rev)
 
29
{
 
30
    h->signature = cpu_to_le32(sig);
 
31
    h->length = cpu_to_le32(len);
 
32
    h->revision = rev;
 
33
    memcpy(h->oem_id, BUILD_APPNAME6, 6);
 
34
    memcpy(h->oem_table_id, BUILD_APPNAME4, 4);
 
35
    memcpy(h->oem_table_id + 4, (void*)&sig, 4);
 
36
    h->oem_revision = cpu_to_le32(1);
 
37
    memcpy(h->asl_compiler_id, BUILD_APPNAME4, 4);
 
38
    h->asl_compiler_revision = cpu_to_le32(1);
 
39
    h->checksum -= checksum(h, len);
 
40
}
 
41
 
 
42
static void piix4_fadt_setup(struct pci_device *pci, void *arg)
 
43
{
 
44
    struct fadt_descriptor_rev1 *fadt = arg;
 
45
 
 
46
    fadt->model = 1;
 
47
    fadt->reserved1 = 0;
 
48
    fadt->sci_int = cpu_to_le16(PIIX_PM_INTRRUPT);
 
49
    fadt->smi_cmd = cpu_to_le32(PORT_SMI_CMD);
 
50
    fadt->acpi_enable = PIIX_ACPI_ENABLE;
 
51
    fadt->acpi_disable = PIIX_ACPI_DISABLE;
 
52
    fadt->pm1a_evt_blk = cpu_to_le32(acpi_pm_base);
 
53
    fadt->pm1a_cnt_blk = cpu_to_le32(acpi_pm_base + 0x04);
 
54
    fadt->pm_tmr_blk = cpu_to_le32(acpi_pm_base + 0x08);
 
55
    fadt->gpe0_blk = cpu_to_le32(PIIX_GPE0_BLK);
 
56
    fadt->pm1_evt_len = 4;
 
57
    fadt->pm1_cnt_len = 2;
 
58
    fadt->pm_tmr_len = 4;
 
59
    fadt->gpe0_blk_len = PIIX_GPE0_BLK_LEN;
 
60
    fadt->plvl2_lat = cpu_to_le16(0xfff); // C2 state not supported
 
61
    fadt->plvl3_lat = cpu_to_le16(0xfff); // C3 state not supported
 
62
    fadt->flags = cpu_to_le32(ACPI_FADT_F_WBINVD |
 
63
                              ACPI_FADT_F_PROC_C1 |
 
64
                              ACPI_FADT_F_SLP_BUTTON |
 
65
                              ACPI_FADT_F_RTC_S4 |
 
66
                              ACPI_FADT_F_USE_PLATFORM_CLOCK);
 
67
}
 
68
 
 
69
/* PCI_VENDOR_ID_INTEL && PCI_DEVICE_ID_INTEL_ICH9_LPC */
 
70
static void ich9_lpc_fadt_setup(struct pci_device *dev, void *arg)
 
71
{
 
72
    struct fadt_descriptor_rev1 *fadt = arg;
 
73
 
 
74
    fadt->model = 1;
 
75
    fadt->reserved1 = 0;
 
76
    fadt->sci_int = cpu_to_le16(9);
 
77
    fadt->smi_cmd = cpu_to_le32(PORT_SMI_CMD);
 
78
    fadt->acpi_enable = ICH9_ACPI_ENABLE;
 
79
    fadt->acpi_disable = ICH9_ACPI_DISABLE;
 
80
    fadt->pm1a_evt_blk = cpu_to_le32(acpi_pm_base);
 
81
    fadt->pm1a_cnt_blk = cpu_to_le32(acpi_pm_base + 0x04);
 
82
    fadt->pm_tmr_blk = cpu_to_le32(acpi_pm_base + 0x08);
 
83
    fadt->gpe0_blk = cpu_to_le32(acpi_pm_base + ICH9_PMIO_GPE0_STS);
 
84
    fadt->pm1_evt_len = 4;
 
85
    fadt->pm1_cnt_len = 2;
 
86
    fadt->pm_tmr_len = 4;
 
87
    fadt->gpe0_blk_len = ICH9_PMIO_GPE0_BLK_LEN;
 
88
    fadt->plvl2_lat = cpu_to_le16(0xfff); // C2 state not supported
 
89
    fadt->plvl3_lat = cpu_to_le16(0xfff); // C3 state not supported
 
90
    fadt->flags = cpu_to_le32(ACPI_FADT_F_WBINVD |
 
91
                              ACPI_FADT_F_PROC_C1 |
 
92
                              ACPI_FADT_F_SLP_BUTTON |
 
93
                              ACPI_FADT_F_RTC_S4 |
 
94
                              ACPI_FADT_F_USE_PLATFORM_CLOCK);
 
95
}
 
96
 
 
97
static const struct pci_device_id fadt_init_tbl[] = {
 
98
    /* PIIX4 Power Management device (for ACPI) */
 
99
    PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82371AB_3,
 
100
               piix4_fadt_setup),
 
101
    PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_ICH9_LPC,
 
102
               ich9_lpc_fadt_setup),
 
103
    PCI_DEVICE_END
 
104
};
 
105
 
 
106
static void fill_dsdt(struct fadt_descriptor_rev1 *fadt, void *dsdt)
 
107
{
 
108
    if (fadt->dsdt) {
 
109
        free((void *)le32_to_cpu(fadt->dsdt));
 
110
    }
 
111
    fadt->dsdt = cpu_to_le32((u32)dsdt);
 
112
    fadt->checksum -= checksum(fadt, sizeof(*fadt));
 
113
    dprintf(1, "ACPI DSDT=%p\n", dsdt);
 
114
}
 
115
 
 
116
static void *
 
117
build_fadt(struct pci_device *pci)
 
118
{
 
119
    struct fadt_descriptor_rev1 *fadt = malloc_high(sizeof(*fadt));
 
120
    struct facs_descriptor_rev1 *facs = memalign_high(64, sizeof(*facs));
 
121
 
 
122
    if (!fadt || !facs) {
 
123
        warn_noalloc();
 
124
        return NULL;
 
125
    }
 
126
 
 
127
    /* FACS */
 
128
    memset(facs, 0, sizeof(*facs));
 
129
    facs->signature = cpu_to_le32(FACS_SIGNATURE);
 
130
    facs->length = cpu_to_le32(sizeof(*facs));
 
131
 
 
132
    /* FADT */
 
133
    memset(fadt, 0, sizeof(*fadt));
 
134
    fadt->firmware_ctrl = cpu_to_le32((u32)facs);
 
135
    fadt->dsdt = 0;  /* dsdt will be filled later in acpi_setup()
 
136
                        by fill_dsdt() */
 
137
    pci_init_device(fadt_init_tbl, pci, fadt);
 
138
 
 
139
    build_header((void*)fadt, FACP_SIGNATURE, sizeof(*fadt), 1);
 
140
 
 
141
    return fadt;
 
142
}
 
143
 
 
144
static void*
 
145
build_madt(void)
 
146
{
 
147
    int madt_size = (sizeof(struct multiple_apic_table)
 
148
                     + sizeof(struct madt_processor_apic) * MaxCountCPUs
 
149
                     + sizeof(struct madt_io_apic)
 
150
                     + sizeof(struct madt_intsrcovr) * 16
 
151
                     + sizeof(struct madt_local_nmi));
 
152
 
 
153
    struct multiple_apic_table *madt = malloc_high(madt_size);
 
154
    if (!madt) {
 
155
        warn_noalloc();
 
156
        return NULL;
 
157
    }
 
158
    memset(madt, 0, madt_size);
 
159
    madt->local_apic_address = cpu_to_le32(BUILD_APIC_ADDR);
 
160
    madt->flags = cpu_to_le32(1);
 
161
    struct madt_processor_apic *apic = (void*)&madt[1];
 
162
    int i;
 
163
    for (i=0; i<MaxCountCPUs; i++) {
 
164
        apic->type = APIC_PROCESSOR;
 
165
        apic->length = sizeof(*apic);
 
166
        apic->processor_id = i;
 
167
        apic->local_apic_id = i;
 
168
        if (apic_id_is_present(apic->local_apic_id))
 
169
            apic->flags = cpu_to_le32(1);
 
170
        else
 
171
            apic->flags = cpu_to_le32(0);
 
172
        apic++;
 
173
    }
 
174
    struct madt_io_apic *io_apic = (void*)apic;
 
175
    io_apic->type = APIC_IO;
 
176
    io_apic->length = sizeof(*io_apic);
 
177
    io_apic->io_apic_id = BUILD_IOAPIC_ID;
 
178
    io_apic->address = cpu_to_le32(BUILD_IOAPIC_ADDR);
 
179
    io_apic->interrupt = cpu_to_le32(0);
 
180
 
 
181
    struct madt_intsrcovr *intsrcovr = (void*)&io_apic[1];
 
182
    if (romfile_loadint("etc/irq0-override", 0)) {
 
183
        memset(intsrcovr, 0, sizeof(*intsrcovr));
 
184
        intsrcovr->type   = APIC_XRUPT_OVERRIDE;
 
185
        intsrcovr->length = sizeof(*intsrcovr);
 
186
        intsrcovr->source = 0;
 
187
        intsrcovr->gsi    = cpu_to_le32(2);
 
188
        intsrcovr->flags  = cpu_to_le16(0); /* conforms to bus specifications */
 
189
        intsrcovr++;
 
190
    }
 
191
    for (i = 1; i < 16; i++) {
 
192
        if (!(BUILD_PCI_IRQS & (1 << i)))
 
193
            /* No need for a INT source override structure. */
 
194
            continue;
 
195
        memset(intsrcovr, 0, sizeof(*intsrcovr));
 
196
        intsrcovr->type   = APIC_XRUPT_OVERRIDE;
 
197
        intsrcovr->length = sizeof(*intsrcovr);
 
198
        intsrcovr->source = i;
 
199
        intsrcovr->gsi    = cpu_to_le32(i);
 
200
        intsrcovr->flags  = cpu_to_le16(0xd); /* active high, level triggered */
 
201
        intsrcovr++;
 
202
    }
 
203
 
 
204
    struct madt_local_nmi *local_nmi = (void*)intsrcovr;
 
205
    local_nmi->type         = APIC_LOCAL_NMI;
 
206
    local_nmi->length       = sizeof(*local_nmi);
 
207
    local_nmi->processor_id = 0xff; /* all processors */
 
208
    local_nmi->flags        = cpu_to_le16(0);
 
209
    local_nmi->lint         = 1; /* LINT1 */
 
210
    local_nmi++;
 
211
 
 
212
    build_header((void*)madt, APIC_SIGNATURE, (void*)local_nmi - (void*)madt, 1);
 
213
    return madt;
 
214
}
 
215
 
 
216
// Encode a hex value
 
217
static inline char getHex(u32 val) {
 
218
    val &= 0x0f;
 
219
    return (val <= 9) ? ('0' + val) : ('A' + val - 10);
 
220
}
 
221
 
 
222
// Encode a length in an SSDT.
 
223
static u8 *
 
224
encodeLen(u8 *ssdt_ptr, int length, int bytes)
 
225
{
 
226
    switch (bytes) {
 
227
    default:
 
228
    case 4: ssdt_ptr[3] = ((length >> 20) & 0xff);
 
229
    case 3: ssdt_ptr[2] = ((length >> 12) & 0xff);
 
230
    case 2: ssdt_ptr[1] = ((length >> 4) & 0xff);
 
231
            ssdt_ptr[0] = (((bytes-1) & 0x3) << 6) | (length & 0x0f);
 
232
            break;
 
233
    case 1: ssdt_ptr[0] = length & 0x3f;
 
234
    }
 
235
    return ssdt_ptr + bytes;
 
236
}
 
237
 
 
238
#include "fw/ssdt-proc.hex"
 
239
 
 
240
/* 0x5B 0x83 ProcessorOp PkgLength NameString ProcID */
 
241
#define PROC_OFFSET_CPUHEX (*ssdt_proc_name - *ssdt_proc_start + 2)
 
242
#define PROC_OFFSET_CPUID1 (*ssdt_proc_name - *ssdt_proc_start + 4)
 
243
#define PROC_OFFSET_CPUID2 (*ssdt_proc_id - *ssdt_proc_start)
 
244
#define PROC_SIZEOF (*ssdt_proc_end - *ssdt_proc_start)
 
245
#define PROC_AML (ssdp_proc_aml + *ssdt_proc_start)
 
246
 
 
247
/* 0x5B 0x82 DeviceOp PkgLength NameString */
 
248
#define PCIHP_OFFSET_HEX (*ssdt_pcihp_name - *ssdt_pcihp_start + 1)
 
249
#define PCIHP_OFFSET_ID (*ssdt_pcihp_id - *ssdt_pcihp_start)
 
250
#define PCIHP_OFFSET_ADR (*ssdt_pcihp_adr - *ssdt_pcihp_start)
 
251
#define PCIHP_OFFSET_EJ0 (*ssdt_pcihp_ej0 - *ssdt_pcihp_start)
 
252
#define PCIHP_SIZEOF (*ssdt_pcihp_end - *ssdt_pcihp_start)
 
253
#define PCIHP_AML (ssdp_pcihp_aml + *ssdt_pcihp_start)
 
254
#define PCI_SLOTS 32
 
255
 
 
256
#define SSDT_SIGNATURE 0x54445353 // SSDT
 
257
#define SSDT_HEADER_LENGTH 36
 
258
 
 
259
#include "fw/ssdt-misc.hex"
 
260
#include "fw/ssdt-pcihp.hex"
 
261
 
 
262
#define PCI_RMV_BASE 0xae0c
 
263
 
 
264
static u8*
 
265
build_notify(u8 *ssdt_ptr, const char *name, int skip, int count,
 
266
             const char *target, int ofs)
 
267
{
 
268
    count -= skip;
 
269
 
 
270
    *(ssdt_ptr++) = 0x14; // MethodOp
 
271
    ssdt_ptr = encodeLen(ssdt_ptr, 2+5+(12*count), 2);
 
272
    memcpy(ssdt_ptr, name, 4);
 
273
    ssdt_ptr += 4;
 
274
    *(ssdt_ptr++) = 0x02; // MethodOp
 
275
 
 
276
    int i;
 
277
    for (i = skip; count-- > 0; i++) {
 
278
        *(ssdt_ptr++) = 0xA0; // IfOp
 
279
        ssdt_ptr = encodeLen(ssdt_ptr, 11, 1);
 
280
        *(ssdt_ptr++) = 0x93; // LEqualOp
 
281
        *(ssdt_ptr++) = 0x68; // Arg0Op
 
282
        *(ssdt_ptr++) = 0x0A; // BytePrefix
 
283
        *(ssdt_ptr++) = i;
 
284
        *(ssdt_ptr++) = 0x86; // NotifyOp
 
285
        memcpy(ssdt_ptr, target, 4);
 
286
        ssdt_ptr[ofs] = getHex(i >> 4);
 
287
        ssdt_ptr[ofs + 1] = getHex(i);
 
288
        ssdt_ptr += 4;
 
289
        *(ssdt_ptr++) = 0x69; // Arg1Op
 
290
    }
 
291
    return ssdt_ptr;
 
292
}
 
293
 
 
294
static void patch_pcihp(int slot, u8 *ssdt_ptr, u32 eject)
 
295
{
 
296
    ssdt_ptr[PCIHP_OFFSET_HEX] = getHex(slot >> 4);
 
297
    ssdt_ptr[PCIHP_OFFSET_HEX+1] = getHex(slot);
 
298
    ssdt_ptr[PCIHP_OFFSET_ID] = slot;
 
299
    ssdt_ptr[PCIHP_OFFSET_ADR + 2] = slot;
 
300
 
 
301
    /* Runtime patching of EJ0: to disable hotplug for a slot,
 
302
     * replace the method name: _EJ0 by EJ0_. */
 
303
    /* Sanity check */
 
304
    if (memcmp(ssdt_ptr + PCIHP_OFFSET_EJ0, "_EJ0", 4)) {
 
305
        warn_internalerror();
 
306
    }
 
307
    if (!eject) {
 
308
        memcpy(ssdt_ptr + PCIHP_OFFSET_EJ0, "EJ0_", 4);
 
309
    }
 
310
}
 
311
 
 
312
static void*
 
313
build_ssdt(void)
 
314
{
 
315
    int acpi_cpus = MaxCountCPUs > 0xff ? 0xff : MaxCountCPUs;
 
316
    int length = (sizeof(ssdp_misc_aml)                     // _S3_ / _S4_ / _S5_
 
317
                  + (1+3+4)                                 // Scope(_SB_)
 
318
                  + (acpi_cpus * PROC_SIZEOF)               // procs
 
319
                  + (1+2+5+(12*acpi_cpus))                  // NTFY
 
320
                  + (6+2+1+(1*acpi_cpus))                   // CPON
 
321
                  + (1+3+4)                                 // Scope(PCI0)
 
322
                  + ((PCI_SLOTS - 1) * PCIHP_SIZEOF)        // slots
 
323
                  + (1+2+5+(12*(PCI_SLOTS - 1))));          // PCNT
 
324
    u8 *ssdt = malloc_high(length);
 
325
    if (! ssdt) {
 
326
        warn_noalloc();
 
327
        return NULL;
 
328
    }
 
329
    u8 *ssdt_ptr = ssdt;
 
330
 
 
331
    // Copy header and encode fwcfg values in the S3_ / S4_ / S5_ packages
 
332
    int sys_state_size;
 
333
    char *sys_states = romfile_loadfile("etc/system-states", &sys_state_size);
 
334
    if (!sys_states || sys_state_size != 6)
 
335
        sys_states = (char[]){128, 0, 0, 129, 128, 128};
 
336
 
 
337
    memcpy(ssdt_ptr, ssdp_misc_aml, sizeof(ssdp_misc_aml));
 
338
    if (!(sys_states[3] & 128))
 
339
        ssdt_ptr[acpi_s3_name[0]] = 'X';
 
340
    if (!(sys_states[4] & 128))
 
341
        ssdt_ptr[acpi_s4_name[0]] = 'X';
 
342
    else
 
343
        ssdt_ptr[acpi_s4_pkg[0] + 1] = ssdt[acpi_s4_pkg[0] + 3] = sys_states[4] & 127;
 
344
 
 
345
    // store pci io windows
 
346
    *(u32*)&ssdt_ptr[acpi_pci32_start[0]] = cpu_to_le32(pcimem_start);
 
347
    *(u32*)&ssdt_ptr[acpi_pci32_end[0]] = cpu_to_le32(pcimem_end - 1);
 
348
    if (pcimem64_start) {
 
349
        ssdt_ptr[acpi_pci64_valid[0]] = 1;
 
350
        *(u64*)&ssdt_ptr[acpi_pci64_start[0]] = cpu_to_le64(pcimem64_start);
 
351
        *(u64*)&ssdt_ptr[acpi_pci64_end[0]] = cpu_to_le64(pcimem64_end - 1);
 
352
        *(u64*)&ssdt_ptr[acpi_pci64_length[0]] = cpu_to_le64(
 
353
            pcimem64_end - pcimem64_start);
 
354
    } else {
 
355
        ssdt_ptr[acpi_pci64_valid[0]] = 0;
 
356
    }
 
357
 
 
358
    int pvpanic_port = romfile_loadint("etc/pvpanic-port", 0x0);
 
359
    *(u16 *)(ssdt_ptr + *ssdt_isa_pest) = pvpanic_port;
 
360
 
 
361
    ssdt_ptr += sizeof(ssdp_misc_aml);
 
362
 
 
363
    // build Scope(_SB_) header
 
364
    *(ssdt_ptr++) = 0x10; // ScopeOp
 
365
    ssdt_ptr = encodeLen(ssdt_ptr, length - (ssdt_ptr - ssdt), 3);
 
366
    *(ssdt_ptr++) = '_';
 
367
    *(ssdt_ptr++) = 'S';
 
368
    *(ssdt_ptr++) = 'B';
 
369
    *(ssdt_ptr++) = '_';
 
370
 
 
371
    // build Processor object for each processor
 
372
    int i;
 
373
    for (i=0; i<acpi_cpus; i++) {
 
374
        memcpy(ssdt_ptr, PROC_AML, PROC_SIZEOF);
 
375
        ssdt_ptr[PROC_OFFSET_CPUHEX] = getHex(i >> 4);
 
376
        ssdt_ptr[PROC_OFFSET_CPUHEX+1] = getHex(i);
 
377
        ssdt_ptr[PROC_OFFSET_CPUID1] = i;
 
378
        ssdt_ptr[PROC_OFFSET_CPUID2] = i;
 
379
        ssdt_ptr += PROC_SIZEOF;
 
380
    }
 
381
 
 
382
    // build "Method(NTFY, 2) {If (LEqual(Arg0, 0x00)) {Notify(CP00, Arg1)} ...}"
 
383
    // Arg0 = Processor ID = APIC ID
 
384
    ssdt_ptr = build_notify(ssdt_ptr, "NTFY", 0, acpi_cpus, "CP00", 2);
 
385
 
 
386
    // build "Name(CPON, Package() { One, One, ..., Zero, Zero, ... })"
 
387
    *(ssdt_ptr++) = 0x08; // NameOp
 
388
    *(ssdt_ptr++) = 'C';
 
389
    *(ssdt_ptr++) = 'P';
 
390
    *(ssdt_ptr++) = 'O';
 
391
    *(ssdt_ptr++) = 'N';
 
392
    *(ssdt_ptr++) = 0x12; // PackageOp
 
393
    ssdt_ptr = encodeLen(ssdt_ptr, 2+1+(1*acpi_cpus), 2);
 
394
    *(ssdt_ptr++) = acpi_cpus;
 
395
    for (i=0; i<acpi_cpus; i++)
 
396
        *(ssdt_ptr++) = (apic_id_is_present(i)) ? 0x01 : 0x00;
 
397
 
 
398
    // build Scope(PCI0) opcode
 
399
    *(ssdt_ptr++) = 0x10; // ScopeOp
 
400
    ssdt_ptr = encodeLen(ssdt_ptr, length - (ssdt_ptr - ssdt), 3);
 
401
    *(ssdt_ptr++) = 'P';
 
402
    *(ssdt_ptr++) = 'C';
 
403
    *(ssdt_ptr++) = 'I';
 
404
    *(ssdt_ptr++) = '0';
 
405
 
 
406
    // build Device object for each slot
 
407
    u32 rmvc_pcrm = inl(PCI_RMV_BASE);
 
408
    for (i=1; i<PCI_SLOTS; i++) {
 
409
        u32 eject = rmvc_pcrm & (0x1 << i);
 
410
        memcpy(ssdt_ptr, PCIHP_AML, PCIHP_SIZEOF);
 
411
        patch_pcihp(i, ssdt_ptr, eject != 0);
 
412
        ssdt_ptr += PCIHP_SIZEOF;
 
413
    }
 
414
 
 
415
    ssdt_ptr = build_notify(ssdt_ptr, "PCNT", 1, PCI_SLOTS, "S00_", 1);
 
416
 
 
417
    build_header((void*)ssdt, SSDT_SIGNATURE, ssdt_ptr - ssdt, 1);
 
418
 
 
419
    //hexdump(ssdt, ssdt_ptr - ssdt);
 
420
 
 
421
    return ssdt;
 
422
}
 
423
 
 
424
#define HPET_ID         0x000
 
425
#define HPET_PERIOD     0x004
 
426
 
 
427
static void*
 
428
build_hpet(void)
 
429
{
 
430
    struct acpi_20_hpet *hpet;
 
431
    const void *hpet_base = (void *)BUILD_HPET_ADDRESS;
 
432
    u32 hpet_vendor = readl(hpet_base + HPET_ID) >> 16;
 
433
    u32 hpet_period = readl(hpet_base + HPET_PERIOD);
 
434
 
 
435
    if (hpet_vendor == 0 || hpet_vendor == 0xffff ||
 
436
        hpet_period == 0 || hpet_period > 100000000)
 
437
        return NULL;
 
438
 
 
439
    hpet = malloc_high(sizeof(*hpet));
 
440
    if (!hpet) {
 
441
        warn_noalloc();
 
442
        return NULL;
 
443
    }
 
444
 
 
445
    memset(hpet, 0, sizeof(*hpet));
 
446
    /* Note timer_block_id value must be kept in sync with value advertised by
 
447
     * emulated hpet
 
448
     */
 
449
    hpet->timer_block_id = cpu_to_le32(0x8086a201);
 
450
    hpet->addr.address = cpu_to_le64(BUILD_HPET_ADDRESS);
 
451
    build_header((void*)hpet, HPET_SIGNATURE, sizeof(*hpet), 1);
 
452
 
 
453
    return hpet;
 
454
}
 
455
 
 
456
static void
 
457
acpi_build_srat_memory(struct srat_memory_affinity *numamem,
 
458
                       u64 base, u64 len, int node, int enabled)
 
459
{
 
460
    numamem->type = SRAT_MEMORY;
 
461
    numamem->length = sizeof(*numamem);
 
462
    memset(numamem->proximity, 0, 4);
 
463
    numamem->proximity[0] = node;
 
464
    numamem->flags = cpu_to_le32(!!enabled);
 
465
    numamem->base_addr = cpu_to_le64(base);
 
466
    numamem->range_length = cpu_to_le64(len);
 
467
}
 
468
 
 
469
static void *
 
470
build_srat(void)
 
471
{
 
472
    int numadatasize, numacpusize;
 
473
    u64 *numadata = romfile_loadfile("etc/numa-nodes", &numadatasize);
 
474
    u64 *numacpumap = romfile_loadfile("etc/numa-cpu-map", &numacpusize);
 
475
    if (!numadata || !numacpumap)
 
476
        goto fail;
 
477
    int max_cpu = numacpusize / sizeof(u64);
 
478
    int nb_numa_nodes = numadatasize / sizeof(u64);
 
479
 
 
480
    struct system_resource_affinity_table *srat;
 
481
    int srat_size = sizeof(*srat) +
 
482
        sizeof(struct srat_processor_affinity) * max_cpu +
 
483
        sizeof(struct srat_memory_affinity) * (nb_numa_nodes + 2);
 
484
 
 
485
    srat = malloc_high(srat_size);
 
486
    if (!srat) {
 
487
        warn_noalloc();
 
488
        goto fail;
 
489
    }
 
490
 
 
491
    memset(srat, 0, srat_size);
 
492
    srat->reserved1=cpu_to_le32(1);
 
493
    struct srat_processor_affinity *core = (void*)(srat + 1);
 
494
    int i;
 
495
    u64 curnode;
 
496
 
 
497
    for (i = 0; i < max_cpu; ++i) {
 
498
        core->type = SRAT_PROCESSOR;
 
499
        core->length = sizeof(*core);
 
500
        core->local_apic_id = i;
 
501
        curnode = *numacpumap++;
 
502
        core->proximity_lo = curnode;
 
503
        memset(core->proximity_hi, 0, 3);
 
504
        core->local_sapic_eid = 0;
 
505
        if (apic_id_is_present(i))
 
506
            core->flags = cpu_to_le32(1);
 
507
        else
 
508
            core->flags = cpu_to_le32(0);
 
509
        core++;
 
510
    }
 
511
 
 
512
 
 
513
    /* the memory map is a bit tricky, it contains at least one hole
 
514
     * from 640k-1M and possibly another one from 3.5G-4G.
 
515
     */
 
516
    struct srat_memory_affinity *numamem = (void*)core;
 
517
    int slots = 0;
 
518
    u64 mem_len, mem_base, next_base = 0;
 
519
 
 
520
    acpi_build_srat_memory(numamem, 0, 640*1024, 0, 1);
 
521
    next_base = 1024 * 1024;
 
522
    numamem++;
 
523
    slots++;
 
524
    for (i = 1; i < nb_numa_nodes + 1; ++i) {
 
525
        mem_base = next_base;
 
526
        mem_len = *numadata++;
 
527
        if (i == 1)
 
528
            mem_len -= 1024 * 1024;
 
529
        next_base = mem_base + mem_len;
 
530
 
 
531
        /* Cut out the PCI hole */
 
532
        if (mem_base <= RamSize && next_base > RamSize) {
 
533
            mem_len -= next_base - RamSize;
 
534
            if (mem_len > 0) {
 
535
                acpi_build_srat_memory(numamem, mem_base, mem_len, i-1, 1);
 
536
                numamem++;
 
537
                slots++;
 
538
            }
 
539
            mem_base = 1ULL << 32;
 
540
            mem_len = next_base - RamSize;
 
541
            next_base += (1ULL << 32) - RamSize;
 
542
        }
 
543
        acpi_build_srat_memory(numamem, mem_base, mem_len, i-1, 1);
 
544
        numamem++;
 
545
        slots++;
 
546
    }
 
547
    for (; slots < nb_numa_nodes + 2; slots++) {
 
548
        acpi_build_srat_memory(numamem, 0, 0, 0, 0);
 
549
        numamem++;
 
550
    }
 
551
 
 
552
    build_header((void*)srat, SRAT_SIGNATURE, srat_size, 1);
 
553
 
 
554
    free(numadata);
 
555
    free(numacpumap);
 
556
    return srat;
 
557
fail:
 
558
    free(numadata);
 
559
    free(numacpumap);
 
560
    return NULL;
 
561
}
 
562
 
 
563
static void *
 
564
build_mcfg_q35(void)
 
565
{
 
566
    struct acpi_table_mcfg *mcfg;
 
567
 
 
568
    int len = sizeof(*mcfg) + 1 * sizeof(mcfg->allocation[0]);
 
569
    mcfg = malloc_high(len);
 
570
    if (!mcfg) {
 
571
        warn_noalloc();
 
572
        return NULL;
 
573
    }
 
574
    memset(mcfg, 0, len);
 
575
    mcfg->allocation[0].address = cpu_to_le64(Q35_HOST_BRIDGE_PCIEXBAR_ADDR);
 
576
    mcfg->allocation[0].pci_segment = cpu_to_le16(Q35_HOST_PCIE_PCI_SEGMENT);
 
577
    mcfg->allocation[0].start_bus_number = Q35_HOST_PCIE_START_BUS_NUMBER;
 
578
    mcfg->allocation[0].end_bus_number = Q35_HOST_PCIE_END_BUS_NUMBER;
 
579
 
 
580
    build_header((void *)mcfg, MCFG_SIGNATURE, len, 1);
 
581
    return mcfg;
 
582
}
 
583
 
 
584
static const struct pci_device_id acpi_find_tbl[] = {
 
585
    /* PIIX4 Power Management device. */
 
586
    PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82371AB_3, NULL),
 
587
    PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_ICH9_LPC, NULL),
 
588
    PCI_DEVICE_END,
 
589
};
 
590
 
 
591
#define MAX_ACPI_TABLES 20
 
592
void
 
593
acpi_setup(void)
 
594
{
 
595
    if (! CONFIG_ACPI)
 
596
        return;
 
597
 
 
598
    dprintf(3, "init ACPI tables\n");
 
599
 
 
600
    // This code is hardcoded for PIIX4 Power Management device.
 
601
    struct pci_device *pci = pci_find_init_device(acpi_find_tbl, NULL);
 
602
    if (!pci)
 
603
        // Device not found
 
604
        return;
 
605
 
 
606
    // Build ACPI tables
 
607
    u32 tables[MAX_ACPI_TABLES], tbl_idx = 0;
 
608
 
 
609
#define ACPI_INIT_TABLE(X)                                   \
 
610
    do {                                                     \
 
611
        tables[tbl_idx] = cpu_to_le32((u32)(X));             \
 
612
        if (le32_to_cpu(tables[tbl_idx]))                    \
 
613
            tbl_idx++;                                       \
 
614
    } while(0)
 
615
 
 
616
    struct fadt_descriptor_rev1 *fadt = build_fadt(pci);
 
617
    ACPI_INIT_TABLE(fadt);
 
618
    ACPI_INIT_TABLE(build_ssdt());
 
619
    ACPI_INIT_TABLE(build_madt());
 
620
    ACPI_INIT_TABLE(build_hpet());
 
621
    ACPI_INIT_TABLE(build_srat());
 
622
    if (pci->device == PCI_DEVICE_ID_INTEL_ICH9_LPC)
 
623
        ACPI_INIT_TABLE(build_mcfg_q35());
 
624
 
 
625
    struct romfile_s *file = NULL;
 
626
    for (;;) {
 
627
        file = romfile_findprefix("acpi/", file);
 
628
        if (!file)
 
629
            break;
 
630
        struct acpi_table_header *table = malloc_high(file->size);
 
631
        if (!table) {
 
632
            warn_noalloc();
 
633
            continue;
 
634
        }
 
635
        int ret = file->copy(file, table, file->size);
 
636
        if (ret <= sizeof(*table))
 
637
            continue;
 
638
        if (table->signature == DSDT_SIGNATURE) {
 
639
            if (fadt) {
 
640
                fill_dsdt(fadt, table);
 
641
            }
 
642
        } else {
 
643
            ACPI_INIT_TABLE(table);
 
644
        }
 
645
        if (tbl_idx == MAX_ACPI_TABLES) {
 
646
            warn_noalloc();
 
647
            break;
 
648
        }
 
649
    }
 
650
 
 
651
    if (CONFIG_ACPI_DSDT && fadt && !fadt->dsdt) {
 
652
        /* default DSDT */
 
653
        struct acpi_table_header *dsdt = malloc_high(sizeof(AmlCode));
 
654
        if (!dsdt) {
 
655
            warn_noalloc();
 
656
            return;
 
657
        }
 
658
        memcpy(dsdt, AmlCode, sizeof(AmlCode));
 
659
        fill_dsdt(fadt, dsdt);
 
660
        /* Strip out compiler-generated header if any */
 
661
        memset(dsdt, 0, sizeof *dsdt);
 
662
        build_header(dsdt, DSDT_SIGNATURE, sizeof(AmlCode), 1);
 
663
    }
 
664
 
 
665
    // Build final rsdt table
 
666
    struct rsdt_descriptor_rev1 *rsdt;
 
667
    size_t rsdt_len = sizeof(*rsdt) + sizeof(u32) * tbl_idx;
 
668
    rsdt = malloc_high(rsdt_len);
 
669
    if (!rsdt) {
 
670
        warn_noalloc();
 
671
        return;
 
672
    }
 
673
    memset(rsdt, 0, rsdt_len);
 
674
    memcpy(rsdt->table_offset_entry, tables, sizeof(u32) * tbl_idx);
 
675
    build_header((void*)rsdt, RSDT_SIGNATURE, rsdt_len, 1);
 
676
 
 
677
    // Build rsdp pointer table
 
678
    struct rsdp_descriptor rsdp;
 
679
    memset(&rsdp, 0, sizeof(rsdp));
 
680
    rsdp.signature = cpu_to_le64(RSDP_SIGNATURE);
 
681
    memcpy(rsdp.oem_id, BUILD_APPNAME6, 6);
 
682
    rsdp.rsdt_physical_address = cpu_to_le32((u32)rsdt);
 
683
    rsdp.checksum -= checksum(&rsdp, 20);
 
684
    copy_acpi_rsdp(&rsdp);
 
685
}