update dsdt ressources at runtime
Write the pci window location to memory and add a pointer to the SSDT
(BDAT region). Turn \\SB.PCI0._CRS into a method which looks up the
information there and updates the ressources accordingly.
Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
diff --git a/src/acpi-dsdt.dsl b/src/acpi-dsdt.dsl
index 4bdc268..15299ee 100644
--- a/src/acpi-dsdt.dsl
+++ b/src/acpi-dsdt.dsl
@@ -132,7 +132,7 @@
B0EJ, 32,
}
- Name (_CRS, ResourceTemplate ()
+ Name (CRES, ResourceTemplate ()
{
WordBusNumber (ResourceProducer, MinFixed, MaxFixed, PosDecode,
0x0000, // Address Space Granularity
@@ -174,8 +174,68 @@
0xFEBFFFFF, // Address Range Maximum
0x00000000, // Address Translation Offset
0x1EC00000, // Address Length
- ,, , AddressRangeMemory, TypeStatic)
+ ,, PW32, AddressRangeMemory, TypeStatic)
})
+ Name (CR64, ResourceTemplate ()
+ {
+ QWordMemory (ResourceProducer, PosDecode, MinFixed, MaxFixed, Cacheable, ReadWrite,
+ 0x00000000, // Address Space Granularity
+ 0x8000000000, // Address Range Minimum
+ 0xFFFFFFFFFF, // Address Range Maximum
+ 0x00000000, // Address Translation Offset
+ 0x8000000000, // Address Length
+ ,, PW64, AddressRangeMemory, TypeStatic)
+ })
+ Method (_CRS, 0)
+ {
+ /* see see acpi.h, struct bfld */
+ External (BDAT, OpRegionObj)
+ Field(BDAT, QWordAcc, NoLock, Preserve) {
+ P0S, 64,
+ P0E, 64,
+ P0L, 64,
+ P1S, 64,
+ P1E, 64,
+ P1L, 64,
+ }
+ Field(BDAT, DWordAcc, NoLock, Preserve) {
+ P0SL, 32,
+ P0SH, 32,
+ P0EL, 32,
+ P0EH, 32,
+ P0LL, 32,
+ P0LH, 32,
+ P1SL, 32,
+ P1SH, 32,
+ P1EL, 32,
+ P1EH, 32,
+ P1LL, 32,
+ P1LH, 32,
+ }
+
+ /* fixup 32bit pci io window */
+ CreateDWordField (CRES,\_SB.PCI0.PW32._MIN, PS32)
+ CreateDWordField (CRES,\_SB.PCI0.PW32._MAX, PE32)
+ CreateDWordField (CRES,\_SB.PCI0.PW32._LEN, PL32)
+ Store (P0SL, PS32)
+ Store (P0EL, PE32)
+ Store (P0LL, PL32)
+
+ If (LAnd(LEqual(P1SL, 0x00), LEqual(P1SH, 0x00))) {
+ Return (CRES)
+ } Else {
+ /* fixup 64bit pci io window */
+ CreateQWordField (CR64,\_SB.PCI0.PW64._MIN, PS64)
+ CreateQWordField (CR64,\_SB.PCI0.PW64._MAX, PE64)
+ CreateQWordField (CR64,\_SB.PCI0.PW64._LEN, PL64)
+ Store (P1S, PS64)
+ Store (P1E, PE64)
+ Store (P1L, PL64)
+ /* add window and return result */
+ ConcatenateResTemplate (CRES, CR64, Local0)
+ Return (Local0)
+ }
+ }
}
}
diff --git a/src/acpi.c b/src/acpi.c
index 5387183..365267b 100644
--- a/src/acpi.c
+++ b/src/acpi.c
@@ -415,7 +415,8 @@
int length = ((1+3+4)
+ (acpi_cpus * SD_SIZEOF)
+ (1+2+5+(12*acpi_cpus))
- + (6+2+1+(1*acpi_cpus)));
+ + (6+2+1+(1*acpi_cpus))
+ + 17);
u8 *ssdt = malloc_high(sizeof(struct acpi_table_header) + length);
if (! ssdt) {
warn_noalloc();
@@ -477,6 +478,31 @@
for (i=0; i<acpi_cpus; i++)
*(ssdt_ptr++) = (i < CountCPUs) ? 0x01 : 0x00;
+ // store pci io windows: start, end, length
+ // this way we don't have to do the math in the dsdt
+ struct bfld *bfld = malloc_high(sizeof(struct bfld));
+ bfld->p0s = pcimem_start;
+ bfld->p0e = pcimem_end - 1;
+ bfld->p0l = pcimem_end - pcimem_start;
+ bfld->p1s = pcimem64_start;
+ bfld->p1e = pcimem64_end - 1;
+ bfld->p1l = pcimem64_end - pcimem64_start;
+
+ // build "OperationRegion(BDAT, SystemMemory, 0x12345678, 0x87654321)"
+ *(ssdt_ptr++) = 0x5B; // ExtOpPrefix
+ *(ssdt_ptr++) = 0x80; // OpRegionOp
+ *(ssdt_ptr++) = 'B';
+ *(ssdt_ptr++) = 'D';
+ *(ssdt_ptr++) = 'A';
+ *(ssdt_ptr++) = 'T';
+ *(ssdt_ptr++) = 0x00; // SystemMemory
+ *(ssdt_ptr++) = 0x0C; // DWordPrefix
+ *(u32*)ssdt_ptr = (u32)bfld;
+ ssdt_ptr += 4;
+ *(ssdt_ptr++) = 0x0C; // DWordPrefix
+ *(u32*)ssdt_ptr = sizeof(struct bfld);
+ ssdt_ptr += 4;
+
build_header((void*)ssdt, SSDT_SIGNATURE, ssdt_ptr - ssdt, 1);
//hexdump(ssdt, ssdt_ptr - ssdt);
diff --git a/src/acpi.h b/src/acpi.h
index e01315a..cb21561 100644
--- a/src/acpi.h
+++ b/src/acpi.h
@@ -98,4 +98,13 @@
#endif
} PACKED;
+struct bfld {
+ u64 p0s; /* pci window 0 (below 4g) - start */
+ u64 p0e; /* pci window 0 (below 4g) - end */
+ u64 p0l; /* pci window 0 (below 4g) - length */
+ u64 p1s; /* pci window 1 (above 4g) - start */
+ u64 p1e; /* pci window 1 (above 4g) - end */
+ u64 p1l; /* pci window 1 (above 4g) - length */
+} PACKED;
+
#endif // acpi.h