#!/usr/bin/env python2 # Copyright (c) 2017-2018 Metempsy Technology Consulting # All rights reserved. # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions are # met: redistributions of source code must retain the above copyright # notice, this list of conditions and the following disclaimer; # redistributions in binary form must reproduce the above copyright # notice, this list of conditions and the following disclaimer in the # documentation and/or other materials provided with the distribution; # neither the name of the copyright holders nor the names of its # contributors may be used to endorse or promote products derived from # this software without specific prior written permission. # # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR # A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT # OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, # SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT # LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. # # Authors: Pau Cabre from optparse import OptionParser from subprocess import call from platform import machine from distutils import spawn from glob import glob import sys import os def run_cmd(explanation, working_dir, cmd, stdout = None): print "Running phase '%s'" % explanation sys.stdout.flush() # some of the commands need $PWD to be properly set env = os.environ.copy() env['PWD'] = working_dir return_code = call(cmd, cwd = working_dir, stdout = stdout, env = env) if return_code == 0: return print "Error running phase %s. Returncode: %d" % (explanation, return_code) sys.exit(1) script_dir = os.path.dirname(os.path.abspath(sys.argv[0])) gem5_dir = os.path.dirname(script_dir) parser = OptionParser() parser.add_option("--gem5-dir", default = gem5_dir, metavar = "GEM5_DIR", help = "gem5 root directory to be used for bootloader and " "VExpress_GEM5_V1 DTB sources. The default value is the gem5 root " "directory of the executed script (%default)") parser.add_option("--dest-dir", default = "/tmp", metavar = "DEST_DIR", help = "Directory to use for checking out the different kernel " "repositories. Generated files will be copied to " "DEST_DIR/binaries (which must not exist). The default " "value is %default") parser.add_option("--make-jobs", type = "int", default = 1, metavar = "MAKE_JOBS", help = "Number of jobs to use with the 'make' commands. Default value: " "%default") (options, args) = parser.parse_args() if args: print "Unrecognized argument(s) %s." % args sys.exit(1) if not os.path.isdir(options.dest_dir): print "Error: %s is not a directory." % options.dest_dir sys.exit(1) if not os.path.isdir(options.gem5_dir): print "Error: %s is not a directory." % options.gem5_dir sys.exit(1) if machine() != "x86_64": print "Error: This script should run in a x86_64 machine" sys.exit(1) binaries_dir = options.dest_dir + "/binaries" if os.path.exists(binaries_dir): print "Error: %s already exists." % binaries_dir sys.exit(1) revisions_dir = options.dest_dir + "/revisions" if os.path.exists(revisions_dir): print "Error: %s already exists." %revisions_dir sys.exit(1) # Some basic dependency checking needed_programs = [ "make", "aarch64-linux-gnu-gcc", "arm-linux-gnueabihf-gcc", "aarch64-linux-gnu-gcc-4.8", "arm-linux-gnueabihf-gcc-4.8", "gcc", "bc", "dtc", "arm-linux-gnueabi-gcc" ] for program in needed_programs: if not spawn.find_executable(program): print "Error: command %s not found in $PATH" % program print ("If running on an Debian-based linux, please try the following " "cmd to get all the necessary packages: ") print ("sudo apt-get install -y make gcc bc gcc-aarch64-linux-gnu " "gcc-4.8-aarch64-linux-gnu gcc-4.8-arm-linux-gnueabihf " "gcc-arm-linux-gnueabihf device-tree-compiler " "gcc-arm-linux-gnueabi") sys.exit(1) os.mkdir(binaries_dir); os.mkdir(revisions_dir); make_jobs_str = "-j" + str(options.make_jobs) rev_file = open(revisions_dir + "/gem5", "w+") run_cmd("write revision of gem5 repo", gem5_dir, ["git", "rev-parse", "--short", "HEAD"], rev_file) rev_file.close() # Checkout and build linux kernel for VExpress_GEM5_V1 (arm and arm64) kernel_vexpress_gem5_dir = options.dest_dir + "/linux-kernel-vexpress_gem5" run_cmd("clone linux kernel for VExpress_GEM5_V1 platform", options.dest_dir, ["git", "clone", "https://gem5.googlesource.com/arm/linux", kernel_vexpress_gem5_dir]) rev_file = open(revisions_dir + "/linux", "w+") run_cmd("write revision of linux-kernel-vexpress_gem5 repo", kernel_vexpress_gem5_dir, ["git", "rev-parse", "--short", "HEAD"], rev_file) rev_file.close() run_cmd("configure kernel for arm64", kernel_vexpress_gem5_dir, ["make", "ARCH=arm64", "CROSS_COMPILE=aarch64-linux-gnu-", "gem5_defconfig", make_jobs_str]) run_cmd("compile kernel for arm64", kernel_vexpress_gem5_dir, ["make", "ARCH=arm64", "CROSS_COMPILE=aarch64-linux-gnu-", make_jobs_str]) run_cmd("copy arm64 vmlinux", kernel_vexpress_gem5_dir, ["cp", "vmlinux", binaries_dir + "/vmlinux.vexpress_gem5_v1_64"]) run_cmd("cleanup arm64 kernel compilation", kernel_vexpress_gem5_dir, ["make", "distclean"]) run_cmd("configure kernel for arm", kernel_vexpress_gem5_dir, ["make", "ARCH=arm", "CROSS_COMPILE=arm-linux-gnueabihf-", "gem5_defconfig"]) run_cmd("compile kernel for arm", kernel_vexpress_gem5_dir, ["make", "ARCH=arm", "CROSS_COMPILE=arm-linux-gnueabihf-", make_jobs_str]) run_cmd("copy arm vmlinux", kernel_vexpress_gem5_dir, ["cp", "vmlinux", binaries_dir + "/vmlinux.vexpress_gem5_v1"]) # Checkout and build linux kernel and DTB for VExpress_EMM64 kernel_vexpress_emm64_dir = options.dest_dir + "/linux-kernel-vexpress_emm64" run_cmd("clone linux kernel for VExpress_EMM64 platform", options.dest_dir, ["git", "clone", "https://gem5.googlesource.com/arm/linux-arm64-legacy", kernel_vexpress_emm64_dir]) rev_file = open(revisions_dir + "/linux-arm64-legacy", "w+") run_cmd("write revision of linux-kernel-vexpress_emm64 repo", kernel_vexpress_emm64_dir, ["git", "rev-parse", "--short", "HEAD"], rev_file) rev_file.close() run_cmd("configure kernel", kernel_vexpress_emm64_dir, ["make", "ARCH=arm64", "CROSS_COMPILE=aarch64-linux-gnu-", "CC=aarch64-linux-gnu-gcc-4.8", "gem5_defconfig"]) run_cmd("compile kernel", kernel_vexpress_emm64_dir, ["make", "ARCH=arm64", "CROSS_COMPILE=aarch64-linux-gnu-", "CC=aarch64-linux-gnu-gcc-4.8", make_jobs_str]) run_cmd("copy vmlinux", kernel_vexpress_emm64_dir, ["cp", "vmlinux", binaries_dir + "/vmlinux.vexpress_emm64"]) run_cmd("copy DTB", kernel_vexpress_emm64_dir, ["cp", "arch/arm64/boot/dts/aarch64_gem5_server.dtb", binaries_dir]) # Checkout and build linux kernel and DTBs for VExpress_EMM kernel_vexpress_emm_dir = options.dest_dir + "/linux-kernel-vexpress_emm" run_cmd("clone linux kernel for VExpress_EMM platform", options.dest_dir, ["git", "clone", "https://gem5.googlesource.com/arm/linux-arm-legacy", kernel_vexpress_emm_dir]) rev_file = open(revisions_dir + "/linux-arm-legacy", "w+") run_cmd("write revision of linux-kernel-vexpress_emm64 repo", kernel_vexpress_emm_dir, ["git", "rev-parse", "--short", "HEAD"], rev_file) rev_file.close() run_cmd("configure kernel", kernel_vexpress_emm_dir, ["make", "ARCH=arm", "CROSS_COMPILE=arm-linux-gnueabihf-", "CC=arm-linux-gnueabihf-gcc-4.8", "vexpress_gem5_server_defconfig"]) run_cmd("compile kernel", kernel_vexpress_emm_dir, ["make", "ARCH=arm", "CROSS_COMPILE=arm-linux-gnueabihf-", "CC=arm-linux-gnueabihf-gcc-4.8", make_jobs_str]) run_cmd("copy vmlinux", kernel_vexpress_emm_dir, ["cp", "vmlinux", binaries_dir + "/vmlinux.vexpress_emm"]) run_cmd("rename DTB for 1 CPU", kernel_vexpress_emm_dir, ["cp", "arch/arm/boot/dts/vexpress-v2p-ca15-tc1-gem5.dtb", binaries_dir + "/vexpress-v2p-ca15-tc1-gem5_1cpus.dtb"]) run_cmd("copy DTBs", kernel_vexpress_emm_dir, ["cp"] + glob(kernel_vexpress_emm_dir + "/arch/arm/boot/dts/*gem5_*dtb") + [binaries_dir]) # Build DTBs for VExpress_GEM5_V1 dt_dir = gem5_dir + "/system/arm/dt" run_cmd("compile DTBs for VExpress_GEM5_V1 platform", dt_dir, ["make", make_jobs_str]) run_cmd("copy DTBs", dt_dir, ["cp"] + glob(dt_dir + "/*dtb") + [binaries_dir]) # Build bootloaders arm64 bootloader_arm64_dir = gem5_dir + "/system/arm/aarch64_bootloader" run_cmd("compile arm64 bootloader", bootloader_arm64_dir, ["make"]) run_cmd("copy arm64 bootloader", bootloader_arm64_dir, ["cp", "boot_emm.arm64", binaries_dir]) # Build bootloaders arm bootloader_arm_dir = gem5_dir + "/system/arm/simple_bootloader" run_cmd("compile arm bootloader", bootloader_arm_dir, ["make"]) run_cmd("copy arm bootloaders", bootloader_arm_dir, ["cp", "boot.arm", "boot_emm.arm", binaries_dir]) # Build m5 binaries m5_dir = gem5_dir + "/util/m5" run_cmd("compile arm64 m5", m5_dir, ["make", "-f", "Makefile.aarch64"]) run_cmd("copy arm64 m5", m5_dir, ["cp", "m5", binaries_dir + "/m5.aarch64"]) run_cmd("clean arm64 m5", m5_dir, ["make", "clean", "-f", "Makefile.aarch64"]) run_cmd("compile arm m5", m5_dir, ["make", "-f", "Makefile.arm"]) run_cmd("copy arm m5", m5_dir, ["cp", "m5", binaries_dir + "/m5.aarch32"]) print "Done! All the generated files can be found in %s" % binaries_dir sys.exit(0)