Skip to content

Instantly share code, notes, and snippets.

@Ashymad

Ashymad/PKGBUILD Secret

Last active April 10, 2021 19:32
Show Gist options
  • Star 7 You must be signed in to star a gist
  • Fork 2 You must be signed in to fork a gist
  • Save Ashymad/2c8192519492dec262b344deb68fed44 to your computer and use it in GitHub Desktop.
Save Ashymad/2c8192519492dec262b344deb68fed44 to your computer and use it in GitHub Desktop.
diff --git a/OvmfPkg/AcpiPlatformDxe/QemuFwCfgAcpi.c b/OvmfPkg/AcpiPlatformDxe/QemuFwCfgAcpi.c
index a0b1cfd2be..0e74f870d8 100644
--- a/OvmfPkg/AcpiPlatformDxe/QemuFwCfgAcpi.c
+++ b/OvmfPkg/AcpiPlatformDxe/QemuFwCfgAcpi.c
@@ -24,6 +24,8 @@
#include <Library/PcdLib.h>
#include <Library/OrderedCollectionLib.h>
#include <IndustryStandard/Acpi.h>
+#include "vrom.h"
+#include "vrom_table.h"
//
@@ -1108,6 +1110,77 @@ InstallQemuFwCfgTables (
}
}
+ // modification: add additional SSDT
+ UINT32 VromSize = 256*1024;
+ UINT8* FwData = AllocateRuntimePool(VromSize); // 256*1024 = 256 KB = size of VROM image
+
+ // copy VROM to FwData
+ CopyMem (FwData, VROM_BIN, VROM_BIN_LEN);
+
+ // header of SSDT table: DefinitionBlock ("Ssdt.aml", "SSDT", 1, "REDHAT", "OVMF ", 1)
+ unsigned char Ssdt_header[] = {
+ 0x53, 0x53, 0x44, 0x54, 0x24, 0x00, 0x00, 0x00, 0x01, 0x86, 0x52, 0x45,
+ 0x44, 0x48, 0x41, 0x54, 0x4f, 0x56, 0x4d, 0x46, 0x20, 0x20, 0x20, 0x20,
+ 0x01, 0x00, 0x00, 0x00, 0x49, 0x4e, 0x54, 0x4c, 0x31, 0x08, 0x16, 0x20
+ };
+
+ // byte 4-7: length header + table in little endian (so equal to SsdtSize)
+ // byte 8: version complicance number: nothing needs to change
+ // byte 9: set such that when all bytes are added modulo 256 the sum equals 0
+ // calculate checksum: already implemented as CalculateCheckSum8(offset, length)
+
+ unsigned int Ssdt_header_len = 36;
+
+ UINTN SsdtSize;
+ UINT8 *Ssdt;
+
+ SsdtSize = Ssdt_header_len + 17 + vrom_table_len;
+ Ssdt = AllocatePool (SsdtSize);
+
+ UINT8 *SsdtPtr = Ssdt;
+
+ // copy header to Ssdt table
+ CopyMem (SsdtPtr, Ssdt_header, Ssdt_header_len);
+ SsdtPtr += Ssdt_header_len;
+
+ // build "OperationRegion(FWDT, SystemMemory, 0x12345678, 0x87654321)"
+ //
+ *(SsdtPtr++) = 0x5B; // ExtOpPrefix
+ *(SsdtPtr++) = 0x80; // OpRegionOp
+ *(SsdtPtr++) = 'V';
+ *(SsdtPtr++) = 'B';
+ *(SsdtPtr++) = 'O';
+ *(SsdtPtr++) = 'R';
+ *(SsdtPtr++) = 0x00; // SystemMemory
+ *(SsdtPtr++) = 0x0C; // DWordPrefix
+
+ //
+ // no virtual addressing yet, take the four least significant bytes
+ //
+ CopyMem(SsdtPtr, &FwData, 4);
+ SsdtPtr += 4;
+
+ *(SsdtPtr++) = 0x0C; // DWordPrefix
+
+ *(UINT32*) SsdtPtr = VromSize;
+ SsdtPtr += 4;
+
+ CopyMem (SsdtPtr, vrom_table, vrom_table_len);
+
+ // set the correct size in the header
+ UINT32* size_ptr = (UINT32*) &Ssdt[4];
+ *size_ptr = SsdtSize;
+
+ // set byte 9 of header so the checksum equals 0
+ Ssdt[9] = 0;
+ UINT32 checksum = CalculateCheckSum8(Ssdt, SsdtSize);
+ Ssdt[9] = (256 - checksum) % 256;
+
+ Status = AcpiProtocol->InstallAcpiTable (AcpiProtocol,
+ (VOID *) Ssdt, SsdtSize,
+ &InstalledKey[Installed]);
+ ++Installed;
+
//
// Translating the condensed QEMU_LOADER_WRITE_POINTER commands to ACPI S3
// Boot Script opcodes has to be the last operation in this function, because
# Maintainer: Ashymad
pkgname=ovmf-patched-vbios
pkgver=r24601.6861765935
epoch=1
pkgrel=1
arch=('x86_64')
pkgdesc="Tianocore UEFI firmware for qemu with vbios patched in."
url="http://sourceforge.net/apps/mediawiki/tianocore/index.php?title=EDK2"
license=('custom')
conflicts=(ovmf)
makedepends=('git' 'python2' 'iasl' 'nasm' 'subversion' 'perl-libwww' 'vim' 'dos2unix')
_commit=6861765935d5b69803321ba6e43240845c7ab0e5
_openssl_ver=1.1.0h
source=("edk2::git+https://github.com/tianocore/edk2#commit=$_commit"
"https://www.openssl.org/source/openssl-$_openssl_ver.tar.gz"
"file://$startdir/nvidia-hack.diff"
"file://$startdir/ssdt.asl"
"file://$startdir/vBIOS.bin")
sha256sums=('SKIP'
'5835626cde9e99656585fc7aaa2302a73a7e1340bf8c14fd635a62c66802a517'
'0281bc0229c0722772b5e230b0ebf1985f1b6b88e6f52161486dbe88664bdb6f'
'e7dc727fd2aeb581f9fd052cf70a01e883585ce6c0b2cbde82fee91122f51f04'
'SKIP')
validpgpkeys=(8657ABB260F056B1E5190839D9C4D26D0E604491)
options=(!makeflags)
_toolchain_opt=GCC5
pkgver() {
cd "${srcdir}"/edk2
printf "r%s.%s" "$(git rev-list --count HEAD)" "$(git rev-parse --short HEAD)"
}
prepare() {
cd "${srcdir}"
xxd -i vBIOS.bin vrom.h
sed -i 's/vBIOS_bin/VROM_BIN/g; s/_len/_LEN/g' vrom.h
rom_len=$(grep VROM_BIN_LEN vrom.h | cut -d' ' -f5 | sed 's/;//g')
sed -i "s/103936/$rom_len/g" ssdt.asl
iasl -f ssdt.asl
xxd -c1 Ssdt.aml | tail -n +37 | cut -f2 -d' ' | paste -sd' ' | sed 's/ //g' | xxd -r -p > vrom_table.aml
xxd -i vrom_table.aml | sed 's/vrom_table_aml/vrom_table/g' > vrom_table.h
mv "$srcdir/vrom.h" "${srcdir}/edk2/OvmfPkg/AcpiPlatformDxe/"
mv "$srcdir/vrom_table.h" "${srcdir}/edk2/OvmfPkg/AcpiPlatformDxe/"
dos2unix "$srcdir/edk2/OvmfPkg/AcpiPlatformDxe/QemuFwCfgAcpi.c"
cd "$srcdir/edk2"
patch -p1 < "$srcdir/nvidia-hack.diff"
unix2dos "$srcdir/edk2/OvmfPkg/AcpiPlatformDxe/QemuFwCfgAcpi.c"
cd "${srcdir}"
# edk2 uses python everywhere, but expects python2
mkdir -p bin
ln -sf /usr/bin/python2 bin/python
rm -rf $srcdir/edk2/CryptoPkg/Library/OpensslLib/openssl
ln -sf $srcdir/openssl-$_openssl_ver $srcdir/edk2/CryptoPkg/Library/OpensslLib/openssl
}
build() {
if [ "$CARCH" != "x86_64" ]; then
error "This package must be built under the x86_64 architecture."
false
fi
export PATH="${srcdir}/bin:$PATH"
cd "${srcdir}/"edk2
make -C BaseTools
export EDK_TOOLS_PATH="${srcdir}"/edk2/BaseTools
. edksetup.sh BaseTools
./BaseTools/BinWrappers/PosixLike/build -t $_toolchain_opt -a X64 -p OvmfPkg/OvmfPkgX64.dsc -n $(nproc) -b RELEASE -D FD_SIZE_2MB -D NETWORK_IP6_ENABLE -D TPM2_ENABLE -D SECURE_BOOT_ENABLE -D HTTP_BOOT_ENABLE -D TLS_ENABLE
# build fails for 32bit binary
# ./BaseTools/BinWrappers/PosixLike/build -t $_toolchain_opt -a IA32 -p OvmfPkg/OvmfPkgIa32.dsc -n $(nproc) -b RELEASE -D FD_SIZE_2MB
}
package() {
install -D -m644 "${srcdir}"/edk2/Build/OvmfX64/RELEASE_${_toolchain_opt}/FV/OVMF_CODE.fd "${pkgdir}"/usr/share/ovmf/x64/OVMF_CODE.fd
install -D -m644 "${srcdir}"/edk2/Build/OvmfX64/RELEASE_${_toolchain_opt}/FV/OVMF_VARS.fd "${pkgdir}"/usr/share/ovmf/x64/OVMF_VARS.fd
install -D -m644 "${srcdir}"/edk2/OvmfPkg/License.txt "${pkgdir}"/usr/share/licenses/ovmf/License.txt
}
DefinitionBlock ("Ssdt.aml", "SSDT", 1, "REDHAT", "OVMF2 ", 1) {
/* copied from jscinoz */
External(\_SB.PCI0.FWCF, DeviceObj)
External(\_SB.PCI0.FWCF._CRS, BuffObj)
Device (\_SB.PCI0.PEG0) {
Name (_ADR, 0x00010000)
}
Device (\_SB.PCI0.PEG0.PEGP) {
Name (_ADR, Zero)
/* ROML and ROMB not necessary here */
CreateByteField(\_SB.PCI0.FWCF._CRS, 0, ID)
CreateWordField(\_SB.PCI0.FWCF._CRS, 2, BMIN)
CreateWordField(\_SB.PCI0.FWCF._CRS, 4, BMAX)
CreateByteField(\_SB.PCI0.FWCF._CRS, 7, LEN)
// XXX: Unsure why, but these must be two separate regions, even though
// FWD is entirely contained within FWC
OperationRegion(FWC, SystemIO, BMIN, 2)
OperationRegion(FWD, SystemIO, BMIN + 1, 1)
Field(FWC, WordAcc, Lock, Preserve) {
CTRL, 16
}
// Yes, DATA overlaps CTRL. This is not a mistake
Field(FWD, ByteAcc, NoLock, Preserve) {
DATA, 8
}
}
/* define the ROM call */
Scope (\_SB.PCI0.PEG0.PEGP)
{
Name (RVBS, 103936) // size of ROM in bytes
External (\VBOR, OpRegionObj)
Field (\VBOR, DWordAcc, Lock, Preserve)
{
VBS1, 262144, // length of segment in bits
VBS2, 262144,
VBS3, 262144,
VBS4, 262144,
VBS5, 262144,
VBS6, 262144,
VBS7, 262144,
VBS8, 262144
}
Method (_ROM, 2, Serialized) // _ROM: Read-Only Memory
{
Local0 = Arg0 // offset in bytes
Local1 = Arg1 // length in bytes
// create a buffer to store the result
// initialize to empty buffer
Name (VROM, Buffer (Local1)
{
0x00
})
// length > 4k
If (Local1 > 0x1000)
{
Local1 = 0x1000
}
// offset > size of ROM in bytes
If (Local0 > RVBS)
{
Return (VROM) /* \_SB_.PCI0.PEG0.PEGP._ROM.VROM */
}
// end position
Local2 = (Arg0 + Arg1)
// end position > ROM size
If (Local2 > RVBS)
{
// set length to image length - start offset
Local1 = (RVBS - Local0)
}
// 0x8000: segment size in bytes
// Local3: remainder, Local4: in which segment
Divide (Local0, 0x8000, Local3, Local4)
// set Local5 to the right segment
If (Local4 == 0)
{
Local5 = \_SB.PCI0.PEG0.PEGP.VBS1
}
ElseIf (Local4 == 1)
{
Local5 = \_SB.PCI0.PEG0.PEGP.VBS2
}
ElseIf (Local4 == 2)
{
Local5 = \_SB.PCI0.PEG0.PEGP.VBS3
}
ElseIf (Local4 == 3)
{
Local5 = \_SB.PCI0.PEG0.PEGP.VBS4
}
ElseIf (Local4 == 4)
{
Local5 = \_SB.PCI0.PEG0.PEGP.VBS5
}
ElseIf (Local4 == 5)
{
Local5 = \_SB.PCI0.PEG0.PEGP.VBS6
}
ElseIf (Local4 == 6)
{
Local5 = \_SB.PCI0.PEG0.PEGP.VBS7
}
ElseIf (Local4 == 7)
{
Local5 = \_SB.PCI0.PEG0.PEGP.VBS8
}
// extract from the segment starting from offset Local3 of size Local1
// from Local 5 and store into VROM
Mid (Local5, Local3, Local1, VROM)
Return (VROM) /* \_SB_.PCI0.PEG0.PEGP._ROM.VROM */
}
}
}
@ktod16
Copy link

ktod16 commented Jul 20, 2019

Dear Sir,
I'm trying to passthrough GPU on a Lenovo P71 and I completed all the steps until OVMF Patch. I runned your script (or I think I did) but nothing happens. Can you give me some instructions on how to do this? My linux skills are verry limmited. I just started with Fedora 3o and i would like to run also win10 in parallel.

Thank you for your support..

@Ashymad
Copy link
Author

Ashymad commented Jul 20, 2019

This PKGBUILD can only be used on distributions using the pacman manager, than means Arch Linux or derivatives. On Fedora you would probably need to run the steps manually. Also, I am not using VFIO anymore, as it proved to be more hassle than it's worth just to play some games on Optimus devices, so I'm not actively maintaining this PKGBUILD, I don't even know if it's needed anymore... You should probably search for help elsewhere, sorry :)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment