From mboxrd@z Thu Jan 1 00:00:00 1970 Received: from dfw.source.kernel.org (dfw.source.kernel.org [139.178.84.217]) by mx.groups.io with SMTP id smtpd.web11.41013.1674116528077567672 for ; Thu, 19 Jan 2023 00:22:08 -0800 Authentication-Results: mx.groups.io; dkim=pass header.i=@kernel.org header.s=k20201202 header.b=PmxAJQzX; spf=pass (domain: kernel.org, ip: 139.178.84.217, mailfrom: ardb@kernel.org) Received: from smtp.kernel.org (relay.kernel.org [52.25.139.140]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by dfw.source.kernel.org (Postfix) with ESMTPS id 8AAAC611FB; Thu, 19 Jan 2023 08:22:07 +0000 (UTC) Received: by smtp.kernel.org (Postfix) with ESMTPSA id CE34BC433EF; Thu, 19 Jan 2023 08:22:05 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1674116527; bh=biqzD6iFcq8B/pYUFWXkhuxRp8BEB4Zk/+Mc/FxLC1s=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=PmxAJQzXJ3f8OA7vLg7XLiir/KWcZlf+0MNFJhkVHG4RUb5O4kDRBbg8600JggDzE araogr2eFzWPU4kuTByOerE7mxuwpl7CDES4ez/qAhN0XCufZgyHOWZ7P/8X2o/ecD 1xd0IzoKebugpGAyvkfpBvAcY4cTTv5crsdOdIRNTAVbb8Qym0KYrZZVh2Xesmpj8E 229nLYslm+x1gokwppAqd9KhGvHj/3his1Y01fQV3J7e4KR4Ry4hcoArXE5IsvcuNV U//LUgNqjtEDm6yUN7f6i79bZvL+erbo4dI8TMjWQmZpA4RiZfgXU6SiKOjpx1mkNo QlB/ivj7eqsgQ== From: "Ard Biesheuvel" To: devel@edk2.groups.io Cc: Ard Biesheuvel , Gerd Hoffmann , Michael Kubacki , Oliver Steffen Subject: [PATCH 2/3] ArmVirtPkg: CI: Perform build and boot test of ArmVirtQemuKernel Date: Thu, 19 Jan 2023 09:21:52 +0100 Message-Id: <20230119082153.1520196-3-ardb@kernel.org> X-Mailer: git-send-email 2.39.0 In-Reply-To: <20230119082153.1520196-1-ardb@kernel.org> References: <20230119082153.1520196-1-ardb@kernel.org> MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Signed-off-by: Ard Biesheuvel --- ArmVirtPkg/PlatformCI/.azurepipelines/Ubuntu-GCC5.yml | 43 ++++ ArmVirtPkg/PlatformCI/QemuKernelBuild.py | 268 ++++++++++++++= ++++++ 2 files changed, 311 insertions(+) diff --git a/ArmVirtPkg/PlatformCI/.azurepipelines/Ubuntu-GCC5.yml b/ArmVir= tPkg/PlatformCI/.azurepipelines/Ubuntu-GCC5.yml index 5fa7518d2c5e..f39d52aed541 100644 --- a/ArmVirtPkg/PlatformCI/.azurepipelines/Ubuntu-GCC5.yml +++ b/ArmVirtPkg/PlatformCI/.azurepipelines/Ubuntu-GCC5.yml @@ -72,6 +72,49 @@ jobs: Run.Flags: $(run_flags)=0D Run: $(should_run)=0D =0D + QEMU_KERNEL_AARCH64_DEBUG:=0D + Build.File: "$(package)/PlatformCI/QemuKernelBuild.py"=0D + Build.Arch: "AARCH64"=0D + Build.Flags: ""=0D + Build.Target: "DEBUG"=0D + Run.Flags: $(run_flags)=0D + Run: $(should_run)=0D + QEMU_KERNEL_AARCH64_RELEASE:=0D + Build.File: "$(package)/PlatformCI/QemuKernelBuild.py"=0D + Build.Arch: "AARCH64"=0D + Build.Flags: ""=0D + Build.Target: "RELEASE"=0D + Run.Flags: $(run_flags)=0D + Run: $(should_run)=0D + QEMU_KERNEL_AARCH64_NOOPT:=0D + Build.File: "$(package)/PlatformCI/QemuKernelBuild.py"=0D + Build.Arch: "AARCH64"=0D + Build.Flags: ""=0D + Build.Target: "NOOPT"=0D + Run.Flags: $(run_flags)=0D + Run: $(should_run)=0D + QEMU_KERNEL_ARM_DEBUG:=0D + Build.File: "$(package)/PlatformCI/QemuKernelBuild.py"=0D + Build.Arch: "ARM"=0D + Build.Flags: ""=0D + Build.Target: "DEBUG"=0D + Run.Flags: $(run_flags)=0D + Run: $(should_run)=0D + QEMU_KERNEL_ARM_RELEASE:=0D + Build.File: "$(package)/PlatformCI/QemuKernelBuild.py"=0D + Build.Arch: "ARM"=0D + Build.Flags: ""=0D + Build.Target: "RELEASE"=0D + Run.Flags: $(run_flags)=0D + Run: $(should_run)=0D + QEMU_KERNEL_ARM_NOOPT:=0D + Build.File: "$(package)/PlatformCI/QemuKernelBuild.py"=0D + Build.Arch: "ARM"=0D + Build.Flags: ""=0D + Build.Target: "NOOPT"=0D + Run.Flags: $(run_flags)=0D + Run: $(should_run)=0D +=0D workspace:=0D clean: all=0D =0D diff --git a/ArmVirtPkg/PlatformCI/QemuKernelBuild.py b/ArmVirtPkg/Platform= CI/QemuKernelBuild.py new file mode 100644 index 000000000000..1c652478cb41 --- /dev/null +++ b/ArmVirtPkg/PlatformCI/QemuKernelBuild.py @@ -0,0 +1,268 @@ +# @file=0D +# Script to Build ArmVirtPkg UEFI firmware=0D +#=0D +# Copyright (c) Microsoft Corporation.=0D +# SPDX-License-Identifier: BSD-2-Clause-Patent=0D +##=0D +import os=0D +import logging=0D +import io=0D +=0D +from edk2toolext.environment import shell_environment=0D +from edk2toolext.environment.uefi_build import UefiBuilder=0D +from edk2toolext.invocables.edk2_platform_build import BuildSettingsManage= r=0D +from edk2toolext.invocables.edk2_setup import SetupSettingsManager, Requir= edSubmodule=0D +from edk2toolext.invocables.edk2_update import UpdateSettingsManager=0D +from edk2toolext.invocables.edk2_pr_eval import PrEvalSettingsManager=0D +from edk2toollib.utility_functions import RunCmd=0D +from edk2toollib.utility_functions import GetHostInfo=0D +=0D +# ########################################################################= ############### #=0D +# Common Configuration = #=0D +# ########################################################################= ############### #=0D +=0D +=0D +class CommonPlatform():=0D + ''' Common settings for this platform. Define static data here and us= e=0D + for the different parts of stuart=0D + '''=0D + PackagesSupported =3D ("ArmVirtPkg",)=0D + ArchSupported =3D ("AARCH64", "ARM")=0D + TargetsSupported =3D ("DEBUG", "RELEASE", "NOOPT")=0D + Scopes =3D ('armvirt', 'edk2-build')=0D + WorkspaceRoot =3D os.path.realpath(os.path.join(=0D + os.path.dirname(os.path.abspath(__file__)), "..", ".."))=0D +=0D + # ####################################################################= ################### #=0D + # Configuration for Update & Setup = #=0D + # ####################################################################= ################### #=0D +=0D +=0D +class SettingsManager(UpdateSettingsManager, SetupSettingsManager, PrEvalS= ettingsManager):=0D +=0D + def GetPackagesSupported(self):=0D + ''' return iterable of edk2 packages supported by this build.=0D + These should be edk2 workspace relative paths '''=0D + return CommonPlatform.PackagesSupported=0D +=0D + def GetArchitecturesSupported(self):=0D + ''' return iterable of edk2 architectures supported by this build = '''=0D + return CommonPlatform.ArchSupported=0D +=0D + def GetTargetsSupported(self):=0D + ''' return iterable of edk2 target tags supported by this build ''= '=0D + return CommonPlatform.TargetsSupported=0D +=0D + def GetRequiredSubmodules(self):=0D + ''' return iterable containing RequiredSubmodule objects.=0D + If no RequiredSubmodules return an empty iterable=0D + '''=0D + rs =3D []=0D +=0D + # intentionally declare this one with recursive false to avoid ove= rhead=0D + rs.append(RequiredSubmodule(=0D + "CryptoPkg/Library/OpensslLib/openssl", False))=0D +=0D + # To avoid maintenance of this file for every new submodule=0D + # lets just parse the .gitmodules and add each if not already in l= ist.=0D + # The GetRequiredSubmodules is designed to allow a build to optimi= ze=0D + # the desired submodules but it isn't necessary for this repositor= y.=0D + result =3D io.StringIO()=0D + ret =3D RunCmd("git", "config --file .gitmodules --get-regexp path= ", workingdir=3Dself.GetWorkspaceRoot(), outstream=3Dresult)=0D + # Cmd output is expected to look like:=0D + # submodule.CryptoPkg/Library/OpensslLib/openssl.path CryptoPkg/Li= brary/OpensslLib/openssl=0D + # submodule.SoftFloat.path ArmPkg/Library/ArmSoftFloatLib/berkeley= -softfloat-3=0D + if ret =3D=3D 0:=0D + for line in result.getvalue().splitlines():=0D + _, _, path =3D line.partition(" ")=0D + if path is not None:=0D + if path not in [x.path for x in rs]:=0D + rs.append(RequiredSubmodule(path, True)) # add it = with recursive since we don't know=0D + return rs=0D +=0D + def SetArchitectures(self, list_of_requested_architectures):=0D + ''' Confirm the requests architecture list is valid and configure = SettingsManager=0D + to run only the requested architectures.=0D +=0D + Raise Exception if a list_of_requested_architectures is not suppor= ted=0D + '''=0D + unsupported =3D set(list_of_requested_architectures) - \=0D + set(self.GetArchitecturesSupported())=0D + if(len(unsupported) > 0):=0D + errorString =3D (=0D + "Unsupported Architecture Requested: " + " ".join(unsuppor= ted))=0D + logging.critical(errorString)=0D + raise Exception(errorString)=0D + self.ActualArchitectures =3D list_of_requested_architectures=0D +=0D + def GetWorkspaceRoot(self):=0D + ''' get WorkspacePath '''=0D + return CommonPlatform.WorkspaceRoot=0D +=0D + def GetActiveScopes(self):=0D + ''' return tuple containing scopes that should be active for this = process '''=0D +=0D + scopes =3D CommonPlatform.Scopes=0D + ActualToolChainTag =3D shell_environment.GetBuildVars().GetValue("= TOOL_CHAIN_TAG", "")=0D +=0D + if GetHostInfo().os.upper() =3D=3D "LINUX" and ActualToolChainTag.= upper().startswith("GCC"):=0D + if "AARCH64" in self.ActualArchitectures:=0D + scopes +=3D ("gcc_aarch64_linux",)=0D + if "ARM" in self.ActualArchitectures:=0D + scopes +=3D ("gcc_arm_linux",)=0D + return scopes=0D +=0D + def FilterPackagesToTest(self, changedFilesList: list, potentialPackag= esList: list) -> list:=0D + ''' Filter other cases that this package should be built=0D + based on changed files. This should cover things that can't=0D + be detected as dependencies. '''=0D + build_these_packages =3D []=0D + possible_packages =3D potentialPackagesList.copy()=0D + for f in changedFilesList:=0D + # BaseTools files that might change the build=0D + if "BaseTools" in f:=0D + if os.path.splitext(f) not in [".txt", ".md"]:=0D + build_these_packages =3D possible_packages=0D + break=0D +=0D + # if the azure pipeline platform template file changed=0D + if "platform-build-run-steps.yml" in f:=0D + build_these_packages =3D possible_packages=0D + break=0D +=0D +=0D + return build_these_packages=0D +=0D + def GetPlatformDscAndConfig(self) -> tuple:=0D + ''' If a platform desires to provide its DSC then Policy 4 will ev= aluate if=0D + any of the changes will be built in the dsc.=0D +=0D + The tuple should be (, )=0D + '''=0D + return (os.path.join("ArmVirtPkg", "ArmVirtQemuKernel.dsc"), {})=0D +=0D +=0D + # ####################################################################= ################### #=0D + # Actual Configuration for Platform Build = #=0D + # ####################################################################= ################### #=0D +=0D +=0D +class PlatformBuilder(UefiBuilder, BuildSettingsManager):=0D + def __init__(self):=0D + UefiBuilder.__init__(self)=0D +=0D + def AddCommandLineOptions(self, parserObj):=0D + ''' Add command line options to the argparser '''=0D + parserObj.add_argument('-a', "--arch", dest=3D"build_arch", type= =3Dstr, default=3D"AARCH64",=0D + help=3D"Optional - Architecture to build. = Default =3D AARCH64")=0D +=0D + def RetrieveCommandLineOptions(self, args):=0D + ''' Retrieve command line options from the argparser '''=0D +=0D + shell_environment.GetBuildVars().SetValue(=0D + "TARGET_ARCH", args.build_arch.upper(), "From CmdLine")=0D +=0D + shell_environment.GetBuildVars().SetValue(=0D + "ACTIVE_PLATFORM", "ArmVirtPkg/ArmVirtQemuKernel.dsc", "From C= mdLine")=0D +=0D + def GetWorkspaceRoot(self):=0D + ''' get WorkspacePath '''=0D + return CommonPlatform.WorkspaceRoot=0D +=0D + def GetPackagesPath(self):=0D + ''' Return a list of workspace relative paths that should be mappe= d as edk2 PackagesPath '''=0D + return ()=0D +=0D + def GetActiveScopes(self):=0D + ''' return tuple containing scopes that should be active for this = process '''=0D + scopes =3D CommonPlatform.Scopes=0D + ActualToolChainTag =3D shell_environment.GetBuildVars().GetValue("= TOOL_CHAIN_TAG", "")=0D + Arch =3D shell_environment.GetBuildVars().GetValue("TARGET_ARCH", = "")=0D +=0D + if GetHostInfo().os.upper() =3D=3D "LINUX" and ActualToolChainTag.= upper().startswith("GCC"):=0D + if "AARCH64" =3D=3D Arch:=0D + scopes +=3D ("gcc_aarch64_linux",)=0D + elif "ARM" =3D=3D Arch:=0D + scopes +=3D ("gcc_arm_linux",)=0D + return scopes=0D +=0D + def GetName(self):=0D + ''' Get the name of the repo, platform, or product being build '''= =0D + ''' Used for naming the log file, among others '''=0D + # check the startup nsh flag and if set then rename the log file.= =0D + # this helps in CI so we don't overwrite the build log since runni= ng=0D + # uses the stuart_build command.=0D + if(shell_environment.GetBuildVars().GetValue("MAKE_STARTUP_NSH", "= FALSE") =3D=3D "TRUE"):=0D + return "ArmVirtPkg_With_Run"=0D + return "ArmVirtPkg"=0D +=0D + def GetLoggingLevel(self, loggerType):=0D + ''' Get the logging level for a given type=0D + base =3D=3D lowest logging level supported=0D + con =3D=3D Screen logging=0D + txt =3D=3D plain text file logging=0D + md =3D=3D markdown file logging=0D + '''=0D + return logging.DEBUG=0D +=0D + def SetPlatformEnv(self):=0D + logging.debug("PlatformBuilder SetPlatformEnv")=0D + self.env.SetValue("PRODUCT_NAME", "ArmVirtQemuKernel", "Platform H= ardcoded")=0D + self.env.SetValue("MAKE_STARTUP_NSH", "FALSE", "Default to false")= =0D + self.env.SetValue("QEMU_HEADLESS", "FALSE", "Default to false")=0D + return 0=0D +=0D + def PlatformPreBuild(self):=0D + return 0=0D +=0D + def PlatformPostBuild(self):=0D + return 0=0D +=0D + def FlashRomImage(self):=0D + VirtualDrive =3D os.path.join(self.env.GetValue(=0D + "BUILD_OUTPUT_BASE"), "VirtualDrive")=0D + os.makedirs(VirtualDrive, exist_ok=3DTrue)=0D + OutputPath_FV =3D os.path.join(=0D + self.env.GetValue("BUILD_OUTPUT_BASE"), "FV")=0D + Built_FV =3D os.path.join(OutputPath_FV, "QEMU_EFI.fd")=0D +=0D + # Unique Command and Args parameters per ARCH=0D + if (self.env.GetValue("TARGET_ARCH").upper() =3D=3D "AARCH64"):=0D + cmd =3D "qemu-system-aarch64"=0D + args =3D "-M virt"=0D + args +=3D " -cpu cortex-a57" = # emulate cpu=0D + elif(self.env.GetValue("TARGET_ARCH").upper() =3D=3D "ARM"):=0D + cmd =3D "qemu-system-arm"=0D + args =3D "-M virt,highmem=3Doff"=0D + args +=3D " -cpu cortex-a15" = # emulate cpu=0D + else:=0D + raise NotImplementedError()=0D +=0D + # Common Args=0D + args +=3D " -kernel " + Built_FV = # path to fw=0D + args +=3D " -m 1024" = # 1gb memory=0D + # turn off network=0D + args +=3D " -net none"=0D + # Serial messages out=0D + args +=3D " -serial stdio"=0D + # Mount disk with startup.nsh=0D + args +=3D f" -drive file=3Dfat:rw:{VirtualDrive},format=3Draw,medi= a=3Ddisk"=0D +=0D + # Conditional Args=0D + if (self.env.GetValue("QEMU_HEADLESS").upper() =3D=3D "TRUE"):=0D + args +=3D " -display none" # no graphics=0D +=0D + if (self.env.GetValue("MAKE_STARTUP_NSH").upper() =3D=3D "TRUE"):= =0D + f =3D open(os.path.join(VirtualDrive, "startup.nsh"), "w")=0D + f.write("BOOT SUCCESS !!! \n")=0D + # add commands here=0D + f.write("reset -s\n")=0D + f.close()=0D +=0D + ret =3D RunCmd(cmd, args)=0D +=0D + if ret =3D=3D 0xc0000005:=0D + # for some reason getting a c0000005 on successful return=0D + return 0=0D +=0D + return ret=0D --=20 2.39.0