sonic-buildimage/files/Aboot/boot0.j2
Samuel Angebault e9e6bc58a7 [arista] Improve platform detection mechanism (#3921)
Rely on platform= and sid= on the command line to detect the platform rather than the eeprom
The platform will now properly initialize even if the system eeprom died or is unreachable.

Add support for the 7260CX3-64E
This is a variant of the 7260CX3-64 with no real difference for software.
2019-12-18 22:46:26 -08:00

418 lines
13 KiB
Django/Jinja

#!/bin/sh
# Copyright (C) 2016 Arista Networks, Inc.
#
# 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 3 of the License, 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 <http://www.gnu.org/licenses/>.
# Aboot stage 0 boot script
#
# This boot0 script can be used in different scenario
# - Installation and boot from Aboot (manual or reboot on a new image)
# - EOS to SONiC fast-reboot (installation and kexec in EOS)
# - SONiC to SONiC fast-reboot (installation and kexec in SONiC)
#
# Use it this way:
# - swipath=path/to/swi install=true boot0
# - swipath=path/to/swi install=true force=true boot0
# - swipath=path/to/swi kexec=true boot0
#
# The logic defaults to the first scenario but providing extra environment variable
# will affect the behavior of the script.
# The list of variables is maintained here
# - KERNEL : relative path to the kernel to execute
# - INITRD : relative path to the initrd to load
# - CMDLINE : place to find the default kernel cmdline to use for the platform
# - VERBOSE : setting it to 1 will enable debug traces
#
# By default the boot0 script will behave for an Aboot based behavior.
# Options can be provided to only run some features of this script.
#
# Extra kernel parameters can be provided at runtime by the user by adding them
# into a kernel-params file.
image_name="image-%%IMAGE_VERSION%%"
dockerfs="{{ FILESYSTEM_DOCKERFS }}"
do_not_clean="do-not-clean"
kernel_params="kernel-params"
aboot_machine="arista_unknown"
info() { printf "%04.2f: $@\n" "$(cut -f1 -d' ' /proc/uptime)"; }
err() { info "Error: $@"; }
warn() { info "Warning: $@"; }
# extract mount point from the swi path, e.g., /mnt/flash/sonic.swi --> /mnt/flash
if [ -z "$target_path" ]; then
if [ -z "$swipath" ]; then
err "target_path= is required when swipath= is not provided"
exit 1
fi
target_path=$(df "$swipath" | tail -1 | tr -s " " | cut -d ' ' -f6)
fi
image_path="$target_path/$image_name"
hook_path="$image_path/platform/hooks"
data_path="$image_path/platform/data"
cmdline_base="$target_path/kernel-params-base"
cmdline_image="$image_path/kernel-cmdline"
boot_config="$target_path/boot-config"
bootconfigvars="KERNEL INITRD CONSOLESPEED PASSWORD NETDEV NETAUTO NETIP NETMASK NETGW NETDOMAIN NETDNS NETHW memtest"
flash_re=" /mnt/flash| /host"
# for backward compatibility with the sonic_upgrade= behavior
install="${install:-${sonic_upgrade:-}}"
parse_environment_config() {
for n in ${bootconfigvars}; do
eval v="\$$n"
if [ "$v" ]; then
echo "$n=$v"
fi
done
}
clean_flash() {
## Remove all the other unnecssary files except swi file, boot-config
for f in $(ls -A $target_path); do
if [ $f != "${swipath##*/}" ] &&
[ $f != "boot-config" ] &&
[ $f != "$kernel_params" ] &&
[ $f != "$cmdline_base" ] &&
[ $f != "aquota.user" ] &&
[ $f != "old_config" ] &&
[ $f != "minigraph.xml" ] &&
[ $f != "snmp.yml" ] &&
[ $f != "acl.json" ]
then
rm -rf "$target_path/$f"
fi
done
}
update_boot_config() {
local key="$1"
local value="$2"
if grep "$key" "$boot_config" 2>&1 > /dev/null; then
sed -i "s#^$key=.*\$#$key=$value#" "$boot_config"
else
echo "$key=$value" >> "$boot_config"
fi
}
get_boot_config() {
local key="$1"
sed -n "s#^$key=##p" "$boot_config" || :
}
update_next_boot() {
local default="$(get_boot_config SWI_DEFAULT)"
if [ -z "$default" ]; then
warn "boot-config has no variable SWI_DEFAULT"
else
update_boot_config SWI "$default"
fi
}
extract_image() {
mkdir -p "$image_path"
info "Extracting swi content"
## Unzip the image except boot0 and dockerfs archive
unzip -oq "$swipath" -x boot0 "$dockerfs" -d "$image_path"
## detect rootfs type
rootfs_type=`grep " $target_path " /proc/mounts | cut -d' ' -f3`
info "Extracting $dockerfs from swi"
## Unpacking dockerfs delayed
## 1. when disk is vfat as it does not support symbolic link
## 2. when disk is small, expand it into ramfs during initrd
if [ "$rootfs_type" != "vfat" -a x"$docker_inram" != x"on" ]; then
mkdir -p "$image_path/{{ DOCKERFS_DIR }}"
if [ -n "$install" ]; then
TAR_EXTRA_OPTION="--numeric-owner --warning=no-timestamp"
fi
## extract docker archive
info "Unpacking $dockerfs"
unzip -oqp "$swipath" "$dockerfs" | tar xzf - -C "$image_path/{{ DOCKERFS_DIR }}" $TAR_EXTRA_OPTION
else
## save dockerfs archive in the image directory
unzip -oq "$swipath" "$dockerfs" -d "$image_path"
info "Unpacking $dockerfs delayed to initrd because $target_path is $rootfs_type or docker_inram is on"
fi
## use new reduced-size boot swi
local swi_boot_path="flash:$image_name/{{ ABOOT_BOOT_IMAGE }}"
update_boot_config SWI "$swi_boot_path"
update_boot_config SWI_DEFAULT "$swi_boot_path"
## Remove installer swi as it has lots of redundunt contents
rm -f "$swipath"
## sync disk operations
sync
}
write_machine_config() {
## Detect SKU and create a hardware description file
aboot_version=$(grep ^Aboot "$cmdline_base" | sed 's/^.*norcal.-//' | tail -n 1)
if [ -x /bin/sysinit ]; then
aboot_build_date=$(stat -c %y /bin/sysinit | sed 's/ /T/')
else
aboot_build_date="unknown"
fi
cat <<EOF > ${target_path}/machine.conf
aboot_version=$aboot_version
aboot_vendor=arista
aboot_platform=x86_64-$aboot_machine
aboot_machine=$aboot_machine
aboot_arch=x86_64
aboot_build_date=$aboot_build_date
EOF
chmod a+r "${target_path}/machine.conf"
}
platform_specific() {
local platform="$(grep -Eo 'platform=[^ ]+' "$cmdline_base" | cut -f2 -d=)"
local sid="$(grep -Eo 'sid=[^ ]+' "$cmdline_base" | cut -f2 -d=)"
# set varlog size to 100MB
local varlog_size=100
# detect the size of the flash partition from name in Aboot/EOS/SONiC
local flash_size=$(($(df | grep -E "$flash_re" | tr -s ' ' | cut -f2 -d' ') / 1000))
if [ "$platform" = "raven" ]; then
aboot_machine=arista_7050_qx32
flash_size=2000
docker_inram=on
echo "modprobe.blacklist=radeon,sp5100_tco acpi=off docker_inram=on" >>/tmp/append
fi
if [ "$platform" = "crow" ]; then
aboot_machine=arista_7050_qx32s
flash_size=3700
echo "modprobe.blacklist=radeon,sp5100_tco" >>/tmp/append
fi
if [ "$sid" = "Upperlake" ] || [ "$sid" = "UpperlakeES" ]; then
aboot_machine=arista_7060_cx32s
flash_size=3700
echo "amd_iommu=off" >> /tmp/append
fi
if [ "$sid" = "Gardena" ] || [ "$sid" = "GardenaSsd" ] || [ "$sid" = "GardenaE" ]; then
aboot_machine=arista_7260cx3_64
flash_size=28000
fi
if [ "$sid" = "Alhambra" ] || [ "$sid" = "AlhambraSsd" ]; then
aboot_machine=arista_7170_64c
flash_size=28000
echo "hugepages=128" >> /tmp/append
fi
if [ "$platform" = "rook" ]; then
echo "iommu=on intel_iommu=on tsc=reliable pcie_ports=native" >>/tmp/append
echo "rhash_entries=1 usb-storage.delay_use=0" >>/tmp/append
if [ -x /bin/readprefdl ]; then
readprefdl -f /tmp/.system-prefdl -d > /mnt/flash/.system-prefdl
elif [ -f /etc/prefdl ]; then
cp /etc/prefdl /mnt/flash/.system-prefdl
chmod a+r /mnt/flash/.system-prefdl
fi
echo "reassign_prefmem" >> /tmp/append
fi
if [ $flash_size -ge 28000 ]; then
varlog_size=4096
elif [ $flash_size -ge 3700 ]; then
varlog_size=400
fi
echo "varlog_size=$varlog_size" >>/tmp/append
# disable deterministic interface naming
echo "net.ifnames=0" >>/tmp/append
}
get_uuid_for() {
local dev="$1"
if type lsblk 2>&1 > /dev/null; then
lsblk "$dev" -n --output UUID
elif type blkid 2>&1 > /dev/null; then
blkid | grep "^$dev" | sed -n "s/^.* UUID=\"//p" | grep -Eo '[^"]+'
fi
}
write_boot_configs() {
if $in_aboot; then
# generate the default kernel parameters for the platform
echo "$append" > $cmdline_base
cat /etc/cmdline | sed "/^\(${bootconfigvars// /\|}\|crashkernel\|loglevel\|ignore_loglevel\)\(\$\|=\)/d;/^\$/d" >> $cmdline_base
parse_environment_config >> $cmdline_base
elif [ ! -f "$cmdline_base" ]; then
# some systems were started with other versions of this script and therefore
# do not have the $cmdline_base file. we assume that we are on Sonic or EOS.
cat /proc/cmdline | sed -E 's/^(.*) rw .*$/\1/' | tr ' ' '\n' > $cmdline_base
fi
cp $cmdline_base /tmp/append
platform_specific
echo "rw loop=$image_name/fs.squashfs loopfstype=squashfs apparmor=1 security=apparmor quiet" >> /tmp/append
# Pass the MAC address to the new kernel as a command line parameter. This makes it
# possible to restore the MAC address in the new kernel without requiring driver modifications.
if [ -f /sys/class/net/ma1/address ]; then
echo "hwaddr_ma1=$(cat /sys/class/net/ma1/address)" >> /tmp/append
elif [ -f /sys/class/net/eth0/address ]; then
echo "hwaddr_ma1=$(cat /sys/class/net/eth0/address)" >> /tmp/append
else
err "Management port not found."
fi
# use extra parameters from kernel-params hook if the file exists
if [ -f "$target_path/$kernel_params" ]; then
cat "$target_path/$kernel_params" >> /tmp/append
fi
# setting root partition if not overridden by kernel-params
if ! grep -q "root=" /tmp/append; then
rootdev="$(mount | grep -E "$flash_re" | cut -f1 -d' ')"
rootfstype="$(mount | grep -E "$flash_re" | cut -f5 -d' ')"
rootuuid="$(get_uuid_for $rootdev)"
if [ -z "$rootuuid" ] || [ "$rootfstype" = "vfat" ] ; then
echo "root=$rootdev" >> /tmp/append
else
echo "root=UUID=$rootuuid" >> /tmp/append
fi
fi
mkdir -p "$image_path"
mv /tmp/append $cmdline_image
[ -e ${target_path}/machine.conf ] || write_machine_config
}
run_kexec() {
local cmdline="$(cat $cmdline_image | tr '\n' ' ')"
local kernel="${KERNEL:-$(find $image_path/boot -name 'vmlinuz-*' -type f | head -n 1)}"
local initrd="${INITRD:-$(find $image_path/boot -name 'initrd.img-*' -type f | head -n 1)}"
if ! $verbose; then
# Start showing systemd information from the first failing unit if any.
# systemd.show_status=false or quiet can be used to silence systemd entierly
cmdline="$cmdline systemd.show_status=auto"
fi
kexec --load --initrd="$initrd" --append="$cmdline" "$kernel"
[ -z "$testonly" ] || exit 0
info "Kexecing..."
kexec --exec
}
get_sorted_hooks() {
echo $(find "$1" -name '[0-9][0-9]-*' -type f)
}
run_hooks() {
if [ -d "$hook_path/$1" ]; then
for hook in $(get_sorted_hooks "$hook_path/$1"); do
if [ ! -z "$hook" ]; then
info "Running hook $(basename $hook)"
. "$hook"
fi
done
fi
}
# In Aboot no option will be provided therefore these are the default values to use
in_aboot=true
do_clean=true
do_install=true
do_kexec=true
# prevent the flash from being cleaned if the do-not-clean file exists
if [ -f "$target_path/$do_not_clean" ]; then
do_clean=false
fi
# Parse the cmdline options (used from EOS or from SONiC)
if [ ! -z "$install" ]; then
# install from SONiC or EOS
in_aboot=false
do_clean=false
do_kexec=false
elif [ ! -z "$kexec" ]; then
# kexec from SONiC or EOS
in_aboot=false
do_install=false
do_clean=false
elif [ $# -ne 0 ]; then
echo "usage: $0 (see code)"
exit 1
fi
# Verbosity can be defined by the caller, default to false otherwise
verbose=${verbose:-false}
if [ -f "$target_path/verbose-boot" ] ||
[ "$(get_boot_config VERBOSE)" = "1" ] ||
! $in_aboot; then
verbose=true
fi
# enable shell debug mode to get the most verbosity
if $verbose; then
set -x
fi
# install the image if newer
if $do_install; then
# we expect the swi to install to be a non empty file
if [ ! -s "$swipath" ]; then
err "The swipath= environment variable does not point to a valid SWI"
exit 1
fi
# check the hash file in the image, and determine to install or just skip
GIT_REVISION=$(unzip -p "$swipath" .imagehash)
LOCAL_IMAGEHASH=$(cat $image_path/.imagehash 2>/dev/null || true)
if [ "$GIT_REVISION" != "$LOCAL_IMAGEHASH" ] || [ ! -z "$force" ]; then
if $do_clean; then
info "Cleaning flash content $target_path"
clean_flash
fi
info "Generating boot-config, machine.conf and cmdline"
write_boot_configs
info "Installing image under $image_path"
extract_image
run_hooks post-install
else
info "Using previously installed image"
fi
fi
# chainloading using kexec
if $do_kexec; then
run_hooks pre-kexec
update_next_boot
run_kexec
fi