Skip to content

Commit

Permalink
armvirt: add EFI support
Browse files Browse the repository at this point in the history
EFI booting is used on newer machines compatible with the
Arm SystemReady specifications.

This commit restructures armvirt into a more 'generic'
target similar to x86.

See #4956
for a history of this port.

Signed-off-by: Mathew McBride <matt@traverse.com.au>
  • Loading branch information
mcbridematt authored and ynezz committed Jun 2, 2023
1 parent 16a2051 commit e0f06dd
Show file tree
Hide file tree
Showing 11 changed files with 393 additions and 19 deletions.
2 changes: 2 additions & 0 deletions target/linux/armvirt/32/config-6.1
Expand Up @@ -4,6 +4,7 @@ CONFIG_ARCH_MIGHT_HAVE_PC_PARPORT=y
CONFIG_ARCH_MULTIPLATFORM=y
CONFIG_ARCH_MULTI_V6_V7=y
CONFIG_ARCH_MULTI_V7=y
CONFIG_ARCH_MMAP_RND_BITS=8
CONFIG_ARCH_NR_GPIO=0
CONFIG_ARCH_OPTIONAL_KERNEL_RWX=y
CONFIG_ARCH_OPTIONAL_KERNEL_RWX_DEFAULT=y
Expand All @@ -13,6 +14,7 @@ CONFIG_ARM=y
CONFIG_ARM_CPU_SUSPEND=y
CONFIG_ARM_HAS_SG_CHAIN=y
CONFIG_ARM_HEAVY_MB=y
# CONFIG_ARM_HIGHBANK_CPUIDLE is not set
CONFIG_ARM_L1_CACHE_SHIFT=6
CONFIG_ARM_L1_CACHE_SHIFT_6=y
CONFIG_ARM_LPAE=y
Expand Down
2 changes: 1 addition & 1 deletion target/linux/armvirt/32/target.mk
@@ -1,6 +1,6 @@
ARCH:=arm
SUBTARGET:=32
BOARDNAME:=QEMU ARM Virtual Machine (cortex-a15)
BOARDNAME:=32-bit ARM QEMU Virtual Machine
CPU_TYPE:=cortex-a15
CPU_SUBTYPE:=neon-vfpv4
KERNELNAME:=zImage
Expand Down
4 changes: 1 addition & 3 deletions target/linux/armvirt/64/target.mk
@@ -1,8 +1,6 @@
ARCH:=aarch64
SUBTARGET:=64
BOARDNAME:=QEMU ARMv8 Virtual Machine (cortex-a53)
CPU_TYPE:=cortex-a53
KERNELNAME:=Image
BOARDNAME:=64-bit ARM machines

define Target/Description
Build multi-platform images for the ARMv8 instruction set architecture
Expand Down
5 changes: 4 additions & 1 deletion target/linux/armvirt/Makefile
Expand Up @@ -6,7 +6,7 @@ include $(TOPDIR)/rules.mk

BOARD:=armvirt
BOARDNAME:=QEMU ARM Virtual Machine
FEATURES:=fpu pci rtc usb
FEATURES:=fpu pci pcie rtc usb boot-part rootfs-part
FEATURES+=cpiogz ext4 ramdisk squashfs targz

KERNEL_PATCHVER:=5.15
Expand All @@ -15,5 +15,8 @@ KERNEL_TESTING_PATCHVER:=6.1
include $(INCLUDE_DIR)/target.mk

DEFAULT_PACKAGES += mkf2fs e2fsprogs
# blkid used for resolving PARTUUID
# in sysupgrade
DEFAULT_PACKAGES += blkid

$(eval $(call BuildTarget))
19 changes: 19 additions & 0 deletions target/linux/armvirt/base-files/etc/board.d/01_led
@@ -0,0 +1,19 @@
#!/bin/sh
# SPDX-License-Identifier: GPL-2.0-or-later

. /lib/functions/uci-defaults.sh

board_config_update

board=$(board_name)

case "$board" in
traverse,ten64)
ucidef_set_led_netdev "sfp1" "SFP 1" "ten64:green:sfp1:down" "eth8" "link tx rx"
ucidef_set_led_netdev "sfp2" "SFP 2" "ten64:green:sfp2:up" "eth9" "link tx rx"
;;
esac

board_config_flush

exit 0
18 changes: 18 additions & 0 deletions target/linux/armvirt/base-files/etc/board.d/02_network
@@ -0,0 +1,18 @@
#!/bin/sh
# SPDX-License-Identifier: GPL-2.0-or-later

