78c41a1e58
Why I did it After docker_inram is enabled, the docker folder's default max size is 1.5G. It's not big enough for some tests which need to install additional docker images or install extra packages. Work item tracking Microsoft ADO 24199761: How I did it add docker_inram into cmdline_allowlist How to verify it sudo sh -c 'echo "docker_inram_size=3000M" >> kernel-cmdline-append' sudo reboot and check the docker folder size
964 lines
28 KiB
Django/Jinja
964 lines
28 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 the kernel-params file.
|
|
#
|
|
# Secureboot of SONiC SWI images is also supported.
|
|
# In such cases, there will only be a partial install on the flash.
|
|
# SONiC will be mostly booting in RAM as a live operating system.
|
|
|
|
# All templated variables should be declared here
|
|
image_name="image-%%IMAGE_VERSION%%"
|
|
dockerfs="{{ FILESYSTEM_DOCKERFS }}"
|
|
boot_image="{{ ABOOT_BOOT_IMAGE }}"
|
|
installer_image="sonic.swi"
|
|
docker_dir="{{ DOCKERFS_DIR }}"
|
|
|
|
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: $@"; }
|
|
|
|
if [ $# -ne 0 ]; then
|
|
echo "usage: $0 (see code)"
|
|
exit 1
|
|
fi
|
|
|
|
mountpoint_for_file() {
|
|
local file="$1"
|
|
df "$file" 2>/dev/null | tail -1 | tr -s " " | cut -d ' ' -f6
|
|
}
|
|
|
|
# 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=$(mountpoint_for_file "$swipath")
|
|
fi
|
|
image_path="$target_path/$image_name"
|
|
hook_path="$image_path/platform/hooks"
|
|
data_path="$image_path/platform/data"
|
|
boot_image_path="$image_path/$boot_image"
|
|
installer_image_path="$image_path/$installer_image"
|
|
|
|
boot_config="$target_path/boot-config"
|
|
|
|
cmdline_allowlist="crashkernel hwaddr_ma1 sonic_fips docker_inram"
|
|
|
|
# for backward compatibility with the sonic_upgrade= behavior
|
|
install="${install:-${sonic_upgrade:-}}"
|
|
|
|
is_secureboot_enabled() {
|
|
if $in_aboot; then
|
|
if [ -x /bin/securebootctl ] && securebootctl sb -display | grep -q "Secure Boot enabled"; then
|
|
return 0
|
|
fi
|
|
return 1
|
|
else
|
|
if grep -q aboot.secureboot /proc/cmdline; then
|
|
return 0
|
|
fi
|
|
# FIXME: EOS is not handled here
|
|
return 1
|
|
fi
|
|
}
|
|
|
|
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 != "preserve-installer" ] &&
|
|
[ $f != "$kernel_params" ] &&
|
|
[ $f != "aquota.user" ] &&
|
|
[ $f != "old_config" ] &&
|
|
[ $f != "minigraph.xml" ] &&
|
|
[ $f != "snmp.yml" ] &&
|
|
[ $f != "acl.json" ] &&
|
|
[ $f != "port_config.json" ] &&
|
|
[ $f != "golden_config_db.json" ]
|
|
then
|
|
rm -rf "$target_path/$f"
|
|
fi
|
|
done
|
|
}
|
|
|
|
in_array() {
|
|
local value="$1"
|
|
shift
|
|
|
|
for other in $@; do
|
|
if [ "$value" = "$other" ]; then
|
|
return 0
|
|
fi
|
|
done
|
|
|
|
return 1
|
|
}
|
|
|
|
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
|
|
info "Next reboot will use $default"
|
|
update_boot_config SWI "$default"
|
|
fi
|
|
}
|
|
|
|
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
|
|
}
|
|
|
|
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' | sed 's/".*$//'
|
|
fi
|
|
}
|
|
|
|
cmdline_append() {
|
|
cat >> /tmp/append
|
|
}
|
|
|
|
cmdline_clear() {
|
|
echo -n > /tmp/append
|
|
}
|
|
|
|
cmdline_add() {
|
|
echo "$@" >> /tmp/append
|
|
}
|
|
|
|
cmdline_has() {
|
|
grep -q "$1" /tmp/append
|
|
}
|
|
|
|
cmdline_echo() {
|
|
# echo trims and remove whitespace duplicates
|
|
echo $(cat /tmp/append | tr '\n' ' ')
|
|
}
|
|
|
|
cmdline_get() {
|
|
# extract last matching value for key
|
|
sed -nr "s/.*$1=([^ ]+).*/\1/p" /tmp/append | tail -n 1
|
|
}
|
|
|
|
find_first_kernel_under() {
|
|
local path="$1"
|
|
find "$path" -name 'vmlinuz-*' -type f | head -n 1
|
|
}
|
|
|
|
find_first_initrd_under() {
|
|
local path="$1"
|
|
find "$path" -name 'initrd.img-*' -type f | head -n 1
|
|
}
|
|
|
|
is_file_in_memory() {
|
|
local file="$1"
|
|
local filemnt=$(mountpoint_for_file "$file")
|
|
local filemntfs=$(mount | grep " $filemnt " | cut -f5 -d' ')
|
|
|
|
case "$filemntfs" in
|
|
tmpfs|ramfs) return 0;;
|
|
*) return 1;;
|
|
esac
|
|
}
|
|
|
|
get_tmpfs() {
|
|
local tmpfs="$(mktemp -d)"
|
|
|
|
mkdir -p "$tmpfs"
|
|
if ! $in_aboot && ! mount | grep -q ' /tmp type tmpfs'; then
|
|
# mount a real tmpfs on /tmp/xxx if /tmp is not one already.
|
|
mount -t tmpfs "$(dirname $tmpfs)" "$tmpfs"
|
|
fi
|
|
echo "$tmpfs"
|
|
}
|
|
|
|
clean_tmpfs() {
|
|
local tmpfs="$1"
|
|
|
|
case "$tmpfs" in
|
|
/tmp) return 0;;
|
|
/tmp/*);; # only cleanup tmpfs created by this script
|
|
*) return 0;;
|
|
esac
|
|
|
|
if mount | grep -q "$tmpfs"; then
|
|
umount "$tmpfs" || :
|
|
fi
|
|
}
|
|
|
|
move_swi_to_tmpfs() {
|
|
local oldswi="$1"
|
|
|
|
if is_file_in_memory "$oldswi"; then
|
|
echo "$oldswi"
|
|
return 0
|
|
fi
|
|
|
|
local tmpfs="$(get_tmpfs)"
|
|
local newswi="$tmpfs/$(basename "$oldswi")"
|
|
|
|
mv "$oldswi" "$newswi"
|
|
echo "$newswi"
|
|
}
|
|
|
|
cleanup_swi_tmpfs() {
|
|
rm -f "$swipath"
|
|
clean_tmpfs "$(mountpoint_for_file "$swipath")"
|
|
}
|
|
|
|
mount_relpath() {
|
|
local abspath="$1"
|
|
local mountpath="$(df "$abspath" | sed -nr '/\//s/^.* ([^ ]+)$/\1/p')"
|
|
|
|
echo "$abspath" | sed "s#^$mountpath/##"
|
|
}
|
|
|
|
zip_file_offset() {
|
|
local zipfile="$1"
|
|
local filename="$2"
|
|
|
|
if $in_aboot; then
|
|
unzip -qqf "$zipfile" "$filename"
|
|
else
|
|
local hexoffset="$(zipdetails "$zipfile" | sed -En "/Filename +'$filename'/,/^$/p" | sed -En 's/^([^ ]+) PAYLOAD$/\1/p')"
|
|
echo "$((0x$hexoffset))"
|
|
fi
|
|
}
|
|
|
|
SWI_ALREADY_INSTALLED=0
|
|
SWI_NOT_INSTALLED=1
|
|
SWI_VERSION_MISMATCH=2
|
|
SWI_OTHER_VARIANT_INSTALLED=3
|
|
|
|
is_swi_installed() {
|
|
local swi_path="$1"
|
|
local swi_version="$(unzip -qp "$swi_path" .imagehash)"
|
|
local local_version="$(cat $image_path/.imagehash 2>/dev/null || :)"
|
|
|
|
if [ -z "$local_version" ]; then
|
|
# no image installed for this version
|
|
return $SWI_NOT_INSTALLED
|
|
fi
|
|
|
|
if [ "$swi_version" != "$local_version" ]; then
|
|
warn "Installed image has a different version than $swipath"
|
|
return $SWI_VERSION_MISMATCH
|
|
fi
|
|
|
|
if $secureboot; then
|
|
if [ -s "$installer_image_path" ]; then
|
|
# secureboot image already installed
|
|
return $SWI_ALREADY_INSTALLED
|
|
else
|
|
# regular image of the same version already installed
|
|
return $SWI_OTHER_VARIANT_INSTALLED
|
|
fi
|
|
else
|
|
if [ -s "$boot_image_path" ]; then
|
|
# regular image already installed
|
|
return $SWI_ALREADY_INSTALLED
|
|
else
|
|
# secureboot image of the same version already installed
|
|
return $SWI_OTHER_VARIANT_INSTALLED
|
|
fi
|
|
fi
|
|
}
|
|
|
|
extract_image() {
|
|
info "Moving swi to a tmpfs"
|
|
## Avoid problematic flash usage spike on older systems, also improves I/O
|
|
swipath="$(move_swi_to_tmpfs "$swipath")"
|
|
|
|
info "Extracting swi content"
|
|
## Unzip the image except boot0 and dockerfs archive
|
|
unzip -oq "$swipath" -x boot0 "$dockerfs" "platform.tar.gz" -d "$image_path"
|
|
|
|
## Extract the platform.tar.gz
|
|
info "Extracting platform.tar.gz"
|
|
mkdir -p "$image_path/platform"
|
|
unzip -oqp "$swipath" "platform.tar.gz" | tar xzf - -C "$image_path/platform" $TAR_EXTRA_OPTION
|
|
|
|
## detect rootfs type
|
|
local mountstr="$(grep " $target_path " /proc/mounts)"
|
|
local rootdev="$(echo $mountstr | cut -f1 -d' ')"
|
|
rootfs_type="$(echo $mountstr | 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" ] && ! cmdline_has docker_inram=on; then
|
|
mkdir -p "$image_path/$docker_dir"
|
|
|
|
if [ -n "$install" ]; then
|
|
TAR_EXTRA_OPTION="--numeric-owner --warning=no-timestamp"
|
|
fi
|
|
|
|
## extract docker archive
|
|
unzip -oqp "$swipath" "$dockerfs" | tar xzf - -C "$image_path/$docker_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
|
|
|
|
## remove installer since it's not needed anymore
|
|
if $preserve_installer; then
|
|
info "Preserving installer under $installer_image_path"
|
|
mv "$swipath" "$installer_image_path"
|
|
chmod a+r "$installer_image_path"
|
|
else
|
|
info "Remove installer"
|
|
cleanup_swi_tmpfs "$swipath"
|
|
fi
|
|
|
|
## use new reduced-size boot swi
|
|
local swi_boot_path="flash:$image_name/$boot_image"
|
|
update_boot_config SWI "$swi_boot_path"
|
|
update_boot_config SWI_DEFAULT "$swi_boot_path"
|
|
|
|
## sync disk operations
|
|
sync
|
|
}
|
|
|
|
extract_image_secureboot() {
|
|
info "Extracting necessary swi content"
|
|
# NOTE: boot/ is not used by the boot process but only extracted for kdump
|
|
unzip -oq "$swipath" 'boot/*' .imagehash kernel-cmdline-append -d "$image_path"
|
|
|
|
## Extract platform.tar.gz
|
|
info "Extracting platform.tar.gz"
|
|
mkdir -p "$image_path/platform"
|
|
unzip -oqp "$swipath" "platform.tar.gz" | tar xzf - -C "$image_path/platform" $TAR_EXTRA_OPTION
|
|
|
|
info "Installing swi under $installer_image_path"
|
|
mv "$swipath" "$installer_image_path"
|
|
chmod a+r "$installer_image_path"
|
|
swipath="$installer_image_path"
|
|
|
|
local swi_boot_path="flash:$image_name/$installer_image"
|
|
update_boot_config SWI "$swi_boot_path"
|
|
update_boot_config SWI_DEFAULT "$swi_boot_path"
|
|
|
|
sync
|
|
}
|
|
|
|
prepare_image_secureboot() {
|
|
local boot_tmpfs="$(get_tmpfs)"
|
|
|
|
info "Extracting boot content in tmpfs"
|
|
unzip -oq "$swipath" 'boot/*' -d "$boot_tmpfs"
|
|
|
|
info "Generating machine.conf and cmdline"
|
|
write_secureboot_configs
|
|
|
|
sync
|
|
|
|
# override environment variables preventing external tamper on kernel execution
|
|
CMDLINE="$(cmdline_echo) $ENV_EXTRA_CMDLINE"
|
|
KERNEL="$(find_first_kernel_under "$boot_tmpfs")"
|
|
INITRD="$(find_first_initrd_under "$boot_tmpfs")"
|
|
}
|
|
|
|
write_machine_config() {
|
|
## Detect SKU and create a hardware description file
|
|
aboot_version=$(cmdline_get Aboot | sed 's/^.*norcal.-//')
|
|
if [ -x /bin/sysinit ]; then
|
|
aboot_build_date=$(stat -c %y /bin/sysinit | sed 's/ /T/g')
|
|
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"
|
|
}
|
|
|
|
read_system_eeprom() {
|
|
if [ -x /bin/readprefdl ] && [ -f /tmp/.system-prefdl ]; then
|
|
readprefdl -f /tmp/.system-prefdl -d > $target_path/.system-prefdl
|
|
elif [ -f /etc/prefdl ]; then
|
|
cp /etc/prefdl $target_path/.system-prefdl
|
|
chmod a+r $target_path/.system-prefdl
|
|
fi
|
|
}
|
|
|
|
write_platform_specific_cmdline() {
|
|
local platform="$(cmdline_get platform)"
|
|
local sid="$(cmdline_get sid | sed 's/Ssd$//')"
|
|
|
|
local varlog_size=0
|
|
|
|
# sonic_mode is set to fixed by default.
|
|
sonic_mode="fixed"
|
|
supervisor_mode="supervisor"
|
|
linecard_mode="linecard"
|
|
|
|
# detect the size of the flash partition from name in Aboot/EOS/SONiC
|
|
local flash_size=$(($(df "$target_path" | tail -1 | tr -s ' ' | cut -f2 -d' ') / 1000))
|
|
|
|
if [ "$platform" = "raven" ]; then
|
|
# Assuming sid=Cloverdale
|
|
aboot_machine=arista_7050_qx32
|
|
cmdline_add modprobe.blacklist=radeon,sp5100_tco
|
|
cmdline_add acpi=off
|
|
fi
|
|
if [ "$platform" = "crow" ]; then
|
|
# Assuming sid=Clearlake
|
|
aboot_machine=arista_7050_qx32s
|
|
cmdline_add modprobe.blacklist=radeon,sp5100_tco
|
|
fi
|
|
if in_array "$sid" "Upperlake" "UpperlakeES" "UpperlakeElite"; then
|
|
aboot_machine=arista_7060_cx32s
|
|
flash_size=3700
|
|
fi
|
|
if [ "$sid" = "UpperlakePlus" ]; then
|
|
aboot_machine=arista_7060cx2_32s
|
|
flash_size=3700
|
|
fi
|
|
if [ "$sid" = "Gardena" ] || [ "$sid" = "GardenaE" ]; then
|
|
aboot_machine=arista_7260cx3_64
|
|
flash_size=28000
|
|
cmdline_add logs_inram=on
|
|
fi
|
|
if [ "$sid" = "Alhambra" ]; then
|
|
aboot_machine=arista_7170_64c
|
|
flash_size=28000
|
|
cmdline_add hugepages=128
|
|
fi
|
|
if [ "$sid" = "Mineral" ]; then
|
|
aboot_machine=arista_7170_32c
|
|
flash_size=28000
|
|
cmdline_add hugepages=128
|
|
fi
|
|
if [ "$sid" = "MineralD" ]; then
|
|
aboot_machine=arista_7170_32cd
|
|
flash_size=28000
|
|
cmdline_add hugepages=128
|
|
fi
|
|
if [ "$sid" = "Woodleaf" ]; then
|
|
aboot_machine=arista_7170b_64c
|
|
cmdline_add hugepages=128
|
|
fi
|
|
if [ "$sid" = "Lodoga" ]; then
|
|
aboot_machine=arista_7050cx3_32s
|
|
cmdline_add logs_inram=on
|
|
cmdline_add libata.force=2.00:noncq
|
|
fi
|
|
if [ "$sid" = "Marysville" ]; then
|
|
aboot_machine=arista_7050sx3_48yc8
|
|
flash_size=7382
|
|
fi
|
|
if [ "$sid" = "Marysville10" ]; then
|
|
aboot_machine=arista_7050sx3_48c8
|
|
flash_size=7382
|
|
fi
|
|
if [ "$sid" = "BlackhawkO" ]; then
|
|
aboot_machine=arista_7060px4_32
|
|
flash_size=28000
|
|
fi
|
|
if [ "$sid" = "BlackhawkDD" ] || [ "$sid" = "BlackhawkDDM" ]; then
|
|
aboot_machine=arista_7060dx4_32
|
|
flash_size=28000
|
|
fi
|
|
if in_array "$sid" "PikeIslandZ" "PikeIslandZ-F" "PikeIslandZ-2F" "PikeIslandZ-R" "PikeIslandZ-2R"; then
|
|
aboot_machine=arista_720dt_48s
|
|
varlog_size=2048
|
|
fi
|
|
if [ "$sid" = "BlackhawkT4O" ]; then
|
|
aboot_machine=arista_7050px4_32s
|
|
fi
|
|
if [ "$sid" = "BlackhawkT4DD" ]; then
|
|
aboot_machine=arista_7050dx4_32s
|
|
fi
|
|
if [ "$sid" = "Smartsville" ]; then
|
|
aboot_machine=arista_7280cr3_32p4
|
|
fi
|
|
if [ "$sid" = "SmartsvilleBK" ]; then
|
|
aboot_machine=arista_7280cr3k_32p4
|
|
fi
|
|
if [ "$sid" = "SmartsvilleBkMs" ] || [ "$sid" = "SmartsvilleBkMsTpm" ]; then
|
|
aboot_machine=arista_7280cr3mk_32p4
|
|
fi
|
|
if [ "$sid" = "SmartsvilleDD" ]; then
|
|
aboot_machine=arista_7280cr3_32d4
|
|
fi
|
|
if [ "$sid" = "SmartsvilleDDBK" ]; then
|
|
aboot_machine=arista_7280cr3k_32d4
|
|
fi
|
|
if [ "$sid" = "SmartsvilleDDBkMs" ] || [ "$sid" = "SmartsvilleDDBkMsTpm" ]; then
|
|
aboot_machine=arista_7280cr3mk_32d4
|
|
fi
|
|
if [ "$sid" = "CatalinaP" ]; then
|
|
aboot_machine=arista_7060px5_64s
|
|
fi
|
|
if [ "$sid" = "CatalinaDD" ]; then
|
|
aboot_machine=arista_7060dx5_64s
|
|
fi
|
|
if [ "$sid" = "Clearwater2" ]; then
|
|
aboot_machine=arista_7800r3_48cq2_lc
|
|
sonic_mode="$linecard_mode"
|
|
fi
|
|
if [ "$sid" = "Clearwater2Ms" ]; then
|
|
aboot_machine=arista_7800r3_48cqm2_lc
|
|
sonic_mode="$linecard_mode"
|
|
fi
|
|
if [ "$sid" = "WolverineQCpu" ]; then
|
|
aboot_machine=arista_7800r3a_36d2_lc
|
|
sonic_mode="$linecard_mode"
|
|
fi
|
|
if [ "$sid" = "WolverineQCpuBk" ]; then
|
|
aboot_machine=arista_7800r3ak_36d2_lc
|
|
sonic_mode="$linecard_mode"
|
|
fi
|
|
if [ "$sid" = "WolverineQCpuMs" ]; then
|
|
aboot_machine=arista_7800r3a_36dm2_lc
|
|
sonic_mode="$linecard_mode"
|
|
fi
|
|
if [ "$sid" = "WolverineQCpuBkMs" ]; then
|
|
aboot_machine=arista_7800r3ak_36dm2_lc
|
|
sonic_mode="$linecard_mode"
|
|
fi
|
|
if [ "$sid" = "OtterLake" ]; then
|
|
aboot_machine=arista_7800_sup
|
|
flash_size=30000
|
|
sonic_mode=$supervisor_mode
|
|
fi
|
|
if [ "$sid" = "SmartsvilleBkMs" ]; then
|
|
aboot_machine=arista_7280cr3mk_32p4
|
|
flash_size=7382
|
|
fi
|
|
if in_array "$platform" "rook" "magpie" "woodpecker" "sprucefish"; then
|
|
cmdline_add tsc=reliable
|
|
cmdline_add pcie_ports=native
|
|
cmdline_add rhash_entries=1
|
|
cmdline_add usb-storage.delay_use=0
|
|
cmdline_add reassign_prefmem
|
|
fi
|
|
if in_array "$platform" "rook" "sprucefish"; then
|
|
cmdline_add iommu=on
|
|
cmdline_add intel_iommu=on
|
|
cmdline_add intel_idle.max_cstate=0
|
|
read_system_eeprom
|
|
fi
|
|
if in_array "$platform" "rook"; then
|
|
# Currently applies to Alhambra, Blackhawk, Gardena and Mineral
|
|
cmdline_add libata.force=1.00:noncq
|
|
fi
|
|
if in_array "$platform" "crow" "magpie"; then
|
|
cmdline_add amd_iommu=off
|
|
cmdline_add modprobe.blacklist=snd_hda_intel,hdaudio
|
|
cmdline_add sdhci.append_quirks2=0x40
|
|
read_system_eeprom
|
|
fi
|
|
if in_array "$platform" "woodpecker"; then
|
|
cmdline_add modprobe.blacklist=snd_hda_intel,hdaudio
|
|
read_system_eeprom
|
|
fi
|
|
if in_array "$platform" "lorikeet" "hedgehog"; then
|
|
cmdline_add processor.max_cstate=1
|
|
cmdline_add reassign_prefmem
|
|
read_system_eeprom
|
|
fi
|
|
if in_array "$platform" "prairieisland"; then
|
|
read_system_eeprom
|
|
fi
|
|
|
|
if [ $varlog_size -eq 0 ]; then
|
|
if [ $flash_size -ge 28000 ]; then
|
|
varlog_size=4096
|
|
elif [ $flash_size -gt 4000 ]; then
|
|
varlog_size=400
|
|
else
|
|
varlog_size=256
|
|
cmdline_add logs_inram=on
|
|
cmdline_add docker_inram=on
|
|
cmdline_add docker_inram_algo=zstd
|
|
if [ $flash_size -le 2000 ]; then
|
|
# enable docker_inram for switches with less than 2G of flash
|
|
varlog_size=128
|
|
fi
|
|
fi
|
|
fi
|
|
|
|
cmdline_add "varlog_size=$varlog_size"
|
|
cmdline_add "sonic.mode=$sonic_mode"
|
|
}
|
|
|
|
write_image_specific_cmdline() {
|
|
# security
|
|
cmdline_add security=apparmor
|
|
cmdline_add apparmor=1
|
|
|
|
# fs configuration
|
|
cmdline_add rw
|
|
|
|
# disable deterministic interface naming
|
|
cmdline_add net.ifnames=0
|
|
|
|
# disable unified cgroup hierarchy to workaround dockerd limitation
|
|
cmdline_add systemd.unified_cgroup_hierarchy=0
|
|
|
|
# increase kernel log buffer size
|
|
cmdline_add log_buf_len=1M
|
|
|
|
# verbosity
|
|
cmdline_add quiet
|
|
# 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_add systemd.show_status=auto
|
|
|
|
# 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
|
|
cmdline_add "hwaddr_ma1=$(cat /sys/class/net/ma1/address)"
|
|
elif [ -f /sys/class/net/eth0/address ]; then
|
|
cmdline_add "hwaddr_ma1=$(cat /sys/class/net/eth0/address)"
|
|
else
|
|
err "Management port not found."
|
|
fi
|
|
|
|
# Obtain root partition uuid
|
|
local mountstr="$(mount | grep " $target_path ")"
|
|
local rootdev="$(echo $mountstr | cut -f1 -d' ')"
|
|
local rootfstype="$(echo $mountstr | cut -f5 -d' ')"
|
|
local rootuuid="$(get_uuid_for $rootdev)"
|
|
if [ -z "$rootuuid" ] || [ "$rootfstype" = "vfat" ] ; then
|
|
cmdline_add "root=$rootdev"
|
|
else
|
|
cmdline_add "root=UUID=$rootuuid"
|
|
fi
|
|
}
|
|
|
|
write_default_cmdline() {
|
|
local delimiter="cmdline-aboot-end"
|
|
|
|
cmdline_clear
|
|
|
|
if $in_aboot; then
|
|
# generate the default kernel parameters for the platform
|
|
cat /etc/cmdline | sed "/^\(${bootconfigvars// /\|}\|crashkernel\|loglevel\|ignore_loglevel\)\(\$\|=\)/d;/^\$/d" | cmdline_append
|
|
elif grep -q "$delimiter" /proc/cmdline; then
|
|
# we are on a recent sonic image using delimiter. extracting the part of the
|
|
# cmdline coming from aboot is trivial.
|
|
cat /proc/cmdline | sed -E "s/^(.*) $delimiter .*$/\1/" | tr ' ' '\n' | cmdline_append
|
|
else
|
|
# we are either on SONiC or EOS and the commandline doesn't have a delimiter
|
|
# for the Aboot part. Take an educated guess at a right delimiter.
|
|
# Subject to breakage if EOS or SONiC cmdline change.
|
|
cat /proc/cmdline | sed -E 's/^(.*) rw .*$/\1/' | tr ' ' '\n' | cmdline_append
|
|
fi
|
|
|
|
cmdline_add "$delimiter"
|
|
}
|
|
|
|
write_cmdline() {
|
|
# use extra parameters from kernel-params hook if the file exists
|
|
if [ -f "$target_path/$kernel_params" ] && ! $secureboot; then
|
|
info "Loading extra kernel parameters from $kernel_params"
|
|
cat "$target_path/$kernel_params" | cmdline_append
|
|
fi
|
|
|
|
# NOTE: SONiC might need to provide some extra kernel parameter to change the
|
|
# next boot behavior. The following lines lookup allowed parameters and
|
|
# append them to the cmdline.
|
|
# - kernel-cmdline is still modified but its usage should ideally be deprecated over time
|
|
# - kernel-cmdline-append is for the user (SONiC) to use.
|
|
# this file can be either packaged in the swi or generated from userland
|
|
for cpath in "$image_path/kernel-cmdline" "$image_path/kernel-cmdline-append"; do
|
|
if [ -f "$cpath" ]; then
|
|
for field in $cmdline_allowlist; do
|
|
cat "$cpath" | tr ' ' '\n' | grep -E "$field" | tail -n 1 | cmdline_append
|
|
done
|
|
fi
|
|
done
|
|
|
|
# FIXME: legacy configuration files used by fast-reboot and eos2sonic
|
|
# these should be deprecated over time.
|
|
cmdline_echo > "$image_path/kernel-cmdline"
|
|
cmdline_echo | sed 's/ cmdline-aboot-end.*$//' > "$target_path/kernel-params-base"
|
|
}
|
|
|
|
write_common_configs() {
|
|
write_default_cmdline
|
|
write_platform_specific_cmdline
|
|
write_image_specific_cmdline
|
|
write_machine_config
|
|
}
|
|
|
|
write_secureboot_configs() {
|
|
write_common_configs
|
|
cmdline_add "loop=$(mount_relpath "$installer_image_path")"
|
|
cmdline_add loopfstype=squashfs
|
|
cmdline_add "loopoffset=$(zip_file_offset "$installer_image_path" fs.squashfs)"
|
|
cmdline_add docker_inram=on
|
|
cmdline_add secure_boot_enable=y
|
|
cmdline_add aboot.secureboot=enabled
|
|
# setting panic= has the side effect of disabling the initrd shell on error
|
|
cmdline_add panic=0
|
|
write_cmdline
|
|
}
|
|
|
|
write_regular_configs() {
|
|
write_common_configs
|
|
cmdline_add "loop=$image_name/fs.squashfs"
|
|
cmdline_add loopfstype=squashfs
|
|
write_cmdline
|
|
}
|
|
|
|
run_kexec() {
|
|
local cmdline="${CMDLINE:-$(cmdline_echo) $ENV_EXTRA_CMDLINE}"
|
|
local kernel="${KERNEL:-$(find_first_kernel_under "$image_path/boot")}"
|
|
local initrd="${INITRD:-$(find_first_initrd_under "$image_path/boot")}"
|
|
|
|
if $verbose; then
|
|
# show systemd showdown sequence when verbose is set
|
|
cmdline="$(echo "$cmdline" | sed 's/systemd.show_status=auto/systemd.show_status=true/')"
|
|
fi
|
|
|
|
if $debug; then
|
|
# enable initrd debug as well as kernel verbose output
|
|
cmdline="$(echo "$cmdline" | sed 's/ quiet//')"
|
|
cmdline="$cmdline debug loglevel=7 log_buf_len=8M printk.devmsg=on"
|
|
fi
|
|
|
|
sync
|
|
kexec --load --initrd="$initrd" --append="$cmdline" "$kernel"
|
|
|
|
( [ -z "$testonly" ] && [ -z "$loadonly" ] ) || exit 0
|
|
info "Kexecing..."
|
|
kexec --exec
|
|
}
|
|
|
|
secureboot_install() {
|
|
if [ -e "$image_path" ]; then
|
|
warn "Image folder $image_path already exist (likely regular install)"
|
|
fi
|
|
|
|
mkdir -p "$image_path"
|
|
|
|
info "Installing image as $installer_image_path"
|
|
extract_image_secureboot
|
|
}
|
|
|
|
regular_install() {
|
|
if [ -e "$image_path" ]; then
|
|
warn "Image folder $image_path already exist (likely secureboot install)"
|
|
fi
|
|
|
|
mkdir -p $image_path
|
|
|
|
info "Generating boot-config, machine.conf and cmdline"
|
|
write_regular_configs "$image_path"
|
|
|
|
info "Installing image under $image_path"
|
|
extract_image
|
|
|
|
# NOTE: this call is necessary to process the kernel-cmdline-append file coming
|
|
# from the just extracted swi
|
|
write_cmdline
|
|
|
|
run_hooks post-install
|
|
}
|
|
|
|
secureboot_boot() {
|
|
# boot material is extracted and generated in RAM.
|
|
# SONiC starts as a live OS.
|
|
info "Preparing image for secureboot"
|
|
prepare_image_secureboot
|
|
update_next_boot
|
|
run_kexec
|
|
}
|
|
|
|
regular_boot() {
|
|
# boot uses the image installed on the flash
|
|
write_regular_configs "$image_path"
|
|
run_hooks pre-kexec
|
|
update_next_boot
|
|
run_kexec
|
|
}
|
|
|
|
|
|
# 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
|
|
fi
|
|
|
|
# Make sure boot-config exists to avoid noise
|
|
touch "$boot_config"
|
|
|
|
# Verbosity can be defined by the caller, default to false otherwise
|
|
verbose=${verbose:-false}
|
|
debug=${debug:-false}
|
|
if [ -f "$target_path/verbose-boot" ] ||
|
|
[ "$(get_boot_config VERBOSE)" = "1" ] ||
|
|
! $in_aboot; then
|
|
verbose=true
|
|
fi
|
|
if [ -f "$target_path/debug-boot" ] || [ "$(get_boot_config DEBUG)" = "1" ]; then
|
|
verbose=true
|
|
debug=true
|
|
fi
|
|
|
|
# behavioral configuration for secureboot
|
|
# can be overidden by passing secureboot=true via env
|
|
if [ -z "$secureboot" ]; then
|
|
if is_secureboot_enabled; then
|
|
secureboot=true
|
|
else
|
|
secureboot=false
|
|
fi
|
|
fi
|
|
|
|
# preserve original installer during regular install when set
|
|
preserve_installer=false
|
|
if [ -f "$target_path/preserve-installer" ] ||
|
|
[ "$(get_boot_config PRESERVE_INSTALLER)" = "1" ]; then
|
|
preserve_installer=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
|
|
if ! unzip -ql "$swipath" 2>&1 > /dev/null; then
|
|
err "The swipath= environment variable does not point to a valid SWI"
|
|
exit 1
|
|
fi
|
|
|
|
swi_installed=0
|
|
is_swi_installed "$swipath" || swi_installed=$?
|
|
|
|
if [ "$swi_installed" -ne $SWI_ALREADY_INSTALLED ] || [ -n "$force" ]; then
|
|
if [ "$swi_installed" -eq $SWI_VERSION_MISMATCH ] || [ -n "$force" ]; then
|
|
warn "Removing existing installation folder $image_path"
|
|
rm -rf $image_path
|
|
fi
|
|
if [ "$swi_installed" -ne $SWI_OTHER_VARIANT_INSTALLED ] && $do_clean; then
|
|
info "Cleaning flash content $target_path"
|
|
clean_flash
|
|
fi
|
|
if $secureboot; then
|
|
secureboot_install
|
|
else
|
|
regular_install
|
|
fi
|
|
else
|
|
info "Using previously installed image"
|
|
fi
|
|
fi
|
|
|
|
# chainloading using kexec
|
|
if $do_kexec; then
|
|
if $secureboot; then
|
|
secureboot_boot
|
|
else
|
|
regular_boot
|
|
fi
|
|
fi
|