#!/usr/bin/bash # Copyright (C) 2017-2020 Daniel Tartavel-jeannot # 2019-2020 Jean-Baptiste Biernacki # Copyright (C) 2020 Neal Gompa # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2 of the License,dnf or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program. If not, see . #Change the local to the most global export LC_ALL=C function timestamp() { date "+[%H:%M:%S]" } function cleanExit(){ if [ 0 -ne ${#} ]; then if [ 0 -ne ${1} ]; then warning "unmounting all mounted files before exit" unmountingPartitions unloopingImage fi fi exit $@ } function WaitToContinue() { read -p "Break... Press [ENTER] to continue." GARBAGE } function title() { echo -e "\e[1;32m$(timestamp) ${1}\e[0m" } function print_info() { echo -e "\e[36m$(timestamp) ${1}\e[0m" } function warning() { echo -e "\e[1;35m$(timestamp) ${1}\e[0m" } function error() { echo -e "\e[1;31m$(timestamp) ${1}\e[0m" } function check_environment() { if [ "x${INSTALL_METHOD}" == "xurpmi" ]; then hash /usr/sbin/urpmi if [ 0 -ne ${?} ]; then error "urpmi is missing." fi elif [ "x${INSTALL_METHOD}" == "xurpmi" ]; then hash /usr/bin/dnf if [ 0 -ne ${?} ]; then error "dnf is missing." fi fi ### TODO add other environmnet things, like : from function createchroot() } function verify_disk_space() { title "Verifying if there is enough space on disk to make the image" DISK_SPACE=$(/usr/bin/df -BG --output=avail "${INSTALL_PATH}" | sed '1d;s/[^0-9]//g') print_info "Free disk space: ${DISK_SPACE}G" if [ ${DISK_SPACE} -lt ${IMAGE_SIZE} ]; then warning "image size is greater than disk space" print_info "correct the problem and relaunch the script with parameter --create-rpi-image" print_info "${0} --size ${IMAGE_SIZE} --create-rpi-image" return 1 fi return 0 } # creation of install path and copy of qemu ( installing it if not yet installed ) function createchroot() { title "Making chroot" if ! [ -f /usr/share/distribution-gpg-keys/mageia/RPM-GPG-KEY-Mageia ]; then title "distribution-gpg-keys package not present : installing distribution-gpg-keys" #/usr/bin/dnf --assumeyes --setopt=install_weak_deps=False install distribution-gpg-keys installhostpkg "distribution-gpg-keys" "--setopt=install_weak_deps=False" if [ ${?} -ne 0 ]; then error "line ${LINENO} can't install distribution-gpg-keys : exiting" cleanExit ${ERR_1} fi fi if [ `arch` != "${ARM_VERSION}" ]; then if ! [ -f /usr/bin/qemu-arm-static ]; then title "Qemu package not present : installing qemu packages" #/usr/bin/dnf --assumeyes --setopt=install_weak_deps=False install qemu-user-static installhostpkg "qemu-user-static" "--setopt=install_weak_deps=False" if [ ${?} -ne 0 ]; then error "line ${LINENO} can't install qemu-user-static : exiting" cleanExit ${ERR_1} fi fi # Starting qemu service if not started print_info "check systemd-binfmt service : " /usr/bin/systemctl is-active systemd-binfmt.service if [ ${?} -ne 0 ]; then title "Starting systemd-binfmt.service" /usr/bin/systemctl start systemd-binfmt.service if [ ${?} -ne 0 ]; then error "line ${LINENO} can't start qemu-user-static : exiting" cleanExit ${ERR_1} fi fi fi return 0 } # enabling extra Mageia repositories function genusemirroroptions() { DNF_MIRROROPTS="--config=${DNF_CONFIGPATH} --forcearch=${ARM_VERSION} --nogpgcheck --releasever=${MAGEIA_VERSION}" if [ ! -z "${MIRROR}" ]; then DNF_MIRROROPTS="${DNF_MIRROROPTS} --disablerepo=* --repofrompath=mgarel,${MIRROR}/media/core/release/ --enablerepo=mgarel" if [ "${MAGEIA_VERSION}" != "cauldron" ]; then DNF_MIRROROPTS="${DNF_MIRROROPTS} --repofrompath=mgaup,${MIRROR}/media/core/updates/ --enablerepo=mgaup" fi if [ ${NONFREE} -eq 1 ]; then DNF_MIRROROPTS="${DNF_MIRROROPTS} --repofrompath=mgarel-nonfree,${MIRROR}/media/nonfree/release/ --enablerepo=mgarel-nonfree " if [ "${MAGEIA_VERSION}" != "cauldron" ]; then DNF_MIRROROPTS="${DNF_MIRROROPTS} --repofrompath=mgaup-nonfree,${MIRROR}/media/nonfree/updates/ --enablerepo=mgaup-nonfree" fi fi if [ ${TAINTED} -eq 1 ]; then DNF_MIRROROPTS="${DNF_MIRROROPTS} --repofrompath=mgarel-tainted,${MIRROR}/media/tainted/release/ --enablerepo=mgarel-tainted " if [ "${MAGEIA_VERSION}" != "cauldron" ]; then DNF_MIRROROPTS="${DNF_MIRROROPTS} --repofrompath=mgaup-tainted,${MIRROR}/media/tainted/updates/ --enablerepo=mgaup-tainted" fi fi fi export DNF_MIRROROPTS enableextrarepos return 0 } # enabling extra Mageia repositories function enableextrarepos() { extrasect_baseprefix="mageia" # if [ "${MAGEIA_VERSION}" = "cauldron" ]; then # extrasect_baseprefix="cauldron" # extrasect_updatesprefix="" # else # extrasect_baseprefix="mageia" extrasect_updatesprefix="updates" # fi if [ ${NONFREE} -eq 1 ]; then title "activating non-free repos" DNFPARAM=--installroot="${BUILD_PATH}" config-manager --set-enabled "${extrasect_baseprefix}-${ARM_VERSION}-nonfree" if [ "${MAGEIA_VERSION}" != "cauldron" ]; then DNFPARAM=$DNFPARAM" --set-enabled ${extrasect_updatesprefix}-${ARM_VERSION}-nonfree" fi /usr/bin/dnf $DNFPARAM err=${?} if [ ${err} -ne 0 ]; then error "line ${LINENO} error ${err} - can't activate nonfree repositories : exiting" cleanExit ${ERR_1} fi fi if [ ${TAINTED} -eq 1 ]; then title "activating tainted repos" DNFPARAM=--installroot="${BUILD_PATH}" config-manager --set-enabled "${extrasect_baseprefix}-${ARM_VERSION}-tainted" if [ "${MAGEIA_VERSION}" != "cauldron" ]; then DNFPARAM=$DNFPARAM" --set-enabled ${extrasect_updatesprefix}-${ARM_VERSION}-tainted" fi /usr/bin/dnf $DNFPARAM err=${?} if [ ${err} -ne 0 ]; then error "line ${LINENO} error ${err} - can't activate tainted repositories : exiting" cleanExit ${ERR_1} fi fi return 0 } # adding Mageia urpmi repositories function addurpmimedia() { title "Creating media from mirror: ${MIRROR}" print_info "Removing old media" /sbin/urpmi.removemedia --urpmi-root "${BUILD_PATH}" -a print_info "Adding media" if [ ! -z "${MIRROR}" ] ; then echo ${MIRROR} | grep ${ARM_VERSION} 2>&1 1>/dev/null if [ 0 -eq ${?} ]; then /sbin/urpmi.addmedia --urpmi-root "${BUILD_PATH}" --ignorearch --distrib "${MIRROR}" else /sbin/urpmi.addmedia --urpmi-root "${BUILD_PATH}" --ignorearch --distrib "${MIRROR}/${ARM_VERSION}" fi else print_info "MIRROR variable not set, using mirrorlist." /sbin/urpmi.addmedia --urpmi-root "${BUILD_PATH}" --ignorearch --distrib --mirrorlist "http://mirrors.mageia.org/api/mageia.${MAGEIA_VERSION}.${ARM_VERSION}.list" fi err=${?} if [ ${err} -ne 0 ]; then error "line ${LINENO} error ${err} - can't add medias from ${MIRROR} : exiting" cleanExit ${ERR_1} fi if [ ${NONFREE} -eq 1 ]; then title "activating non-free repos" /sbin/urpmi.update --urpmi-root "${BUILD_PATH}" --no-ignore Nonfree\ Release Nonfree\ Updates err=${?} if [ ${err} -ne 0 ]; then error "line ${LINENO} error ${err} - can't activate medias nonfree : exiting" cleanExit ${ERR_1} fi fi if [ ${TAINTED} -eq 1 ]; then title "activating tainted repos" /sbin/urpmi.update --urpmi-root "${BUILD_PATH}" --no-ignore Tainted\ Release Tainted\ Updates err=${?} if [ ${err} -ne 0 ]; then error "line ${LINENO} error ${err} - can't activate medias tainted : exiting" cleanExit ${ERR_1} fi fi return 0 } function updateurpmmirror() { title "updating mirror" /sbin/urpmi.update -a --urpmi-root "${BUILD_PATH}" if [ ${?} -ne 0 ]; then error "line ${LINENO} can't update mirrors : exiting" cleanExit ${ERR_1} fi return 0 } function installbasesystem() { # Create Build path if ! [ -d "${BUILD_PATH}" ]; then warning "Build path ( ${BUILD_PATH} ) does not exist, do you want to create it ? [Y|n] " read yn if [ -z ${yn} ] || [ ${yn} = "Y" ] || [ ${yn} = "y" ]; then title "Creating ${BUILD_PATH}" /usr/bin/mkdir -p "${BUILD_PATH}/usr/bin" "${BUILD_PATH}/usr/lib/binfmt.d" if [ ${?} -ne 0 ]; then error "line ${LINENO} can't create ${BUILD_PATH} : exiting" cleanExit ${ERR_1} fi else cleanExit ${ERR_1} fi else print_info "Build path exists" fi # Workaround mga#26044. print_info "Preparing root filesystem tree" mkdir -p "${BUILD_PATH}/usr/bin" mkdir -p "${BUILD_PATH}/usr/sbin" mkdir -p "${BUILD_PATH}/usr/lib" ln -sr "${BUILD_PATH}/usr/bin" "${BUILD_PATH}/bin" ln -sr "${BUILD_PATH}/usr/sbin" "${BUILD_PATH}/sbin" ln -sr "${BUILD_PATH}/usr/lib" "${BUILD_PATH}/lib" if [ "${ARM_VERSION}" = "aarch64" ]; then mkdir -p "${BUILD_PATH}/usr/lib64" ln -sr "${BUILD_PATH}/usr/lib64" "${BUILD_PATH}/lib64" fi title "installing basesystem" installpkg "shadow-utils basesystem-minimal" if [ ${?} -ne 0 ]; then error "line ${LINENO} error installing shadow-utils or basesystem-minimal : exiting" cleanExit ${ERR_1} fi if [ ${INSTALL_METHOD} = "urpmi" ]; then installpkg "urpmi locales" else installpkg "dnf dnf-plugins-core locales" fi return 0 } function installhostpkg() { if [ ${INSTALL_METHOD} = "urpmi" ]; then /usr/sbin/urpmi --auto $3 $1; else /usr/bin/dnf $2 ${DNF_MIRROROPTS} --assumeyes install $1; fi } function installpkg() { if [ ${INSTALL_METHOD} = "urpmi" ]; then /usr/sbin/urpmi --urpmi-root "${BUILD_PATH}" --root "${BUILD_PATH}" --ignorearch --no-verify-rpm --auto --split-level 200 --split-length 200 $3 $1; else /usr/bin/dnf $2 --installroot="${BUILD_PATH}" ${DNF_MIRROROPTS} --assumeyes install $1; fi } function preparechroot() { title "Preparing chrooting in ${BUILD_PATH}" print_info "making /etc/hostname" echo "${HOSTNAME:="localhost.localdomain"}" > "${BUILD_PATH}/etc/hostname" print_info "copying second stage script in ${BUILD_PATH}" cp --preserve=mode "${CONFIG_PATH}/second_stage_install.sh" "${BUILD_PATH}/second_stage_install.sh" if [ ${?} -ne 0 ]; then error "line ${LINENO} error copying ${CONFIG_PATH}/second_stage_install.sh : exiting" cleanExit ${ERR_1} fi print_info "configuring second_stage_install.sh for ${INSTALL_METHOD}" if [ ${INSTALL_METHOD} = "urpmi" ]; then sed -i -e "s//sbin\/urpmi --no-verify-rpm --auto --split-length 0/g" "${BUILD_PATH}/second_stage_install.sh" else sed -i -e "s//bin\/dnf --nogpgcheck --assumeyes install/g" "${BUILD_PATH}/second_stage_install.sh" fi print_info "Preparation for setting root and user account" if [ -n "${ROOT_PWD}" ]; then #If root password defined, it will be setted at the end of the chroot of the second_stage_install.sh script echo -e "/usr/bin/passwd << EOF\n${ROOT_PWD}\n${ROOT_PWD}\nEOF\n" >>"${BUILD_PATH}/second_stage_install.sh" else print_info "No root password... One password will be set at the first login." echo -e "/usr/bin/passwd -d root\n/usr/bin/passwd -e root\n" >>"${BUILD_PATH}/second_stage_install.sh" fi if [ -n "${ID_USER}" ]; then #If user ID defined, it will be setted at the end of the chroot of the second_stage_install.sh script echo -e " /sbin/useradd ${ID_USER}\n" >>"${BUILD_PATH}/second_stage_install.sh" if [ -n "${PASSWORD}" ]; then echo -e "/usr/bin/passwd ${ID_USER} << EOF\n${PASSWORD}\n${PASSWORD}\nEOF" >>"${BUILD_PATH}/second_stage_install.sh" else echo -e "/usr/bin/passwd -d ${ID_USER}\n" >>"${BUILD_PATH}/second_stage_install.sh" fi else print_info "No user defined, no user account created." fi postPrepareChroot if [ ${?} -ne 0 ]; then error "line ${LINENO} error in postPrepareChroot function." cleanExit ${ERR_1} fi return 0 } function mountdevsysproc(){ print_info "mounting dev, sys, proc directories in chroot" mkdir -p "${BUILD_PATH}/dev" "${BUILD_PATH}/sys" "${BUILD_PATH}/proc" /usr/bin/mount -B /dev "${BUILD_PATH}/dev" # mkdir ${BUILD_PATH}/dev # ln -s ${DEVICE} ${BUILD_PATH}/dev/loop0 # if [ 1 -eq ${SEPARATE_BOOT_PARTITION} ]; then # ln -s ${BOOTP} ${BUILD_PATH}/dev/loop0p1 # ln -s ${ROOTP} ${BUILD_PATH}/dev/loop0p2 # else # ln -s ${ROOTP} ${BUILD_PATH}/dev/loop0p1 # fi if [ ${?} -ne 0 ]; then error "line ${LINENO} error mounting ${BUILD_PATH}/dev : exiting" cleanExit ${ERR_1} fi MOUNTED_DEV=true /usr/bin/mount -B /sys "${BUILD_PATH}/sys" if [ ${?} -ne 0 ]; then error "line ${LINENO} error mounting ${BUILD_PATH}/sys : exiting" cleanExit ${ERR_1} fi MOUNTED_SYS=true /usr/bin/mount -B /proc "${BUILD_PATH}/proc" if [ ${?} -ne 0 ]; then error "line ${LINENO} error mounting ${BUILD_PATH}/proc : exiting" cleanExit ${ERR_1} fi MOUNTED_PROC=true return 0 } function unmountdevsysproc(){ print_info "unmounting dev, sys, proc" # LIST_MOUNTED=$(/usr/bin/mount -l | grep mageia4arm) if [ ${MOUNTED_DEV:=false} = true ]; then /usr/bin/umount -lf "${BUILD_PATH}/dev" if [ ${?} -ne 0 ]; then warning "line ${LINENO} Warning : error unmounting ${BUILD_PATH}/dev, continuing anyway" ERRORN=$((${ERRORN}+1)) fi fi if [ ${MOUNTED_PROC:=false} = true ]; then /usr/bin/umount -lf "${BUILD_PATH}/proc" if [ ${?} -ne 0 ]; then warning "line ${LINENO} Warning : error unmounting ${BUILD_PATH}/proc, continuing anyway" ERRORN=$((${ERRORN}+1)) fi fi if [ ${MOUNTED_SYS:=false} = true ]; then /usr/bin/umount -lf "${BUILD_PATH}/sys" if [ ${?} -ne 0 ]; then warning "line ${LINENO} Warning : error unmounting ${BUILD_PATH}/sys, continuing anyway" ERRORN=$((${ERRORN}+1)) fi fi return 0 } function jumpchroot() { title "chrooting to ${BUILD_PATH}" print_info "Copying resolv.conf" /usr/bin/cp -v --preserve=mode /etc/resolv.conf "${BUILD_PATH}/etc/" if [ ${?} -ne 0 ]; then error "line ${LINENO} error copying ${BUILD_PATH}/etc/resolv.conf : exiting" cleanExit ${ERR_1} fi print_info "chrooting to ${BUILD_PATH}" if [ "$OPT" = "chroot" ]; then print_info "/sbin/chroot ${BUILD_PATH}" /sbin/chroot "${BUILD_PATH}" RET=${?} if [ ${RET} -ne 0 ]; then error "line ${LINENO} Warning : chrooting to ${BUILD_PATH} retrurn an error ${RET}" ERRORN=$((${ERRORN}+1)) fi else print_info "/sbin/chroot --userspec root:root ${BUILD_PATH} /usr/bin/bash -v -c 'bash /second_stage_install.sh 2>&1'" /sbin/chroot --userspec root:root "${BUILD_PATH}" /usr/bin/bash -v -c 'bash /second_stage_install.sh 2>&1' RET=${?} if [ ${RET} -ne 0 ]; then error "line ${LINENO} Warning : chrooting to ${BUILD_PATH} retrurn an error ${RET}" ERRORN=$((${ERRORN}+1)) fi fi return 0 } function createImageWrap() { title "Wrap image creation" preImgCreation if [ ${?} -ne 0 ]; then error "line ${LINENO} error in the process ${CONFIG_PATH}/specialFunctions.sh ." cleanExit ${ERR_1} fi createimage # loopingImage partitionningimage BOOTFS=${BOOTFS:="ext4"} formatpartitions ${BOOTFS} ext4 loopingImage return 0 } function createimage() { title "Createimage" print_info "will be the file : ${INSTALL_PATH}/${IMAGE}" if [ -f "${INSTALL_PATH}/${IMAGE}" ]; then warning "Deleting previous image" /usr/bin/rm -f "${INSTALL_PATH}/${IMAGE}" if [ ${?} -ne 0 ]; then error "line ${LINENO} error can't remove previous image at ${INSTALL_PATH}/${IMAGE} : exiting" cleanExit ${ERR_1} fi fi # warning "please wait until end of image creation" # /usr/bin/dd if=/dev/zero of="${INSTALL_PATH}/${IMAGE}" bs=1MB count=$(( ${IMAGE_SIZE} * 1024 )) status=progress /usr/bin/truncate -s ${IMAGE_SIZE}G "${INSTALL_PATH}/${IMAGE}" if [ ${?} -ne 0 ]; then error "line ${LINENO} can't make image at ${INSTALL_PATH}/${IMAGE} : exiting" cleanExit ${ERR_1} fi /usr/bin/chown ${USER}:${USER} "${INSTALL_PATH}/${IMAGE}" return 0 } function partitionningimage() { title "Partitionning image" # if [ "x" != "${FDISK_SCRIPT:="x"}" ]; then # echo -e "${FDISK_SCRIPT}" | /sbin/fdisk ${DEVICE} # el if [ "x" != "${SFDISK_SCRIPT:="x"}" ]; then HDD_INFO="$(echo -e "${SFDISK_SCRIPT}" | /usr/sbin/sfdisk "${INSTALL_PATH}/${IMAGE}")" echo "${HDD_INFO}" SECTOR_SIZE="$(echo "${HDD_INFO}" | grep -m1 "Units: sectors" | sed -e 's/^.* \([[:digit:]]\+\) bytes[[:space:]]*$/\1/')" if [ 1 -eq ${SEPARATE_BOOT_PARTITION} ]; then BOOT_P_INFO=$(echo "${HDD_INFO}" | grep -m1 -A3 "^Device" | grep "${IMAGE}1" | tr '*' ' ' | sed -e 's/[[:space:]]\+/ /g') ROOT_P_INFO=$(echo "${HDD_INFO}" | grep -m1 -A3 "^Device" | grep "${IMAGE}2" | tr '*' ' ' | sed -e 's/[[:space:]]\+/ /g') BOOT_OFFSET_S="$(echo "${BOOT_P_INFO}" | sed -e "s/^.*${IMAGE}[[:digit:]][[:space:]\*]\+//g" | cut -d ' ' -f 1)" BOOT_NB_SECTORS=$(echo "${BOOT_P_INFO}" | sed -e "s/^.*${IMAGE}[[:digit:]][[:space:]\*]\+//g" | cut -d ' ' -f 3) BOOT_SIZE_KB="$((${SECTOR_SIZE}*${BOOT_NB_SECTORS}/1024))" BOOT_SIZE_B="$((${SECTOR_SIZE}*${BOOT_NB_SECTORS}))" BOOT_OFFSET_KB="$((${SECTOR_SIZE}*${BOOT_OFFSET_S}/1024))" print_info "Boot offset : ${BOOT_OFFSET_S}" print_info "Boot offset (kB) : ${BOOT_OFFSET_KB}" print_info "Boot sectors : ${BOOT_NB_SECTORS}" print_info "Boot size (kB) : ${BOOT_SIZE_KB}" print_info "Boot size (B) : ${BOOT_SIZE_B}" else ROOT_P_INFO=$(echo "${HDD_INFO}" | grep -m1 -A3 "^Device" | grep "${IMAGE}1") fi ROOT_OFFSET_S=$(echo "${ROOT_P_INFO}" | sed -e "s/^.*${IMAGE}[[:digit:]][[:space:]\*]\+//g" | cut -d ' ' -f 1) ROOT_NB_SECTORS=$(echo "${ROOT_P_INFO}" | sed -e "s/^.*${IMAGE}[[:digit:]][[:space:]\*]\+//g" | cut -d ' ' -f 3) ROOT_SIZE_KB="$((${SECTOR_SIZE}*${ROOT_NB_SECTORS}/1024))" ROOT_OFFSET_B="$((${SECTOR_SIZE}*${ROOT_OFFSET_S}))" print_info "Root offset : ${ROOT_OFFSET_S}" print_info "Root offset (B) : ${ROOT_OFFSET_B}" print_info "Root sectors : ${ROOT_NB_SECTORS}" print_info "Root size kB : ${ROOT_SIZE_KB}" else error "Error, no partitionning script found." cleanExit ${ERR_1} fi return 0 } function loopingImage() { title "Looping image ..." if ! [ -x /usr/bin/udisksctl ]; then error "Error, udisks2 is missing." cleanExit ${ERR_1} fi # Mettre en place et contrôler des périphériques boucle. # -f, --find trouver le premier périphérique inutilisé # --show afficher le nom du périphérique après configuration (avec -f) # DEVICE=$(/usr/sbin/losetup -f --show "${INSTALL_PATH}/${IMAGE}") DEVICE=$(/usr/bin/udisksctl loop-setup -f ${INSTALL_PATH}/${IMAGE} | sed -e 's/^.*\/dev\//\/dev\//' -e 's/\.$//') if [ -z "${DEVICE}" ]; then error "Error, device missing from udisksctl loop-setup output." cleanExit ${ERR_1} fi print_info "Image looped on ${DEVICE}" #Previous function give us a list of partition. It is easy to get it and define prior this list the partition. #But... How to distinguish between the boot p1 and the root p2 if both are empty and ext4 ? ... if [ 1 -eq ${SEPARATE_BOOT_PARTITION} ]; then BOOTP="${DEVICE}p1" ROOTP="${DEVICE}p2" # BOOT_UUID=$(/usr/sbin/blkid -s UUID -o value UUID "${BOOTP}") BOOT_UUID=$(/usr/bin/lsblk -n -o UUID "${BOOTP}") print_info "Boot UUID: ${BOOT_UUID}" else ROOTP="${DEVICE}p1" fi # ROOT_UUID=$(/usr/sbin/blkid -s UUID -o value UUID "${ROOTP}") ROOT_UUID=$(/usr/bin/lsblk -n -o UUID "${ROOTP}") print_info "Root UUID: ${ROOT_UUID}" return 0 } function formatpartitions() { print_info "Formatting partitions" if [ 1 -eq ${SEPARATE_BOOT_PARTITION} ]; then print_info "Boot : ${BOOTP} as ${1}" if [ "vfat" = ${1} ]; then temporary=$(mktemp) truncate -s ${BOOT_SIZE_B} ${temporary} FSINFO=$(/usr/sbin/mkfs.vfat -v ${temporary} ) # $((${BOOT_SIZE_KB}))) /usr/bin/dd seek=${BOOT_OFFSET_S} if=${temporary} of=${INSTALL_PATH}/${IMAGE} BOOT_UUID=$(echo "${FSINFO}" | grep 'Volume ID is' | sed 's/Volume ID is \([[:alnum:]]*\),.*$/\1/') print_info "Boot UUID = ${BOOT_UUID}" rm -f ${temporary} else FSINFO=$(yes | /usr/sbin/mkfs.ext4 -E offset=${BOOT_OFFSET_B} ${INSTALL_PATH}/${IMAGE} $((${BOOT_SIZE_KB}))k) BOOT_UUID=$(echo "${FSINFO}" | grep 'Filesystem UUID' | sed 's/Filesystem UUID: //') fi # "/sbin/mkfs.${1}" "${BOOTP}" if [ ${?} -ne 0 ]; then error "line ${LINENO} error formating ${BOOTP} : exiting" # /usr/sbin/losetup -d "${DEVICE}" udisksctl unmount -b ${BOOTP} cleanExit ${ERR_1} fi # BOOT_UUID=$(/usr/sbin/blkid -s UUID -o value UUID "${BOOTP}") # print_info "Boot UUID: ${BOOT_UUID}" fi print_info "Root : ${ROOTP} as ${2}" # "/sbin/mkfs.${2}" "${ROOTP}" echo /usr/sbin/mkfs.ext4 -E offset=${ROOT_OFFSET_B} ${INSTALL_PATH}/${IMAGE} $((${ROOT_SIZE_KB}))k FSINFO=$(yes | /usr/sbin/mkfs.ext4 -E offset=${ROOT_OFFSET_B} ${INSTALL_PATH}/${IMAGE} $((${ROOT_SIZE_KB}))k) if [ ${?} -ne 0 ]; then error "line ${LINENO} error formating ${ROOTP} : exiting" # /usr/sbin/losetup -d "${DEVICE}" # udisksctl unmount -b ${ROOTP} cleanExit ${ERR_1} fi ROOT_UUID=$(echo "${FSINFO}" | grep 'Filesystem UUID' | sed 's/Filesystem UUID: //') # ROOT_UUID=$(/usr/sbin/blkid -s UUID -o value UUID "${ROOTP}") print_info "Root UUID: ${ROOT_UUID}" return 0 } function generateExtlinux() { print_info "Generate extlinux if extlinux.conf exists." if [ -e "${CONFIG_PATH}/extlinux.conf" ]; then print_info "\tFound extlinux.conf" if [ ! -d "${BUILD_PATH}/boot/extlinux" ]; then print_info "making /boot/extlinux/extlinux.conf" /usr/bin/rm -rf "${BUILD_PATH}/boot/extlinux" mkdir -p "${BUILD_PATH}/boot/extlinux" fi # if [ ! -f "${BUILD_PATH}/boot/extlinux/extlinux.conf" ]; then print_info "\tTuning extlinux.conf" cp "${CONFIG_PATH}/extlinux.conf" "${BUILD_PATH}/boot/extlinux/extlinux.conf" #In order to use the UUID, a initrd file is necessary. sed -i -e "s//${ROOT_UUID}/g" "${BUILD_PATH}/boot/extlinux/extlinux.conf" sed -i -e "s//${BOOT_ARGS}/g" "${BUILD_PATH}/boot/extlinux/extlinux.conf" KERNEL_ID=$(basename ${BUILD_PATH}/usr/lib/linux-*) sed -i -e "s//${KERNEL_ID}/g" "${BUILD_PATH}/boot/extlinux/extlinux.conf" # fi fi } function copyingsystem() { generateExtlinux print_info "Remove second_stage_install.sh" /usr/bin/rm -f "${BUILD_PATH}/second_stage_install.sh" ### BUG : rpi3b+64b is using a bootloader partition, in which only the bootloader lays. Here, everything is copying into. if [ 1 -eq ${SEPARATE_BOOT_PARTITION} ]; then ARM_BOOT="${BUILD_PATH}/mnt/arm_boot" if ! [ -d "${ARM_BOOT}" ]; then rm -rf "${ARM_BOOT}" mkdir -p "${ARM_BOOT}" fi print_info "copying Mageia image to root partition" /usr/bin/rsync -rlptogDHx --exclude "${ARM_BOOT}/" --exclude "qemu-arm-static*" "${BUILD_PATH}/" "${ROOT}/" /usr/bin/rsync -rlptogDHx "${ARM_BOOT}/" "${BOOT}/" #/usr/bin/rsync -rlptogDHx "${BUILD_PATH}/boot/" "${BOOT}/" else print_info "copying Mageia image to root partition" /usr/bin/rsync -rlptogDHx --exclude "qemu-arm-static*" "${BUILD_PATH}/" "${ROOT}/" fi copyingCustomSystem if [ ${?} -ne 0 ]; then error "line ${LINENO} error in the process ${CONFIG_PATH}/specialFunctions.sh ." cleanExit ${ERR_1} fi copyingcommon sync # warning "You can now burn the image ( ${INSTALL_PATH}/${IMAGE} ) on SD card" # print_info "pv \"${INSTALL_PATH}/${IMAGE}\" | dd of=/dev/mmcblk#" return 0 } function mountPartitions() { title "mounting partitions, making mountpoint if necessary" ROOT=$(/usr/bin/udisksctl mount -b ${ROOTP} | sed -e 's/^.* at //' -e 's/\.$//' ) if [ ${?} -ne 0 ]; then error "line ${LINENO} error mounting ${ROOTP} : exiting" cleanExit ${ERR_1} fi MOUNTED_ROOT=true print_info "Root partition mount in ${ROOT}" BUILD_PATH=${ROOT} if [ 1 -eq ${SEPARATE_BOOT_PARTITION} ]; then BOOT=$(/usr/bin/udisksctl mount -b ${BOOTP} | sed -e 's/^.* at //' -e 's/\.$//' ) if [ ${?} -ne 0 ]; then error "line ${LINENO} error mounting ${BOOTP} : exiting" cleanExit ${ERR_1} fi print_info "boot partition mount in ${BOOT}" MOUNTED_BOOT=true mkdir -p "${BUILD_PATH}/boot/EFI" /usr/bin/mount -B ${BOOT} "${BUILD_PATH}/boot/EFI" fi mountdevsysproc } function unmountingPartitions() { title "Unmounting partitions..." unmountdevsysproc # Syncing devices before unmounting /usr/bin/sync if [ -z "${BOOTP}" ] && [ -z "${ROOTP}" ] ; then warning "Root partition and Boot partition not defined !" for LOOP in $(/usr/sbin/losetup -l -O NAME,BACK-FILE -n | grep "${IMAGE}" | cut -d ' ' -f 1 ) ; do IFS=$'\n' for PARTITION in $(/usr/bin/mount -l | grep ${LOOP}); do MOUNTPOINT=$(echo "$PARTITION" | cut -d ' ' -f 3) PARTITION=$(echo "$PARTITION" | cut -d ' ' -f 1) print_info "unmount ${PARTITION}" # and remove ${MOUNTPOINT}" udisksctl unmount -b ${PARTITION} # if [ ${?} -eq 0 ]; then # /usr/bin/rmdir "${MOUNTPOINT}" # else # error "line ${LINENO} error unmounting ${BOOT}..." # fi if [ 0 -ne ${?} ]; then error "line ${LINENO} error unmounting ${PARTITION}..." fi done unset IFS done else if [ ${MOUNTED_BOOT:=false} = true ]; then umount "${BUILD_PATH}/boot/EFI" udisksctl unmount -b ${BOOTP} if [ 0 -ne ${?} ]; then error "line ${LINENO} error unmounting ${BOOTP}..." fi sync sleep 4s fi if [ ${MOUNTED_ROOT:=false} = true ]; then udisksctl unmount -b ${ROOTP} if [ 0 -ne ${?} ]; then error "line ${LINENO} error unmounting ${ROOT}..." fi fi # if [ ! -z "${BOOTP}" ]; then # udisksctl unmount -b ${BOOTP} # if [ ${?} -eq 0 ]; then # /usr/bin/rmdir "${BOOT}" # else # error "line ${LINENO} error unmounting ${BOOT}..." # fi # fi # udisksctl unmount -b ${ROOTP} # if [ ${?} -eq 0 ]; then # /usr/bin/rmdir "${ROOT}" # else # error "line ${LINENO} error unmounting ${ROOT}..." # fi fi return 0 } function unloopingImage() { title "Unlooping image..." # Syncing devices before unmounting /usr/bin/sync if [ "x" != "${DEVICE:="x"}" ]; then /usr/bin/udisksctl loop-delete -b ${DEVICE} else # if [ 0 -ne ${?} ]; then warning "Unloop failed, try to unmount all partitions from the image..." print_info "Looped devices to unmount : $(/usr/sbin/losetup -l -O NAME,BACK-FILE -n | grep "${IMAGE}" | cut -d ' ' -f 1 ) " for LOOP in $(/usr/sbin/losetup -l -O NAME,BACK-FILE -n | grep "${IMAGE}" | cut -d ' ' -f 1 ) ; do for PARTITION in ${LOOP}p* ; do print_info "Unmount ${PARTITION}" udisksctl unmount -b ${PARTITION} done print_info "Unloop ${LOOP}" /usr/bin/udisksctl loop-delete -b ${LOOP} done fi return 0 } # Copying files common to all systems function copyingcommon() { title "Copying common files and configuration" rsync -rlptDHx "${SOURCE_PATH}/common/" "${ROOT}/" rsync -rlptDHx "${SOURCE_PATH}/tools/"*.sh "${ROOT}/usr/local/bin/" chown root:root "${ROOT}/usr/local/bin/" return 0 } function mkfstab() { title "making /etc/fstab" # BUG : For installing kernel inside a chroot, the UUID of root partition is NOT found, Workaround to try : using ${ROOTP} instead. if [ 1 -eq ${SEPARATE_BOOT_PARTITION} ]; then echo -e "proc\t/proc\tproc\tdefaults\t0\t0\nUUID=${BOOT_UUID}\t/boot/EFI\t${BOOTFS}\tdefaults\t0\t0\nUUID=${ROOT_UUID}\t/\text4\tdefaults\t0\t0" > "${BUILD_PATH}/etc/fstab" else echo -e "proc\t/proc\tproc\tdefaults\t0\t0\nUUID=${ROOT_UUID}\t/\text4\tdefaults\t0\t0" > "${BUILD_PATH}/etc/fstab" fi return 0 } # cleaning build space function clean() { title "Cleaning" print_info "In case script failed or crash inside the chroot, need to unmount dev|sys|proc..." # TODO find what blocks the umount. unmountingPartitions unloopingImage # removing old image print_info "Removing ${IMAGE_BASE}* files" /usr/bin/rm -f "${INSTALL_PATH}/${IMAGE_BASE}*.img" /usr/bin/rm -f "${INSTALL_PATH}/${IMAGE_BASE}*.gz" /usr/bin/rm -f "${INSTALL_PATH}/${IMAGE_BASE}*.md5" /usr/bin/rm -f "${INSTALL_PATH}/${IMAGE_BASE}*.sha512" /usr/bin/rm -f "${INSTALL_PATH}/${IMAGE_BASE}*.sha3" return 0 } function check_extrapackage() { for i in ${PACKAGE} ; do /usr/bin/urpmq --urpmi-root "${BUILD_PATH}" --root "${BUILD_PATH}" --ignorearch --no-verify-rpm ${i} if [ 0 -ne ${?} ]; then warning "Package ${i} not found !" else PACKAGE_VALID+="${i} " fi done return 0 } function extrapackage() { if [ "x${DESKTOP_TASK}" != "x" ]; then installpkg ${DESKTOP_TASK} fi if [ "x${PACKAGE_VALID}" != "x" ]; then installpkg "${PACKAGE_VALID}" fi return 0 } function generateExtra() { #Set values by default to false. GEN_CHECKSUM=${GEN_CHECKSUM:="false"} GEN_GZ=${GEN_GZ:="false"} GEN_SIGN=${GEN_SIGN:="false"} if ${GEN_CHECKSUM} ; then title "Generate checksum" md5sum "${INSTALL_PATH}/${IMAGE}" > "${INSTALL_PATH}/${IMAGE}.md5" sha512sum "${INSTALL_PATH}/${IMAGE}" > "${INSTALL_PATH}/${IMAGE}.sha512" sha384sum "${INSTALL_PATH}/${IMAGE}" > "${INSTALL_PATH}/${IMAGE}.sha3" print_info "${INSTALL_PATH}/${IMAGE}.md5" print_info "${INSTALL_PATH}/${IMAGE}.sha512" print_info "${INSTALL_PATH}/${IMAGE}.sha3" fi if ${GEN_GZ} ; then title "Image compression" pv "${INSTALL_PATH}/${IMAGE}" | gzip -9 >"${INSTALL_PATH}/${IMAGE}.gz" fi if ${GEN_SIGN} ; then title "Signing checksums" pushd "${INSTALL_PATH}" if [ -e "${INSTALL_PATH}/${IMAGE}.md5" ]; then gpg --sign ${IMAGE}.md5 fi if [ -e "${INSTALL_PATH}/${IMAGE}.sha512" ]; then gpg --sign ${IMAGE}.sha512 fi if [ -e "${INSTALL_PATH}/${IMAGE}.sha3" ]; then gpg --sign ${IMAGE}.sha384 fi popd fi } function preImgCreation() { error "This function is called if no sourced file about fdisk was lauched." return 1 } function postPrepareChroot() { error "This function is called if no sourced file is containing postPrepareChroot function." return 1 } function bunrningBootloader() { error "This function is called if no sourced file is containing bunrningBootloader function." return 1 } function copyingCustomSystem() { error "This function is called if no sourced file is containing copyingCustomSystem function." return 1 } ERRORN=0 ERR_1=1 ERR_DEFAULT_CONFIG=2 ERR_NO_CONFIG_FILE=3 ERR_NOT_ROOT=4 ERR_DEPENDENCY_MISSING=5 ERR_NO_SPACE=6 ERR_7=7 ERR_8=8 ERR_9=9 SEPARATE_BOOT_PARTITION=1