# Maintainer: David Runge <dvzrv@archlinux.org>
# Contributor: Alexander Epaneshnikov <alex19ep@archlinux.org>

pkgbase=edk2
pkgname=(edk2-aarch64 edk2-riscv64 edk2-shell edk2-ovmf)
pkgver=202605
_upstream_pkgrel=1
pkgrel=3
pkgdesc="Modern, feature-rich firmware development environment for the UEFI specifications"
arch=(aarch64) # Avoid conflicting with the official package in the x86 repo
url="https://github.com/tianocore/edk2"
license=(
  Apache-2.0
  BSD-2-Clause-Patent
  MIT
)
makedepends=(
  aarch64-linux-gnu-gcc
  acpica
  git
  util-linux-libs
  nasm
  python
  riscv64-linux-gnu-gcc
)
options=(!makeflags)
source=(
  git+$url#tag=$pkgbase-stable$pkgver
  openssl::git+https://github.com/openssl/openssl.git  # also submodule for libspdm
  pyca-cryptography::git+https://github.com/pyca/cryptography.git  # submodule for openssl
  krb5::git+https://github.com/krb5/krb5.git  # submodule for openssl
  gost-engine::git+https://github.com/gost-engine/engine.git  # submodule for openssl
  libprov::git+https://github.com/provider-corner/libprov.git  # submodule for gost-engine
  wycheproof::git+https://github.com/google/wycheproof.git  # submodule for openssl
  berkeley-softfloat-3::git+https://github.com/ucb-bar/berkeley-softfloat-3.git
  $pkgbase-cmocka::git+https://github.com/tianocore/edk2-cmocka.git
  oniguruma::git+https://github.com/kkos/oniguruma.git
  brotli::git+https://github.com/google/brotli.git
  jansson::git+https://github.com/akheron/jansson.git
  googletest::git+https://github.com/google/googletest.git  # also a submodule for public-mipi-sys-t
  edk2-subhook::git+https://github.com/tianocore/edk2-subhook.git
  pylibfdt::git+https://github.com/devicetree-org/pylibfdt.git
  public-mipi-sys-t::git+https://github.com/MIPI-Alliance/public-mipi-sys-t.git
  pugixml::git+https://github.com/zeux/pugixml.git  # submodule for public-mipi-sys-t
  mbedtls::git+https://github.com/Mbed-TLS/mbedtls.git  # also submodule for libspdm
  libspdm::git+https://github.com/DMTF/libspdm.git
  cmocka::git+https://gitlab.com/cmocka/cmocka.git  # submodule for libspdm
  50-edk2-ovmf-x86_64-secure-4m.json
  60-edk2-ovmf-x86_64-4m.json
  60-edk2-ovmf-microvm-4m.json
  60-edk2-aarch64.json
  60-edk2-riscv64.json
  80-edk2-ovmf-ia32-on-x86_64-secure-4m.json
  81-edk2-ovmf-ia32-on-x86_64-4m.json
)
sha512sums=('4bde4a2526cc840db839e19bd38c14510a2c1b00df5dcd1b48d8b547cd013894bd59b7305f7aecb9aa4814d63f167b7f15ff5ec1ccaec54d5a921393cec07d35'
            'faed7bde6e32d8b86678d17ceb126404845cbab0935a568a5c700affb11c38033824243bb59aef332189e1ef468b117edd22b514f65385a10789a2b3f79c0898'
            'c0b00c9a506de48be62c170aa5365660bad3b6fa77c329bfe78b861626090106e6333d54da8db8c698c131b5318af01069eb3ad414f790693c6cc63231bc71fd'
            '9f45e46d3c73abad68c43fbc37889f43ac463778dea21b272e3a8ec21fab15415b05f892b49cb7c6b7fb36f122ec6dae9a9513fcae52e28549486e0ca02fe432')