. /lib/functions/system.sh
. /lib/functions/uci-defaults.sh

board_config_update

case "$(board_name)" in
traverse,ten64)
ucidef_set_interface_lan "eth0 eth1 eth2 eth3"
ucidef_set_interface_wan "eth6"
;;
esac

board_config_flush

exit 0
23 changes: 23 additions & 0 deletions target/linux/armvirt/base-files/etc/board.d/03_gpio_switches
@@ -0,0 +1,23 @@
#!/bin/sh
# SPDX-License-Identifier: GPL-2.0-or-later

. /lib/functions/uci-defaults.sh

board_config_update

board=$(board_name)

case "$board" in
traverse,ten64)
ucidef_add_gpio_switch "lte_reset" "Cell Modem Reset" "376"
ucidef_add_gpio_switch "lte_power" "Cell Modem Power" "377"
ucidef_add_gpio_switch "lte_disable" "Cell Modem Airplane mode" "378"
ucidef_add_gpio_switch "gnss_disable" "Cell Modem Disable GNSS receiver" "379"
ucidef_add_gpio_switch "lower_sfp_txidsable" "Lower SFP+ TX Disable" "369"
ucidef_add_gpio_switch "upper_sfp_txdisable" "Upper SFP+ TX Disable" "373"
;;
esac

board_config_flush

exit 0
52 changes: 52 additions & 0 deletions target/linux/armvirt/base-files/lib/preinit/01_sysinfo_acpi
@@ -0,0 +1,52 @@
# SPDX-License-Identifier: GPL-2.0-or-later

sanitize_name_arm64() {
sed -e '
y/ABCDEFGHIJKLMNOPQRSTUVWXYZ/abcdefghijklmnopqrstuvwxyz/;
s/[^a-z0-9_-]\+/-/g;
s/^-//;
s/-$//;
' "$@"
}

do_sysinfo_arm64() {
local vendor product file

for file in sys_vendor board_vendor; do
vendor="$(cat /sys/devices/virtual/dmi/id/$file 2>/dev/null)"
case "$vendor" in
empty | \
System\ manufacturer | \
To\ [bB]e\ [fF]illed\ [bB]y\ O\.E\.M\.)
continue
;;
esac
[ -n "$vendor" ] && break
done

for file in product_name board_name; do
product="$(cat /sys/devices/virtual/dmi/id/$file 2>/dev/null)"
case "$vendor:$product" in
?*:empty | \
?*:System\ Product\ Name | \
?*:To\ [bB]e\ [fF]illed\ [bB]y\ O\.E\.M\.)
continue
;;
?*:?*)
break
;;
esac
done

[ -d "/sys/firmware/devicetree/base" ] && return

[ -n "$vendor" -a -n "$product" ] || return

mkdir -p /tmp/sysinfo

echo "$vendor $product" > /tmp/sysinfo/model

sanitize_name_arm64 /tmp/sysinfo/model > /tmp/sysinfo/board_name
}

boot_hook_add preinit_main do_sysinfo_arm64
164 changes: 164 additions & 0 deletions target/linux/armvirt/base-files/lib/upgrade/platform.sh
@@ -0,0 +1,164 @@
# SPDX-License-Identifier: GPL-2.0-or-later

RAMFS_COPY_BIN="/usr/sbin/blkid"

platform_check_image() {
local board=$(board_name)
local diskdev partdev diff
[ "$#" -gt 1 ] && return 1

v "Board is ${board}"

export_bootdevice && export_partdevice diskdev 0 || {
v "platform_check_image: Unable to determine upgrade device"
return 1
}

get_partitions "/dev/$diskdev" bootdisk

v "Extract boot sector from the image"
get_image_dd "$1" of=/tmp/image.bs count=63 bs=512b

get_partitions /tmp/image.bs image

#compare tables
diff="$(grep -F -x -v -f /tmp/partmap.bootdisk /tmp/partmap.image)"

rm -f /tmp/image.bs /tmp/partmap.bootdisk /tmp/partmap.image

if [ -n "$diff" ]; then
v "Partition layout has changed. Full image will be written."
ask_bool 0 "Abort" && exit 1
return 0
fi
}

platform_copy_config() {
local partdev parttype=ext4

if export_partdevice partdev 2; then
mount -t $parttype -o rw,noatime "/dev/$partdev" /mnt
cp -af "$UPGRADE_BACKUP" "/mnt/$BACKUP_FILE"
umount /mnt
else
v "ERROR: Unable to find partition to copy config data to"
fi

sleep 5
}

