blob: eb80ef8daf2add8bc5dd44f22f2c5accfd4095f5 [file] [log] [blame]
# Copyright (c) 2012 The Chromium OS Authors. All rights reserved.
# Distributed under the terms of the GNU General Public License v2
EAPI=4
CROS_WORKON_PROJECT="chromiumos/platform/initramfs"
CROS_WORKON_LOCALNAME="initramfs"
CROS_WORKON_OUTOFTREE_BUILD="1"
inherit cros-workon cros-board
DESCRIPTION="Create Chrome OS initramfs"
HOMEPAGE="http://www.chromium.org/"
LICENSE="GPL-2"
SLOT="0"
KEYWORDS="~*"
IUSE="netboot_ramfs"
# Dependencies used to build the netboot initramfs.
# Look for the `idobin` and such calls.
DEPEND_netboot="
app-arch/sharutils
app-shells/bash
chromeos-base/chromeos-factoryinstall
chromeos-base/chromeos-init
chromeos-base/chromeos-installer
chromeos-base/chromeos-installshim
chromeos-base/memento_softwareupdate
chromeos-base/platform2
dev-libs/openssl
dev-util/shflags
net-misc/wget
sys-apps/coreutils
sys-apps/iproute2
sys-apps/util-linux
sys-block/parted
sys-fs/dosfstools
sys-fs/e2fsprogs
"
DEPEND="chromeos-base/chromeos-assets
chromeos-base/chromeos-assets-split
chromeos-base/vboot_reference
chromeos-base/vpd
media-gfx/ply-image
sys-apps/busybox[-make-symlinks]
sys-apps/flashrom
sys-apps/pv
sys-fs/lvm2
netboot_ramfs? ( ${DEPEND_netboot} )"
RDEPEND=""
src_prepare() {
local srcroot='/mnt/host/source'
BUILD_LIBRARY_DIR="${srcroot}/src/scripts/build_library"
# Need the lddtree from the chromite dir.
local chromite_bin="${srcroot}/chromite/bin"
export PATH="${chromite_bin}:${PATH}"
}
# doexe for initramfs
idoexe() {
einfo "Copied: $*"
lddtree \
--verbose \
--copy-non-elfs \
--root="${SYSROOT}" \
--copy-to-tree="${INITRAMFS_TMP_S}" \
--libdir='/lib' \
"$@" || die "failed to copy $*"
}
# dobin for initramfs
idobin() {
idoexe --bindir='/bin' "$@"
}
# Special handling for futility wrapper. This will go away once futility is
# converted to a single binary.
idofutility() {
local src base
idobin "$@"
for src in "$@"; do
base=$(basename "${src}")
mv -f "${INITRAMFS_TMP_S}/bin/${base}" \
"${INITRAMFS_TMP_S}/bin/old_bins/${base}" ||
die "Cannot mv: ${src}"
ln -sf futility "${INITRAMFS_TMP_S}/bin/${base}" ||
die "Cannot symlink: ${src}"
einfo "Symlinked: /bin/${base} -> futility"
done
}
idoko() {
local module_root_path="${SYSROOT}/lib/modules"
local module_list=()
local module_queue=("$@")
# Parses module dependencies.
local missing_module=false
while [[ ${#module_queue[@]} -gt 0 ]]; do
local module="${module_queue[0]}"
module_queue=("${module_queue[@]:1}")
if has "${module}" "${module_list[@]}"; then
continue
else
module_list+=("${module}")
fi
local module_depends=($(modinfo -F depends "${module}" | tr ',' ' '))
local depend
for depend in "${module_depends[@]}"; do
local module_depend_path=$(find "${module_root_path}" -name "${depend}.ko")
if [[ -z "${module_depend_path}" ]]; then
missing_module=true
eerror "Can't find ${depend}.ko in ${module_root_path}"
continue
fi
module_queue+=("${module_depend_path}")
done
done
${missing_module} && die "Some modules are missing, see messages above"
# Copies modules.
for module in "${module_list[@]}"; do
local module_install_path="${module#${SYSROOT}}"
local dst_path="${INITRAMFS_TMP_S}/${module_install_path}"
mkdir -p "${dst_path%/*}"
cp -p "${module}" "${dst_path}" ||
die "Can't copy ${module} to ${dst_path}"
einfo "Copied: ${module_install_path}"
done
}
# install a list of images (presumably .png files) in /etc/screens
insimage() {
cp "$@" "${INITRAMFS_TMP_S}"/etc/screens || die
}
pull_initramfs_binary() {
# For busybox and sh
idobin /bin/busybox
ln -s busybox "${INITRAMFS_TMP_S}/bin/sh"
# For verified rootfs
idobin /sbin/dmsetup
# For message screen display and progress bars
idobin /usr/bin/ply-image
idobin /usr/bin/pv
idobin /usr/sbin/vpd
# /usr/sbin/vpd invokes 'flashrom' via system()
idobin /usr/sbin/flashrom
# For recovery behavior
idobin /usr/bin/futility
idofutility /usr/bin/old_bins/cgpt
idofutility /usr/bin/old_bins/crossystem
idofutility /usr/bin/old_bins/dump_kernel_config
idofutility /usr/bin/old_bins/tpmc
idofutility /usr/bin/old_bins/vbutil_kernel
# PNG image assets
local shared_assets="${SYSROOT}"/usr/share/chromeos-assets
insimage "${shared_assets}"/images/boot_message.png
insimage "${S}"/assets/spinner_*.png
insimage "${S}"/assets/icon_check.png
insimage "${S}"/assets/icon_warning.png
${S}/make_images "${S}/localized_text" \
"${INITRAMFS_TMP_S}/etc/screens" || die
}
pull_netboot_ramfs_binary() {
# We want to keep GNU sh at /bin/sh, so let's change shebang for init
# to busybox explicitly.
sed -i '1s|.*|#!/bin/busybox sh\nset -x|' "${INITRAMFS_TMP_S}/init" || die
# Busybox and utilities
idobin /bin/busybox
local bin_name
local busybox_bins=(
awk
basename
cat
chmod
chroot
cp
cut
date
dirname
expr
find
grep
gzip
head
id
ifconfig
ip
mkdir
mkfs.vfat
mktemp
modprobe
mount
rm
rmdir
route
sed
sleep
stty
sync
tee
tftp
tr
true
udhcpc
umount
uname
uniq
)
for bin_name in ${busybox_bins[@]}; do
ln -s busybox "${INITRAMFS_TMP_S}/bin/${bin_name}" || die
done
#
# Any new files added here must include dependencies in RDEPEND above.
#
# Factory installer
# chromeos-base/chromeos-factoryinstall
idobin /usr/sbin/factory_install.sh
idobin /usr/sbin/netboot_postinst.sh
idobin /usr/sbin/ping_shopfloor.sh
idobin /usr/sbin/secure_less.sh
# chromeos-base/chromeos-installer
idobin /usr/sbin/chromeos-common.sh
idobin /usr/sbin/chromeos-install
# dev-util/shflags
cp "${SYSROOT}"/usr/share/misc/shflags "${INITRAMFS_TMP_S}"/usr/share/misc
# Binaries used by factory installer
idobin /bin/bash
idobin /bin/dd
idobin /bin/sh
idobin /bin/xxd
idobin /sbin/blockdev
idobin /usr/sbin/fsck.vfat
idobin /sbin/resize2fs
idobin /sbin/sfdisk
idofutility /usr/bin/old_bins/cgpt
idofutility /usr/bin/old_bins/crossystem
idobin /usr/bin/backlight_tool
idobin /usr/bin/futility
idobin /usr/bin/getopt
idobin /usr/bin/openssl
idobin /usr/bin/uudecode
idobin /usr/bin/wget
idobin /usr/sbin/flashrom
idobin /usr/sbin/htpdate
idobin /usr/sbin/partprobe
ln -s "/bin/cgpt" "${INITRAMFS_TMP_S}/usr/bin/cgpt" || die
# Install ectool if there is one
if [ -e "${SYSROOT}"/usr/sbin/ectool ]; then
idobin /usr/sbin/ectool
else
einfo "Skipping ectool"
fi
# We don't need to display image. Create empty constants.sh so that
# messages.sh doesn't freak out.
touch "${INITRAMFS_TMP_S}/etc/screens/constants.sh"
# Network support
cp "${FILESDIR}"/udhcpc.script "${INITRAMFS_TMP_S}/etc" || die
chmod +x "${INITRAMFS_TMP_S}/etc/udhcpc.script"
# Create a dummy /etc/passwd with root and nobody. This is
# necessary to let processes drop privileges and become
# nobody. We use the same settings as in the root fs.
cp "${FILESDIR}"/passwd "${INITRAMFS_TMP_S}/etc" || die
chmod 400 "${INITRAMFS_TMP_S}/etc/passwd"
# Create /var/empty as home directory for nobody user.
mkdir -p "${INITRAMFS_TMP_S}/var/empty"
# USB Ethernet kernel modules.
MODULE_ROOT_PATH="${SYSROOT}/lib/modules"
local module_path=$(find "${MODULE_ROOT_PATH}" -name "usbnet.ko" -printf "%h")
[[ -n "${module_path}" ]] || die "Can't find usbnet.ko"
local module_list=()
while read -d $'\0' -r module; do
module_list+=("${module}")
done < <(find "${module_path}" -name "*.ko" -print0)
idoko "${module_list[@]}"
# Generates lsb-factory
LSBDIR="mnt/stateful_partition/dev_image/etc"
GENERATED_LSB_FACTORY="${INITRAMFS_TMP_S}/${LSBDIR}/lsb-factory"
SERVER_ADDR="${SERVER_ADDR-10.0.0.1}"
BOARD="$(get_current_board_with_variant)"
mkdir -p "${INITRAMFS_TMP_S}/${LSBDIR}"
cat "${FILESDIR}"/lsb-factory.template | \
sed "s/%BOARD%/${BOARD}/g" |
sed "s/%SERVER_ADDR%/${SERVER_ADDR}/g" \
>"${GENERATED_LSB_FACTORY}"
ln -s "/$LSBDIR/lsb-factory" "${INITRAMFS_TMP_S}/etc/lsb-release"
# Partition table
cp "${SYSROOT}"/root/.gpt_layout "${INITRAMFS_TMP_S}"/root/
cp "${SYSROOT}"/root/.pmbr_code "${INITRAMFS_TMP_S}"/root/
# Generates write_gpt.sh
INSTALLED_SCRIPT="${INITRAMFS_TMP_S}"/usr/sbin/write_gpt.sh
BOARD=$(get_current_board_with_variant)
. "${BUILD_LIBRARY_DIR}"/disk_layout_util.sh || die
write_partition_script usb "${INSTALLED_SCRIPT}" || die
# Install Memento updater
idoexe '/opt/google/memento_updater/*'
}
build_initramfs_file() {
local dir
local subdirs=(
bin
bin/old_bins
dev
etc
etc/screens
lib
log
newroot
proc
root
stateful
sys
tmp
usb
usr/bin
usr/sbin
usr/share/misc
)
for dir in ${subdirs[@]}; do
mkdir -p "${INITRAMFS_TMP_S}/$dir" || die
done
# On amd64, shared libraries must live in /lib64. More generally,
# $(get_libdir) tells us the directory name we need for the target
# platform's libraries. The 'copy_elf' script installs in /lib; to
# keep that script simple we just create a symlink to /lib, if
# necessary.
local libdir=$(get_libdir)
if [ "${libdir}" != "lib" ]; then
ln -s lib "${INITRAMFS_TMP_S}/${libdir}"
fi
# Copy source files not merged from our dependencies.
cp "${S}"/init "${INITRAMFS_TMP_S}/init" || die
chmod +x "${INITRAMFS_TMP_S}/init"
cp "${S}"/*.sh "${INITRAMFS_TMP_S}/lib" || die
if use netboot_ramfs; then
pull_netboot_ramfs_binary
else
pull_initramfs_binary
fi
# The kernel emake expects the file in cpio format.
( cd "${INITRAMFS_TMP_S}"
find . | cpio -o -H newc |
xz -9 --check=crc32 > \
"${WORKDIR}/${INITRAMFS_FILE}" ) ||
die "cannot package initramfs"
}
src_compile() {
INITRAMFS_TMP_S=${WORKDIR}/initramfs_tmp
if use netboot_ramfs; then
INITRAMFS_FILE="netboot_ramfs.cpio.xz"
else
INITRAMFS_FILE="initramfs.cpio.xz"
fi
einfo "Creating ${INITRAMFS_FILE}"
build_initramfs_file
INITRAMFS_FILE_SIZE=$(stat --printf="%s" "${WORKDIR}/${INITRAMFS_FILE}")
einfo "${INITRAMFS_FILE}: ${INITRAMFS_FILE_SIZE} bytes"
}
src_install() {
insinto /var/lib/misc
doins "${WORKDIR}/${INITRAMFS_FILE}"
}