1#!/usr/bin/env python2.7
2
3# Copyright (c) 2017-2018 Metempsy Technology Consulting
4# All rights reserved.
5#
6# Redistribution and use in source and binary forms, with or without
7# modification, are permitted provided that the following conditions are
8# met: redistributions of source code must retain the above copyright
9# notice, this list of conditions and the following disclaimer;
10# redistributions in binary form must reproduce the above copyright
11# notice, this list of conditions and the following disclaimer in the
12# documentation and/or other materials provided with the distribution;
13# neither the name of the copyright holders nor the names of its
14# contributors may be used to endorse or promote products derived from
15# this software without specific prior written permission.
16#
17# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
18# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
19# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
20# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
21# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
22# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
23# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
24# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
25# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
26# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
27# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28#
29# Authors: Pau Cabre
30
31from optparse import OptionParser
32from subprocess import call
33from platform import machine
34from distutils import spawn
35from glob import glob
36
37import sys
38import os
39
40def run_cmd(explanation, working_dir, cmd, stdout = None):
41    print "Running phase '%s'" % explanation
42    sys.stdout.flush()
43
44    # some of the commands need $PWD to be properly set
45    env = os.environ.copy()
46    env['PWD'] = working_dir
47
48    return_code = call(cmd, cwd = working_dir, stdout = stdout,
49                       env = env)
50
51    if return_code == 0:
52        return
53
54    print "Error running phase %s. Returncode: %d" % (explanation, return_code)
55    sys.exit(1)
56
57script_dir = os.path.dirname(os.path.abspath(sys.argv[0]))
58gem5_dir = os.path.dirname(script_dir)
59
60parser = OptionParser()
61
62parser.add_option("--gem5-dir", default = gem5_dir,
63    metavar = "GEM5_DIR",
64    help = "gem5 root directory to be used for bootloader and "
65           "VExpress_GEM5_V1 DTB sources. The default value is the gem5 root "
66           "directory of the executed script (%default)")
67parser.add_option("--dest-dir", default = "/tmp",
68    metavar = "DEST_DIR",
69    help = "Directory to use for checking out the different kernel "
70           "repositories. Generated files will be copied to "
71           "DEST_DIR/binaries (which must not exist). The default "
72           "value is %default")
73parser.add_option("--make-jobs", type = "int", default = 1,
74    metavar = "MAKE_JOBS",
75    help = "Number of jobs to use with the 'make' commands. Default value: "
76           "%default")
77
78(options, args) = parser.parse_args()
79
80if args:
81    print "Unrecognized argument(s) %s." % args
82    sys.exit(1)
83
84if not os.path.isdir(options.dest_dir):
85    print "Error: %s is not a directory." % options.dest_dir
86    sys.exit(1)
87
88if not os.path.isdir(options.gem5_dir):
89    print "Error: %s is not a directory." % options.gem5_dir
90    sys.exit(1)
91
92if machine() != "x86_64":
93    print "Error: This script should run in a x86_64 machine"
94    sys.exit(1)
95
96binaries_dir = options.dest_dir + "/binaries"
97
98if os.path.exists(binaries_dir):
99    print "Error: %s already exists." % binaries_dir
100    sys.exit(1)
101
102revisions_dir = options.dest_dir + "/revisions"
103
104if os.path.exists(revisions_dir):
105    print "Error: %s already exists." %revisions_dir
106    sys.exit(1)
107
108# Some basic dependency checking
109needed_programs = [
110    "make",
111    "aarch64-linux-gnu-gcc",
112    "arm-linux-gnueabihf-gcc",
113    "aarch64-linux-gnu-gcc-4.8",
114    "arm-linux-gnueabihf-gcc-4.8",
115    "gcc",
116    "bc",
117    "dtc",
118    "arm-linux-gnueabi-gcc"
119]
120
121for program in needed_programs:
122    if not spawn.find_executable(program):
123        print "Error: command %s not found in $PATH" % program
124        print ("If running on an Debian-based linux, please try the following "
125               "cmd to get all the necessary packages: ")
126        print ("sudo apt-get install -y make gcc bc gcc-aarch64-linux-gnu "
127              "gcc-4.8-aarch64-linux-gnu gcc-4.8-arm-linux-gnueabihf "
128              "gcc-arm-linux-gnueabihf device-tree-compiler "
129              "gcc-arm-linux-gnueabi")
130        sys.exit(1)
131
132os.mkdir(binaries_dir);
133os.mkdir(revisions_dir);
134
135make_jobs_str = "-j" + str(options.make_jobs)
136
137rev_file = open(revisions_dir + "/gem5", "w+")
138run_cmd("write revision of gem5 repo",
139    gem5_dir,
140    ["git", "rev-parse", "--short", "HEAD"],
141    rev_file)
142rev_file.close()
143
144# Checkout and build linux kernel for VExpress_GEM5_V1 (arm and arm64)
145kernel_vexpress_gem5_dir = options.dest_dir + "/linux-kernel-vexpress_gem5"
146run_cmd("clone linux kernel for VExpress_GEM5_V1 platform",
147    options.dest_dir,
148    ["git", "clone", "https://gem5.googlesource.com/arm/linux",
149     kernel_vexpress_gem5_dir])
150rev_file = open(revisions_dir + "/linux", "w+")
151run_cmd("write revision of linux-kernel-vexpress_gem5 repo",
152    kernel_vexpress_gem5_dir,
153    ["git", "rev-parse", "--short", "HEAD"],
154    rev_file)
155rev_file.close()
156run_cmd("configure kernel for arm64",
157    kernel_vexpress_gem5_dir,
158    ["make", "ARCH=arm64", "CROSS_COMPILE=aarch64-linux-gnu-",
159     "gem5_defconfig", make_jobs_str])
160run_cmd("compile kernel for arm64",
161    kernel_vexpress_gem5_dir,
162    ["make", "ARCH=arm64", "CROSS_COMPILE=aarch64-linux-gnu-", make_jobs_str])
163run_cmd("copy arm64 vmlinux",
164    kernel_vexpress_gem5_dir,
165    ["cp", "vmlinux", binaries_dir + "/vmlinux.vexpress_gem5_v1_64"])
166run_cmd("cleanup arm64 kernel compilation",
167    kernel_vexpress_gem5_dir,
168    ["make", "distclean"])
169run_cmd("configure kernel for arm",
170    kernel_vexpress_gem5_dir,
171    ["make", "ARCH=arm", "CROSS_COMPILE=arm-linux-gnueabihf-",
172     "gem5_defconfig"])
173run_cmd("compile kernel for arm",
174    kernel_vexpress_gem5_dir,
175    ["make", "ARCH=arm", "CROSS_COMPILE=arm-linux-gnueabihf-", make_jobs_str])
176run_cmd("copy arm vmlinux",
177    kernel_vexpress_gem5_dir,
178    ["cp", "vmlinux", binaries_dir + "/vmlinux.vexpress_gem5_v1"])
179
180# Checkout and build linux kernel and DTB for VExpress_EMM64
181kernel_vexpress_emm64_dir = options.dest_dir + "/linux-kernel-vexpress_emm64"
182run_cmd("clone linux kernel for VExpress_EMM64 platform",
183    options.dest_dir,
184    ["git", "clone", "https://gem5.googlesource.com/arm/linux-arm64-legacy",
185     kernel_vexpress_emm64_dir])
186rev_file = open(revisions_dir + "/linux-arm64-legacy", "w+")
187run_cmd("write revision of linux-kernel-vexpress_emm64 repo",
188    kernel_vexpress_emm64_dir,
189    ["git", "rev-parse", "--short", "HEAD"],
190    rev_file)
191rev_file.close()
192run_cmd("configure kernel",
193    kernel_vexpress_emm64_dir,
194    ["make", "ARCH=arm64", "CROSS_COMPILE=aarch64-linux-gnu-",
195     "CC=aarch64-linux-gnu-gcc-4.8", "gem5_defconfig"])
196run_cmd("compile kernel",
197    kernel_vexpress_emm64_dir,
198    ["make", "ARCH=arm64", "CROSS_COMPILE=aarch64-linux-gnu-",
199     "CC=aarch64-linux-gnu-gcc-4.8", make_jobs_str])
200run_cmd("copy vmlinux",
201    kernel_vexpress_emm64_dir,
202    ["cp", "vmlinux", binaries_dir + "/vmlinux.vexpress_emm64"])
203run_cmd("copy DTB",
204    kernel_vexpress_emm64_dir,
205    ["cp", "arch/arm64/boot/dts/aarch64_gem5_server.dtb", binaries_dir])
206
207# Checkout and build linux kernel and DTBs for VExpress_EMM
208kernel_vexpress_emm_dir = options.dest_dir + "/linux-kernel-vexpress_emm"
209run_cmd("clone linux kernel for VExpress_EMM platform",
210    options.dest_dir,
211    ["git", "clone", "https://gem5.googlesource.com/arm/linux-arm-legacy",
212     kernel_vexpress_emm_dir])
213rev_file = open(revisions_dir + "/linux-arm-legacy", "w+")
214run_cmd("write revision of linux-kernel-vexpress_emm64 repo",
215    kernel_vexpress_emm_dir,
216    ["git", "rev-parse", "--short", "HEAD"],
217    rev_file)
218rev_file.close()
219run_cmd("configure kernel",
220    kernel_vexpress_emm_dir,
221    ["make", "ARCH=arm", "CROSS_COMPILE=arm-linux-gnueabihf-",
222     "CC=arm-linux-gnueabihf-gcc-4.8", "vexpress_gem5_server_defconfig"])
223run_cmd("compile kernel",
224    kernel_vexpress_emm_dir,
225    ["make", "ARCH=arm", "CROSS_COMPILE=arm-linux-gnueabihf-",
226     "CC=arm-linux-gnueabihf-gcc-4.8", make_jobs_str])
227run_cmd("copy vmlinux",
228    kernel_vexpress_emm_dir,
229    ["cp", "vmlinux", binaries_dir + "/vmlinux.vexpress_emm"])
230run_cmd("rename DTB for 1 CPU",
231    kernel_vexpress_emm_dir,
232    ["cp", "arch/arm/boot/dts/vexpress-v2p-ca15-tc1-gem5.dtb",
233     binaries_dir + "/vexpress-v2p-ca15-tc1-gem5_1cpus.dtb"])
234run_cmd("copy DTBs",
235    kernel_vexpress_emm_dir,
236    ["cp"] + glob(kernel_vexpress_emm_dir + "/arch/arm/boot/dts/*gem5_*dtb") +
237    [binaries_dir])
238
239# Build DTBs for VExpress_GEM5_V1
240dt_dir = gem5_dir + "/system/arm/dt"
241run_cmd("compile DTBs for VExpress_GEM5_V1 platform",
242    dt_dir,
243    ["make", make_jobs_str])
244run_cmd("copy DTBs",
245    dt_dir,
246    ["cp"] + glob(dt_dir + "/*dtb") + [binaries_dir])
247
248# Build bootloaders arm64
249bootloader_arm64_dir = gem5_dir + "/system/arm/aarch64_bootloader"
250run_cmd("compile arm64 bootloader",
251    bootloader_arm64_dir,
252    ["make"])
253run_cmd("copy arm64 bootloader",
254    bootloader_arm64_dir,
255    ["cp", "boot_emm.arm64", binaries_dir])
256
257# Build bootloaders arm
258bootloader_arm_dir = gem5_dir + "/system/arm/simple_bootloader"
259run_cmd("compile arm bootloader",
260    bootloader_arm_dir,
261    ["make"])
262run_cmd("copy arm bootloaders",
263    bootloader_arm_dir,
264    ["cp", "boot.arm", "boot_emm.arm", binaries_dir])
265
266# Build m5 binaries
267m5_dir = gem5_dir + "/util/m5"
268run_cmd("compile arm64 m5",
269    m5_dir,
270    ["make", "-f", "Makefile.aarch64"])
271run_cmd("copy arm64 m5",
272    m5_dir,
273    ["cp", "m5", binaries_dir + "/m5.aarch64"])
274run_cmd("clean arm64 m5",
275    m5_dir,
276    ["make", "clean", "-f", "Makefile.aarch64"])
277run_cmd("compile arm m5",
278    m5_dir,
279    ["make", "-f", "Makefile.arm"])
280run_cmd("copy arm m5",
281    m5_dir,
282    ["cp", "m5", binaries_dir + "/m5.aarch32"])
283
284print "Done! All the generated files can be found in %s" % binaries_dir
285
286sys.exit(0)
287
288