Skip to content

Instantly share code, notes, and snippets.

@midi1996
Forked from Ashymad/PKGBUILD
Last active August 24, 2023 02:19
Show Gist options
  • Star 3 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save midi1996/c7db7b5f71d51fd418e8dd2554188498 to your computer and use it in GitHub Desktop.
Save midi1996/c7db7b5f71d51fd418e8dd2554188498 to your computer and use it in GitHub Desktop.
Slightly updated ovmf-patched-vbios (as of April 2021, now 19 September 2021)
{
"description": "UEFI firmware for x86_64, with Secure Boot and SMM",
"interface-types": [
"uefi"
],
"mapping": {
"device": "flash",
"executable": {
"filename": "/usr/share/edk2-ovmf/x64/OVMF_CODE.secboot.fd",
"format": "raw"
},
"nvram-template": {
"filename": "/usr/share/edk2-ovmf/x64/OVMF_VARS.fd",
"format": "raw"
}
},
"targets": [
{
"architecture": "x86_64",
"machines": [
"pc-q35-*"
]
}
],
"features": [
"acpi-s3",
"amd-sev",
"requires-smm",
"secure-boot",
"verbose-dynamic"
],
"tags": [
]
}
{
"description": "UEFI firmware for x86_64",
"interface-types": [
"uefi"
],
"mapping": {
"device": "flash",
"executable": {
"filename": "/usr/share/edk2-ovmf/x64/OVMF_CODE.fd",
"format": "raw"
},
"nvram-template": {
"filename": "/usr/share/edk2-ovmf/x64/OVMF_VARS.fd",
"format": "raw"
}
},
"targets": [
{
"architecture": "x86_64",
"machines": [
"pc-i440fx-*",
"pc-q35-*"
]
}
],
"features": [
"acpi-s3",
"amd-sev",
"verbose-dynamic"
],
"tags": [
]
}
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
@@ -20,6 +20,8 @@
#include <Library/UefiBootServicesTableLib.h> // gBS
#include "AcpiPlatform.h"
+#include "vrom.h"
+#include "vrom_table.h"
//
// The user structure for the ordered collection that will track the fw_cfg
@@ -1103,6 +1105,78 @@
}
}
+ // 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
# Edited by midi1996 -- fork
# Updated 19 September 2021
# Note: this replaces the edk2-ovmf from archlinux repositories, change `pkgname` and
# the paths in `package()`, `provides`, `conflicts` and `replaces` accordingly if you
# want both packages, for me I do not need both, and I made this PKGBUILD with that
# in mind.
pkgname=edk2-ovmf
pkgver=r29285.542cba73d2
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' 'python' 'iasl' 'nasm' 'subversion' 'perl-libwww' 'vim' 'dos2unix')
source=("edk2::git+https://github.com/tianocore/edk2#commit=master"
"nvidia-hack.diff"
"ssdt.asl"
"vBIOS.bin")
sha256sums=('SKIP'
'961ab6a5866052b9e45e61b44f12fa2657e40b03fbff890688ba917333659ac2'
'e7dc727fd2aeb581f9fd052cf70a01e883585ce6c0b2cbde82fee91122f51f04'
'SKIP')
options=(!makeflags)
_build_type='RELEASE'
_build_plugin='GCC5'
_arch=X64
pkgver() {
cd "${srcdir}"/edk2
printf "r%s.%s" "$(git rev-list --count HEAD)" "$(git rev-parse --short HEAD)"
}
prepare() {
# pulling submodules
cd "${srcdir}"/edk2
git submodule update --init --recursive
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"
}
build() {
cd "${srcdir}/"edk2
make -C BaseTools
export EDK_TOOLS_PATH="${srcdir}"/edk2/BaseTools
. edksetup.sh BaseTools
./BaseTools/BinWrappers/PosixLike/build \
-t "${_build_plugin}" \
-a X64 \
-p OvmfPkg/OvmfPkgX64.dsc \
-n "$(nproc)" \
-b "${_build_type}" \
-D NETWORK_IP6_ENABLE \
-D TPM_ENABLE \
-D FD_SIZE_2MB \
-D TLS_ENABLE \
-D HTTP_BOOT_ENABLE \
-D SECURE_BOOT_ENABLE \
-D EXCLUDE_SHELL_FROM_FD
# Duplicating the secureboot build for the json, too lazy to edit it
cp -rv Build/OvmfX64{,-secure}
}
package() {
# This section is copied (with some modifications) from the main archlinux edk2 PKGBUILD
pkgdesc="Firmware for Virtual Machines (x86_64, i686) with vBIOS patch"
provides=('ovmf')
conflicts=('ovmf')
replaces=('ovmf')
cd "${srcdir}/"edk2
install -vDm 644 "Build/Ovmf${_arch}/${_build_type}_${_build_plugin}/FV/OVMF.fd" \
-t "${pkgdir}/usr/share/${pkgname}/${_arch,,}"
install -vDm 644 "Build/Ovmf${_arch}/${_build_type}_${_build_plugin}/FV/OVMF_CODE.fd" \
-t "${pkgdir}/usr/share/${pkgname}/${_arch,,}"
install -vDm 644 "Build/Ovmf${_arch}/${_build_type}_${_build_plugin}/FV/OVMF_VARS.fd" \
-t "${pkgdir}/usr/share/${pkgname}/${_arch,,}"
install -vDm 644 "Build/Ovmf${_arch}-secure/${_build_type}_${_build_plugin}/FV/OVMF_CODE.fd" \
"${pkgdir}/usr/share/${pkgname}/${_arch,,}/OVMF_CODE.secboot.fd"
# installing qemu descriptors in accordance with qemu:
# https://git.qemu.org/?p=qemu.git;a=tree;f=pc-bios/descriptors
# https://bugs.archlinux.org/task/64206
install -vDm 644 "${srcdir}"/*"${pkgname}"*.json -t "${pkgdir}/usr/share/qemu/firmware"
# adding symlink for previous ovmf location
# https://bugs.archlinux.org/task/66528
ln -svf "/usr/share/${pkgname}" "${pkgdir}/usr/share/ovmf"
# adding a symlink for applications with questionable heuristics (such as lxd)
ln -svf "/usr/share/${pkgname}" "${pkgdir}/usr/share/OVMF"
# licenses
install -vDm 644 License.txt -t "${pkgdir}/usr/share/licenses/${pkgname}"
install -vDm 644 OvmfPkg/License.txt \
"${pkgdir}/usr/share/licenses/${pkgname}/OvmfPkg.License.txt"
# docs
install -vDm 644 {OvmfPkg/README,ReadMe.rst,Maintainers.txt} \
-t "${pkgdir}/usr/share/doc/${pkgname}"
}
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 */
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment