ArmVirtPkg: Add Platform CI and configuration for Core CI
REF:https://bugzilla.tianocore.org/show_bug.cgi?id=2570 Add new Azure Pipeline definitions to build and run ArmVirtPkg with: * Ubuntu GCC5 Add PyTool based build of ArmVirtPkg Add extdep for managing the iasl dependency Add ArmVirtPkg.ci.yaml for Core CI Add ReadMe.md for details and instructions Cc: Laszlo Ersek <lersek@redhat.com> Cc: Ard Biesheuvel <ard.biesheuvel@arm.com> Cc: Leif Lindholm <leif@nuviainc.com> Signed-off-by: Michael Kubacki <michael.kubacki@microsoft.com> Reviewed-by: Shenglei Zhang <shenglei.zhang@intel.com> Acked-by: Laszlo Ersek <lersek@redhat.com> Acked-by: Ard Biesheuvel <ard.biesheuvel@arm.com> Reviewed-by: Bret Barkelew <bret.barkelew@microsoft.com>
This commit is contained in:
		
				
					committed by
					
						![mergify[bot]](/avatar/e3df20cd7a67969c41a65f03bea54961?size=40) mergify[bot]
						mergify[bot]
					
				
			
			
				
	
			
			
			
						parent
						
							4fcfd089aa
						
					
				
				
					commit
					0c7f189e60
				
			
							
								
								
									
										103
									
								
								ArmVirtPkg/ArmVirtPkg.ci.yaml
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										103
									
								
								ArmVirtPkg/ArmVirtPkg.ci.yaml
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,103 @@ | ||||
| ## @file | ||||
| # Core CI configuration for ArmVirtPkg | ||||
| # | ||||
| # ArmVirtPkg is part of Platform Ci for builds so this is only | ||||
| # used for code analysis. | ||||
| # | ||||
| # Copyright (c) Microsoft Corporation | ||||
| # SPDX-License-Identifier: BSD-2-Clause-Patent | ||||
| ## | ||||
| { | ||||
|     ## options defined .pytool/Plugin/CompilerPlugin | ||||
|     "CompilerPlugin": { | ||||
|         "DscPath": "" # Don't support this test | ||||
|     }, | ||||
|  | ||||
|     ## options defined .pytool/Plugin/HostUnitTestCompilerPlugin | ||||
|     "HostUnitTestCompilerPlugin": { | ||||
|         "DscPath": "" # Don't support this test | ||||
|     }, | ||||
|  | ||||
|     ## options defined .pytool/Plugin/CharEncodingCheck | ||||
|     "CharEncodingCheck": { | ||||
|         "IgnoreFiles": [] | ||||
|     }, | ||||
|  | ||||
|     ## options defined .pytool/Plugin/DependencyCheck | ||||
|     "DependencyCheck": { | ||||
|         "AcceptableDependencies": [ | ||||
|             "MdePkg/MdePkg.dec", | ||||
|             "MdeModulePkg/MdeModulePkg.dec", | ||||
|             "ArmVirtPkg/ArmVirtPkg.dec", | ||||
|             "NetworkPkg/NetworkPkg.dec", | ||||
|             "ArmPkg/ArmPkg.dec", | ||||
|             "OvmfPkg/OvmfPkg.dec", | ||||
|             "EmbeddedPkg/EmbeddedPkg.dec", | ||||
|             "ArmPlatformPkg/ArmPlatformPkg.dec", | ||||
|             "SecurityPkg/SecurityPkg.dec", | ||||
|             "ShellPkg/ShellPkg.dec"  #Is this ok? | ||||
|         ], | ||||
|         # For host based unit tests | ||||
|         "AcceptableDependencies-HOST_APPLICATION":[ | ||||
|             "UnitTestFrameworkPkg/UnitTestFrameworkPkg.dec" | ||||
|         ], | ||||
|         # For UEFI shell based apps | ||||
|         "AcceptableDependencies-UEFI_APPLICATION":[ | ||||
|  | ||||
|         ], | ||||
|         "IgnoreInf": [] | ||||
|     }, | ||||
|  | ||||
|     ## options defined .pytool/Plugin/DscCompleteCheck | ||||
|     "DscCompleteCheck": { | ||||
|         "IgnoreInf": [""], | ||||
|         "DscPath": ""  # Don't support this test | ||||
|     }, | ||||
|  | ||||
|     ## options defined .pytool/Plugin/HostUnitTestDscCompleteCheck | ||||
|     "HostUnitTestDscCompleteCheck": { | ||||
|         "IgnoreInf": [""], | ||||
|         "DscPath": "" # Don't support this test | ||||
|     }, | ||||
|  | ||||
|     ## options defined .pytool/Plugin/GuidCheck | ||||
|     "GuidCheck": { | ||||
|         "IgnoreGuidName": [], | ||||
|         "IgnoreGuidValue": [], | ||||
|         "IgnoreFoldersAndFiles": [], | ||||
|         "IgnoreDuplicates": [], | ||||
|     }, | ||||
|  | ||||
|     ## options defined .pytool/Plugin/LibraryClassCheck | ||||
|     "LibraryClassCheck": { | ||||
|         "IgnoreHeaderFile": [] | ||||
|     }, | ||||
|  | ||||
|     ## options defined .pytool/Plugin/SpellCheck | ||||
|     "SpellCheck": { | ||||
|         "AuditOnly": False,           # Fails right now with over 270 errors | ||||
|         "IgnoreFiles": [],           # use gitignore syntax to ignore errors in matching files | ||||
|         "ExtendWords": [ | ||||
|             "setjump", | ||||
|             "plong", | ||||
|             "lparam", | ||||
|             "lpdword", | ||||
|             "lpthread", | ||||
|             "lresult", | ||||
|             "bootable", | ||||
|             "bsymbolic", | ||||
|             "endiannness", | ||||
|             "fvmain", | ||||
|             "multiboot", | ||||
|             "qemu's", | ||||
|             "ramdisk", | ||||
|             "ramfb", | ||||
|             "unbootable", | ||||
|             "virt's", | ||||
|             "werror", | ||||
|             "xenio" | ||||
|         ],           # words to extend to the dictionary for this package | ||||
|         "IgnoreStandardPaths": [],   # Standard Plugin defined paths that should be ignore | ||||
|         "AdditionalIncludePaths": [] # Additional paths to spell check (wildcards supported) | ||||
|     } | ||||
| } | ||||
							
								
								
									
										89
									
								
								ArmVirtPkg/PlatformCI/.azurepipelines/Ubuntu-GCC5.yml
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										89
									
								
								ArmVirtPkg/PlatformCI/.azurepipelines/Ubuntu-GCC5.yml
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,89 @@ | ||||
| ## @file | ||||
| # Azure Pipeline build file for building a platform. | ||||
| # | ||||
| # Platform: ArmVirtQemu | ||||
| # OS: Ubuntu | ||||
| # Toolchain: GCC5 | ||||
| # | ||||
| # Copyright (c) Microsoft Corporation. | ||||
| # SPDX-License-Identifier: BSD-2-Clause-Patent | ||||
| ## | ||||
| trigger: | ||||
|   - master | ||||
| pr: | ||||
|   - master | ||||
|  | ||||
| jobs: | ||||
|   - job: Platform_CI | ||||
|     variables: | ||||
|       package: 'ArmVirtPkg' | ||||
|       vm_image: 'ubuntu-latest' | ||||
|       should_run: true | ||||
|       run_flags: "MAKE_STARTUP_NSH=TRUE QEMU_HEADLESS=TRUE" | ||||
|  | ||||
|     #Use matrix to speed up the build process | ||||
|     strategy: | ||||
|         matrix: | ||||
|           QEMU_AARCH64_DEBUG: | ||||
|             Build.File: "$(package)/PlatformCI/PlatformBuild.py" | ||||
|             Build.Arch: "AARCH64" | ||||
|             Build.Flags: "" | ||||
|             Build.Target: "DEBUG" | ||||
|             Run.Flags: $(run_flags) | ||||
|             Run: $(should_run) | ||||
|           QEMU_AARCH64_RELEASE: | ||||
|             Build.File: "$(package)/PlatformCI/PlatformBuild.py" | ||||
|             Build.Arch: "AARCH64" | ||||
|             Build.Flags: "" | ||||
|             Build.Target: "RELEASE" | ||||
|             Run.Flags: $(run_flags) | ||||
|             Run: $(should_run) | ||||
|           QEMU_AARCH64_NOOPT: | ||||
|             Build.File: "$(package)/PlatformCI/PlatformBuild.py" | ||||
|             Build.Arch: "AARCH64" | ||||
|             Build.Flags: "" | ||||
|             Build.Target: "NOOPT" | ||||
|             Run.Flags: $(run_flags) | ||||
|             Run: $(should_run) | ||||
|           QEMU_ARM_DEBUG: | ||||
|             Build.File: "$(package)/PlatformCI/PlatformBuild.py" | ||||
|             Build.Arch: "ARM" | ||||
|             Build.Flags: "" | ||||
|             Build.Target: "DEBUG" | ||||
|             Run.Flags: $(run_flags) | ||||
|             Run: $(should_run) | ||||
|           QEMU_ARM_RELEASE: | ||||
|             Build.File: "$(package)/PlatformCI/PlatformBuild.py" | ||||
|             Build.Arch: "ARM" | ||||
|             Build.Flags: "" | ||||
|             Build.Target: "RELEASE" | ||||
|             Run.Flags: $(run_flags) | ||||
|             Run: $(should_run) | ||||
|           QEMU_ARM_NOOPT: | ||||
|             Build.File: "$(package)/PlatformCI/PlatformBuild.py" | ||||
|             Build.Arch: "ARM" | ||||
|             Build.Flags: "" | ||||
|             Build.Target: "NOOPT" | ||||
|             Run.Flags: $(run_flags) | ||||
|             Run: $(should_run) | ||||
|  | ||||
|     workspace: | ||||
|       clean: all | ||||
|  | ||||
|     pool: | ||||
|       vmImage: $(vm_image) | ||||
|  | ||||
|     steps: | ||||
|     - template: ../../../.azurepipelines/templates/platform-build-run-steps.yml | ||||
|       parameters: | ||||
|         tool_chain_tag: GCC5 | ||||
|         build_pkg: $(package) | ||||
|         build_target: $(Build.Target) | ||||
|         build_arch: $(Build.Arch) | ||||
|         build_file: $(Build.File) | ||||
|         build_flags: $(Build.Flags) | ||||
|         run_flags: $(Run.Flags) | ||||
|         extra_install_step: | ||||
|         - bash: sudo apt-get install qemu | ||||
|           displayName: Install qemu | ||||
|           condition: and(gt(variables.pkg_count, 0), succeeded()) | ||||
							
								
								
									
										276
									
								
								ArmVirtPkg/PlatformCI/PlatformBuild.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										276
									
								
								ArmVirtPkg/PlatformCI/PlatformBuild.py
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,276 @@ | ||||
| # @file | ||||
| # Script to Build ArmVirtPkg UEFI firmware | ||||
| # | ||||
| # Copyright (c) Microsoft Corporation. | ||||
| # SPDX-License-Identifier: BSD-2-Clause-Patent | ||||
| ## | ||||
| import os | ||||
| import logging | ||||
| import io | ||||
|  | ||||
| from edk2toolext.environment import shell_environment | ||||
| from edk2toolext.environment.uefi_build import UefiBuilder | ||||
| from edk2toolext.invocables.edk2_platform_build import BuildSettingsManager | ||||
| from edk2toolext.invocables.edk2_setup import SetupSettingsManager, RequiredSubmodule | ||||
| from edk2toolext.invocables.edk2_update import UpdateSettingsManager | ||||
| from edk2toolext.invocables.edk2_pr_eval import PrEvalSettingsManager | ||||
| from edk2toollib.utility_functions import RunCmd | ||||
| from edk2toollib.utility_functions import GetHostInfo | ||||
|  | ||||
| # ####################################################################################### # | ||||
| #                                Common Configuration                                     # | ||||
| # ####################################################################################### # | ||||
|  | ||||
|  | ||||
| class CommonPlatform(): | ||||
|     ''' Common settings for this platform.  Define static data here and use | ||||
|         for the different parts of stuart | ||||
|     ''' | ||||
|     PackagesSupported = ("ArmVirtPkg",) | ||||
|     ArchSupported = ("AARCH64", "ARM") | ||||
|     TargetsSupported = ("DEBUG", "RELEASE", "NOOPT") | ||||
|     Scopes = ('armvirt', 'edk2-build') | ||||
|     WorkspaceRoot = os.path.realpath(os.path.join( | ||||
|         os.path.dirname(os.path.abspath(__file__)), "..", "..")) | ||||
|  | ||||
|     # ####################################################################################### # | ||||
|     #                         Configuration for Update & Setup                                # | ||||
|     # ####################################################################################### # | ||||
|  | ||||
|  | ||||
| class SettingsManager(UpdateSettingsManager, SetupSettingsManager, PrEvalSettingsManager): | ||||
|  | ||||
|     def GetPackagesSupported(self): | ||||
|         ''' return iterable of edk2 packages supported by this build. | ||||
|         These should be edk2 workspace relative paths ''' | ||||
|         return CommonPlatform.PackagesSupported | ||||
|  | ||||
|     def GetArchitecturesSupported(self): | ||||
|         ''' return iterable of edk2 architectures supported by this build ''' | ||||
|         return CommonPlatform.ArchSupported | ||||
|  | ||||
|     def GetTargetsSupported(self): | ||||
|         ''' return iterable of edk2 target tags supported by this build ''' | ||||
|         return CommonPlatform.TargetsSupported | ||||
|  | ||||
|     def GetRequiredSubmodules(self): | ||||
|         ''' return iterable containing RequiredSubmodule objects. | ||||
|         If no RequiredSubmodules return an empty iterable | ||||
|         ''' | ||||
|         rs = [] | ||||
|  | ||||
|         # intentionally declare this one with recursive false to avoid overhead | ||||
|         rs.append(RequiredSubmodule( | ||||
|             "CryptoPkg/Library/OpensslLib/openssl", False)) | ||||
|  | ||||
|         # To avoid maintenance of this file for every new submodule | ||||
|         # lets just parse the .gitmodules and add each if not already in list. | ||||
|         # The GetRequiredSubmodules is designed to allow a build to optimize | ||||
|         # the desired submodules but it isn't necessary for this repository. | ||||
|         result = io.StringIO() | ||||
|         ret = RunCmd("git", "config --file .gitmodules --get-regexp path", workingdir=self.GetWorkspaceRoot(), outstream=result) | ||||
|         # Cmd output is expected to look like: | ||||
|         # submodule.CryptoPkg/Library/OpensslLib/openssl.path CryptoPkg/Library/OpensslLib/openssl | ||||
|         # submodule.SoftFloat.path ArmPkg/Library/ArmSoftFloatLib/berkeley-softfloat-3 | ||||
|         if ret == 0: | ||||
|             for line in result.getvalue().splitlines(): | ||||
|                 _, _, path = line.partition(" ") | ||||
|                 if path is not None: | ||||
|                     if path not in [x.path for x in rs]: | ||||
|                         rs.append(RequiredSubmodule(path, True)) # add it with recursive since we don't know | ||||
|         return rs | ||||
|  | ||||
|     def SetArchitectures(self, list_of_requested_architectures): | ||||
|         ''' Confirm the requests architecture list is valid and configure SettingsManager | ||||
|         to run only the requested architectures. | ||||
|  | ||||
|         Raise Exception if a list_of_requested_architectures is not supported | ||||
|         ''' | ||||
|         unsupported = set(list_of_requested_architectures) - \ | ||||
|             set(self.GetArchitecturesSupported()) | ||||
|         if(len(unsupported) > 0): | ||||
|             errorString = ( | ||||
|                 "Unsupported Architecture Requested: " + " ".join(unsupported)) | ||||
|             logging.critical(errorString) | ||||
|             raise Exception(errorString) | ||||
|         self.ActualArchitectures = list_of_requested_architectures | ||||
|  | ||||
|     def GetWorkspaceRoot(self): | ||||
|         ''' get WorkspacePath ''' | ||||
|         return CommonPlatform.WorkspaceRoot | ||||
|  | ||||
|     def GetActiveScopes(self): | ||||
|         ''' return tuple containing scopes that should be active for this process ''' | ||||
|  | ||||
|         scopes = CommonPlatform.Scopes | ||||
|         ActualToolChainTag = shell_environment.GetBuildVars().GetValue("TOOL_CHAIN_TAG", "") | ||||
|  | ||||
|         if GetHostInfo().os.upper() == "LINUX" and ActualToolChainTag.upper().startswith("GCC"): | ||||
|             if "AARCH64" in self.ActualArchitectures: | ||||
|                 scopes += ("gcc_aarch64_linux",) | ||||
|             if "ARM" in self.ActualArchitectures: | ||||
|                 scopes += ("gcc_arm_linux",) | ||||
|         return scopes | ||||
|  | ||||
|     def FilterPackagesToTest(self, changedFilesList: list, potentialPackagesList: list) -> list: | ||||
|         ''' Filter other cases that this package should be built | ||||
|         based on changed files. This should cover things that can't | ||||
|         be detected as dependencies. ''' | ||||
|         build_these_packages = [] | ||||
|         possible_packages = potentialPackagesList.copy() | ||||
|         for f in changedFilesList: | ||||
|             # BaseTools files that might change the build | ||||
|             if "BaseTools" in f: | ||||
|                 if os.path.splitext(f) not in [".txt", ".md"]: | ||||
|                     build_these_packages = possible_packages | ||||
|                     break | ||||
|  | ||||
|             # if the azure pipeline platform template file changed | ||||
|             if "platform-build-run-steps.yml" in f: | ||||
|                 build_these_packages = possible_packages | ||||
|                 break | ||||
|  | ||||
|  | ||||
|         return build_these_packages | ||||
|  | ||||
|     def GetPlatformDscAndConfig(self) -> tuple: | ||||
|         ''' If a platform desires to provide its DSC then Policy 4 will evaluate if | ||||
|         any of the changes will be built in the dsc. | ||||
|  | ||||
|         The tuple should be (<workspace relative path to dsc file>, <input dictionary of dsc key value pairs>) | ||||
|         ''' | ||||
|         return (os.path.join("ArmVirtPkg", "ArmVirtQemu.dsc"), {}) | ||||
|  | ||||
|  | ||||
|     # ####################################################################################### # | ||||
|     #                         Actual Configuration for Platform Build                         # | ||||
|     # ####################################################################################### # | ||||
|  | ||||
|  | ||||
| class PlatformBuilder(UefiBuilder, BuildSettingsManager): | ||||
|     def __init__(self): | ||||
|         UefiBuilder.__init__(self) | ||||
|  | ||||
|     def AddCommandLineOptions(self, parserObj): | ||||
|         ''' Add command line options to the argparser ''' | ||||
|         parserObj.add_argument('-a', "--arch", dest="build_arch", type=str, default="AARCH64", | ||||
|                                help="Optional - Architecture to build.  Default = AARCH64") | ||||
|  | ||||
|     def RetrieveCommandLineOptions(self, args): | ||||
|         '''  Retrieve command line options from the argparser ''' | ||||
|  | ||||
|         shell_environment.GetBuildVars().SetValue( | ||||
|             "TARGET_ARCH", args.build_arch.upper(), "From CmdLine") | ||||
|  | ||||
|         shell_environment.GetBuildVars().SetValue( | ||||
|             "ACTIVE_PLATFORM", "ArmVirtPkg/ArmVirtQemu.dsc", "From CmdLine") | ||||
|  | ||||
|     def GetWorkspaceRoot(self): | ||||
|         ''' get WorkspacePath ''' | ||||
|         return CommonPlatform.WorkspaceRoot | ||||
|  | ||||
|     def GetPackagesPath(self): | ||||
|         ''' Return a list of workspace relative paths that should be mapped as edk2 PackagesPath ''' | ||||
|         return () | ||||
|  | ||||
|     def GetActiveScopes(self): | ||||
|         ''' return tuple containing scopes that should be active for this process ''' | ||||
|         scopes = CommonPlatform.Scopes | ||||
|         ActualToolChainTag = shell_environment.GetBuildVars().GetValue("TOOL_CHAIN_TAG", "") | ||||
|         Arch = shell_environment.GetBuildVars().GetValue("TARGET_ARCH", "") | ||||
|  | ||||
|         if GetHostInfo().os.upper() == "LINUX" and ActualToolChainTag.upper().startswith("GCC"): | ||||
|             if "AARCH64" == Arch: | ||||
|                 scopes += ("gcc_aarch64_linux",) | ||||
|             elif "ARM" == Arch: | ||||
|                 scopes += ("gcc_arm_linux",) | ||||
|         return scopes | ||||
|  | ||||
|     def GetName(self): | ||||
|         ''' Get the name of the repo, platform, or product being build ''' | ||||
|         ''' Used for naming the log file, among others ''' | ||||
|         # check the startup nsh flag and if set then rename the log file. | ||||
|         # this helps in CI so we don't overwrite the build log since running | ||||
|         # uses the stuart_build command. | ||||
|         if(shell_environment.GetBuildVars().GetValue("MAKE_STARTUP_NSH", "FALSE") == "TRUE"): | ||||
|             return "ArmVirtPkg_With_Run" | ||||
|         return "ArmVirtPkg" | ||||
|  | ||||
|     def GetLoggingLevel(self, loggerType): | ||||
|         ''' Get the logging level for a given type | ||||
|         base == lowest logging level supported | ||||
|         con  == Screen logging | ||||
|         txt  == plain text file logging | ||||
|         md   == markdown file logging | ||||
|         ''' | ||||
|         return logging.DEBUG | ||||
|  | ||||
|     def SetPlatformEnv(self): | ||||
|         logging.debug("PlatformBuilder SetPlatformEnv") | ||||
|         self.env.SetValue("PRODUCT_NAME", "ArmVirtQemu", "Platform Hardcoded") | ||||
|         self.env.SetValue("MAKE_STARTUP_NSH", "FALSE", "Default to false") | ||||
|         self.env.SetValue("QEMU_HEADLESS", "FALSE", "Default to false") | ||||
|         return 0 | ||||
|  | ||||
|     def PlatformPreBuild(self): | ||||
|         return 0 | ||||
|  | ||||
|     def PlatformPostBuild(self): | ||||
|         return 0 | ||||
|  | ||||
|     def FlashRomImage(self): | ||||
|         VirtualDrive = os.path.join(self.env.GetValue( | ||||
|             "BUILD_OUTPUT_BASE"), "VirtualDrive") | ||||
|         os.makedirs(VirtualDrive, exist_ok=True) | ||||
|         OutputPath_FV = os.path.join( | ||||
|             self.env.GetValue("BUILD_OUTPUT_BASE"), "FV") | ||||
|         Built_FV = os.path.join(OutputPath_FV, "QEMU_EFI.fd") | ||||
|  | ||||
|         # pad fd to 64mb | ||||
|         with open(Built_FV, "ab") as fvfile: | ||||
|             fvfile.seek(0, os.SEEK_END) | ||||
|             additional = b'\0' * ((64 * 1024 * 1024)-fvfile.tell()) | ||||
|             fvfile.write(additional) | ||||
|  | ||||
|         # QEMU must be on that path | ||||
|  | ||||
|         # Unique Command and Args parameters per ARCH | ||||
|         if (self.env.GetValue("TARGET_ARCH").upper() == "AARCH64"): | ||||
|             cmd = "qemu-system-aarch64" | ||||
|             args = "-M virt" | ||||
|             args += " -cpu cortex-a57"                                          # emulate cpu | ||||
|         elif(self.env.GetValue("TARGET_ARCH").upper() == "ARM"): | ||||
|             cmd = "qemu-system-arm" | ||||
|             args = "-M virt" | ||||
|             args += " -cpu cortex-a15"                                          # emulate cpu | ||||
|         else: | ||||
|             raise NotImplementedError() | ||||
|  | ||||
|         # Common Args | ||||
|         args += " -pflash " + Built_FV                                     # path to fw | ||||
|         args += " -m 1024"                                                  # 1gb memory | ||||
|         # turn off network | ||||
|         args += " -net none" | ||||
|         # Serial messages out | ||||
|         args += " -serial stdio" | ||||
|         # Mount disk with startup.nsh | ||||
|         args += f" -drive file=fat:rw:{VirtualDrive},format=raw,media=disk" | ||||
|  | ||||
|         # Conditional Args | ||||
|         if (self.env.GetValue("QEMU_HEADLESS").upper() == "TRUE"): | ||||
|             args += " -display none"  # no graphics | ||||
|  | ||||
|         if (self.env.GetValue("MAKE_STARTUP_NSH").upper() == "TRUE"): | ||||
|             f = open(os.path.join(VirtualDrive, "startup.nsh"), "w") | ||||
|             f.write("BOOT SUCCESS !!! \n") | ||||
|             # add commands here | ||||
|             f.write("reset -s\n") | ||||
|             f.close() | ||||
|  | ||||
|         ret = RunCmd(cmd, args) | ||||
|  | ||||
|         if ret == 0xc0000005: | ||||
|             # for some reason getting a c0000005 on successful return | ||||
|             return 0 | ||||
|  | ||||
|         return ret | ||||
							
								
								
									
										125
									
								
								ArmVirtPkg/PlatformCI/ReadMe.md
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										125
									
								
								ArmVirtPkg/PlatformCI/ReadMe.md
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,125 @@ | ||||
| # ArmVirtPkg - Platform CI | ||||
|  | ||||
| This Readme.md describes the Azure DevOps based Platform CI for ArmVirtPkg and how | ||||
| to use the same Pytools based build infrastructure locally. | ||||
|  | ||||
| ## Supported Configuration Details | ||||
|  | ||||
| This solution for building and running ArmVirtPkg has only been validated with Ubuntu | ||||
| 18.04 and the GCC5 toolchain. Two different firmware builds are supported and are | ||||
| described below. | ||||
|  | ||||
| | Configuration name      | Architecture       | DSC File         |Additional Flags | | ||||
| | :----------             | :-----             | :-----           | :----           | | ||||
| | AARCH64                 | AARCH64            | ArmVirtQemu.dsc  | None            | | ||||
| | ARM                     | ARM                | ArmVirtQemu.dsc  | None            | | ||||
|  | ||||
| ## EDK2 Developer environment | ||||
|  | ||||
| - [Python 3.8.x - Download & Install](https://www.python.org/downloads/) | ||||
| - [GIT - Download & Install](https://git-scm.com/download/) | ||||
| - [QEMU - Download, Install, and add to your path](https://www.qemu.org/download/) | ||||
| - [Edk2 Source](https://github.com/tianocore/edk2) | ||||
| - Additional packages found necessary for Ubuntu 18.04 | ||||
|   - apt-get install gcc g++ make uuid-dev | ||||
|  | ||||
| Note: edksetup, Submodule initialization and manual installation of NASM, iASL, or | ||||
| the required cross-compiler toolchains are **not** required, this is handled by the | ||||
| Pytools build system. | ||||
|  | ||||
| ## Building with Pytools for ArmVirtPkg | ||||
|  | ||||
| 1. [Optional] Create a Python Virtual Environment - generally once per workspace | ||||
|  | ||||
|     ``` bash | ||||
|     python -m venv <name of virtual environment> | ||||
|     ``` | ||||
|  | ||||
| 2. [Optional] Activate Virtual Environment - each time new shell opened | ||||
|     - Windows | ||||
|  | ||||
|       ``` bash | ||||
|       <name of virtual environment>/Scripts/activate.bat | ||||
|       ``` | ||||
|  | ||||
|     - Linux | ||||
|  | ||||
|       ```bash | ||||
|       source <name of virtual environment>/bin/activate | ||||
|       ``` | ||||
|  | ||||
| 3. Install Pytools - generally once per virtual env or whenever pip-requirements.txt changes | ||||
|  | ||||
|     ``` bash | ||||
|     pip install --upgrade -r pip-requirements.txt | ||||
|     ``` | ||||
|  | ||||
| 4. Initialize & Update Submodules - only when submodules updated | ||||
|  | ||||
|     ``` bash | ||||
|     stuart_setup -c ArmVirtPkg/PlatformCI/PlatformBuild.py TOOL_CHAIN_TAG=<TOOL_CHAIN_TAG> -a <TARGET_ARCH> | ||||
|     ``` | ||||
|  | ||||
| 5. Initialize & Update Dependencies - only as needed when ext_deps change | ||||
|  | ||||
|     ``` bash | ||||
|     stuart_update -c ArmVirtPkg/PlatformCI/PlatformBuild.py TOOL_CHAIN_TAG=<TOOL_CHAIN_TAG> -a <TARGET_ARCH> | ||||
|     ``` | ||||
|  | ||||
| 6. Compile the basetools if necessary - only when basetools C source files change | ||||
|  | ||||
|     ``` bash | ||||
|     python BaseTools/Edk2ToolsBuild.py -t <ToolChainTag> | ||||
|     ``` | ||||
|  | ||||
| 7. Compile Firmware | ||||
|  | ||||
|     ``` bash | ||||
|     stuart_build -c ArmVirtPkg/PlatformCI/PlatformBuild.py TOOL_CHAIN_TAG=<TOOL_CHAIN_TAG> -a <TARGET_ARCH> | ||||
|     ``` | ||||
|  | ||||
|     - use `stuart_build -c ArmVirtPkg/PlatformCI/PlatformBuild.py -h` option to see additional | ||||
|     options like `--clean` | ||||
|  | ||||
| 8. Running Emulator | ||||
|     - You can add `--FlashRom` to the end of your build command and the emulator will run after the | ||||
|     build is complete. | ||||
|     - or use the `--FlashOnly` feature to just run the emulator. | ||||
|  | ||||
|       ``` bash | ||||
|       stuart_build -c ArmVirtPkg/PlatformCI/PlatformBuild.py TOOL_CHAIN_TAG=<TOOL_CHAIN_TAG> -a <TARGET_ARCH> --FlashOnly | ||||
|       ``` | ||||
|  | ||||
| ### Notes | ||||
|  | ||||
| 1. Including the expected build architecture and toolchain to the _stuart_update_ command is critical. | ||||
|    This is because there are extra scopes and tools that will be resolved during the update step that | ||||
|    need to match your build step. | ||||
| 2. Configuring *ACTIVE_PLATFORM* and *TARGET_ARCH* in Conf/target.txt is **not** required. This | ||||
|    environment is set by PlatformBuild.py based upon the `[-a <TARGET_ARCH>]` parameter. | ||||
| 3. QEMU must be on your path.  On Windows this is a manual process and not part of the QEMU installer. | ||||
|  | ||||
| **NOTE:** Logging the execution output will be in the normal stuart log as well as to your console. | ||||
|  | ||||
| ### Custom Build Options | ||||
|  | ||||
| **MAKE_STARTUP_NSH=TRUE** will output a *startup.nsh* file to the location mapped as fs0. This is | ||||
| used in CI in combination with the `--FlashOnly` feature to run QEMU to the UEFI shell and then execute | ||||
| the contents of *startup.nsh*. | ||||
|  | ||||
| **QEMU_HEADLESS=TRUE** Since CI servers run headless QEMU must be told to run with no display otherwise | ||||
| an error occurs. Locally you don't need to set this. | ||||
|  | ||||
| ### Passing Build Defines | ||||
|  | ||||
| To pass build defines through _stuart_build_, prepend `BLD_*_`to the define name and pass it on the | ||||
| command-line. _stuart_build_ currently requires values to be assigned, so add an`=1` suffix for bare defines. | ||||
| For example, to enable the TPM2 support, instead of the traditional "-D TPM2_ENABLE=TRUE", the stuart_build | ||||
| command-line would be: | ||||
|  | ||||
| `stuart_build -c ArmVirtPkg/PlatformCI/PlatformBuild.py BLD_*_TPM2_ENABLE=TRUE` | ||||
|  | ||||
| ## References | ||||
|  | ||||
| - [Installing and using Pytools](https://github.com/tianocore/edk2-pytool-extensions/blob/master/docs/using.md#installing) | ||||
| - More on [python virtual environments](https://docs.python.org/3/library/venv.html) | ||||
							
								
								
									
										21
									
								
								ArmVirtPkg/PlatformCI/iasl_ext_dep.yaml
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										21
									
								
								ArmVirtPkg/PlatformCI/iasl_ext_dep.yaml
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,21 @@ | ||||
| ## @file | ||||
| # Download iasl executable tool from a nuget.org package | ||||
| # - package contains different binaries based on host | ||||
| # Add the folder with the tool to the path | ||||
| # | ||||
| # This is only downloaded for scope armvirt thus | ||||
| # should have no impact on the asl compiler used by any | ||||
| # other platform build | ||||
| # | ||||
| # Copyright (c) Microsoft Corporation. | ||||
| # SPDX-License-Identifier: BSD-2-Clause-Patent | ||||
| ## | ||||
| { | ||||
|   "id": "iasl-armvirt-1", | ||||
|   "scope": "armvirt", | ||||
|   "type": "nuget", | ||||
|   "name": "iasl", | ||||
|   "source": "https://api.nuget.org/v3/index.json", | ||||
|   "version": "20190215.0.0", | ||||
|   "flags": ["set_path", "host_specific"], | ||||
| } | ||||
		Reference in New Issue
	
	Block a user