blob: 5fe743f47cdda96a04831b0f1b7ad97ff428f931 [file] [log] [blame]
#!/usr/bin/env bash
# Copyright 2017 The Fuchsia Authors
#
# Use of this source code is governed by a MIT-style
# license that can be found in the LICENSE file or at
# https://opensource.org/licenses/MIT
set -eo pipefail
# Where the dash sources are expected to be.
DASH_SRC_DIR="/tmp/dash"
usage() {
echo "usage: ${0} [options] {arm64, x64}"
echo
echo " -d Directory to clone toybox into."
echo " -o Disk image output path."
echo " -s Directory to clone dash into."
echo " -u Update before building."
echo
exit 1
}
# Ensures the toybox sources are downloaded.
#
# $1 - Directory to unpack the sources into.
get_toybox_source() {
local toybox_src=$1
if [ ! -d "$toybox_src" ]; then
git clone --depth 1 https://zircon-guest.googlesource.com/third_party/toybox "$toybox_src"
elif [[ "${UPDATE}" = "true" ]]; then
pushd "$toybox_src"
git pull --depth 1
popd
fi
}
# Build toybox and create a sysroot.
#
# $1 - Toybox source directory.
# $2 - Directory to build the toybox sysroot with the toybox binary and symlinks.
build_toybox() {
local toybox_src=$1
local sysroot_dir="$2"
make -C "$toybox_src" defconfig
CROSS_COMPILE="${AC_HOST}-" CC="gcc" LDFLAGS="--static" make -C "$toybox_src" -j100
mkdir -p "$sysroot_dir"/{bin,sbin,etc,proc,sys,usr/{bin,sbin},dev,tmp}
PREFIX=$sysroot_dir make -C "$toybox_src" install
}
# Ensures the dash sources are downloaded.
#
# $1 - Directory to unpack the sources into.
get_dash_source() {
local dash_src=$1
if [ ! -d "$dash_src" ]; then
git clone --depth 1 https://zircon-guest.googlesource.com/third_party/dash "$dash_src"
elif [[ "${UPDATE}" = "true" ]]; then
pushd "$dash_src"
git pull --depth 1
popd
fi
}
# Build dash, copy it to sysroot and make it sh.
#
# $1 - Dash source directory.
# $2 - Directory of toybox sysroot.
build_dash() {
local dash_src=$1
local sysroot_dir="$2"
pushd $dash_src
./autogen.sh
./configure LDFLAGS="-static" --host="${AC_HOST}" --build=x86_64-linux-gnu
make -j100
popd
mkdir -p "$sysroot_dir/bin"
cp "$dash_src/src/dash" "$sysroot_dir/bin/sh"
}
# Generate a simple init script at /init in the target sysroot.
#
# $1 - Toybox sysroot directory.
generate_init() {
local sysroot_dir="$1"
mkdir -p "${sysroot_dir}/etc"
mkdir -p "${sysroot_dir}/test_utils"
# Write an init script for toybox.
cat > "${sysroot_dir}/etc/init" <<'_EOF'
#!/bin/sh
mount -t proc proc /proc
mount -t sysfs sysfs /sys
mount -t ext2 /dev/vdb /test_utils
echo Launched init
exec /bin/sh
_EOF
chmod +x "${sysroot_dir}/etc/init"
}
# e2tools provides utilities for manipulating EXT2 filesystems.
check_e2tools() {
type -P e2cp &>/dev/null && return 0
echo "Required package e2tools is not installed. (sudo apt install e2tools)"
exit 1
}
# Generate an EXT2 filesystem image of the toybox sysroot.
#
# $1 - Toybox sysroot directory.
# $2 - Filepath of the created EXT2 image file.
package_rootfs() {
local sysroot="$1"
local rootfs="$2"
dd if=/dev/zero of=$rootfs bs=1M count=20
mkfs.ext2 -F $rootfs
for dir in `find "${sysroot}" -type d -printf '%P\n'`; do
e2mkdir "${rootfs}:/${dir}"
done
for file in `find "${sysroot}" -type f -printf '%P\n'`; do
e2cp -p -G 0 -O 0 "${sysroot}/${file}" "${rootfs}:/${file}"
done
# e2cp follows symlinks which would create a copy of the toybox binary for
# every link. To work around this we enumerate all the symlinks in the
# sysroot and create a corresponding hardlink in the ext2 filesystem (e2ln
# does not currently support soft links).
for link in `find "${sysroot}" -type l -printf '%P\n'`; do
local dirname=`dirname ${link}`
local target=`readlink "${sysroot}/${link}"`
e2ln "${rootfs}:${dirname}/${target}" "/${link}"
done
}
declare UPDATE="${UPDATE:-false}"
while getopts "d:o:s:u" opt; do
case "${opt}" in
d) TOYBOX_SRC_DIR="${OPTARG}" ;;
o) DISK_OUT="${OPTARG}" ;;
s) DASH_SRC_DIR="${OPTARG}" ;;
u) UPDATE="true" ;;
*) usage ;;
esac
done
shift $((OPTIND - 1))
case "${1}" in
arm64)
ARCH=${1}
type aarch64-linux-gnu-gcc ||
{ echo "Required package gcc-aarch64-linux-gnu is not installed."
echo "(sudo apt install gcc-aarch64-linux-gnu)"; exit 1; };
AC_HOST="aarch64-linux-gnu";;
x64)
ARCH=${1}
AC_HOST="x86_64-linux-gnu";;
*)
usage;;
esac
# Where the toybox sources are expected to be.
TOYBOX_SRC_DIR="${TOYBOX_SRC_DIR:-/tmp/toybox-${ARCH}}"
# Toybox root filesystem image.
TOYBOX_ROOTFS="${TOYBOX_SRC_DIR}/rootfs.ext2"
# Where to prep the toybox directory structure.
TOYBOX_SYSROOT="${TOYBOX_SRC_DIR}/fs"
check_e2tools
get_toybox_source "${TOYBOX_SRC_DIR}"
build_toybox "${TOYBOX_SRC_DIR}" "${TOYBOX_SYSROOT}"
get_dash_source "${DASH_SRC_DIR}"
build_dash "${DASH_SRC_DIR}" "${TOYBOX_SYSROOT}"
generate_init "${TOYBOX_SYSROOT}"
package_rootfs "${TOYBOX_SYSROOT}" "${TOYBOX_ROOTFS}"
if [ -n "${DISK_OUT}" ]; then
mv "${TOYBOX_ROOTFS}" "${DISK_OUT}"
echo "filesystem image at ${DISK_OUT}"
else
echo "filesystem image at ${TOYBOX_ROOTFS}"
fi