#!/bin/sh R="" export LD_LIBRARY_PATH=/platform/lib:/nic/lib:$LD_LIBRARY_PATH export PATH=/platform/bin:$PATH if [ $(arch) != aarch64 ]; then export PATH=$(pwd)/bin:$PATH R=$(pwd)/data fi root_mnt=$R/mnt image_version={{ SONIC_IMAGE_VERSION }} image_dir=image-$image_version INSTALLER_PAYLOAD=fs.zip DOCKERFS_DIR=docker FILESYSTEM_DOCKERFS=dockerfs.tar.gz BL_CONF=boot.conf DATA_PARTUUID=6ED62003-DD8D-44B8-9538-0A2B7C7E628F ROOT_PARTUUID=C7F48DD2-C265-404B-959D-C64D21D49168 ROOT_PARTSIZE=24G exec 0< /dev/tty 1> /dev/tty 2> /dev/tty PKG="" ACTION="" root_pn=0 data_pn=0 REPART_NEEDED=0 set -e fatal() { echo "FATAL: $1" >&2 exit 1 } hash() { sha512sum $1 | awk '{ print $1 }' } check_running_goldfw() { local fw=$(expr "$(cat $R/proc/cmdline)" : '.*FW_NAME=\([a-z]\+\)') if [ "$fw" != "goldfw" ]; then fatal "Installer can only be run from goldfw" fi } check_package() { local f want_hash got_hash echo "==> Checking package" for f in $(jq -r ".shas | keys | join(\" \") | tostring" MANIFEST); do echo -n "${f}..." want_hash=$(jq -r .shas.\"$f\" MANIFEST) got_hash=$(tar xfO $PKG $f | hash /dev/stdin) if [ "$got_hash" != "$want_hash" ]; then echo " BAD" echo "WANT: $want_hash" echo "GOT: $got_hash" fatal "Package file error" else echo " OK" fi done } get_install_mode() { local r while [ -z "$install_mode" ]; do echo "### Select install mode:" echo "### 1. Whole disk (wipe all Pensando filesystems)" echo "### 2. Half of /data (lose /data contents)" echo "### 3. Half of /data (save/restore /data contents)" read -p '### Selection: ' r case "X-$r" in X-1) install_mode=FULL_DISK; ;; X-2) install_mode=DATA_LOSE; ;; X-3) install_mode=DATA_KEEP; ;; *) fatal "ABORTED"; ;; esac done } check_existing_parts() { local nparts i partuuid boot_partsize boot_lastsec data_firstsec nparts=$(sgdisk -p /dev/mmcblk0 | grep '^[ ]*[1-9]' | wc -l) for i in $(seq $nparts); do partuuid=$(sgdisk -i $i /dev/mmcblk0 | awk '/Partition unique GUID/ { print $NF }') case "$partuuid" in $DATA_PARTUUID) data_pn=$i; ;; $ROOT_PARTUUID) root_pn=$i; ;; esac done if [ $install_mode != FULL_DISK ]; then if [ $root_pn -ne 0 ]; then boot_partsize=$(sgdisk -i $root_pn /dev/mmcblk0 | awk -F '[( ]' '/Partition size/ {print int($6)}') boot_lastsec=$(sgdisk -i $root_pn /dev/mmcblk0 | awk '/Last sector/ {print $3}') if [ ${boot_partsize}G = $ROOT_PARTSIZE ]; then echo "SONiC root partitions already present with requested size. No repartition, only formatting" else echo "SONiC root partitions already present with mismatch size ${partsize}G. Repartition needed" REPART_NEEDED=1 fi fi if [ $data_pn -eq 0 ]; then echo "Data partition not found; Repartition needed" REPART_NEEDED=1 elif [ $data_pn -ne $nparts ]; then fatal "Data partition is not the last partition; exiting." >&2 else data_firstsec=$(sgdisk -i $data_pn /dev/mmcblk0 | awk '/First sector/ {print $3}') if [ $data_firstsec -ne $((boot_lastsec+1)) ]; then echo "Data partition not contigent with boot partition. Repartition needed" REPART_NEEDED=1 fi fi fi } save_data() { echo "==> Saving /data" mount /dev/mmcblk0p$data_pn $R/mnt tar cvf $R/root/data.tar -C $R/mnt . umount $R/mnt } setup_partitions_full() { local i echo "==> Setting up partitions..." root_pn=1 set +e sgdisk -Z /dev/mmcblk0 >/dev/null 2>&1 partprobe >/dev/null 2>&1 sgdisk \ -n $root_pn:+0:+$ROOT_PARTSIZE -t $root_pn:8300 \ -u $root_pn:$ROOT_PARTUUID -c $root_pn:"SONiC Root Filesystem" \ /dev/mmcblk0 >/dev/null while true; do partprobe if [ ! -e $R/dev/mmcblk0p3 ]; then break fi sleep 1 done echo "==> Creating filesystems" for i in $root_pn; do mkfs.ext4 -F -q /dev/mmcblk0p$i >/dev/null done set -e } setup_partitions_multi() { echo "==> Setting up partitions..." set +e if [ $REPART_NEEDED -eq 0 ]; then mkfs.ext4 -F -q /dev/mmcblk0p$root_pn >/dev/null else if [ $root_pn -ne 0 ]; then sgdisk -d $root_pn /dev/mmcblk0 >/dev/null fi [ $data_pn -ne 0 ] && sgdisk -d $data_pn /dev/mmcblk0 >/dev/null if [ $root_pn -eq 0 ]; then root_pn=10 data_pn=$(($root_pn + 1)) fi if [ $data_pn -eq 0 ]; then data_pn=$(($root_pn + 1)) fi sgdisk \ -n $root_pn:+0:+$ROOT_PARTSIZE -t $root_pn:8300 \ -u $root_pn:$ROOT_PARTUUID -c $root_pn:"SONiC Root Filesystem" \ -n $data_pn:+0:0 -t $data_pn:8300 -u $data_pn:$DATA_PARTUUID \ -c $data_pn:"Data Filesystem" \ /dev/mmcblk0 >/dev/null sgdisk -U R /dev/mmcblk0 >/dev/null while true; do partprobe if [ -e $R/dev/mmcblk0p$data_pn ]; then break fi sleep 1 done echo "==> Creating filesystems" for i in $root_pn $data_pn; do mkfs.ext4 -F -q /dev/mmcblk0p$i >/dev/null done fi set -e } setup_partitions() { if [ $install_mode = INSTALL_FULL ]; then setup_partitions_full else setup_partitions_multi fi } restore_data() { echo "==> Restoring /data" if [ -f $R/root/data.tar ]; then mount /dev/mmcblk0p$data_pn $R/mnt tar xpvf $R/root/data.tar -C $R/mnt umount $R/mnt fi } create_bootloader_conf() { echo "==> Create bootloader config" cat <> $root_mnt/$BL_CONF default main label main kernel /$image_dir/boot/vmlinuz-6.1.0-11-2-arm64 initrd /$image_dir/boot/initrd.img-6.1.0-11-2-arm64 devicetree /$image_dir/boot/elba-asic-psci.dtb append softdog.soft_panic=1 FW_NAME=mainfwa root=/dev/mmcblk0p10 rw rootwait rootfstype=ext4 loopfstype=squashfs loop=/$image_dir/fs.squashfs } EOF } install_root_filesystem() { echo "==> Installing root filesystem" mount /dev/mmcblk0p$root_pn $root_mnt mkdir -p $root_mnt/$image_dir # Decompress the file for the file system directly to the partition if [ x"$docker_inram" = x"on" ]; then # when disk is small, keep dockerfs.tar.gz in disk, expand it into ramfs during initrd tar xfO $PKG $INSTALLER_PAYLOAD | unzip -o - -x "platform.tar.gz" -d $root_mnt/$image_dir else tar xfO $PKG $INSTALLER_PAYLOAD | unzip -o - -x "$FILESYSTEM_DOCKERFS" "platform.tar.gz" -d $root_mnt/$image_dir TAR_EXTRA_OPTION="--numeric-owner" mkdir -p $root_mnt/$image_dir/$DOCKERFS_DIR tar xfO $PKG $INSTALLER_PAYLOAD | unzip -op - "$FILESYSTEM_DOCKERFS" | tar xz $TAR_EXTRA_OPTION -f - -C $root_mnt/$image_dir/$DOCKERFS_DIR fi create_bootloader_conf umount $root_mnt } set_boot_command() { local pn #set to mainfwa where sonic is installed mtd=/dev/$(grep fwsel /proc/mtd | sed -e 's/:.*//') flash_erase -q $mtd 0 1 echo -n mainfwa | dd of=$mtd status=none echo "==> Setting u-boot environment for Debian Boot" pn=$(printf "%x" $root_pn) fwenv -E \ -s kernel_comp_addr_r 88000000 \ -s kernel_comp_size 8000000 \ -s kernel_addr_r a0000000 \ -s fdt_addr_r bb100000 \ -s ramdisk_addr_r a4000000 \ -s bootcmd "sysboot mmc 0:$pn any bf000000 /$BL_CONF" } main() { while getopts ":p:i:" opt; do case "$opt" in p) PKG=$OPTARG; ;; i) ACTION=INSTALL; ;; *) true; ;; esac done if [ "$PKG" = "" -o "$ACTION" != "INSTALL" ]; then fatal "Needs -p filename -i all" fi tar xf $PKG MANIFEST check_running_goldfw check_package # get_install_mode install_mode=DATA_KEEP check_existing_parts if [ $install_mode = DATA_KEEP -a $REPART_NEEDED -eq 1 -a $data_pn -ne 0 ]; then save_data fi setup_partitions if [ $install_mode = DATA_KEEP -a $REPART_NEEDED -eq 1 ]; then restore_data fi install_root_filesystem set_boot_command echo "==> Installation complete" } main "$@"