b2sums=('09330fd7b45d1dca43bdc7ead86bcae3a8232d4b6a3ce76aa69bfbc1a22d4e462a620c794dcd0adc9b4e136b3959d6c8ab2c0e5889d67366d7724bff46b34af6'
        '65df6015b76e61096a3220767544e71069b8a6c9fafec63e8981bc8994346aab4fd7a5f0a391d9ba4ef2bbab7f51bb9b32cdd758c25275efa25853d7423e70b7'
        'b68db228018d61ed75c9ac86e5773268af32662c8c9221b0ccf65ec19ec9915700a61448d9754e6ba8f38418011d90dcb2304455db2f64f28f6ff5706cb873df'
        '71b84d657feddf99b39631d14072af405e1c7b62ab628e0cd029628b77274e8033d73bd1d70479eaf487ed035147db0c790ff38d22d4c8879f1cba953c6a9038')
_arch_list=(AArch64 RiscV64 X64)
_build_type=RELEASE
_build_plugin=GCC

prepare() {
  local submodule

  cd $pkgbase

  git submodule init
  git config submodule.CryptoPkg/Library/OpensslLib/openssl.url ../openssl
  git config submodule.SoftFloat.url ../berkeley-softfloat-3
  git config submodule.UnitTestFrameworkPkg/Library/CmockaLib/cmocka.url ../$pkgbase-cmocka
  git config submodule.MdeModulePkg/Universal/RegularExpressionDxe/oniguruma.url ../oniguruma
  git config submodule.MdeModulePkg/Library/BrotliCustomDecompressLib/brotli.url ../brotli
  git config submodule.BaseTools/Source/C/BrotliCompress/brotli.url ../brotli
  git config submodule.RedfishPkg/Library/JsonLib/jansson.url ../jansson
  git config submodule.UnitTestFrameworkPkg/Library/GoogleTestLib/googletest.url ../googletest
  git config submodule.UnitTestFrameworkPkg/Library/SubhookLib/subhook.url ../$pkgbase-subhook
  git config submodule.MdePkg/Library/BaseFdtLib/libfdt.url ../pylibfdt
  git config submodule.MdePkg/Library/MipiSysTLib/mipisyst.url ../public-mipi-sys-t
  git config submodule.CryptoPkg/Library/MbedTlsLib/mbedtls.url ../mbedtls
  git config submodule.SecurityPkg/DeviceSecurity/SpdmLib/libspdm.url ../libspdm
  git -c protocol.file.allow=always submodule update

  # submodule setup for CryptoPkg/Library/OpensslLib/openssl
  submodule=CryptoPkg/Library/OpensslLib/openssl
  git -C $submodule submodule init
  git -C $submodule config submodule.pyca.cryptography.url "$srcdir/pyca-cryptography"
  git -C $submodule config submodule.krb5.url "$srcdir/krb5"
  git -C $submodule config submodule.gost-engine.url "$srcdir/gost-engine"
  git -C $submodule config submodule.wycheproof.url "$srcdir/wycheproof"
  git -C $submodule -c protocol.file.allow=always submodule update

  # submodule setup for CryptoPkg/Library/OpensslLib/openssl/gost-engine
  submodule=CryptoPkg/Library/OpensslLib/openssl/gost-engine
  git -C $submodule submodule init
  git -C $submodule config submodule.libprov.url "$srcdir/libprov"
  git -C $submodule -c protocol.file.allow=always submodule update

  # submodule setup for MdePkg/Library/MipiSysTLib/mipisyst
  submodule=MdePkg/Library/MipiSysTLib/mipisyst
  git -C $submodule submodule init
  git -C $submodule config submodule.external/pugixml.url "$srcdir/pugixml"
  git -C $submodule config submodule.external/googletest.url "$srcdir/googletest"
  git -C $submodule -c protocol.file.allow=always submodule update

  # submodule setup for SecurityPkg/DeviceSecurity/SpdmLib/libspdm
  submodule=SecurityPkg/DeviceSecurity/SpdmLib/libspdm
  git -C $submodule submodule init
  git -C $submodule config submodule.os_stub/openssllib/openssl.url "$srcdir/openssl"
  git -C $submodule config submodule.os_stub/mbedtlslib/mbedtls.url "$srcdir/mbedtls"
  git -C $submodule config submodule.unit_test/cmockalib/cmocka.url "$srcdir/cmocka"
  git -C $submodule -c protocol.file.allow=always submodule update

  # -Werror, not even once
  sed -e 's/ -Werror//g' -i BaseTools/Conf/*.template BaseTools/Source/C/Makefiles/*.makefile
}

# TODO: check TPM_ENABLE/TPM2_ENABLE
build() {
  local _arch
  local _build_options=()
  # shared targets for all
  local _common_args=(
    -b "$_build_type"
    -n "$(nproc)"
    -t "$_build_plugin"
  )
  # shared options for all EFI binaries
  local _efi_args=(
    -D FD_SIZE_4MB
    -D NETWORK_HTTP_BOOT_ENABLE
    -D NETWORK_IP6_ENABLE
    -D TPM_ENABLE
    -D TPM1_ENABLE
    -D TPM2_ENABLE
  )
  # network TLS for some targets (all but )
  local _network_tls=(
    -D NETWORK_TLS_ENABLE
  )

  cd $pkgbase
  # This is used as the prefix for both gcc and objcopy
  # so it cannot be set to x86_64-linux-gnu-
  # (binutils does not provide x86_64-linux-gnu-objcopy)
  export GCC_BIN=""
  export GCC_AARCH64_PREFIX="aarch64-linux-gnu-"
  export GCC_RISCV64_PREFIX="riscv64-linux-gnu-"
  echo "Building base tools"
  make -C BaseTools
  # expose build tooling in PATH
  . edksetup.sh

  for _arch in "${_arch_list[@]}"; do
    # shell
    echo "Building shell ($_arch)."
    _build_options=(
      -p ShellPkg/ShellPkg.dsc
      -a "${_arch^^}"
      "${_common_args[@]}"
    )
    BaseTools/BinWrappers/PosixLike/build "${_build_options[@]}"

    # ovmf
    case "$_arch" in
      X64)
      echo "Building ovmf ($_arch) with microvm support (4MB FD)"
      _build_options=(
        -p OvmfPkg/Microvm/Microvm$_arch.dsc
        -a "$_arch"
        "${_common_args[@]}"
        "${_efi_args[@]}"
        "${_network_tls[@]}"
      )
      BaseTools/BinWrappers/PosixLike/build "${_build_options[@]}"
      mv -v Build/MicrovmX64{,-4mb}

      echo "Building ovmf ($_arch) with secure boot support (4MB FD)"
      _build_options=(
        -p OvmfPkg/OvmfPkgIa32X64.dsc
        -a IA32
        -a "$_arch"
        "${_common_args[@]}"
        "${_efi_args[@]}"
        "${_network_tls[@]}"
        -D SECURE_BOOT_ENABLE
        -D SMM_REQUIRE
      )
      BaseTools/BinWrappers/PosixLike/build "${_build_options[@]}"
      mv -v Build/Ovmf3264{,-secure-4mb}

      echo "Building ovmf (${_arch}) without secure boot (4MB FD)"
      _build_options=(
        -p "OvmfPkg/OvmfPkg$_arch.dsc"
        -a "$_arch"
        "${_common_args[@]}"
        "${_efi_args[@]}"
        "${_network_tls[@]}"
      )
      BaseTools/BinWrappers/PosixLike/build "${_build_options[@]}"
      mv -v Build/OvmfX64{,-4mb}
      ;;
      AArch64)
      echo "Building ArmVirtPkg ($_arch) with secure boot"
      local _build_options=(
        -p ArmVirtPkg/ArmVirtQemu.dsc
        -a "${_arch^^}"
        "${_common_args[@]}"
        "${_efi_args[@]}"
        "${_network_tls[@]}"
        -D SECURE_BOOT_ENABLE
      )
      BaseTools/BinWrappers/PosixLike/build "${_build_options[@]}"
      local _file
      for _file in QEMU_EFI.fd QEMU_VARS.fd; do
        dd if=/dev/null of=Build/ArmVirtQemu-$_arch/${_build_type}_${_build_plugin}/FV/${_file} bs=1M seek=64
      done
      ;;
      RiscV64)
      echo "Building ovmf ($_arch) with secure boot"
      local _build_options=(
        -p OvmfPkg/RiscVVirt/RiscVVirtQemu.dsc
        -a "${_arch^^}"
        "${_common_args[@]}"
        "${_efi_args[@]}"
        "${_network_tls[@]}"
        -D SECURE_BOOT_ENABLE
        -D SECURE_BOOT_DEFAULT_KEYS=FALSE
      )

      BaseTools/BinWrappers/PosixLike/build "${_build_options[@]}"
      local _file
      for _file in RISCV_VIRT_CODE.fd RISCV_VIRT_VARS.fd; do
        dd if=/dev/null of=Build/RiscVVirtQemu/${_build_type}_$_build_plugin/FV/${_file} bs=1M seek=32
      done
      ;;
    esac
  done
}

package_edk2-aarch64() {
  local _arch=AArch64

  pkgdesc="Firmware for Virtual Machines (aarch64)"
  url="https://github.com/tianocore/tianocore.github.io/wiki/ArmVirtPkg"
  conflicts=('edk2-armvirt<202211')
  provides=(edk2-armvirt)
  replaces=('edk2-armvirt<202211')

  cd $pkgbase
  install -vDm 644 Build/ArmVirtQemu-$_arch/${_build_type}_${_build_plugin}/FV/*.fd -t "$pkgdir/usr/share/$pkgbase/${_arch,,}/"
  # add libvirt compatibility (which hardcodes the following paths)
  install -vdm 755 "$pkgdir/usr/share/AAVMF"
  ln -svf /usr/share/$pkgbase/${_arch,,}/QEMU_EFI.fd "$pkgdir/usr/share/AAVMF/AAVMF_CODE.fd"
  ln -svf /usr/share/$pkgbase/${_arch,,}/QEMU_VARS.fd "$pkgdir/usr/share/AAVMF/AAVMF_VARS.fd"
  # install qemu descriptors in accordance with qemu:
  # https://git.qemu.org/?p=qemu.git;a=tree;f=pc-bios/descriptors
  install -vDm 644 ../*$pkgname.json -t "$pkgdir/usr/share/qemu/firmware/"
  # add symlink for the lowercase UEFI machine type short-name
  ln -svT 'aarch64' "$pkgdir/usr/share/$pkgbase/aa64"
  # license
  install -vDm 644 License.txt -t "$pkgdir/usr/share/licenses/$pkgname/"

  # add symlink for previous aarch64 location
  ln -svf /usr/share/$pkgbase "$pkgdir/usr/share/$pkgbase-armvirt"
}

package_edk2-riscv64() {
  local _arch=RiscV64

  pkgdesc="Firmware for Virtual Machines (riscv64)"
  url="https://github.com/tianocore/tianocore.github.io/wiki/RiscVPkg"

  cd $pkgbase
  install -vDm 644 Build/RiscVVirtQemu/${_build_type}_${_build_plugin}/FV/*.fd -t "$pkgdir/usr/share/$pkgbase/${_arch,,}/"
  # install qemu descriptors in accordance with qemu:
  # https://git.qemu.org/?p=qemu.git;a=tree;f=pc-bios/descriptors
  install -vDm 644 ../*$pkgname.json -t "$pkgdir/usr/share/qemu/firmware/"
  # license
  install -vDm 644 License.txt -t "$pkgdir/usr/share/licenses/$pkgname/"
}

package_edk2-shell() {
  local _arch
  # minimal UEFI shell, as defined in ShellPkg/Application/Shell/ShellPkg.inf
  local _min='7C04A583-9E3E-4f1c-AD65-E05268D0B4D1'
  # full UEFI shell, as defined in ShellPkg/ShellPkg.dsc
  local _full='EA4BB293-2D7F-4456-A681-1F22F42CD0BC'

  pkgdesc="EDK2 UEFI Shell"
  provides=(uefi-shell)

  cd $pkgbase
  for _arch in "${_arch_list[@]}"; do
    install -vDm 644 "Build/Shell/${_build_type}_${_build_plugin}/${_arch^^}/Shell_$_min.efi" "$pkgdir/usr/share/$pkgname/${_arch,,}/Shell.efi"
    install -vDm 644 "Build/Shell/${_build_type}_${_build_plugin}/${_arch^^}/Shell_$_full.efi" "$pkgdir/usr/share/$pkgname/${_arch,,}/Shell_Full.efi"
  done
  # add symlink for the lowercase UEFI machine type short-name "aa64"
  if [[ -d "$pkgdir/usr/share/$pkgname/aarch64" ]]; then
    ln -svT 'aarch64' "$pkgdir/usr/share/$pkgname/aa64"
  fi
  # license
  install -vDm 644 License.txt -t "$pkgdir/usr/share/licenses/$pkgname/"
  # docs
  install -vDm 644 {ReadMe.rst,Maintainers.txt} -t "$pkgdir/usr/share/doc/$pkgname/"
}

package_edk2-ovmf() {
  local _arch=X64

  pkgdesc="Firmware for Virtual Machines (x86_64, i686 on x86_64)"
  url="https://github.com/tianocore/tianocore.github.io/wiki/OVMF"
  provides=(ovmf)
  conflicts=(ovmf)
  replaces=(ovmf)
  install=$pkgname.install

  cd $pkgbase
  # installing OVMF.fd for xen: https://bugs.archlinux.org/task/58635
  install -vDm 644 Build/Ovmf$_arch-4mb/${_build_type}_${_build_plugin}/FV/OVMF.fd "$pkgdir/usr/share/$pkgbase/${_arch,,}/OVMF.4m.fd"
  install -vDm 644 Build/Ovmf$_arch-4mb/${_build_type}_${_build_plugin}/FV/OVMF_CODE.fd "$pkgdir/usr/share/$pkgbase/${_arch,,}/OVMF_CODE.4m.fd"
  install -vDm 644 Build/Ovmf$_arch-4mb/${_build_type}_${_build_plugin}/FV/OVMF_VARS.fd "$pkgdir/usr/share/$pkgbase/${_arch,,}/OVMF_VARS.4m.fd"
  install -vDm 644 Build/Ovmf3264-secure-4mb/${_build_type}_${_build_plugin}/FV/OVMF_CODE.fd "$pkgdir/usr/share/$pkgbase/${_arch,,}/OVMF_CODE.secboot.4m.fd"
  install -vDm 644 Build/MicrovmX64-4mb/${_build_type}_${_build_plugin}/FV/MICROVM.fd "$pkgdir/usr/share/$pkgbase/${_arch,,}/MICROVM.4m.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 ../*$pkgname*.json -t "$pkgdir/usr/share/qemu/firmware/"
  # add symlink for previous ovmf locations
  # https://bugs.archlinux.org/task/66528
  ln -svf /usr/share/$pkgbase "$pkgdir/usr/share/ovmf"
  ln -svf /usr/share/$pkgbase "$pkgdir/usr/share/$pkgbase-ovmf"
  # adding a symlink for applications with questionable heuristics (such as lxd)
  ln -svf /usr/share/$pkgbase "$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/"
}

makedepends=()
source=()
noextract=()
for _name in "${pkgname[@]}"; do
  source+=(${_name}-${pkgver}-${_upstream_pkgrel}-any.tar.zst::https://mirrors.kernel.org/archlinux/extra/os/x86_64/${_name}-${pkgver}-${_upstream_pkgrel}-any.pkg.tar.zst)
  noexxtract+=(${_name}-${pkgver}-${_upstream_pkgrel}-any.tar.zst)
  eval "package_$_name() {
    _package $_name
  }"
done

prepare() {
  :
}

build() {
  :
}

_package() {
  _name="$1"
  rm -rf unpack-$_name
  mkdir unpack-$_name
  cd unpack-$_name

  bsdtar xf ../${_name}-${pkgver}-${_upstream_pkgrel}-any.tar.zst

  rm .BUILDINFO .MTREE

  if [[ -f .INSTALL ]]; then
    mv .INSTALL "${startdir}/$_name.install"
    install=$_name.install
  fi
  arch=(aarch64)

  replaces=()
  conflicts=()
  provides=()
  while read line; do
    if ! [[ $line =~ ^([a-z].*)\ =\ (.*) ]]; then
      continue
    fi
    _key="${BASH_REMATCH[1]}"
    _value="${BASH_REMATCH[2]}"
    case $_key in
      pkgdesc)
        pkgdesc="$_value"
        ;;
      url)
        url="$_value"
        ;;
      replaces)
        replaces+=("$_value")
        ;;
      conflict)
        conflicts+=("$_value")
        ;;
      provides)
        provides+=("$_value")
        ;;
      pkgname|pkgbase|xdata|pkgver|builddate|packager|size|arch|license|makedepend)
        ;;
      *)
        echo "Unhandled PKGINFO: $_key = $_value"
        ;;
    esac
  done < .PKGINFO
  rm .PKGINFO
  mv * "${pkgdir}"
}