# To avoid writing over any firmware
# files (e.g ubootefi.var or firmware/X/ aka EBBR)
# Copy efi/openwrt and efi/boot from the new image
# to the existing ESP
platform_do_upgrade_efi_system_partition() {
local image_file=$1
local target_partdev=$2
local image_efisp_start=$3
local image_efisp_size=$4

v "Updating ESP on ${target_partdev}"
NEW_ESP_DIR="/mnt/new_esp_loop"
CUR_ESP_DIR="/mnt/cur_esp"
mkdir "${NEW_ESP_DIR}"
mkdir "${CUR_ESP_DIR}"

get_image_dd "$image_file" of="/tmp/new_efi_sys_part.img" \
skip="$image_efisp_start" count="$image_efisp_size"

mount -t vfat -o loop -o ro /tmp/new_efi_sys_part.img "${NEW_ESP_DIR}"
if [ ! -d "${NEW_ESP_DIR}/efi/boot" ]; then
v "ERROR: Image does not contain EFI boot files (/efi/boot)"
return 1
fi

mount -t vfat "/dev/$partdev" "${CUR_ESP_DIR}"

for d in $(find "${NEW_ESP_DIR}/efi/" -mindepth 1 -maxdepth 1 -type d); do
v "Copying ${d}"
newdir_bname=$(basename "${d}")
rm -rf "${CUR_ESP_DIR}/efi/${newdir_bname}"
cp -r "${d}" "${CUR_ESP_DIR}/efi"
done

umount "${NEW_ESP_DIR}"
umount "${CUR_ESP_DIR}"
}

platform_do_upgrade() {
local board=$(board_name)
local diskdev partdev diff

export_bootdevice && export_partdevice diskdev 0 || {
v "platform_do_upgrade: Unable to determine upgrade device"
return 1
}

sync

if [ "$UPGRADE_OPT_SAVE_PARTITIONS" = "1" ]; then
get_partitions "/dev/$diskdev" bootdisk

v "Extract boot sector from the image"
get_image_dd "$1" of=/tmp/image.bs count=63 bs=512b

get_partitions /tmp/image.bs image

#compare tables
diff="$(grep -F -x -v -f /tmp/partmap.bootdisk /tmp/partmap.image)"
else
diff=1
fi

# Only change the partition table if sysupgrade -p is set,
# otherwise doing so could interfere with embedded "single storage"
# (e.g SoC boot from SD card) setups, as well as other user
# created storage (like uvol)
if [ -n "$diff" ] && [ "${UPGRADE_OPT_SAVE_PARTITIONS}" = "0" ]; then
# Need to remove partitions before dd, otherwise the partitions
# that are added after will have minor numbers offset
partx -d - "/dev/$diskdev"

get_image_dd "$1" of="/dev/$diskdev" bs=4096 conv=fsync

# Separate removal and addtion is necessary; otherwise, partition 1
# will be missing if it overlaps with the old partition 2
partx -a - "/dev/$diskdev"

return 0
fi

#iterate over each partition from the image and write it to the boot disk
while read part start size; do
if export_partdevice partdev $part; then
v "Writing image to /dev/$partdev..."
if [ "$part" = "1" ]; then
platform_do_upgrade_efi_system_partition \
$1 $partdev $start $size || return 1
else
v "Normal partition, doing DD"
get_image_dd "$1" of="/dev/$partdev" ibs=512 obs=1M skip="$start" \
count="$size" conv=fsync
fi
else
v "Unable to find partition $part device, skipped."
fi
done < /tmp/partmap.image

local parttype=ext4

if (blkid > /dev/null) && export_partdevice partdev 1; then
part_magic_fat "/dev/$partdev" && parttype=vfat
mount -t $parttype -o rw,noatime "/dev/$partdev" /mnt
if export_partdevice partdev 2; then
THIS_PART_BLKID=$(blkid -o value -s PARTUUID "/dev/${partdev}")
v "Setting rootfs PARTUUID=${THIS_PART_BLKID}"
sed -i "s/\(PARTUUID=\)[a-f0-9-]\+/\1${THIS_PART_BLKID}/ig" \
/mnt/efi/openwrt/grub.cfg
fi
umount /mnt
fi
# Provide time for the storage medium to flush before system reset
# (despite the sync/umount it appears NVMe etc. do it in the background)
sleep 5
}

0 comments on commit e0f06dd

Please sign in to comment.