🌴 Sync 2026-03-05 23:51:42

This commit is contained in:
github-actions[bot] committed 2026-03-05 23:51:42 +08:00
1 parent 97c049ed0a
commit 0acff03804
14253 files changed
+3893239

No files matched your search

+165
View File
@@ -0,0 +1,165 @@
#!/usr/bin/perl
use strict;
use File::Basename;
my $uci_config_name;
if(-f "/etc/config/amlogic") {
$uci_config_name="amlogic";
} elsif(-f "/etc/config/cpufreq") {
$uci_config_name="cpufreq";
} else {
print "Can not found amlogic or cpufreq config file!\n";
exit(0);
}
my @policy_ids;
my @policy_homes = </sys/devices/system/cpu/cpufreq/policy?>;
if(@policy_homes) {
foreach my $policy_home (@policy_homes) {
push @policy_ids, substr($policy_home, -1);
}
} else {
print "Can not found any policy!\n";
exit 0;
}
our $need_commit = 0;
for(my $i=0; $i <= $#policy_ids; $i++) {
&fix_invalid_value($uci_config_name, $policy_ids[$i], $policy_homes[$i]);
}
if($need_commit > 0) {
&uci_commit($uci_config_name);
}
exit 0;
################################# function ####################################
sub fix_invalid_value {
my($uci_config, $policy_id, $policy_home) = @_;
my %gove_hash = &get_gove_hash($policy_home);
my @freqs = &get_freq_list($policy_home);
my %freq_hash = &get_freq_hash(@freqs);
my $min_freq = &get_min_freq(@freqs);
my $max_freq = &get_max_freq(@freqs);
my $uci_section = "settings";
my $uci_option;
if($uci_config eq "cpufreq" ) {
$uci_option = "governor";
} else {
$uci_option = "governor" . $policy_id;
}
# 如果未设置 governor, 或该 goveernor 不存在, 则修败默认值为 schedutil
my $config_gove = &uci_get_by_type($uci_config, $uci_section, $uci_option, "NA");
if( ($config_gove eq "NA") ||
($gove_hash{$config_gove} != 1)) {
&uci_set_by_type($uci_config, $uci_section, $uci_option, "schedutil");
$need_commit++;
}
# 如果出现不存在的 minfreq, 则修改为实际的 min_freq
if($uci_config eq "cpufreq" ) {
# "minifreq" is a spelling error that has always existed in the upstream source code
$uci_option = "minifreq";
} else {
$uci_option = "minfreq" . $policy_id;
}
my $config_min_freq = &uci_get_by_type($uci_config, $uci_section, $uci_option, "0");
if($freq_hash{$config_min_freq} != 1) {
&uci_set_by_type($uci_config, $uci_section, $uci_option, $min_freq);
$need_commit++;
}
# 如果出现不存在的 maxfreq
# 或 maxfreq < minfreq, 则修改为实际的 max_freq
if($uci_config eq "cpufreq" ) {
$uci_option = "maxfreq";
} else {
$uci_option = "maxfreq" . $policy_id;
}
my $config_max_freq = &uci_get_by_type($uci_config, $uci_section, $uci_option, "0");
if( ( $freq_hash{$config_max_freq} != 1) ||
( $config_max_freq < $config_min_freq)) {
&uci_set_by_type($uci_config, $uci_section, $uci_option, $max_freq);
$need_commit++;
}
}
sub get_freq_list {
my $policy_home = shift;
my @ret_ary;
open my $fh, "<", "${policy_home}/scaling_available_frequencies" or die;
$_ = <$fh>;
chomp;
@ret_ary = split /\s+/;
close($fh);
return @ret_ary;
}
sub get_freq_hash {
my @freq_ary = @_;
my %ret_hash;
foreach my $freq (@freq_ary) {
if($freq =~ m/\d+/) {
$ret_hash{$freq} = 1;
}
}
return %ret_hash;
}
sub get_min_freq {
my @freq_ary = @_;
return (sort {$a<=>$b} @freq_ary)[0];
}
sub get_max_freq {
my @freq_ary = @_;
return (sort {$a<=>$b} @freq_ary)[-1];
}
sub get_gove_hash {
my $policy_home = shift;
my %ret_hash;
open my $fh, "<", "${policy_home}/scaling_available_governors" or die;
$_ = <$fh>;
chomp;
my @gov_ary = split /\s+/;
foreach my $gov (@gov_ary) {
#print "gov: $gov\n";
if($gov =~ m/\w+/) {
$ret_hash{$gov} = 1;
}
}
close($fh);
return %ret_hash;
}
sub uci_get_by_type {
my($config,$section,$option,$default) = @_;
my $ret;
$ret=`uci get ${config}.\@${section}\[0\].${option} 2>/dev/null`;
# 消除回车换行
$ret =~ s/[\n\r]//g;
if($ret eq '') {
return $default;
} else {
return $ret;
}
}
sub uci_set_by_type {
my($config,$section,$option,$value) = @_;
my $ret;
system("uci set ${config}.\@${section}\[0\].${option}=${value}");
return;
}
sub uci_commit {
my $config = shift;
system("uci commit ${config}");
return;
}
+598
View File
@@ -0,0 +1,598 @@
#!/bin/bash
#======================================================================
# Function: Backup and restore config files in the /etc directory
# Copyright (C) 2020-- https://github.com/unifreq/openwrt_packit
# Copyright (C) 2021-- https://github.com/ophub/luci-app-amlogic
#======================================================================
VERSION="v1.3"
ZSTD_LEVEL=6
SNAPSHOT_PRESTR=".snapshots/"
BACKUP_DIR="/.reserved"
BACKUP_NAME="openwrt_config.tar.gz"
BACKUP_FILE="${BACKUP_DIR}/${BACKUP_NAME}"
# Customize backup list
backup_list_conf="/etc/amlogic_backup_list.conf"
if [[ -s "${backup_list_conf}" ]]; then
while IFS= read -r line; do
BACKUP_LIST+="${line} "
done <"${backup_list_conf}"
else
BACKUP_LIST='./etc/AdGuardHome.yaml \
./etc/amlogic_backup_list.conf \
./etc/adblocklist/ \
./etc/amule/ \
./etc/balance_irq \
./etc/bluetooth/ \
./etc/china_ssr.txt \
./etc/cifs/cifsdpwd.db \
./etc/smbd/smbdpwd.db \
./etc/ksmbd/ksmbdpwd.db \
./etc/config/ \
./etc/crontabs/ \
./etc/dae/ \
./etc/daed/ \
./usr/share/openclash/core/ \
./etc/openclash/backup/ \
./etc/openclash/config/ \
./etc/openclash/custom/ \
./etc/openclash/game_rules/ \
./etc/openclash/rule_provider/ \
./etc/openclash/proxy_provider/ \
./etc/dnsforwarder/ \
./etc/dnsmasq.conf \
./etc/dnsmasq.d/ \
./etc/dnsmasq.oversea/ \
./etc/dnsmasq.ssr/ \
./etc/docker/daemon.json \
./etc/docker/key.json \
./etc/dropbear/ \
./etc/easy-rsa/ \
./etc/environment \
./etc/exports \
./etc/firewall.user \
./etc/gfwlist/ \
./etc/haproxy.cfg \
./etc/hosts \
./etc/ipsec.conf \
./etc/ipsec.d/ \
./etc/ipsec.secrets \
./etc/ipsec.user \
./etc/ipset/ \
./etc/mosdns/config.yaml \
./etc/mwan3.user \
./etc/nginx/nginx.conf \
./etc/ocserv/ \
./etc/openvpn/ \
./etc/pptpd.conf \
./etc/qBittorrent/ \
./etc/rc.local \
./etc/samba/smbpasswd \
./etc/shadow \
./etc/smartdns/ \
./etc/sqm/ \
./etc/ssh/*key* \
./etc/ssl/private/ \
./etc/ssrplus/ \
./etc/sysupgrade.conf \
./etc/tailscale/ \
./etc/transmission/ \
./etc/uhttpd.crt \
./etc/uhttpd.key \
./etc/urandom.seed \
./etc/v2raya/ \
./etc/verysync/ \
./root/.ssh/'
fi
error_msg() {
echo -e " [ERROR] ${1}"
exit 1
}
if dmesg | grep 'meson' >/dev/null 2>&1; then
PLATFORM="amlogic"
elif dmesg | grep 'rockchip' >/dev/null 2>&1; then
PLATFORM="rockchip"
elif dmesg | grep 'sun50i-h6' >/dev/null 2>&1; then
PLATFORM="allwinner"
else
source /etc/flippy-openwrt-release
case ${PLATFORM} in
amlogic | rockchip | allwinner | qemu-aarch64) : ;;
*) error_msg "Unknown platform, only support amlogic or rockchip or allwinner h6 or qemu-aarch64!" ;;
esac
fi
get_root_partition_name() {
local paths=("/" "/overlay" "/rom")
local partition_name
for path in "${paths[@]}"; do
partition_name=$(df "${path}" | awk 'NR==2 {print $1}' | awk -F '/' '{print $3}')
[[ -n "${partition_name}" ]] && break
done
[[ -z "${partition_name}" ]] && error_msg "Cannot find the root partition!"
echo "${partition_name}"
}
# Get the partition message of the root file system
get_root_partition_msg() {
local paths=("/" "/overlay" "/rom")
local partition_name
for path in "${paths[@]}"; do
partition_msg=$(lsblk -l -o NAME,PATH,MOUNTPOINT,UUID,FSTYPE,LABEL | awk '$3 ~ "^" "'"${path}"'" "$" {print $0}')
[[ -n "${partition_msg}" ]] && break
done
[[ -z "${partition_msg}" ]] && error_msg "Cannot find the root partition message!"
echo "${partition_msg}"
}
backup() {
cd /
echo -n "Backup config files ... "
[ -d "${BACKUP_DIR}" ] || mkdir -p "${BACKUP_DIR}"
eval tar czf "${BACKUP_FILE}" "${BACKUP_LIST}" 2>/dev/null
sync
if [ -f "${BACKUP_FILE}" ]; then
echo "Has been backed up to [ ${BACKUP_FILE} ], please download and save."
exit 0
else
error_msg "Backup failed!"
fi
}
restore() {
# Find the partition where root is located
ROOT_PTNAME="$(get_root_partition_name)"
# Find the disk where the partition is located, only supports mmcblk?p? sd?? hd?? vd?? and other formats
case ${ROOT_PTNAME} in
mmcblk?p[1-4])
EMMC_NAME=$(echo ${ROOT_PTNAME} | awk '{print substr($1, 1, length($1)-2)}')
PARTITION_NAME="p"
LB_PRE="EMMC_"
;;
[hsv]d[a-z][1-4])
EMMC_NAME=$(echo ${ROOT_PTNAME} | awk '{print substr($1, 1, length($1)-1)}')
PARTITION_NAME=""
LB_PRE=""
;;
*)
error_msg "Unable to recognize the disk type of ${ROOT_PTNAME}!"
;;
esac
[ -d "${BACKUP_DIR}" ] || mkdir -p "${BACKUP_DIR}"
[ -f "/tmp/upload/${BACKUP_NAME}" ] && mv -f "/tmp/upload/${BACKUP_NAME}" ${BACKUP_FILE}
[ -f "/mnt/${EMMC_NAME}${PARTITION_NAME}4/${BACKUP_NAME}" ] && mv -f "/mnt/${EMMC_NAME}${PARTITION_NAME}4/${BACKUP_NAME}" ${BACKUP_FILE}
sync
if [ -f "${BACKUP_FILE}" ]; then
echo -n "restore config files ... "
cd /
tar xzf "${BACKUP_FILE}" 2>/dev/null && sync
echo "Successful recovery. Will start automatically, please refresh later!"
sleep 3
reboot
exit 0
else
error_msg "The backup file [ ${BACKUP_FILE} ] not found!"
fi
}
gen_fstab() {
# Find the partition where root is located
ROOT_PTNAME="$(get_root_partition_name)"
# Find the disk where the partition is located, only supports mmcblk?p? sd?? hd?? vd?? and other formats
case ${ROOT_PTNAME} in
mmcblk?p[1-4])
EMMC_NAME=$(echo ${ROOT_PTNAME} | awk '{print substr($1, 1, length($1)-2)}')
PARTITION_NAME="p"
;;
[hsv]d[a-z][1-4])
EMMC_NAME=$(echo ${ROOT_PTNAME} | awk '{print substr($1, 1, length($1)-1)}')
PARTITION_NAME=""
;;
*)
error_msg "Unable to recognize the disk type of ${ROOT_PTNAME}!"
;;
esac
ROOT_MSG="$(get_root_partition_msg)"
ROOT_NAME=$(echo $ROOT_MSG | awk '{print $1}')
ROOT_DEV=$(echo $ROOT_MSG | awk '{print $2}')
ROOT_UUID=$(echo $ROOT_MSG | awk '{print $4}')
ROOT_FSTYPE=$(echo $ROOT_MSG | awk '{print $5}')
ROOT_LABEL=$(echo $ROOT_MSG | awk '{print $6}')
BOOT_NAME="${EMMC_NAME}${PARTITION_NAME}1"
BOOT_MSG=$(lsblk -l -o NAME,UUID,FSTYPE,LABEL | grep "${BOOT_NAME}")
BOOT_DEV="/dev/${BOOT_NAME}"
BOOT_UUID=$(echo $BOOT_MSG | awk '{print $2}')
BOOT_FSTYPE=$(echo $BOOT_MSG | awk '{print $3}')
BOOT_LABEL=$(echo $BOOT_MSG | awk '{print $4}')
cat >/etc/config/fstab <<EOF
config global
option anon_swap '0'
option anon_mount '1'
option auto_swap '0'
option auto_mount '1'
option delay_root '5'
option check_fs '0'
config mount
option target '/rom'
option uuid '${ROOT_UUID}'
option enabled '1'
option enabled_fsck '1'
option fstype '${ROOT_FSTYPE}'
EOF
if [ "${ROOT_FSTYPE}" == "btrfs" ]; then
echo " option options 'compress=zstd:${ZSTD_LEVEL}'" >>/etc/config/fstab
fi
cat >>/etc/config/fstab <<EOF
config mount
option target '/boot'
EOF
if [ "${BOOT_FSTYPE}" == "vfat" ]; then
echo " option label '${BOOT_LABEL}'" >>/etc/config/fstab
else
echo " option uuid '${BOOT_UUID}'" >>/etc/config/fstab
fi
cat >>/etc/config/fstab <<EOF
option enabled '1'
option enabled_fsck '1'
option fstype '${BOOT_FSTYPE}'
EOF
echo "/etc/config/fstab generated."
echo "Please reboot before continuing."
exit 0
}
print_list() {
echo "${BACKUP_LIST}"
exit 0
}
list_snapshot() {
echo "----------------------------------------------------------------"
btrfs subvolume list -rt /
echo "----------------------------------------------------------------"
read -p "Press [ enter ] to return." q
}
create_snapshot() {
default_snap_name="etc-$(date +"%m.%d.%H%M%S")"
echo "The default snapshot name is: ${default_snap_name}"
echo "If you want to modify the snapshot name, please enter it below. Cannot contain spaces."
echo "If you do not want to modify it, just press [ Enter ]. Or press the [ q ] key to go back directly."
while :; do
read -p "[${default_snap_name}] : " nname
if [ "${nname}" == "" ]; then
snap_name="${default_snap_name}"
break
elif echo "${nname}" | grep -E "\s+" >/dev/null; then
echo "The name [${nname}] contains spaces, please re-enter!"
continue
elif [ "${nname}" == "q" ] || [ "${nname}" == "Q" ]; then
return
else
if btrfs subvolume list -rt / | awk '{print $4}' | grep "^\\${SNAPSHOT_PRESTR}${nname}$" >/dev/null; then
echo "Name: [ ${nname} ] has been used, please re-enter!"
continue
else
snap_name="${nname}"
break
fi
fi
done
(
cd /
chattr -ia etc/config/fstab
btrfs subvolume snapshot -r /etc "${SNAPSHOT_PRESTR}${snap_name}"
if [[ "$?" -eq "0" ]]; then
echo "The snapshot is created successfully: ${snap_name}"
else
echo "Snapshot creation failed!"
fi
)
read -p "Press [ enter ] to return." q
}
restore_snapshot() {
echo "Below are the existing etc snapshots, please enter the name of one of them."
echo "Tip: [ etc-000 ] This is the factory initial configuration."
echo " [ etc-001 ] if it exists, it is the initial configuration after upgrading from the previous version."
echo "----------------------------------------------------------------"
btrfs subvolume list -rt /
echo "----------------------------------------------------------------"
read -p "Please enter the name of the snapshot to be restored (only the part after ${SNAPSHOT_PRESTR} needs to be entered): " snap_name
if btrfs subvolume list -rt / | grep "${SNAPSHOT_PRESTR}${snap_name}" >/dev/null; then
while :; do
echo "Once the snapshot is restored, the current [ /etc ] will be overwritten!"
read -p "Are you sure you want to restore the snapshot: [$snap_name]? y/n [n] " yn
case $yn in
y | Y)
(
cd /
chattr -ia etc/config/fstab
mv etc etc.backup
btrfs subvolume snapshot "${SNAPSHOT_PRESTR}${snap_name}" etc
if [[ "$?" -eq "0" ]]; then
btrfs subvolume delete -c etc.backup
echo "Successfully restored, please enter [ reboot ] to restart the openwrt."
else
rm -rf etc
mv etc.backup etc
echo "Recovery failed, [ etc ] has not changed!"
fi
)
read -p "Press [ enter ] to return." q
break
;;
*)
break
;;
esac
done
else
read -p "The snapshot name is incorrect, please run the program again! Press [ Enter ] to go back." q
fi
}
delete_snapshot() {
echo "Below are the existing [ etc ] snapshots, please enter the name of one of them."
echo "Tip: [ etc-000 ] This is the factory initial configuration (cannot be deleted)"
echo " [ etc-001 ] if it exists, it is the initial configuration after upgrading from the previous version (cannot be deleted)"
echo "----------------------------------------------------------------"
btrfs subvolume list -rt /
echo "----------------------------------------------------------------"
read -p "Please enter the name of the snapshot to be deleted (only the part after ${SNAPSHOT_PRESTR} needs to be entered): " snap_name
if [ "${snap_name}" == "etc-000" ] || [ "${snap_name}" == "etc-001" ]; then
read -p "The key snapshot cannot be deleted! Press [ enter ] to return." q
elif [ "${snap_name}" == "" ]; then
read -p "Name is empty! Press [ enter ] to return." q
else
if btrfs subvolume list -rt / | grep "${SNAPSHOT_PRESTR}${snap_name}" >/dev/null; then
read -p "Are you sure you want to delete ${snap_name}? y/n [n] " yn
case $yn in
y | Y)
(
cd /
btrfs subvolume delete -c "${SNAPSHOT_PRESTR}${snap_name}"
if [[ "$?" -eq "0" ]]; then
echo "Snapshot [ ${snap_name} ] has been deleted."
else
echo "Snapshot [ ${snap_name} ] failed to delete!"
fi
)
read -p "Press [ Enter ] to return." q
;;
*)
break
;;
esac
else
read -p "The name of the snapshot is incorrect, press [ Enter ] to return." q
fi
fi
}
migrate_snapshot() {
cur_rootdev="$(get_root_partition_name)"
dev_pre=$(echo "${cur_rootdev}" | awk '{print substr($1, 1, length($1)-1);}')
rootdev_idx=$(echo "${cur_rootdev}" | awk '{print substr($1, length($1),1);}')
case $rootdev_idx in
2)
old_rootpath="/mnt/${dev_pre}3"
;;
3)
old_rootpath="/mnt/${dev_pre}2"
;;
*)
echo "Judge the old version of rootfs path failed!"
read -p "Press [ enter ] to return." q
return
;;
esac
echo "The following are snapshots of etc found from the old version of rootfs, please enter the name of one of them."
echo "Tip: Automatically exclude etc-000 and etc-001"
echo "-----------------------------------------------------------------------------------"
btrfs subvolume list -rt "${old_rootpath}" | grep -v "${SNAPSHOT_PRESTR}etc-000" | grep -v "${SNAPSHOT_PRESTR}etc-001"
echo "-----------------------------------------------------------------------------------"
read -p "Please enter the name of the snapshot to be migrated (only the part after $(SNAPSHOT_PRESTR) needs to be entered): " old_snap_name
if [ "${old_snap_name}" == "" ]; then
read -p "The name is empty, Press [ enter ] to return." q
return
elif ! btrfs subvolume list -rt "${old_rootpath}" | awk '{print $4}' | grep "^${SNAPSHOT_PRESTR}${old_snap_name}$" >/dev/null; then
echo "The name was entered incorrectly, and the corresponding snapshot was not found!"
read -p "Press [ enter ] to return." q
return
elif [ "${old_snap_name}" == "etc-000" ] || [ "${old_snap_name}" == "etc-001" ]; then
echo "Critical snapshots are not allowed to migrate!"
read -p "Press [ enter ] to return." q
return
fi
# Find out if there is a snapshot with the same name under the current rootfs
if btrfs subvolume list -rt / | awk '{print $4}' | grep "^\\${SNAPSHOT_PRESTR}${old_snap_name}$" >/dev/null; then
echo "A snapshot with the name [ ${old_snap_name} ] already exists and cannot be migrated! (But you can delete the existing snapshot with the same name and then migrate)"
read -p "Press [ enter ] to return." q
return
fi
need_size=$(du -h -d0 ${old_rootpath}/${SNAPSHOT_PRESTR}${old_snap_name} | tail -n1 | awk '{print $1}')
echo "----------------------------------------------------------------------------------------------"
df -h
echo "----------------------------------------------------------------------------------------------"
echo -e "Note: To migrate the snapshot [ ${old_snap_name} ] of [ ${old_rootpath} ] to the current rootfs, it takes about [ ${need_size} ] space,"
echo -e " Please confirm whether the partition [/dev/${cur_rootdev}] where [/] is located has enough free space (Available)?"
read -p "Are you sure to migrate? y/n [n] " yn
if [ "$yn" == "y" ] || [ "$yn" == "Y" ]; then
(
cd /
btrfs send ${old_rootpath}/${SNAPSHOT_PRESTR}${old_snap_name} | btrfs receive ${SNAPSHOT_PRESTR}
if [ $? -eq 0 ]; then
btrfs property set -ts ${SNAPSHOT_PRESTR}${old_snap_name} ro false
cp ${SNAPSHOT_PRESTR}etc-000/config/fstab ${SNAPSHOT_PRESTR}${old_snap_name}/config/
cp ${SNAPSHOT_PRESTR}etc-000/fstab ${SNAPSHOT_PRESTR}${old_snap_name}/
cp ${SNAPSHOT_PRESTR}etc-000/openwrt_release ${SNAPSHOT_PRESTR}${old_snap_name}/
cp ${SNAPSHOT_PRESTR}etc-000/openwrt_version ${SNAPSHOT_PRESTR}${old_snap_name}/
cp ${SNAPSHOT_PRESTR}etc-000/flippy-openwrt-release ${SNAPSHOT_PRESTR}${old_snap_name}/
cp ${SNAPSHOT_PRESTR}etc-000/banner ${SNAPSHOT_PRESTR}${old_snap_name}/banner
btrfs property set -ts ${SNAPSHOT_PRESTR}${old_snap_name} ro true
echo "The migration is complete, if you want to apply the snapshot [ ${old_snap_name} ], please use the restore snapshot function."
else
echo "The migration failed!"
fi
read -p "Press [ enter ] to return." q
return
)
fi
}
snapshot_help() {
clear
cat <<EOF
============================================================================================================================
1. What is a snapshot?
A snapshot is the state record of a certain subvolume at a certain point in time, and a snapshot is a special subvolume;
When the local snapshot is first generated, it shares the disk space with the original subvolume,
so it does not occupy additional space, and only the files that have changed subsequently occupy space;
Snapshots migrated from other places are not snapshots in essence, but just ordinary subvolumes, so they take up space.
2. How to display existing snapshots?
input the command: btrfs subvolume list -rt /
---------------------------------------------------------------------------------------------
EOF
btrfs subvolume list -rt /
cat <<EOF
---------------------------------------------------------------------------------------------
2. How to create a snapshot?
btrfs subvolume snapshot -r /etc /.snapshots/snapshot_1 # -r It means to generate a read-only snapshot
3. How to delete a snapshot?
btrfs subvolume delete -c /.snapshots/snapshot_1 # -c 是 commit 的意思
4. How to rename a snapshot?
Just use the [ mv ] command of the operating system, for example:
mv /.snapshots/snapshot_1 /.snapshots/snapshot_2
5. How to restore the snapshot?
mv /etc /etc.backup # Back up /etc to /etc.backup, that is, rename the subvolume
btrfs subvolume snapshot /.snapshots/etc-001 /etc # Use snapshot etc-001 to generate snapshot etc, no -r parameter
# (Yes, snapshots can also be re-generated snapshots)
btrfs delete -c /etc.backup # After the previous step is successful, you can delete the etc backup just now
6. How to restore a certain file from the snapshot?
Example A: Restore the mount point configuration file from snapshot etc-000: /etc/config/fstab
cp /.snapshots/etc-000/config/fstab /etc/config/
Example B: Restore network configuration from snapshot etc-001:
cp /.snapshots/etc-001/config/network /etc/config/
Example C: Restore the ssr configuration file from snapshot etc-001:
cp /.snapshots/etc-001/config/shadowsocksr /etc/config/
# (Yes, it is the [ cp ] command of the operating system)
7. How to migrate snapshots from remote?
btrfs supports ssh remote migration snapshots, for example:
ssh 192.168.1.1 btrfs send /.snapshots/snapshot_x | btrfs receive /.snapshots
After the command is completed, the remote snapshot_x is copied to the local /.snapshots/snapshot_x
(as mentioned above, the migration is a subvolume, which takes up space)
============================================================================================================================
EOF
exit 0
}
print_help() {
echo "Usage: $0 -b [ backup ]"
echo " $0 -r [ restore ]"
echo " $0 -g [ generate fstab ]"
echo " $0 -p [ print backup list ]"
echo " $0 -l [ list snapshots ]"
echo " $0 -c [ create snapshot ]"
echo " $0 -s [ restore snapshot ]"
echo " $0 -d [ delete snapshot ]"
echo " $0 -h [ help ]"
echo " $0 -q [ quit ]"
exit 0
}
menu() {
while :; do
clear
cat <<EOF
┌────────[ backup config ]────────┐
│ │
│ b. backup config │
│ r. restore config │
│ g. generate fstab │
│ p. print backup list │
│ │
├─────[ Snapshot management ]─────┤
│ │
│ l. list snapshots │
│ c. create snapshot │
│ d. delete snapshot │
│ R. restore snapshot │
│ m. migrate snapshot │
│ s. snapshot help │
│ │
╞═════════════════════════════════╡
│ │
│ h. help │
│ q. quit │
│ │
└─────────────────────────────────┘
EOF
echo -ne "please select: [ ]\b\b"
read select
case $select in
b | backup) backup ;;
r | restore)
restore
gen_fstab
;;
g | gen_fstab) gen_fstab ;;
p | print_list) print_list ;;
l | list_snapshot) list_snapshot ;;
c | create_snapshot) create_snapshot ;;
d | delete_snapshot) delete_snapshot ;;
R | restore_snapshot) restore_snapshot ;;
m | migrate_snapshot) migrate_snapshot ;;
s | snapshot_help) snapshot_help ;;
h | help) print_help ;;
q | quit) exit 0 ;;
esac
done
}
getopts 'brgplcRmsdhq' opts
case $opts in
b | backup) backup ;;
r | restore)
restore
gen_fstab
;;
g | gen_fstab) gen_fstab ;;
p | print_list) print_list ;;
l | list_snapshot) list_snapshot ;;
c | create_snapshot) create_snapshot ;;
d | delete_snapshot) delete_snapshot ;;
R | restore_snapshot) restore_snapshot ;;
m | migrate_snapshot) migrate_snapshot ;;
s | snapshot_help) snapshot_help ;;
h | help) print_help ;;
q | quit) exit 0 ;;
*) menu ;;
esac
+155
View File
@@ -0,0 +1,155 @@
#!/bin/bash
#===========================================================================
#
# This file is licensed under the terms of the GNU General Public
# License version 2. This program is licensed "as is" without any
# warranty of any kind, whether express or implied.
#
# This file is a part of the make OpenWrt for Amlogic s9xxx tv box
# https://github.com/ophub/luci-app-amlogic
#
# Description: Backup and restore the system in emmc
# Copyright (C) 2017- The function borrowed from armbian/ddbr, Author: xXx
# Copyright (C) 2021- https://github.com/unifreq/openwrt_packit
# Copyright (C) 2021- https://github.com/ophub/luci-app-amlogic
#
# Command: openwrt-ddbr
#
#========================= Set default parameters ===========================
#
# Set font color
blue_font_prefix="\033[34m"
purple_font_prefix="\033[35m"
green_font_prefix="\033[32m"
yellow_font_prefix="\033[33m"
red_font_prefix="\033[31m"
font_color_suffix="\033[0m"
INFO="[${blue_font_prefix}INFO${font_color_suffix}]"
STEPS="[${purple_font_prefix}STEPS${font_color_suffix}]"
SUCCESS="[${green_font_prefix}SUCCESS${font_color_suffix}]"
OPT="[${yellow_font_prefix}OPT${font_color_suffix}]"
ERROR="[${red_font_prefix}ERROR${font_color_suffix}]"
#
# Check the output path
out_path="/ddbr"
# File name for backup/restore
ddbr_image="BACKUP-arm-64-emmc.img.gz"
# Need remaining space, unit: GB
need_space="2"
#
#===========================================================================
# Encountered a serious error, abort the script execution
error_msg() {
echo -e "${ERROR} ${1}"
exit 1
}
# Get the partition name of the root file system
get_root_partition_name() {
local paths=("/" "/overlay" "/rom")
local partition_name
for path in "${paths[@]}"; do
partition_name=$(df "${path}" | awk 'NR==2 {print $1}' | awk -F '/' '{print $3}')
[[ -n "${partition_name}" ]] && break
done
[[ -z "${partition_name}" ]] && error_msg "Cannot find the root partition!"
echo "${partition_name}"
}
# Check emmc
do_checkemmc() {
# Get device name
mydevice_name="$(cat /proc/device-tree/model | tr -d '\000')"
echo -e "${INFO} The device name: [ ${mydevice_name} ]"
# Find the partition where root is located
root_ptname="$(get_root_partition_name)"
# Find the EMMC drive
emmc="$(lsblk -l -o NAME | grep -oE "mmcblk[0-9]boot0" | sort | uniq | sed "s/boot0//g")"
# Find emmc disk, find emmc that does not contain the boot0 partition
[[ -z "${emmc}" ]] && emmc="$(lsblk -l -o NAME | grep -oE '(mmcblk[0-9]?)' | grep -vE ^${root_ptname:0:-2} | uniq)"
# Check if emmc exists
[[ -z "${emmc}" ]] && error_msg "The eMMC storage not found in this device!"
# Show the emmc name
echo -e "${INFO} The device eMMC name: [ /dev/${emmc} ]"
# Find the disk where the partition is located, only supports mmcblk?p? sd?? hd?? vd?? and other formats
case "${root_ptname}" in
mmcblk?p[1-4])
disk_name="$(echo ${root_ptname} | awk '{print substr($1, 1, length($1)-2)}')"
if lsblk -l -o NAME | grep "${disk_name}boot0" >/dev/null; then
error_msg "The current system is running on emmc. Please perform backup/restore operation in [ SD/TF/USB ]!"
fi
link_ptname="p"
;;
[hsv]d[a-z][1-4])
disk_name="$(echo ${root_ptname} | awk '{print substr($1, 1, length($1)-1)}')"
link_ptname=""
;;
nvme?n?p[1-4])
disk_name="$(echo ${root_ptname} | awk '{print substr($1, 1, length($1)-2)}')"
link_ptname="p"
;;
*)
error_msg "Unable to recognize the disk type of ${root_ptname}!"
;;
esac
# Set check parameters
out_path="/mnt/${disk_name}${link_ptname}4"
dev_intsize="$(fdisk -s /dev/${emmc})"
[[ -z "$(echo "${dev_intsize}" | sed -n "/^[0-9]\+$/p")" ]] && error_msg "Unable to get EMMC size."
echo -e "${INFO} The device EMMC size: [ $(($dev_intsize / 1024 / 1024))GB ]"
# check directory
[[ -d "${out_path}" ]] || mkdir -p ${out_path}
echo -e "${INFO} The ddbr file path: [ ${out_path}/${ddbr_image} ]\n"
}
# Check the remaining space
do_checkspace() {
remaining_space="$(df -Tk ${out_path} | grep '/dev/' | awk '{print $5}' | echo $(($(xargs) / 1024 / 1024)))"
if [[ -z "$(echo "${remaining_space}" | sed -n "/^[0-9]\+$/p")" ]]; then
error_msg "The path is not available, the remaining space cannot be obtained."
fi
if [[ "${remaining_space}" -lt "${need_space}" ]]; then
error_msg "The remaining space is [ ${remaining_space} ] Gb, and more than [ ${need_space} ] Gb space is required."
fi
}
# Backup the emmc system
do_backup() {
echo -e "${STEPS} Start to backup the system in emmc."
do_checkspace
echo -e "Saving and Compressing [ /dev/${emmc} ] to [ ${out_path}/${ddbr_image} ], Please wait..."
rm -f ${out_path}/${ddbr_image} 2>/dev/null && sync
dd if=/dev/${emmc} | pv -s ${dev_intsize}"K" | gzip >${out_path}/${ddbr_image}
[[ "${?}" -eq "0" ]] && sync && echo -e "${SUCCESS} Backup is complete."
}
# Restore the emmc system
do_restore() {
echo -e "${STEPS} Start to restore the system in emmc."
[[ ! -f ${out_path}/${ddbr_image} ]] && error_msg "The [ ${out_path}/${ddbr_image} ] File not found."
echo -e "Restoring [ ${out_path}/${ddbr_image} ] to [ /dev/${emmc} ], Please wait..."
gunzip -c ${out_path}/${ddbr_image} | pv -s ${dev_intsize}"K" | dd of=/dev/${emmc}
[[ "${?}" -eq "0" ]] && sync && echo -e "${SUCCESS} Restore is complete."
}
echo -e "${STEPS} Welcome to use the EMMC system backup/restore service."
# Check script permission
[[ -x "/usr/sbin/openwrt-ddbr" ]] || error_msg "Please grant execution permission: [ chmod +x /usr/sbin/openwrt-ddbr ]"
# Check emmc
do_checkemmc
# Prompt the user to select backup/restore
echo -ne "${OPT} Do you want to backup or restore? Backup=(b) Restore=(r): "
read br
case "${br}" in
b | B | backup) do_backup ;;
r | R | restore) do_restore ;;
*) exit 0 ;;
esac
+721
View File
@@ -0,0 +1,721 @@
#!/bin/bash
#======================================================================================
# Function: Install openwrt to emmc for Amlogic S9xxx STB
# Copyright (C) 2020-- https://github.com/unifreq/openwrt_packit
# Copyright (C) 2021-- https://github.com/ophub/luci-app-amlogic
#======================================================================================
#
# The script supports directly setting parameters for installation, skipping interactive selection
# openwrt-install-amlogic ${AUTO_MAINLINE_UBOOT} ${ID} ${FDTFILE}:${SOC}:${UBOOT_OVERLOAD} ${SHARED_FSTYPE}
# E.g: openwrt-install-amlogic yes 11 auto ext4
# E.g: openwrt-install-amlogic no 99 meson-gxl-s905d-phicomm-n1.dtb:s905d:u-boot-n1.bin ext4
# Tip: When custom dtb file, set ${SOC_ID} to 99, and parameter ${FDTFILE}:${SOC}:${UBOOT_OVERLOAD} must be set
# Tip: ${SHARED_FSTYPE}: Shared partition can be ext4, xfs, btrfs, f2fs
# You can also execute the script directly, and interactively select related functions
# E.g: openwrt-install-amlogic
#
#======================================================================================
# Encountered a serious error, abort the script execution
error_msg() {
echo -e "[ERROR] ${1}"
exit 1
}
# Get the partition name of the root file system
get_root_partition_name() {
local paths=("/" "/overlay" "/rom")
local partition_name
for path in "${paths[@]}"; do
partition_name=$(df "${path}" | awk 'NR==2 {print $1}' | awk -F '/' '{print $3}')
[[ -n "${partition_name}" ]] && break
done
[[ -z "${partition_name}" ]] && error_msg "Cannot find the root partition!"
echo "${partition_name}"
}
# Receive one-key command related parameters
AUTO_MAINLINE_UBOOT="${1}"
ZSTD_LEVEL="6"
op_release="/etc/flippy-openwrt-release"
# For [luci-app-amlogic] input parameter: DTB, SOC & UBOOT_OVERLOAD
# When there is no input parameter, select manually
SPECIFY_ID=""
SPECIFY_SOC=""
SPECIFY_DTB=""
SPECIFY_UBOOT=""
[[ -n "${2}" ]] && {
SPECIFY_ID="${2}"
if [[ "${2}" -eq "99" ]]; then
if [[ -n "${3}" ]]; then
# E.g: meson-gxl-s905d-phicomm-n1.dtb:s905d:u-boot-n1.bin
SPECIFY_DTB="$(echo "${3}" | awk -F ':' '{print $1}')"
SPECIFY_SOC="$(echo "${3}" | awk -F ':' '{print $2}')"
SPECIFY_UBOOT="$(echo "${3}" | awk -F ':' '{print $3}')"
else
error_msg "Please enter the DTB file name!"
fi
fi
}
# shared partition can be ext4, xfs, btrfs, f2fs
SHARED_FSTYPE="${4}"
echo "AUTO_MAINLINE_UBOOT: ${AUTO_MAINLINE_UBOOT}"
echo "SPECIFY_DTB: ${SPECIFY_DTB}"
echo "SPECIFY_SOC: ${SPECIFY_SOC}"
echo "SPECIFY_UBOOT: ${SPECIFY_UBOOT}"
echo "SHARED_FSTYPE: ${SHARED_FSTYPE}"
# Current device model
MYDEVICE_NAME=$(cat /proc/device-tree/model | tr -d '\000')
if [[ -z "${MYDEVICE_NAME}" ]]; then
error_msg "The device name is empty and cannot be recognized."
elif [[ ! -f "${op_release}" ]]; then
error_msg "The [ ${op_release} ] file is missing."
else
echo -e "Current device: ${MYDEVICE_NAME} [ amlogic ]"
sleep 3
fi
# Find the device name of /
root_devname="$(get_root_partition_name)"
if lsblk -l | grep -E "^${root_devname}boot0" >/dev/null; then
error_msg "you are running in emmc mode, please boot system with usb or tf card!"
fi
install_emmc="$(lsblk -l -o NAME | grep -oE '(mmcblk[0-9]?boot0)' | sed "s/boot0//g")"
if [[ "${install_emmc}" == "" ]]; then
error_msg "No emmc can be found to install the openwrt system!"
fi
# EMMC DEVICE NAME
EMMC_NAME="${install_emmc}"
EMMC_DEVPATH="/dev/${EMMC_NAME}"
echo ${EMMC_DEVPATH}
EMMC_SIZE=$(lsblk -l -b -o NAME,SIZE | grep ${EMMC_NAME} | sort | uniq | head -n1 | awk '{print $2}')
echo "${EMMC_NAME} : ${EMMC_SIZE} bytes"
ROOT_NAME=$(lsblk -l -o NAME,MAJ:MIN,MOUNTPOINT | grep -e '/$' | awk '{print $1}')
echo "ROOTFS: ${ROOT_NAME}"
BOOT_NAME=$(lsblk -l -o NAME,MAJ:MIN,MOUNTPOINT | grep -e '/boot$' | awk '{print $1}')
echo "BOOT: ${BOOT_NAME}"
# box model database
# The field separator is :
# " " or "" or NA or NULL means this field is null
# The fields list:
# 1. id
# 2. model name
# 3. SOC
# 4. FDTFILE
# 5. UBOOT_OVERLOAD
# 6. MAINLINE_UBOOT
# 7. ANDROID_UBOOT
# 8. brief description
#
# allow use external modal database
if [[ -f "/etc/model_database.txt" ]]; then
model_database="$(cat /etc/model_database.txt)"
else
error_msg "[ /etc/model_database.txt ] file is missing."
fi
function display_database() {
while read -r line; do
if [[ "$line" =~ ^# ]]; then
# Process comment lines, starting with #
line="${line/#+\s+/}"
echo "$line >>>"
else
# Process data lines, starting with id
IFS=':' read -r -a fields <<<"$line"
printf "%5s %-48s%-10s%-s\n" "${fields[0]}" "${fields[1]}" "${fields[2]}" "${fields[7]}"
fi
done < <(echo "${model_database}")
}
function search_model() {
local id="${1}"
local ret_count="$(echo "${model_database}" | awk -F ':' "\$1~/^$id\$/ {print \$0}" | wc -l)"
if [[ "${ret_count}" -eq "1" ]]; then
echo "${model_database}" | awk -F ':' "\$1~/^$id\$/ {print \$0}" | sed -e 's/NA//g' -e 's/NULL//g' -e 's/[ ][ ]*//g'
fi
}
echo "Please select s9xxx box model:"
echo "----------------------------------------------------------------------------------------------------"
display_database
echo "----------------------------------------------------------------------------------------------------"
# For [luci-app-amlogic] input parameter: SOC & DTB
# When there is no input parameter, select manually
if [[ -n "${SPECIFY_ID}" ]]; then
boxtype="${SPECIFY_ID}"
else
echo -n "Please choose: "
read boxtype
fi
if [[ "${boxtype}" -eq "99" ]]; then
FDTFILE="${SPECIFY_DTB}"
AMLOGIC_SOC="${SPECIFY_SOC}"
UBOOT_OVERLOAD="${SPECIFY_UBOOT}"
MAINLINE_UBOOT=""
ANDROID_UBOOT=""
elif [[ "${boxtype}" -eq "0" ]]; then
read -p "Please Input SoC Name(such as s9xxx): " AMLOGIC_SOC
AMLOGIC_SOC="${AMLOGIC_SOC}"
read -p "Please Input DTB Name(such as meson-xxx.dtb): " FDTFILE
FDTFILE="${FDTFILE}"
read -p "Please Input UBOOT_OVERLOAD Name(such as u-boot-xxx.bin): " UBOOT_OVERLOAD
UBOOT_OVERLOAD="${UBOOT_OVERLOAD}"
read -p "Please Input MAINLINE_UBOOT Name(such as /lib/u-boot/xxx-u-boot.bin.sd.bin): " MAINLINE_UBOOT
MAINLINE_UBOOT="${MAINLINE_UBOOT}"
read -p "Please Input ANDROID_UBOOT Name(such as /lib/u-boot/xxx-bootloader.img): " ANDROID_UBOOT
ANDROID_UBOOT="${ANDROID_UBOOT}"
else
ret="$(search_model ${boxtype})"
if [[ -z "${ret}" ]]; then
error_msg "Input error, exit!"
fi
# 3. soc
# 4. FDTFILE
# 5. UBOOT_OVERLOAD
# 6. MAINLINE_UBOOT
# 7. ANDROID_UBOOT
AMLOGIC_SOC="$(echo "${ret}" | awk -F ':' '{print $3}')"
FDTFILE="$(echo "${ret}" | awk -F ':' '{print $4}')"
UBOOT_OVERLOAD="$(echo "${ret}" | awk -F ':' '{print $5}')"
MAINLINE_UBOOT="$(echo "${ret}" | awk -F ':' '{print $6}')"
ANDROID_UBOOT="$(echo "${ret}" | awk -F ':' '{print $7}')"
fi
if [[ -z "${FDTFILE}" || ! -f "/boot/dtb/amlogic/${FDTFILE}" ]]; then
error_msg "/boot/dtb/amlogic/${FDTFILE} does not exist!"
fi
echo "AMLOGIC_SOC Value [ ${AMLOGIC_SOC} ]"
echo "FDTFILE Value [ ${FDTFILE} ]"
echo "UBOOT_OVERLOAD Value [ ${UBOOT_OVERLOAD} ]"
echo "MAINLINE_UBOOT Value [ ${MAINLINE_UBOOT} ]"
echo "ANDROID_UBOOT Value [ ${ANDROID_UBOOT} ]"
sed -i "s|^SOC=.*|SOC='${AMLOGIC_SOC}'|g" ${op_release} 2>/dev/null
sed -i "s|^FDTFILE=.*|FDTFILE='${FDTFILE}'|g" ${op_release} 2>/dev/null
sed -i "s|^UBOOT_OVERLOAD=.*|UBOOT_OVERLOAD='${UBOOT_OVERLOAD}'|g" ${op_release} 2>/dev/null
sed -i "s|^MAINLINE_UBOOT=.*|MAINLINE_UBOOT='${MAINLINE_UBOOT}'|g" ${op_release} 2>/dev/null
sed -i "s|^ANDROID_UBOOT=.*|ANDROID_UBOOT='${ANDROID_UBOOT}'|g" ${op_release} 2>/dev/null
K510="1"
[[ "$(hexdump -n 15 -x "/boot/zImage" 2>/dev/null | head -n 1 | awk '{print $7}')" == "0108" ]] && K510="0"
echo -e "K510 [ ${K510} ]"
# backup old bootloader
if [[ ! -f "/root/BackupOldBootloader.img" ]]; then
echo "Backup bootloader -> [ BackupOldBootloader.img ] ... "
dd if=/dev/$EMMC_NAME of=/root/BackupOldBootloader.img bs=1M count=4 conv=fsync
echo "Backup bootloader complete."
echo
fi
swapoff -a
# umount all other mount points
MOUNTS=$(lsblk -l -o MOUNTPOINT)
for mnt in $MOUNTS; do
if [ "$mnt" == "MOUNTPOINT" ]; then
continue
fi
if [ "$mnt" == "" ]; then
continue
fi
if [ "$mnt" == "/" ]; then
continue
fi
if [ "$mnt" == "/boot" ]; then
continue
fi
if [ "$mnt" == "/opt" ]; then
continue
fi
if [ "$mnt" == "[SWAP]" ]; then
echo "swapoff -a"
swapoff -a
continue
fi
if echo $mnt | grep $EMMC_NAME; then
echo "umount -f $mnt"
umount -f $mnt
if [ $? -ne 0 ]; then
error_msg "$mnt Cannot be uninstalled, the installation process is aborted."
fi
fi
done
# Delete old partition if exists
p=$(lsblk -l | grep -e "${EMMC_NAME}p" | wc -l)
echo "A total of [ $p ] old partitions on EMMC will be deleted"
>/tmp/fdisk.script
while [ $p -ge 1 ]; do
echo "d" >>/tmp/fdisk.script
if [ $p -gt 1 ]; then
echo "$p" >>/tmp/fdisk.script
fi
p=$((p - 1))
done
# you can change ROOT size(MB) >= 320
ROOT1="2048"
ROOT2="2048"
if [[ "${AMLOGIC_SOC}" == "s912" ]] && [[ "${boxtype}" == "213" || "${boxtype}" == "2e" ]]; then
BOOT="512"
BLANK1="700"
BLANK2="220"
BLANK3="0"
BLANK4="0"
elif [[ "${AMLOGIC_SOC}" == "s912" || "${AMLOGIC_SOC}" == "s905d" ]]; then
BOOT="512"
BLANK1="68"
BLANK2="220"
BLANK3="0"
BLANK4="0"
elif [[ "${AMLOGIC_SOC}" == "s905x" ]]; then
BOOT="160"
BLANK1="700"
BLANK2="0"
BLANK3="0"
BLANK4="0"
elif [[ "${FDTFILE}" == "meson-sm1-skyworth-lb2004-a4091.dtb" ]]; then
BOOT="512"
BLANK1="108"
BLANK2="562"
BLANK3="0"
BLANK4="0"
elif [[ "${AMLOGIC_SOC}" == "s905l3a" ]] && [[ "${boxtype}" == "304" || "${boxtype}" == "34" ]]; then
# e900v22c/d(s905l3a)
BOOT="256"
BLANK1="570"
BLANK2="0"
BLANK3="0"
BLANK4="0"
elif [[ "${AMLOGIC_SOC}" == "s905l3a" ]] && [[ "${boxtype}" == "305" || "${boxtype}" == "33" ]]; then
# CM311-1a-YST(s905l3a)
BOOT="512"
BLANK1="108"
BLANK2="778"
BLANK3="0"
BLANK4="0"
elif [[ "${AMLOGIC_SOC}" == "s905l3b" ]]; then
# M302A/M304A(s905l3b)
BOOT="512"
BLANK1="128"
BLANK2="720"
BLANK3="0"
BLANK4="0"
elif [[ "${AMLOGIC_SOC}" == "s905x3" ]] && [[ "${boxtype}" == "525" || "${boxtype}" == "5n" ]]; then
# Whale(s905x3)
BOOT="512"
BLANK1="108"
BLANK2="650"
BLANK3="0"
BLANK4="0"
elif [[ "${boxtype}" =~ ^(409|410|49|4a)$ ]]; then
# WXY-OES(A311D):409/49, WXY-OES-PLUS(S922X):410/4a
BOOT="512"
BLANK1="700"
BLANK2="0"
BLANK3="0"
BLANK4="0"
else
BOOT="160"
BLANK1="68"
BLANK2="0"
BLANK3="162"
BLANK4="0"
fi
DST_TOTAL_MB=$((EMMC_SIZE / 1024 / 1024))
start1=$((BLANK1 * 2048))
end1=$((start1 + (BOOT * 2048) - 1))
start2=$(((BLANK2 * 2048) + end1 + 1))
end2=$((start2 + (ROOT1 * 2048) - 1))
start3=$(((BLANK3 * 2048) + end2 + 1))
end3=$((start3 + (ROOT2 * 2048) - 1))
start4=$(((BLANK4 * 2048) + end3 + 1))
end4=$((DST_TOTAL_MB * 2048 - 1))
cat >>/tmp/fdisk.script <<EOF
n
p
1
$start1
$end1
n
p
2
$start2
$end2
n
p
3
$start3
$end3
n
p
$start4
$end4
t
1
c
t
2
83
t
3
83
t
4
83
w
EOF
fdisk /dev/${EMMC_NAME} </tmp/fdisk.script 2>/dev/null
if [ $? -ne 0 ]; then
echo "The fdisk partition fails, Please try again."
dd if=/root/BackupOldBootloader.img of=/dev/${EMMC_NAME} conv=fsync && sync
dd if=/dev/zero of=/dev/${EMMC_NAME} bs=512 count=1 && sync
exit 1
fi
echo "Partition complete."
# write some zero data to part begin
seek=$((start1 / 2048))
dd if=/dev/zero of=/dev/${EMMC_NAME} bs=1M count=1 seek=$seek conv=fsync
seek=$((start2 / 2048))
dd if=/dev/zero of=/dev/${EMMC_NAME} bs=1M count=1 seek=$seek conv=fsync
seek=$((start3 / 2048))
dd if=/dev/zero of=/dev/${EMMC_NAME} bs=1M count=1 seek=$seek conv=fsync
seek=$((start4 / 2048))
dd if=/dev/zero of=/dev/${EMMC_NAME} bs=1M count=1 seek=$seek conv=fsync
#Mainline U-BOOT detection
FLASH_MAINLINE_UBOOT=0
if [[ -n "${MAINLINE_UBOOT}" && -f "${MAINLINE_UBOOT}" ]]; then
cat <<EOF
----------------------------------------------------------------------------------
Found an available mainline bootloader (Mainline u-boot), you can flash into EMMC.
----------------------------------------------------------------------------------
EOF
while :; do
# For [luci-app-amlogic] input parameter: SOC & DTB
# When there is no input parameter, select manually
if [[ "${AUTO_MAINLINE_UBOOT}" == "yes" ]]; then
if [[ "${K510}" -eq "1" ]]; then
yn="y"
else
yn="n"
fi
elif [[ "${AUTO_MAINLINE_UBOOT}" == "no" ]]; then
yn="n"
else
read -p "Please choose whether to write the mainline bootloader to EMMC? y/n " yn
fi
case $yn in
y | Y)
FLASH_MAINLINE_UBOOT=1
break
;;
n | N)
FLASH_MAINLINE_UBOOT=0
break
;;
esac
done
fi
if [[ "${FLASH_MAINLINE_UBOOT}" -eq "1" ]]; then
echo -e "Write Mainline bootloader: [ ${MAINLINE_UBOOT} ]"
dd if=${MAINLINE_UBOOT} of=/dev/${EMMC_NAME} bs=1 count=444 conv=fsync
dd if=${MAINLINE_UBOOT} of=/dev/${EMMC_NAME} bs=512 skip=1 seek=1 conv=fsync
elif [[ -n "${ANDROID_UBOOT}" && -f "${ANDROID_UBOOT}" ]]; then
echo -e "Write Android bootloader: [ ${ANDROID_UBOOT} ]"
dd if=${ANDROID_UBOOT} of=/dev/${EMMC_NAME} bs=1 count=444 conv=fsync
dd if=${ANDROID_UBOOT} of=/dev/${EMMC_NAME} bs=512 skip=1 seek=1 conv=fsync
else
echo "Did not change the original bootloader."
fi
# fix wifi macaddr
if [ -x /usr/bin/fix_wifi_macaddr.sh ]; then
/usr/bin/fix_wifi_macaddr.sh
fi
# mkfs
echo "Start creating file system ... "
echo "Create a boot file system ... "
echo "format boot partiton..."
mkfs.fat -n EMMC_BOOT -F 32 /dev/${EMMC_NAME}p1
mkdir -p /mnt/${EMMC_NAME}p1
sleep 2
umount -f /mnt/${EMMC_NAME}p1 2>/dev/null
echo "format rootfs1 partiton..."
ROOTFS1_UUID=$(/usr/bin/uuidgen)
mkfs.btrfs -f -U ${ROOTFS1_UUID} -L EMMC_ROOTFS1 -m single /dev/${EMMC_NAME}p2
mkdir -p /mnt/${EMMC_NAME}p2
sleep 2
umount -f /mnt/${EMMC_NAME}p2 2>/dev/null
echo "format rootfs2 partiton..."
ROOTFS2_UUID=$(/usr/bin/uuidgen)
mkfs.btrfs -f -U ${ROOTFS2_UUID} -L EMMC_ROOTFS2 -m single /dev/${EMMC_NAME}p3
mkdir -p /mnt/${EMMC_NAME}p3
sleep 2
umount -f /mnt/${EMMC_NAME}p3 2>/dev/null
# mount and copy
echo "Wait for the boot file system to mount ... "
i=1
max_try=10
while [ $i -le $max_try ]; do
mount -t vfat /dev/${EMMC_NAME}p1 /mnt/${EMMC_NAME}p1 2>/dev/null
sleep 2
mnt=$(lsblk -l -o MOUNTPOINT | grep /mnt/${EMMC_NAME}p1)
if [ "$mnt" == "" ]; then
if [ $i -lt $max_try ]; then
echo "Not mounted successfully, try again ..."
i=$((i + 1))
else
error_msg "Cannot mount the boot file system, give up!"
fi
else
echo "Successfully mounted."
echo "copy boot ..."
cd /mnt/${EMMC_NAME}p1
rm -rf /boot/'System Volume Information/'
(cd /boot && tar cf - .) | tar xf -
sync
echo "Edit uEnv.txt ..."
[[ -f "uEnv.txt" ]] && {
sed -i -E \
-e "s|/dtb/amlogic.*|/dtb/amlogic/${FDTFILE}|" \
-e "s|UUID=[^ ]*|UUID=${ROOTFS1_UUID}|" \
-e "s|rootflags=compress=zstd:[^ ]*|rootflags=compress=zstd:${ZSTD_LEVEL}|" \
uEnv.txt
}
# Replace the extlinux/extlinux.conf if it exists
[[ -f "extlinux/extlinux.conf" ]] && {
sed -i -E \
-e "s|/dtb/amlogic.*|/dtb/amlogic/${FDTFILE}|" \
-e "s|UUID=[^ ]*|UUID=${ROOTFS1_UUID}|" \
-e "s|rootflags=compress=zstd:[^ ]*|rootflags=compress=zstd:${ZSTD_LEVEL}|" \
extlinux/extlinux.conf
}
rm -f s905_autoscript* aml_autoscript*
if [ ${K510} -eq 1 ]; then
if [ -f ${UBOOT_OVERLOAD} ]; then
cp -f -v ${UBOOT_OVERLOAD} u-boot.emmc
elif [ -f "u-boot.ext" ]; then
cp -f -v u-boot.ext u-boot.emmc
fi
fi
mv -f boot-emmc.ini boot.ini
mv -f boot-emmc.cmd boot.cmd
mv -f boot-emmc.scr boot.scr
sync
echo "complete."
cd /
umount -f /mnt/${EMMC_NAME}p1
break
fi
done
echo "complete."
echo "Wait for the rootfs file system to mount ... "
i=1
while [ $i -le $max_try ]; do
mount -t btrfs -o compress=zstd:${ZSTD_LEVEL} /dev/${EMMC_NAME}p2 /mnt/${EMMC_NAME}p2 2>/dev/null
sleep 2
mnt=$(lsblk -l -o MOUNTPOINT | grep /mnt/${EMMC_NAME}p2)
if [ "$mnt" == "" ]; then
if [ $i -lt $max_try ]; then
echo "Not mounted successfully, try again ..."
i=$((i + 1))
else
error_msg "Cannot mount rootfs file system, give up!"
fi
else
echo "Successfully mounted"
echo "Create folder ... "
cd /mnt/${EMMC_NAME}p2
btrfs subvolume create etc
mkdir -p bin boot dev lib opt mnt overlay proc rom root run sbin sys tmp usr www .reserved .snapshots
ln -sf lib/ lib64
ln -sf tmp/ var
sync
echo "complete."
COPY_SRC="root etc bin sbin lib opt usr www"
echo "Copy data ... "
for src in $COPY_SRC; do
echo "copy [ $src ] ..."
(cd / && tar cf - $src) | tar xf -
sync
done
echo "Copy complete."
sync
cat >etc/docker/daemon.json <<EOF
{
"bip": "172.31.0.1/24",
"data-root": "/mnt/${EMMC_NAME}p4/docker/",
"log-level": "warn",
"log-driver": "json-file",
"log-opts": {
"max-size": "10m",
"max-file": "5"
},
"registry-mirrors": [
"https://mirror.baidubce.com/",
"https://hub-mirror.c.163.com"
]
}
EOF
# change data_root value in /etc/config/dockerd
if [[ -f "/etc/init.d/dockerman" ]] && [[ -f "/etc/config/dockerd" ]]; then
sed -i "s|option data_root.*|option data_root '/mnt/${EMMC_NAME}p4/docker/'|g" etc/config/dockerd
fi
rm -rf opt/docker && ln -sf /mnt/${EMMC_NAME}p4/docker/ opt/docker >/dev/null
rm -rf usr/bin/AdGuardHome && ln -sf /mnt/${EMMC_NAME}p4/AdGuardHome usr/bin/ >/dev/null
echo "Edit configuration file ..."
#cd /mnt/${EMMC_NAME}p2/usr/bin/
#rm -f openwrt-install-amlogic openwrt-update-amlogic
cd /mnt/${EMMC_NAME}p2/etc/rc.d
ln -sf ../init.d/dockerd S99dockerd
rm -f S??shortcut-fe
if grep "sfe_flow '1'" ../config/turboacc >/dev/null; then
if find ../../lib/modules -name 'shortcut-fe-cm.ko'; then
ln -sf ../init.d/shortcut-fe S99shortcut-fe
fi
fi
cd /mnt/${EMMC_NAME}p2/etc
cat >fstab <<EOF
UUID=${ROOTFS1_UUID} / btrfs compress=zstd:${ZSTD_LEVEL} 0 1
LABEL=EMMC_BOOT /boot vfat defaults 0 2
#tmpfs /tmp tmpfs defaults,nosuid 0 0
EOF
cd /mnt/${EMMC_NAME}p2/etc/config
cat >fstab <<EOF
config global
option anon_swap '0'
option anon_mount '1'
option auto_swap '0'
option auto_mount '1'
option delay_root '5'
option check_fs '0'
config mount
option target '/rom'
option uuid '${ROOTFS1_UUID}'
option enabled '1'
option enabled_fsck '1'
option fstype 'btrfs'
option options 'compress=zstd:${ZSTD_LEVEL}'
config mount
option target '/boot'
option label 'EMMC_BOOT'
option enabled '1'
option enabled_fsck '1'
option fstype 'vfat'
EOF
echo -n "Create initial etc snapshot -> .snapshots/etc-000"
cd /mnt/${EMMC_NAME}p2 &&
btrfs subvolume snapshot -r etc .snapshots/etc-000
sync
cd /
umount -f /mnt/${EMMC_NAME}p2
break
fi
done
echo "complete."
echo "Create a shared file system."
mkdir -p /mnt/${EMMC_NAME}p4
# When there is no input parameter, select manually
if [[ -n "${SHARED_FSTYPE}" ]]; then
TARGET_SHARED_FSTYPE=${SHARED_FSTYPE}
else
cat <<EOF
---------------------------------------------------------------------------------
Please select the type of shared file system:
1. ext4: [Default options] suitable for general use.
2. btrfs: Which can extend the service life of ssd/mmc.
3. f2fs: Fast reading and writing speed, but the compatibility is slightly poor.
4. xfs: Very good file system, alternative to ext4.
---------------------------------------------------------------------------------
EOF
read -p "Please Input ID: " TARGET_SHARED_FSTYPE
fi
case $TARGET_SHARED_FSTYPE in
2 | btrfs)
mkfs.btrfs -f -L EMMC_SHARED -m single /dev/${EMMC_NAME}p4 >/dev/null
mount -t btrfs /dev/${EMMC_NAME}p4 /mnt/${EMMC_NAME}p4
;;
3 | f2fs)
mkfs.f2fs -f -l EMMC_SHARED /dev/${EMMC_NAME}p4 >/dev/null
mount -t f2fs /dev/${EMMC_NAME}p4 /mnt/${EMMC_NAME}p4
;;
4 | xfs)
mkfs.xfs -f -L EMMC_SHARED /dev/${EMMC_NAME}p4 >/dev/null
mount -t xfs /dev/${EMMC_NAME}p4 /mnt/${EMMC_NAME}p4
;;
*)
mkfs.ext4 -F -L EMMC_SHARED /dev/${EMMC_NAME}p4 >/dev/null
mount -t ext4 /dev/${EMMC_NAME}p4 /mnt/${EMMC_NAME}p4
;;
esac
mkdir -p /mnt/${EMMC_NAME}p4/docker /mnt/${EMMC_NAME}p4/AdGuardHome/data
sync
echo "Successful installed, please unplug the USB, re-insert the power supply to start the openwrt."
exit 0
+516
View File
@@ -0,0 +1,516 @@
#!/bin/bash
#====================================================================================
#
# Function: Update the kernel for OpenWrt (Amlogic s9xxx, Allwinner, Rockchip)
# Copyright (C) 2020-- https://github.com/unifreq/openwrt_packit
# Copyright (C) 2021-- https://github.com/ophub/luci-app-amlogic
#
# Support the kernel: boot-*.tar.gz, dtb-*.tar.gz, modules-*.tar.gz
# It is recommended to install MAINLINE_UBOOT for kernel versions above 5.10.y
# openwrt-kernel ${AUTO_MAINLINE_UBOOT}
# E.g: openwrt-kernel yes
# openwrt-kernel no
#
#================================== Functions list ==================================
#
# error_msg : Output error message
# get_textoffset : Get kernel TEXT_OFFSET
# init_var : Initialize all variables
# check_kernel : Check kernel files list
# chech_files_same : Check file consistency
# restore_kernel : Restore current kernel
# update_kernel : Update the kernel
# update_uboot : Update the uboot
#
#============================== Set default parameters ==============================
#
# Receive one-key command related parameters
AUTO_MAINLINE_UBOOT="no"
# Set the release check file
release_file="/etc/flippy-openwrt-release"
#
#====================================================================================
# Encountered a serious error, abort the script execution
error_msg() {
echo -e "[Error] ${1}"
exit 1
}
# Get the partition name of the /boot file system
get_boot_partition_name() {
local paths="/boot"
local partition_name
partition_name=$(df "${paths}" | awk 'NR==2 {print $1}' | awk -F '/' '{print $3}')
echo "${partition_name}"
}
# Get the partition name of the root file system
get_root_partition_name() {
local paths=("/" "/overlay" "/rom")
local partition_name
for path in "${paths[@]}"; do
partition_name=$(df "${path}" | awk 'NR==2 {print $1}' | awk -F '/' '{print $3}')
[[ -n "${partition_name}" ]] && break
done
echo "${partition_name}"
}
# Get kernel TEXT_OFFSET, For u-boot.ext and u-boot.emmc
get_textoffset() {
boot_tgz_file="${1}"
vmlinuz_name="${2}"
K510="1"
temp_dir="$(mktemp -d)"
(
cd ${temp_dir}
tar -xf "${boot_tgz_file}" "${vmlinuz_name}"
)
# With TEXT_OFFSET patch is [ 0108 ], without TEXT_OFFSET patch is [ 0000 ]
[[ "$(hexdump -n 15 -x "${temp_dir}/${vmlinuz_name}" 2>/dev/null | head -n 1 | awk '{print $7}')" == "0108" ]] && K510="0"
}
init_var() {
# Receive one-key command related parameters
[[ "${1}" == "yes" ]] && AUTO_MAINLINE_UBOOT="yes"
# Check dependencies
[[ -n "$(busybox which tar)" ]] || error_msg "Missing [ tar ] in OpenWrt firmware, unable to update kernel"
# Check release file
if [[ -s "${release_file}" ]]; then
source "${release_file}"
PLATFORM="${PLATFORM}"
MODEL_ID="${MODEL_ID}"
UBOOT_OVERLOAD="${UBOOT_OVERLOAD}"
MAINLINE_UBOOT="${MAINLINE_UBOOT}"
ANDROID_UBOOT="${ANDROID_UBOOT}"
SOC="${SOC}"
LOCK_KERNEL="${LOCK_KERNEL}"
else
error_msg "${release_file} file is missing!"
fi
[[ -n "${PLATFORM}" ]] || error_msg "Missing ${PLATFORM} value in ${release_file} file."
# Define supported platforms
support_platform=("allwinner" "rockchip" "amlogic" "qemu-aarch64")
[[ -n "$(echo "${support_platform[@]}" | grep -w "${PLATFORM}")" ]] || error_msg "[ ${PLATFORM} ] is not supported."
# Check and repair partition mount points
[[ -z "$(get_boot_partition_name)" || -z "$(get_root_partition_name)" ]] && {
echo -e "Partition mount point error, start repairing..."
openwrt-backup -g
}
# Set /boot/vmlinuz-* replication names for different SoCs
MYBOOT_VMLINUZ="$(ls -l /boot/*Image 2>/dev/null | awk '{print $9}' | head -n 1)"
MYBOOT_VMLINUZ="${MYBOOT_VMLINUZ##*/}"
[[ -n "${MYBOOT_VMLINUZ}" ]] || error_msg "Failed to get Image name: [ ${MYBOOT_VMLINUZ} ]"
# Find the partition where root is located
ROOT_PTNAME="$(get_root_partition_name)"
# Find the disk where the partition is located, only supports mmcblk?p? sd?? hd?? vd?? and other formats
case "${ROOT_PTNAME}" in
mmcblk?p[1-9])
EMMC_NAME="$(echo ${ROOT_PTNAME} | awk '{print substr($1, 1, length($1)-2)}')"
PARTITION_NAME="p"
;;
[hsv]d[a-z][1-9])
EMMC_NAME="$(echo ${ROOT_PTNAME} | awk '{print substr($1, 1, length($1)-1)}')"
PARTITION_NAME=""
;;
nvme?n?p[1-9])
EMMC_NAME="$(echo ${ROOT_PTNAME} | awk '{print substr($1, 1, length($1)-2)}')"
PARTITION_NAME="p"
;;
*)
error_msg "Unable to recognize the disk type of ${ROOT_PTNAME}!"
;;
esac
P4_PATH="/mnt/${EMMC_NAME}${PARTITION_NAME}4"
# Move kernel related files to the ${P4_PATH} directory
mv -f /tmp/upload/* ${P4_PATH} 2>/dev/null
# Current device model
MYDEVICE_NAME="$(cat /proc/device-tree/model | tr -d '\000')"
[[ "${PLATFORM}" == "qemu-aarch64" ]] && MYDEVICE_NAME="KVM Virtual Machine"
echo -e "Current device: ${MYDEVICE_NAME} [ ${PLATFORM} ], Use in [ ${EMMC_NAME} ]"
sync && echo ""
}
# Check kernel files list
check_kernel() {
cd ${P4_PATH}
# Determine custom kernel filename
kernel_boot="$(ls boot-*.tar.gz 2>/dev/null | head -n 1)"
kernel_name="${kernel_boot:5:-7}"
KERNEL_VERSION="$(echo ${kernel_name} | grep -oE '^[1-9].[0-9]{1,3}.[0-9]+')"
echo -e "Kernel name: ${kernel_name}"
# check if kernel is locked
if [ -n "${LOCK_KERNEL}" ]; then
if [ "${LOCK_KERNEL}" != "${kernel_name}" ]; then
if ! echo "${kernel_name}" | grep -E '^5.10.\d+-.*?rk35.*?$' >/dev/null; then
error_msg "The kernel version is locked to [ ${LOCK_KERNEL} ], but your kernel is [ ${kernel_name} ]. "
fi
fi
fi
# Check if the file is added with TEXT_OFFSET patch
get_textoffset "${P4_PATH}/${kernel_boot}" "vmlinuz-${kernel_name}"
echo -e "K510 [ ${K510} ]"
if [[ "${PLATFORM}" == "amlogic" && "${K510}" -eq "1" ]]; then
[[ -n "${UBOOT_OVERLOAD}" && -f "/boot/${UBOOT_OVERLOAD}" ]] || error_msg "The UBOOT_OVERLOAD file is missing and cannot be update."
fi
# Check the sha256sums file
sha256sums_file="sha256sums"
sha256sums_check="1"
[[ -s "${sha256sums_file}" && -n "$(cat ${sha256sums_file})" ]] || sha256sums_check="0"
[[ -n "$(busybox which sha256sum)" ]] || sha256sums_check="0"
[[ "${sha256sums_check}" -eq "1" ]] && echo -e "Enable sha256sum checking..."
# Loop check file
i="1"
if [[ "${PLATFORM}" == "qemu-aarch64" ]]; then
kernel_list=("boot" "modules")
else
kernel_list=("boot" "dtb-${PLATFORM}" "modules")
fi
for kernel_file in ${kernel_list[*]}; do
# Set check filename
tmp_file="${kernel_file}-${kernel_name}.tar.gz"
# Check if file exists
[[ -s "${tmp_file}" ]] || error_msg "The [ ${kernel_file} ] file is missing."
# Check if the file sha256sum is correct
if [[ "${sha256sums_check}" -eq "1" ]]; then
tmp_sha256sum="$(sha256sum "${tmp_file}" | awk '{print $1}')"
tmp_checkcode="$(cat ${sha256sums_file} | grep ${tmp_file} | awk '{print $1}')"
[[ "${tmp_sha256sum}" == "${tmp_checkcode}" ]] || error_msg "${tmp_file}: sha256sum verification failed."
echo -e "(${i}/3) [ ${tmp_file} ] file sha256sum check same."
fi
let i++
done
sync && echo ""
}
# Check the consistency of amlogic device files
chech_files_same() {
i="0"
max_try="5"
while [[ "${i}" -le "${max_try}" ]]; do
if [[ "$(sha256sum "${1}" | awk '{print $1}')" == "$(sha256sum "${2}" | awk '{print $1}')" ]]; then
echo "" && break
else
cp -f ${1} ${2}
i="$((i + 1))"
fi
done
[[ "${i}" -gt "${max_try}" ]] && echo "God, it's different after ${max_try} copies: [ ${1} ]"
}
# Restore the kernel when the update fails
restore_kernel() {
(
cd /boot
rm -rf \
config-${kernel_name} \
System.map-${kernel_name} \
initrd.img-${kernel_name} \
uInitrd-${kernel_name} \
vmlinuz-${kernel_name} \
initrd.img \
uInitrd \
zImage \
Image \
vmlinuz \
dtb* 2>/dev/null
tar -xzf /tmp/boot-backup.tar.gz 2>/dev/null
)
error_msg "Kernel update failed and has been reverted."
}
# Update the kernel
update_kernel() {
local cur_kernel_name=$(uname -r)
local boot_fstype=$(df -T /boot | tail -n1 | awk '{print $2}')
echo -e "Start unpacking the kernel..."
# 01. for /boot five files
# Backup the current_kernel
(
cd /boot
tar -czf /tmp/boot-backup.tar.gz \
config-${cur_kernel_name} \
System.map-${cur_kernel_name} \
initrd.img-${cur_kernel_name} \
uInitrd-${cur_kernel_name} \
vmlinuz-${cur_kernel_name} \
initrd.img \
uInitrd \
zImage \
Image \
vmlinuz \
dtb* 2>/dev/null
rm -rf \
config-${cur_kernel_name} \
System.map-${cur_kernel_name} \
initrd.img-${cur_kernel_name} \
uInitrd-${cur_kernel_name} \
vmlinuz-${cur_kernel_name} \
initrd.img \
uInitrd \
zImage \
Image \
vmlinuz \
dtb* 2>/dev/null
)
# Extract the new kernel
tar -xf ${P4_PATH}/boot-${kernel_name}.tar.gz -C /boot
# Check if the file exists
local valid_files
if [[ "${PLATFORM}" == "qemu-aarch64" ]]; then
valid_files="vmlinuz-${kernel_name} initrd.img-${kernel_name} config-${kernel_name} System.map-${kernel_name}"
rm -f /boot/uInitrd*
else
valid_files="vmlinuz-${kernel_name} uInitrd-${kernel_name} config-${kernel_name} System.map-${kernel_name}"
# wxy-oect: MODEL_ID numbers r304,r306 and w[0-9]{3}, require special handling of uInitrd
[[ "${MODEL_ID}" =~ ^(r304|r306|w[0-9]{3})$ ]] || rm -f /boot/initrd.img*
fi
for f in ${valid_files}; do [[ -f "/boot/${f}" ]] || restore_kernel; done
# Check if the files are the same
(
cd /boot
if [[ "${PLATFORM}" == "qemu-aarch64" ]]; then
ln -sf initrd.img-${kernel_name} initrd.img
ln -sf vmlinuz-${kernel_name} ${MYBOOT_VMLINUZ}
elif [[ "$boot_fstype" == "vfat" ]]; then
cp -f uInitrd-${kernel_name} uInitrd
[[ -z "$(chech_files_same uInitrd-${kernel_name} uInitrd)" ]] || restore_kernel
cp -f vmlinuz-${kernel_name} ${MYBOOT_VMLINUZ}
[[ -z "$(chech_files_same vmlinuz-${kernel_name} ${MYBOOT_VMLINUZ})" ]] || restore_kernel
else
ln -sf uInitrd-${kernel_name} uInitrd
ln -sf vmlinuz-${kernel_name} ${MYBOOT_VMLINUZ}
fi
# wxy-oect: MODEL_ID numbers r304 and r306, require special handling of uInitrd
[[ "${MODEL_ID}" =~ ^(r304|r306)$ ]] && ln -sf initrd.img-${kernel_name} uInitrd
)
echo -e "(1/3) Unpacking [ boot-${kernel_name}.tar.gz ] done."
if [[ "${PLATFORM}" == "qemu-aarch64" ]]; then
echo -e "(2/3) skip unpack dtb files."
else
# 02. for /boot/dtb/${PLATFORM}/*
if [[ "${boot_fstype}" == "vfat" ]]; then
(cd /boot && mkdir -p dtb/${PLATFORM})
else
(cd /boot && mkdir -p dtb-${kernel_name}/${PLATFORM} && ln -sf dtb-${kernel_name} dtb)
fi
tar -xf ${P4_PATH}/dtb-${PLATFORM}-${kernel_name}.tar.gz -C /boot/dtb/${PLATFORM}
[[ "$(ls /boot/dtb/${PLATFORM} -l 2>/dev/null | grep "^-" | wc -l)" -ge "1" ]] || error_msg "/boot/dtb/${PLATFORM} file is missing."
echo -e "(2/3) Unpacking [ dtb-${PLATFORM}-${kernel_name}.tar.gz ] done."
fi
# 03. for /lib/modules/*
rm -rf /lib/modules/*
tar -xf ${P4_PATH}/modules-${kernel_name}.tar.gz -C /lib/modules
(
cd /lib/modules/${kernel_name}
rm -f *.ko
find ./ -type f -name '*.ko' -exec ln -s {} ./ \;
sync && sleep 3
x=$(ls *.ko -l 2>/dev/null | grep "^l" | wc -l)
[[ "${x}" -eq "0" ]] && error_msg "Error *.ko Files not found."
)
echo -e "(3/3) Unpacking [ modules-${kernel_name}.tar.gz ] done."
# Delete kernel tmpfiles
rm -f ${P4_PATH}/*-${kernel_name}.tar.gz
rm -f ${P4_PATH}/sha256sums
sync && echo ""
}
# Update the uboot
update_uboot() {
# Only amlogic SoCs needs to be updated
if [[ "${PLATFORM}" == "amlogic" ]]; then
# Copy u-boot.ext and u-boot.emmc
if [[ "${K510}" -eq "1" && -n "${UBOOT_OVERLOAD}" && -f "/boot/${UBOOT_OVERLOAD}" ]]; then
[[ ! -f "/boot/u-boot.ext" ]] && cp -f "/boot/${UBOOT_OVERLOAD}" /boot/u-boot.ext && chmod +x /boot/u-boot.ext
[[ ! -f "/boot/u-boot.emmc" ]] && cp -f "/boot/u-boot.ext" /boot/u-boot.emmc && chmod +x /boot/u-boot.emmc
echo -e "The ${UBOOT_OVERLOAD} file copy is complete."
elif [[ "${K510}" -eq "0" ]]; then
rm -f "/boot/u-boot.ext" "/boot/u-boot.emmc"
fi
# Write Mainline bootloader
if [[ -f "${MAINLINE_UBOOT}" && "${AUTO_MAINLINE_UBOOT}" == "yes" ]]; then
echo -e "Write Mainline bootloader: [ ${MAINLINE_UBOOT} ] to [ /dev/${EMMC_NAME} ]"
dd if=${MAINLINE_UBOOT} of=/dev/${EMMC_NAME} bs=1 count=442 conv=fsync
dd if=${MAINLINE_UBOOT} of=/dev/${EMMC_NAME} bs=512 skip=1 seek=1 conv=fsync
echo -e "The MAINLINE_UBOOT file write is complete."
fi
fi
# Update release file
sed -i "s|^KERNEL_VERSION=.*|KERNEL_VERSION='${kernel_name}'|g" ${release_file} 2>/dev/null
# Update banner file
sed -i "s| Kernel.*| Kernel: ${kernel_name}|g" /etc/banner 2>/dev/null
sync && echo ""
}
# Rescue the kernel
sos_kernel() {
echo -e "Start rescuing kernel..."
# Supports specifying disks, such as: [ openwrt-kernel -s mmcblk1 ]
box_disk="${2}"
if [[ -n "${box_disk}" ]]; then
# Format the disk names
box_disk="${box_disk//\/dev\//}"
# Check if the disk exists
[[ -b "/dev/${box_disk}" ]] || error_msg "The specified disk [ ${box_disk} ] does not exist."
# Check if the disk is the same as the current system disk
[[ "${box_disk}" == "${EMMC_NAME}" ]] && error_msg "The specified disk [ ${box_disk} ] is the same as the current system disk [ ${EMMC_NAME} ]."
echo -e "The device name of the specified disk: [ ${box_disk} ]"
else
# Find emmc disk, first find emmc containing boot0 partition
box_disk="$(lsblk -l -o NAME | grep -oE '(mmcblk[0-9]?|nvme[0-9]?n[0-9]?|[hsv]d[a-z])' | grep -vE ^${EMMC_NAME} | sort -u | head -n 1)"
# Check if disk exists
[[ -z "${box_disk}" ]] && error_msg "Unable to locate the storage requiring rescue."
echo -e "The device name of the target disk: [ ${box_disk} ]"
fi
rescue_disk="/dev/${box_disk}"
echo -e "The current OpenWrt is running on [ /dev/${EMMC_NAME} ], and the target disk for restoration is [ ${rescue_disk} ]."
# Create a temporary mount directory
umount ${P4_PATH}/bootfs 2>/dev/null
umount ${P4_PATH}/rootfs 2>/dev/null
rm -rf ${P4_PATH}/bootfs ${P4_PATH}/rootfs 2>/dev/null
mkdir -p ${P4_PATH}/{bootfs/,rootfs/} && sync
[[ "${?}" -ne "0" ]] && error_msg "Failed to create temporary mount directory [ ${P4_PATH} ]"
# Mount target bootfs partition
[[ "${box_disk}" =~ ^([hsv]d[a-z]) ]] && rescue_disk_partition_name="" || rescue_disk_partition_name="p"
mount ${rescue_disk}${rescue_disk_partition_name}1 ${P4_PATH}/bootfs
[[ "${?}" -ne "0" ]] && error_msg "mount ${rescue_disk}${PARTITION_NAME}1 failed!"
echo -e "The [ ${rescue_disk}${rescue_disk_partition_name}1 ] partition is mounted on [ ${P4_PATH}/bootfs ]."
# Search uuid file
if [[ -f "${P4_PATH}/bootfs/uEnv.txt" ]]; then
search_file="uEnv.txt"
elif [[ -f "${P4_PATH}/bootfs/armbianEnv.txt" ]]; then
search_file="armbianEnv.txt"
elif [[ -f "${P4_PATH}/bootfs/extlinux/extlinux.conf" ]]; then
search_file="extlinux/extlinux.conf"
else
error_msg "The [ uEnv.txt, armbianEnv.txt, extlinux/extlinux.conf ] file does not exist, stop rescuing."
fi
# Get the target partition uuid and rootfs
target_parttion_uuid="$(grep '=UUID=' ${P4_PATH}/bootfs/${search_file} | sed -n 's/.*=UUID=\([a-f0-9-]*\).*/\1/p')"
[[ -z "${target_parttion_uuid}" ]] && error_msg "The [ ${search_file} ] file does not contain the UUID value."
target_rootfs="$(blkid | grep ${target_parttion_uuid} | awk -F':' '{print $1;}')"
[[ -z "${target_rootfs}" ]] && error_msg "The [ ${target_parttion_uuid} ] UUID does not exist in the system."
# Mount target rootfs partition
mount ${target_rootfs} ${P4_PATH}/rootfs
[[ "${?}" -ne "0" ]] && error_msg "mount ${rescue_disk}${PARTITION_NAME}2 failed!"
echo -e "The [ ${target_rootfs} ] partition is mounted on [ ${P4_PATH}/rootfs ]."
# Identify the current kernel files
kernel_signature="$(uname -r)"
# 01. For /boot files
[[ -d "${P4_PATH}/bootfs" ]] && {
cd ${P4_PATH}/bootfs
rm -rf config-* initrd.img-* System.map-* vmlinuz-* uInitrd* *Image dtb* u-boot.ext u-boot.emmc
[[ -f "/boot/u-boot.ext" ]] && {
cp -f /boot/u-boot.ext .
cp -f /boot/u-boot.ext u-boot.emmc
chmod +x u-boot.ext u-boot.emmc
}
cp -rf /boot/{*-${kernel_signature},uInitrd,*Image,dtb} .
[[ "${?}" -ne "0" ]] && error_msg "(1/2) [ boot ] kernel files rescue failed."
echo -e "(1/2) [ boot ] kernel files rescue succeeded."
[[ -f "/boot/emmc_autoscript.cmd" ]] && cp -f /boot/emmc_autoscript.cmd .
[[ -f "/boot/emmc_autoscript" ]] && cp -f /boot/emmc_autoscript .
[[ -f "/boot/s905_autoscript.cmd" ]] && cp -f /boot/s905_autoscript.cmd .
[[ -f "/boot/s905_autoscript" ]] && cp -f /boot/s905_autoscript .
} || error_msg "(1/2) The [ ${P4_PATH}/bootfs ] folder does not exist, stop rescuing."
# 02. For /lib/modules/${kernel_signature}
[[ -d "${P4_PATH}/rootfs/lib/modules" ]] && {
cd ${P4_PATH}/rootfs/lib/modules
rm -rf *
cp -rf /lib/modules/${kernel_signature} .
[[ "${?}" -ne "0" ]] && error_msg "(2/2) [ modules ] kernel files rescue failed."
echo -e "(2/2) [ modules ] kernel files rescue succeeded."
} || error_msg "(2/2) The [ ${P4_PATH}/rootfs/lib/modules ] folder does not exist, stop rescuing."
# Unmount the emmc partition
cd ${P4_PATH}
umount -f ${P4_PATH}/bootfs
[[ "${?}" -ne "0" ]] && error_msg "Failed to umount [ ${P4_PATH}/bootfs ]"
umount -f ${P4_PATH}/rootfs
[[ "${?}" -ne "0" ]] && error_msg "Failed to umount [ ${P4_PATH}/rootfs ]"
# Remove the temporary mount directory
rm -rf ${P4_PATH}/bootfs ${P4_PATH}/rootfs
sync && echo ""
}
echo -e "Welcome to the OpenWrt Kernel Management Tool."
# Operation environment check
[[ -x "/usr/sbin/openwrt-kernel" ]] || error_msg "Please grant execution permission: chmod +x /usr/sbin/openwrt-kernel"
# Execute relevant functions based on the options
if [[ "${@}" =~ ^-s(\s)* ]]; then
# Initialize all variables
init_var "${@}"
# Start rescuing the kernel
sos_kernel "${@}"
# Kernel restore successful
sync && sleep 3
echo -e "Kernel rescue successful, please remove the disk and restart the OpenWrt system."
exit 0
else
# Initialize all variables
init_var "${@}"
# Check kernel files list
check_kernel
# Update the kernel
update_kernel
# Update the uboot
update_uboot
# Kernel update successful
sync && sleep 3
echo "Successfully updated, automatic restarting..."
reboot
exit 0
fi
+662
View File
@@ -0,0 +1,662 @@
#!/bin/bash
#======================================================================================
# Function: Update openwrt to emmc for Allwinner STB
# Copyright (C) 2020-- https://github.com/unifreq/openwrt_packit
# Copyright (C) 2021-- https://github.com/ophub/luci-app-amlogic
#======================================================================================
#
# The script supports directly setting parameters for update, skipping interactive selection
# openwrt-update-allwinner ${OPENWRT_FILE} ${AUTO_MAINLINE_UBOOT} ${RESTORE_CONFIG}
# E.g: openwrt-update-allwinner openwrt_s905d.img.gz yes restore
# E.g: openwrt-update-allwinner openwrt_s905d.img.gz no no-restore
# You can also execute the script directly, and interactively select related functions
# E.g: openwrt-update-allwinner
#
#======================================================================================
# Encountered a serious error, abort the script execution
error_msg() {
echo -e "[ERROR] ${1}"
exit 1
}
# Get the partition name of the /boot file system
get_boot_partition_name() {
local paths="/boot"
local partition_name
partition_name=$(df "${paths}" | awk 'NR==2 {print $1}' | awk -F '/' '{print $3}')
echo "${partition_name}"
}
# Get the partition name of the root file system
get_root_partition_name() {
local paths=("/" "/overlay" "/rom")
local partition_name
for path in "${paths[@]}"; do
partition_name=$(df "${path}" | awk 'NR==2 {print $1}' | awk -F '/' '{print $3}')
[[ -n "${partition_name}" ]] && break
done
echo "${partition_name}"
}
# Get the partition message of the root file system
get_root_partition_msg() {
local paths=("/" "/overlay" "/rom")
local partition_name
for path in "${paths[@]}"; do
partition_msg=$(lsblk -l -o NAME,PATH,TYPE,UUID,MOUNTPOINT | awk '$3~/^part$/ && $5 ~ "^" "'"${path}"'" "$" {print $0}')
[[ -n "${partition_msg}" ]] && break
done
[[ -z "${partition_msg}" ]] && error_msg "Cannot find the root partition message!"
echo "${partition_msg}"
}
# Receive one-key command related parameters
IMG_NAME=${1}
AUTO_MAINLINE_UBOOT=${2}
BACKUP_RESTORE_CONFIG=${3}
# Current FDT file
if [[ -f "/boot/uEnv.txt" ]]; then
source /boot/uEnv.txt 2>/dev/null
MYDTB_FDTFILE=$(basename $FDT)
elif [[ -f "/boot/armbianEnv.txt" ]]; then
source /boot/armbianEnv.txt 2>/dev/null
MYDTB_FDTFILE="$(basename $fdtfile)"
elif [[ -f "/etc/flippy-openwrt-release" ]]; then
source /etc/flippy-openwrt-release 2>/dev/null
MYDTB_FDTFILE="${FDTFILE}"
fi
[[ -z "${MYDTB_FDTFILE}" ]] && error_msg "Invalid FDTFILE: [ ${MYDTB_FDTFILE} ]"
# Current device model
MYDEVICE_NAME=$(cat /proc/device-tree/model | tr -d '\000')
if [[ -z "${MYDEVICE_NAME}" ]]; then
error_msg "The device name is empty and cannot be recognized."
elif [[ "$(echo ${MYDEVICE_NAME} | grep "V-Plus Cloud")" == "" ]]; then
error_msg "[ ${MYDEVICE_NAME} ] is not [ V-Plus Cloud ] device, please select the correct script."
else
echo -e "Current device: ${MYDEVICE_NAME} [ vplus ]"
sleep 3
fi
# Check and repair partition mount points
[[ -z "$(get_boot_partition_name)" || -z "$(get_root_partition_name)" ]] && {
echo -e "Partition mount point error, start repairing..."
openwrt-backup -g
}
# Find the partition where root is located
ROOT_PTNAME="$(get_root_partition_name)"
# Find the disk where the partition is located, only supports mmcblk?p? sd?? hd?? vd?? and other formats
case ${ROOT_PTNAME} in
mmcblk?p[1-4])
EMMC_NAME=$(echo ${ROOT_PTNAME} | awk '{print substr($1, 1, length($1)-2)}')
PARTITION_NAME="p"
LB_PRE="EMMC_"
;;
[hsv]d[a-z][1-4])
EMMC_NAME=$(echo ${ROOT_PTNAME} | awk '{print substr($1, 1, length($1)-1)}')
PARTITION_NAME=""
LB_PRE=""
;;
*)
error_msg "Unable to recognize the disk type of ${ROOT_PTNAME}!"
;;
esac
cd /mnt/${EMMC_NAME}${PARTITION_NAME}4/
mv -f /tmp/upload/* . 2>/dev/null && sync
if [[ "${IMG_NAME}" == *.img ]]; then
echo -e "Update using [ ${IMG_NAME} ] file. Please wait a moment ..."
elif [ $(ls *.img -l 2>/dev/null | grep "^-" | wc -l) -ge 1 ]; then
IMG_NAME=$(ls *.img | head -n 1)
echo -e "Update using [ ${IMG_NAME} ] ] file. Please wait a moment ..."
elif [ $(ls *.img.xz -l 2>/dev/null | grep "^-" | wc -l) -ge 1 ]; then
xz_file=$(ls *.img.xz | head -n 1)
echo -e "Update using [ ${xz_file} ] file. Please wait a moment ..."
xz -d ${xz_file} 2>/dev/null
IMG_NAME=$(ls *.img | head -n 1)
elif [ $(ls *.img.gz -l 2>/dev/null | grep "^-" | wc -l) -ge 1 ]; then
gz_file=$(ls *.img.gz | head -n 1)
echo -e "Update using [ ${gz_file} ] file. Please wait a moment ..."
gzip -df ${gz_file} 2>/dev/null
IMG_NAME=$(ls *.img | head -n 1)
elif [ $(ls *.7z -l 2>/dev/null | grep "^-" | wc -l) -ge 1 ]; then
gz_file=$(ls *.7z | head -n 1)
echo -e "Update using [ ${gz_file} ] file. Please wait a moment ..."
bsdtar -xmf ${gz_file} 2>/dev/null
[ $? -eq 0 ] || 7z x ${gz_file} -aoa -y 2>/dev/null
IMG_NAME=$(ls *.img | head -n 1)
elif [ $(ls *.zip -l 2>/dev/null | grep "^-" | wc -l) -ge 1 ]; then
zip_file=$(ls *.zip | head -n 1)
echo -e "Update using [ ${zip_file} ] file. Please wait a moment ..."
unzip -o ${zip_file} 2>/dev/null
IMG_NAME=$(ls *.img | head -n 1)
else
echo -e "Please upload or specify the update openwrt firmware file."
echo -e "Upload method: system menu → Amlogic Service → Manually Upload Update"
echo -e "Specify method: Place the openwrt firmware file in [ /mnt/${EMMC_NAME}${PARTITION_NAME}4/ ]"
echo -e "The supported file suffixes are: *.img, *.img.xz, *.img.gz, *.7z, *.zip"
echo -e "After upload the openwrt firmware file, run again."
exit 1
fi
sync
# check file
if [ ! -f "${IMG_NAME}" ]; then
error_msg "No update file found."
else
echo "Start update from [ ${IMG_NAME} ]"
fi
# find boot partition
BOOT_PART_MSG=$(lsblk -l -o NAME,PATH,TYPE,UUID,MOUNTPOINT | awk '$3~/^part$/ && $5 ~ /^\/boot$/ {print $0}')
if [ "${BOOT_PART_MSG}" == "" ]; then
error_msg "The boot partition is not exists or not mounted, so it cannot be upgraded with this script!"
fi
BR_FLAG=1
echo -ne "Whether to backup and restore the current config files? y/n [y]\b\b"
if [[ ${BACKUP_RESTORE_CONFIG} == "restore" ]]; then
yn="y"
elif [[ ${BACKUP_RESTORE_CONFIG} == "no-restore" ]]; then
yn="n"
else
read yn
fi
case $yn in
n* | N*)
BR_FLAG=0
;;
esac
BOOT_NAME=$(echo ${BOOT_PART_MSG} | awk '{print $1}')
BOOT_PATH=$(echo ${BOOT_PART_MSG} | awk '{print $2}')
BOOT_UUID=$(echo ${BOOT_PART_MSG} | awk '{print $4}')
# find root partition
ROOT_PART_MSG="$(get_root_partition_msg)"
ROOT_NAME=$(echo ${ROOT_PART_MSG} | awk '{print $1}')
ROOT_PATH=$(echo ${ROOT_PART_MSG} | awk '{print $2}')
ROOT_UUID=$(echo ${ROOT_PART_MSG} | awk '{print $4}')
case ${ROOT_NAME} in
${EMMC_NAME}${PARTITION_NAME}2)
NEW_ROOT_NAME="${EMMC_NAME}${PARTITION_NAME}3"
NEW_ROOT_LABEL="${LB_PRE}ROOTFS2"
;;
${EMMC_NAME}${PARTITION_NAME}3)
NEW_ROOT_NAME="${EMMC_NAME}${PARTITION_NAME}2"
NEW_ROOT_LABEL="${LB_PRE}ROOTFS1"
;;
*)
error_msg "The root partition location is invalid, so it cannot be upgraded with this script!"
;;
esac
# find new root partition
NEW_ROOT_PART_MSG=$(lsblk -l -o NAME,PATH,TYPE,UUID,MOUNTPOINT | grep "${NEW_ROOT_NAME}" | awk '$3 ~ /^part$/ && $5 !~ /^\/$/ && $5 !~ /^\/boot$/ {print $0}')
if [ "${NEW_ROOT_PART_MSG}" == "" ]; then
error_msg "The new root partition is not exists, so it cannot be upgraded with this script!"
fi
NEW_ROOT_NAME=$(echo $NEW_ROOT_PART_MSG | awk '{print $1}')
NEW_ROOT_PATH=$(echo $NEW_ROOT_PART_MSG | awk '{print $2}')
NEW_ROOT_UUID=$(echo $NEW_ROOT_PART_MSG | awk '{print $4}')
NEW_ROOT_MP=$(echo $NEW_ROOT_PART_MSG | awk '{print $5}')
# losetup
losetup -f -P $IMG_NAME
if [ $? -eq 0 ]; then
LOOP_DEV=$(losetup | grep "$IMG_NAME" | awk '{print $1}')
if [ "$LOOP_DEV" == "" ]; then
error_msg "loop device not found!"
fi
else
error_msg "losetup $IMG_FILE failed!"
fi
# fix loopdev issue in kernel 5.19
function fix_loopdev() {
local parentdev=${1##*/}
if [ ! -d /sys/block/${parentdev} ]; then
return
fi
subdevs=$(lsblk -l -o NAME | grep -E "^${parentdev}.+\$")
for subdev in $subdevs; do
if [ ! -d /sys/block/${parentdev}/${subdev} ]; then
return
elif [ -b /dev/${sub_dev} ]; then
continue
fi
source /sys/block/${parentdev}/${subdev}/uevent
mknod /dev/${subdev} b ${MAJOR} ${MINOR}
unset MAJOR MINOR DEVNAME DEVTYPE DISKSEQ PARTN PARTNAME
done
}
fix_loopdev ${LOOP_DEV}
WAIT=3
echo -n "The loopdev is $LOOP_DEV, wait ${WAIT} seconds "
while [ $WAIT -ge 1 ]; do
echo -n "."
sleep 1
WAIT=$((WAIT - 1))
done
echo
# umount loop devices (openwrt will auto mount some partition)
MOUNTED_DEVS=$(lsblk -l -o NAME,PATH,MOUNTPOINT | grep "$LOOP_DEV" | awk '$3 !~ /^$/ {print $2}')
for dev in $MOUNTED_DEVS; do
while :; do
echo -n "umount $dev ... "
umount -f $dev
sleep 1
mnt=$(lsblk -l -o NAME,PATH,MOUNTPOINT | grep "$dev" | awk '$3 !~ /^$/ {print $2}')
if [ "$mnt" == "" ]; then
echo "ok"
break
else
echo "try again ..."
fi
done
done
# mount src part
WORK_DIR=$PWD
P1=${WORK_DIR}/boot
P2=${WORK_DIR}/root
mkdir -p $P1 $P2
echo -n "mount ${LOOP_DEV}p1 -> ${P1} ... "
mount -t vfat -o ro ${LOOP_DEV}p1 ${P1}
if [ $? -ne 0 ]; then
echo "mount failed"
losetup -D
exit 1
else
echo "ok"
fi
echo -n "mount ${LOOP_DEV}p2 -> ${P2} ... "
ZSTD_LEVEL=6
mount -t btrfs -o ro,compress=zstd:${ZSTD_LEVEL} ${LOOP_DEV}p2 ${P2}
if [ $? -ne 0 ]; then
echo "mount failed"
umount -f ${P1}
losetup -D
exit 1
else
echo "ok"
fi
# Prepare the dockerman config file
if [ -f ${P2}/etc/init.d/dockerman ] && [ -f ${P2}/etc/config/dockerd ]; then
flg=0
# get current docker data root
data_root=$(uci get dockerd.globals.data_root 2>/dev/null)
if [ "$data_root" == "" ]; then
flg=1
# get current config from /etc/docker/daemon.json
if [ -f "/etc/docker/daemon.json" ] && [ -x "/usr/bin/jq" ]; then
data_root=$(jq -r '."data-root"' /etc/docker/daemon.json)
bip=$(jq -r '."bip"' /etc/docker/daemon.json)
[ "$bip" == "null" ] && bip="172.31.0.1/24"
log_level=$(jq -r '."log-level"' /etc/docker/daemon.json)
[ "$log_level" == "null" ] && log_level="warn"
_iptables=$(jq -r '."iptables"' /etc/docker/daemon.json)
[ "$_iptables" == "null" ] && _iptables="true"
registry_mirrors=$(jq -r '."registry-mirrors"[]' /etc/docker/daemon.json 2>/dev/null)
fi
fi
if [ "$data_root" == "" ]; then
data_root="/opt/docker/" # the default data root
fi
if ! uci get dockerd.globals >/dev/null 2>&1; then
uci set dockerd.globals='globals'
uci commit
fi
# delete alter config , use inner config
if uci get dockerd.globals.alt_config_file >/dev/null 2>&1; then
uci delete dockerd.globals.alt_config_file
uci commit
fi
if [ $flg -eq 1 ]; then
uci set dockerd.globals.data_root=$data_root
[ "$bip" != "" ] && uci set dockerd.globals.bip=$bip
[ "$log_level" != "" ] && uci set dockerd.globals.log_level=$log_level
[ "$_iptables" != "" ] && uci set dockerd.globals.iptables=$_iptables
if [ "$registry_mirrors" != "" ]; then
for reg in $registry_mirrors; do
uci add_list dockerd.globals.registry_mirrors=$reg
done
fi
uci set dockerd.globals.auto_start='1'
uci commit
fi
fi
#format NEW_ROOT
echo "umount ${NEW_ROOT_MP}"
umount -f "${NEW_ROOT_MP}"
if [ $? -ne 0 ]; then
echo "umount failed, please reboot and try again!"
umount -f ${P1}
umount -f ${P2}
losetup -D
exit 1
fi
echo "format ${NEW_ROOT_PATH}"
NEW_ROOT_UUID=$(uuidgen)
mkfs.btrfs -f -U ${NEW_ROOT_UUID} -L ${NEW_ROOT_LABEL} ${NEW_ROOT_PATH}
if [ $? -ne 0 ]; then
echo "format ${NEW_ROOT_PATH} failed!"
umount -f ${P1}
umount -f ${P2}
losetup -D
exit 1
fi
echo "mount ${NEW_ROOT_PATH} to ${NEW_ROOT_MP}"
mount -t btrfs -o compress=zstd:${ZSTD_LEVEL} ${NEW_ROOT_PATH} ${NEW_ROOT_MP}
if [ $? -ne 0 ]; then
echo "mount ${NEW_ROOT_PATH} to ${NEW_ROOT_MP} failed!"
umount -f ${P1}
umount -f ${P2}
losetup -D
exit 1
fi
# begin copy rootfs
cd ${NEW_ROOT_MP}
echo "Start copy data from ${P2} to ${NEW_ROOT_MP} ..."
ENTRYS=$(ls)
for entry in $ENTRYS; do
if [ "$entry" == "lost+found" ]; then
continue
fi
echo -n "remove old $entry ... "
rm -rf $entry
if [ $? -eq 0 ]; then
echo "ok"
else
error_msg "failed"
fi
done
echo
echo "create etc subvolume ..."
btrfs subvolume create etc
echo -n "make dirs ... "
mkdir -p .snapshots .reserved bin boot dev lib opt mnt overlay proc rom root run sbin sys tmp usr www
ln -sf lib/ lib64
ln -sf tmp/ var
echo "done"
echo
COPY_SRC="root etc bin sbin lib opt usr www"
echo "copy data ... "
for src in $COPY_SRC; do
echo -n "copy $src ... "
(cd ${P2} && tar cf - $src) | tar xf -
sync
echo "done"
done
SHFS="/mnt/${EMMC_NAME}${PARTITION_NAME}4"
echo "Modify config files ... "
rm -f "./etc/rc.local.orig" "./etc/first_run.sh" "./etc/part_size"
rm -f ./etc/bench.log
if [ -x ./usr/sbin/balethirq.pl ]; then
if grep "balethirq.pl" "./etc/rc.local"; then
echo "balance irq is enabled"
else
echo "enable balance irq"
sed -e "/exit/i\/usr/sbin/balethirq.pl" -i ./etc/rc.local
fi
fi
cat >./etc/fstab <<EOF
UUID=${NEW_ROOT_UUID} / btrfs compress=zstd:${ZSTD_LEVEL} 0 1
LABEL=${LB_PRE}BOOT /boot vfat defaults 0 2
#tmpfs /tmp tmpfs defaults,nosuid 0 0
EOF
cat >./etc/config/fstab <<EOF
config global
option anon_swap '0'
option anon_mount '1'
option auto_swap '0'
option auto_mount '1'
option delay_root '5'
option check_fs '0'
config mount
option target '/rom'
option uuid '${NEW_ROOT_UUID}'
option enabled '1'
option enabled_fsck '1'
option fstype 'btrfs'
option options 'compress=zstd:${ZSTD_LEVEL}'
config mount
option target '/boot'
option label '${LB_PRE}BOOT'
option enabled '1'
option enabled_fsck '0'
option fstype 'vfat'
EOF
(
cd etc/rc.d
rm -f S??shortcut-fe
if grep "sfe_flow '1'" ../config/turboacc >/dev/null; then
if find ../../lib/modules -name 'shortcut-fe-cm.ko'; then
ln -sf ../init.d/shortcut-fe S99shortcut-fe
fi
fi
)
# move /etc/config/balance_irq to /etc/balance_irq
[ -f "./etc/config/balance_irq" ] && mv ./etc/config/balance_irq ./etc/
sync
echo "create the first etc snapshot -> .snapshots/etc-000"
btrfs subvolume snapshot -r etc .snapshots/etc-000
[ -d ${SHFS}/docker ] || mkdir -p ${SHFS}/docker
rm -rf opt/docker && ln -sf ${SHFS}/docker/ opt/docker
if [ -f /mnt/${NEW_ROOT_NAME}/etc/config/AdGuardHome ]; then
[ -d ${SHFS}/AdGuardHome/data ] || mkdir -p ${SHFS}/AdGuardHome/data
if [ ! -L /usr/bin/AdGuardHome ]; then
[ -d /usr/bin/AdGuardHome ] &&
cp -a /usr/bin/AdGuardHome/* ${SHFS}/AdGuardHome/
fi
ln -sf ${SHFS}/AdGuardHome /mnt/${NEW_ROOT_NAME}/usr/bin/AdGuardHome
fi
BOOTLOADER="./lib/u-boot/u-boot-sunxi-with-spl.bin"
if [ -f ${BOOTLOADER} ]; then
echo "update u-boot ... "
# erase from 8kb to 4mb
dd if=/dev/zero of=/dev/${EMMC_NAME} bs=1024 seek=8 count=4088 conv=fsync
# write u-boot
dd if=${BOOTLOADER} of=/dev/${EMMC_NAME} bs=1024 seek=8 conv=fsync
echo "done"
fi
sync
echo "copy done"
echo
BACKUP_LIST=$(${P2}/usr/sbin/openwrt-backup -p)
if [ $BR_FLAG -eq 1 ]; then
echo -n "Restore your old config files ... "
(
cd /
eval tar czf ${NEW_ROOT_MP}/.reserved/openwrt_config.tar.gz "${BACKUP_LIST}" 2>/dev/null
)
tar xzf ${NEW_ROOT_MP}/.reserved/openwrt_config.tar.gz
[ -f ./etc/config/dockerman ] && sed -e "s/option wan_mode 'false'/option wan_mode 'true'/" -i ./etc/config/dockerman 2>/dev/null
[ -f ./etc/config/dockerd ] && sed -e "s/option wan_mode '0'/option wan_mode '1'/" -i ./etc/config/dockerd 2>/dev/null
[ -f ./etc/config/verysync ] && sed -e 's/config setting/config verysync/' -i ./etc/config/verysync
# 还原 fstab
cp -f .snapshots/etc-000/fstab ./etc/fstab
cp -f .snapshots/etc-000/config/fstab ./etc/config/fstab
# 还原 luci
cp -f .snapshots/etc-000/config/luci ./etc/config/luci
# 还原/etc/config/rpcd
cp -f .snapshots/etc-000/config/rpcd ./etc/config/rpcd
sync
echo "done"
echo
fi
rm -f ./etc/bench.log
cat >>./etc/crontabs/root <<EOF
17 3 * * * /etc/coremark.sh
EOF
sed -e 's/ttyAMA0/ttyS0/' -i ./etc/inittab
sss=$(date +%s)
ddd=$((sss / 86400))
sed -e "s/:0:0:99999:7:::/:${ddd}:0:99999:7:::/" -i ./etc/shadow
# 修复amule每次升级后重复添加条目的问题
sed -e "/amule:x:/d" -i ./etc/shadow
# 修复dropbear每次升级后重复添加sshd条目的问题
sed -e "/sshd:x:/d" -i ./etc/shadow
if ! grep "sshd:x:22:sshd" ./etc/group >/dev/null; then
echo "sshd:x:22:sshd" >>./etc/group
fi
if ! grep "sshd:x:22:22:sshd:" ./etc/passwd >/dev/null; then
echo "sshd:x:22:22:sshd:/var/run/sshd:/bin/false" >>./etc/passwd
fi
if ! grep "sshd:x:" ./etc/shadow >/dev/null; then
echo "sshd:x:${ddd}:0:99999:7:::" >>./etc/shadow
fi
if [ $BR_FLAG -eq 1 ]; then
if [ -x ./bin/bash ] && [ -f ./etc/profile.d/30-sysinfo.sh ]; then
sed -e 's/\/bin\/ash/\/bin\/bash/' -i ./etc/passwd
fi
sync
echo "done"
echo
fi
sed -e "s/option hw_flow '1'/option hw_flow '0'/" -i ./etc/config/turboacc
(
cd etc/rc.d
rm -f S??shortcut-fe
if grep "sfe_flow '1'" ../config/turboacc >/dev/null; then
if find ../../lib/modules -name 'shortcut-fe-cm.ko'; then
ln -sf ../init.d/shortcut-fe S99shortcut-fe
fi
fi
)
sync
eval tar czf .reserved/openwrt_config.tar.gz "${BACKUP_LIST}" 2>/dev/null
rm -f ./etc/part_size ./etc/first_run.sh
mv ./etc/rc.local ./etc/rc.local.orig
cat >"./etc/rc.local" <<EOF
if ! ls /etc/rc.d/S??dockerd >/dev/null 2>&1;then
/etc/init.d/dockerd enable
/etc/init.d/dockerd start
fi
if ! ls /etc/rc.d/S??dockerman >/dev/null 2>&1 && [ -f /etc/init.d/dockerman ];then
/etc/init.d/dockerman enable
/etc/init.d/dockerman start
fi
opkg remove --force-removal-of-dependent-packages shairport-sync-openssl
mv /etc/rc.local.orig /etc/rc.local
chmod 755 /etc/rc.local
exec /etc/rc.local
exit
EOF
chmod 755 ./etc/rc.local*
# move /etc/config/balance_irq to /etc/balance_irq
[ -f "./etc/config/balance_irq" ] && mv ./etc/config/balance_irq ./etc/
echo "create the second etc snapshot -> .snapshots/etc-001"
btrfs subvolume snapshot -r etc .snapshots/etc-001
# 2021.04.01添加
# 强制锁定fstab,防止用户擅自修改挂载点
# 开启了快照功能之后,不再需要锁定fstab
#chattr +ia ./etc/config/fstab
cd ${WORK_DIR}
echo "Start copy data from ${P1} to /boot ..."
cd /boot
echo -n "remove old boot files ..."
rm -rf *
echo "done"
echo -n "copy new boot files ... "
(cd ${P1} && tar cf - .) | tar xf -
sync
echo "done"
echo
echo -n "Update boot args ... "
cat >uEnv.txt <<EOF
LINUX=/zImage
INITRD=/uInitrd
# Example:
# FDT=/dtb/allwinner/sun50i-h6-vplus-cloud.dtb
# FDT=/dtb/allwinner/sun50i-h6-vplus-cloud-2ghz.dtb
FDT=/dtb/allwinner/${MYDTB_FDTFILE}
APPEND=root=UUID=${NEW_ROOT_UUID} rootfstype=btrfs rootflags=compress=zstd:${ZSTD_LEVEL} console=ttyS0,115200n8 no_console_suspend consoleblank=0 fsck.fix=yes fsck.repair=yes net.ifnames=0 cgroup_enable=cpuset cgroup_memory=1 cgroup_enable=memory swapaccount=1
EOF
# Compatible with armbianEnv.txt file
[[ -f "armbianEnv.txt" ]] && {
echo "Update armbianEnv.txt settings."
sed -i "s|^rootdev=.*|rootdev=UUID=${NEW_ROOT_UUID}|g" armbianEnv.txt
rm -f uEnv.txt
}
# Replace the UUID for extlinux/extlinux.conf if it exists
[[ -f "extlinux/extlinux.conf" ]] && {
sed -i -E "s|UUID=[^ ]*|UUID=${NEW_ROOT_UUID}|" extlinux/extlinux.conf 2>/dev/null
}
sync
echo "done"
echo
cd $WORK_DIR
umount -f ${P1} ${P2} 2>/dev/null
losetup -D 2>/dev/null
rmdir ${P1} ${P2} 2>/dev/null
rm -f ${IMG_NAME} 2>/dev/null
rm -f sha256sums 2>/dev/null
sync
echo "Successfully updated, automatic restarting..."
sleep 3
reboot
exit 0
+859
View File
@@ -0,0 +1,859 @@
#!/bin/bash
#======================================================================================
# Function: Update openwrt to emmc for Amlogic S9xxx STB
# Copyright (C) 2020-- https://github.com/unifreq/openwrt_packit
# Copyright (C) 2021-- https://github.com/ophub/luci-app-amlogic
#======================================================================================
#
# The script supports directly setting parameters for update, skipping interactive selection
# openwrt-update-amlogic ${OPENWRT_FILE} ${AUTO_MAINLINE_UBOOT} ${RESTORE_CONFIG}
# E.g: openwrt-update-amlogic openwrt_s905d.img.gz yes restore
# E.g: openwrt-update-amlogic openwrt_s905d.img.gz no no-restore
# You can also execute the script directly, and interactively select related functions
# E.g: openwrt-update-amlogic
#
#======================================================================================
# Encountered a serious error, abort the script execution
error_msg() {
echo -e "[ERROR] ${1}"
exit 1
}
# Get the partition name of the /boot file system
get_boot_partition_name() {
local paths="/boot"
local partition_name
partition_name=$(df "${paths}" | awk 'NR==2 {print $1}' | awk -F '/' '{print $3}')
echo "${partition_name}"
}
# Get the partition name of the root file system
get_root_partition_name() {
local paths=("/" "/overlay" "/rom")
local partition_name
for path in "${paths[@]}"; do
partition_name=$(df "${path}" | awk 'NR==2 {print $1}' | awk -F '/' '{print $3}')
[[ -n "${partition_name}" ]] && break
done
echo "${partition_name}"
}
# Get the partition message of the root file system
get_root_partition_msg() {
local paths=("/" "/overlay" "/rom")
local partition_name
for path in "${paths[@]}"; do
partition_msg=$(lsblk -l -o NAME,PATH,TYPE,UUID,MOUNTPOINT | awk '$3~/^part$/ && $5 ~ "^" "'"${path}"'" "$" {print $0}')
[[ -n "${partition_msg}" ]] && break
done
[[ -z "${partition_msg}" ]] && error_msg "Cannot find the root partition message!"
echo "${partition_msg}"
}
# Receive one-key command related parameters
IMG_NAME="${1}"
AUTO_MAINLINE_UBOOT="${2}"
BACKUP_RESTORE_CONFIG="${3}"
# Current device model
MYDEVICE_NAME=$(cat /proc/device-tree/model | tr -d '\000')
if [[ -z "${MYDEVICE_NAME}" ]]; then
error_msg "The device name is empty and cannot be recognized."
elif [[ ! -f "/etc/flippy-openwrt-release" ]]; then
error_msg "The [ /etc/flippy-openwrt-release ] file is missing."
else
echo -e "Current device: ${MYDEVICE_NAME} [ amlogic ]"
sleep 3
fi
# Check and repair partition mount points
[[ -z "$(get_boot_partition_name)" || -z "$(get_root_partition_name)" ]] && {
echo -e "Partition mount point error, start repairing..."
openwrt-backup -g
}
# Find the partition where root is located
ROOT_PTNAME="$(get_root_partition_name)"
# Find the disk where the partition is located, only supports mmcblk?p? sd?? hd?? vd?? and other formats
case ${ROOT_PTNAME} in
mmcblk?p[1-4])
EMMC_NAME=$(echo ${ROOT_PTNAME} | awk '{print substr($1, 1, length($1)-2)}')
if lsblk -l -o NAME | grep "${EMMC_NAME}boot0" >/dev/null; then
ROOT_DISK_TYPE="EMMC"
else
ROOT_DISK_TYPE="SD"
fi
PARTITION_NAME="p"
LB_PRE="${ROOT_DISK_TYPE}_"
;;
[hsv]d[a-z][1-4])
EMMC_NAME=$(echo ${ROOT_PTNAME} | awk '{print substr($1, 1, length($1)-1)}')
ROOT_DISK_TYPE="USB"
PARTITION_NAME=""
LB_PRE="${ROOT_DISK_TYPE}_"
;;
*)
error_msg "Unable to recognize the disk type of ${ROOT_PTNAME}!"
;;
esac
DOCKER_ROOT="/mnt/${EMMC_NAME}${PARTITION_NAME}4/docker/"
cd /mnt/${EMMC_NAME}${PARTITION_NAME}4/
mv -f /tmp/upload/* . 2>/dev/null && sync
if [[ "${IMG_NAME}" == *.img ]]; then
echo -e "Update using [ ${IMG_NAME} ] file. Please wait a moment ..."
elif [ $(ls *.img -l 2>/dev/null | grep "^-" | wc -l) -ge 1 ]; then
IMG_NAME=$(ls *.img | head -n 1)
echo -e "Update using [ ${IMG_NAME} ] ] file. Please wait a moment ..."
elif [ $(ls *.img.xz -l 2>/dev/null | grep "^-" | wc -l) -ge 1 ]; then
xz_file=$(ls *.img.xz | head -n 1)
echo -e "Update using [ ${xz_file} ] file. Please wait a moment ..."
xz -d ${xz_file} 2>/dev/null
IMG_NAME=$(ls *.img | head -n 1)
elif [ $(ls *.img.gz -l 2>/dev/null | grep "^-" | wc -l) -ge 1 ]; then
gz_file=$(ls *.img.gz | head -n 1)
echo -e "Update using [ ${gz_file} ] file. Please wait a moment ..."
gzip -df ${gz_file} 2>/dev/null
IMG_NAME=$(ls *.img | head -n 1)
elif [ $(ls *.7z -l 2>/dev/null | grep "^-" | wc -l) -ge 1 ]; then
gz_file=$(ls *.7z | head -n 1)
echo -e "Update using [ ${gz_file} ] file. Please wait a moment ..."
bsdtar -xmf ${gz_file} 2>/dev/null
[ $? -eq 0 ] || 7z x ${gz_file} -aoa -y 2>/dev/null
IMG_NAME=$(ls *.img | head -n 1)
elif [ $(ls *.zip -l 2>/dev/null | grep "^-" | wc -l) -ge 1 ]; then
zip_file=$(ls *.zip | head -n 1)
echo -e "Update using [ ${zip_file} ] file. Please wait a moment ..."
unzip -o ${zip_file} 2>/dev/null
IMG_NAME=$(ls *.img | head -n 1)
else
echo -e "Please upload or specify the update openwrt firmware file."
echo -e "Upload method: system menu → Amlogic Service → Manually Upload Update"
echo -e "Specify method: Place the openwrt firmware file in [ /mnt/${EMMC_NAME}${PARTITION_NAME}4/ ]"
echo -e "The supported file suffixes are: *.img, *.img.xz, *.img.gz, *.7z, *.zip"
echo -e "After upload the openwrt firmware file, run again."
exit 1
fi
sync
# check file
if [ ! -f "${IMG_NAME}" ]; then
error_msg "No update file found."
else
echo "Start update from [ ${IMG_NAME} ]"
fi
# Check the necessary dependencies
DEPENDS="lsblk uuidgen grep awk btrfs mkfs.fat mkfs.btrfs md5sum fatlabel"
echo "Check the necessary dependencies..."
for dep in ${DEPENDS}; do
WITCH=$(busybox which ${dep})
if [ "${WITCH}" == "" ]; then
error_msg "Dependent command: ${dep} does not exist, upgrade cannot be performed, only flash through U disk/TF card!"
else
echo "${dep} path: ${WITCH}"
fi
done
echo "Check passed"
# find boot partition
BOOT_PART_MSG=$(lsblk -l -o NAME,PATH,TYPE,UUID,MOUNTPOINT | awk '$3~/^part$/ && $5 ~ /^\/boot$/ {print $0}')
if [ "${BOOT_PART_MSG}" == "" ]; then
error_msg "Boot The partition does not exist, so the update cannot be continued!"
fi
BOOT_NAME=$(echo ${BOOT_PART_MSG} | awk '{print $1}')
BOOT_PATH=$(echo ${BOOT_PART_MSG} | awk '{print $2}')
BOOT_UUID=$(echo ${BOOT_PART_MSG} | awk '{print $4}')
BR_FLAG=1
echo -ne "Whether to backup and restore the current config files? y/n [y]\b\b"
if [[ ${BACKUP_RESTORE_CONFIG} == "restore" ]]; then
yn="y"
elif [[ ${BACKUP_RESTORE_CONFIG} == "no-restore" ]]; then
yn="n"
else
read yn
fi
case $yn in
n* | N*)
BR_FLAG=0
;;
esac
# find root partition
ROOT_PART_MSG="$(get_root_partition_msg)"
ROOT_NAME=$(echo ${ROOT_PART_MSG} | awk '{print $1}')
ROOT_PATH=$(echo ${ROOT_PART_MSG} | awk '{print $2}')
ROOT_UUID=$(echo ${ROOT_PART_MSG} | awk '{print $4}')
case ${ROOT_NAME} in
${EMMC_NAME}${PARTITION_NAME}2)
NEW_ROOT_NAME="${EMMC_NAME}${PARTITION_NAME}3"
NEW_ROOT_LABEL="${LB_PRE}ROOTFS2"
;;
${EMMC_NAME}${PARTITION_NAME}3)
NEW_ROOT_NAME="${EMMC_NAME}${PARTITION_NAME}2"
NEW_ROOT_LABEL="${LB_PRE}ROOTFS1"
;;
*)
error_msg "ROOTFS The partition location is incorrect, so the update cannot continue!"
;;
esac
echo "NEW_ROOT_NAME: [ ${NEW_ROOT_NAME} ]"
# find new root partition
NEW_ROOT_PART_MSG=$(lsblk -l -o NAME,PATH,TYPE,UUID,MOUNTPOINT | grep "${NEW_ROOT_NAME}" | awk '$3 ~ /^part$/ && $5 !~ /^\/$/ && $5 !~ /^\/boot$/ {print $0}')
if [ "${NEW_ROOT_PART_MSG}" == "" ]; then
error_msg "The new ROOTFS partition does not exist, so the update cannot continue!"
fi
NEW_ROOT_NAME=$(echo ${NEW_ROOT_PART_MSG} | awk '{print $1}')
NEW_ROOT_PATH=$(echo ${NEW_ROOT_PART_MSG} | awk '{print $2}')
NEW_ROOT_UUID=$(echo ${NEW_ROOT_PART_MSG} | awk '{print $4}')
NEW_ROOT_MP=$(echo ${NEW_ROOT_PART_MSG} | awk '{print $5}')
echo "NEW_ROOT_MP: [ ${NEW_ROOT_MP} ]"
# backup old bootloader
if [ ! -f /root/BackupOldBootloader.img ]; then
echo "Backup bootloader -> [ BackupOldBootloader.img ] ... "
dd if=/dev/${EMMC_NAME} of=/root/BackupOldBootloader.img bs=1M count=4 conv=fsync
echo "Backup bootloader complete."
echo
fi
# losetup
losetup -f -P ${IMG_NAME}
if [ ${?} -eq 0 ]; then
LOOP_DEV=$(losetup | grep "${IMG_NAME}" | awk '{print $1}')
if [ "${LOOP_DEV}" == "" ]; then
error_msg "loop device not found!"
fi
else
error_msg "losetup [ ${IMG_FILE} ] failed!"
fi
# fix loopdev issue in kernel 5.19
function fix_loopdev() {
local parentdev=${1##*/}
if [ ! -d /sys/block/${parentdev} ]; then
return
fi
subdevs=$(lsblk -l -o NAME | grep -E "^${parentdev}.+\$")
for subdev in ${subdevs}; do
if [ ! -d /sys/block/${parentdev}/${subdev} ]; then
return
elif [ -b /dev/${sub_dev} ]; then
continue
fi
source /sys/block/${parentdev}/${subdev}/uevent
mknod /dev/${subdev} b ${MAJOR} ${MINOR}
unset MAJOR MINOR DEVNAME DEVTYPE DISKSEQ PARTN PARTNAME
done
}
fix_loopdev ${LOOP_DEV}
WAIT=3
echo "The loopdev is [ $LOOP_DEV ], wait [ ${WAIT} ] seconds. "
while [[ "${WAIT}" -ge "1" ]]; do
sleep 1
WAIT=$((WAIT - 1))
done
# umount loop devices (openwrt will auto mount some partition)
MOUNTED_DEVS=$(lsblk -l -o NAME,PATH,MOUNTPOINT | grep "${LOOP_DEV}" | awk '$3 !~ /^$/ {print $2}')
for dev in ${MOUNTED_DEVS}; do
while :; do
echo "umount [ ${dev} ] ... "
umount -f ${dev}
sleep 1
mnt=$(lsblk -l -o NAME,PATH,MOUNTPOINT | grep "${dev}" | awk '$3 !~ /^$/ {print $2}')
if [ "${mnt}" == "" ]; then
break
else
echo "Retry ..."
fi
done
done
# mount src part
WORK_DIR=${PWD}
P1=${WORK_DIR}/boot
P2=${WORK_DIR}/root
mkdir -p $P1 $P2
echo "Mount [ ${LOOP_DEV}p1 ] -> [ ${P1} ] ... "
mount -t vfat -o ro ${LOOP_DEV}p1 ${P1}
if [ $? -ne 0 ]; then
echo "Mount p1 [ ${LOOP_DEV}p1 ] failed!"
losetup -D
exit 1
fi
echo "Mount [ ${LOOP_DEV}p2 ] -> [ ${P2} ] ... "
ZSTD_LEVEL=6
mount -t btrfs -o ro,compress=zstd:${ZSTD_LEVEL} ${LOOP_DEV}p2 ${P2}
if [ $? -ne 0 ]; then
echo "Mount p2 [ ${LOOP_DEV}p2 ] failed!"
umount -f ${P1}
losetup -D
exit 1
fi
# Prepare the dockerman config file
if [ -f ${P2}/etc/init.d/dockerman ] && [ -f ${P2}/etc/config/dockerd ]; then
flg=0
# get current docker data root
data_root=$(uci get dockerd.globals.data_root 2>/dev/null)
if [ "${data_root}" == "" ]; then
flg=1
# get current config from /etc/docker/daemon.json
if [ -f "/etc/docker/daemon.json" ] && [ -x "/usr/bin/jq" ]; then
data_root=$(jq -r '."data-root"' /etc/docker/daemon.json)
bip=$(jq -r '."bip"' /etc/docker/daemon.json)
[ "${bip}" == "null" ] && bip="172.31.0.1/24"
log_level=$(jq -r '."log-level"' /etc/docker/daemon.json)
[ "${log_level}" == "null" ] && log_level="warn"
_iptables=$(jq -r '."iptables"' /etc/docker/daemon.json)
[ "${_iptables}" == "null" ] && _iptables="true"
registry_mirrors=$(jq -r '."registry-mirrors"[]' /etc/docker/daemon.json 2>/dev/null)
fi
fi
if [ "${data_root}" == "" ]; then
data_root="/opt/docker/" # the default data root
fi
if ! uci get dockerd.globals >/dev/null 2>&1; then
uci set dockerd.globals='globals'
uci commit
fi
# delete alter config , use inner config
if uci get dockerd.globals.alt_config_file >/dev/null 2>&1; then
uci delete dockerd.globals.alt_config_file
uci commit
fi
if [ ${flg} -eq 1 ]; then
uci set dockerd.globals.data_root=${data_root}
[ "${bip}" != "" ] && uci set dockerd.globals.bip=${bip}
[ "${log_level}" != "" ] && uci set dockerd.globals.log_level=${log_level}
[ "${_iptables}" != "" ] && uci set dockerd.globals.iptables=${_iptables}
if [ "${registry_mirrors}" != "" ]; then
for reg in ${registry_mirrors}; do
uci add_list dockerd.globals.registry_mirrors=${reg}
done
fi
uci set dockerd.globals.auto_start='1'
uci commit
fi
fi
#update version prompt
source /boot/uEnv.txt 2>/dev/null
CUR_FDTFILE=${FDT}
echo -e "FDT Value [ ${CUR_FDTFILE} ]"
cp /boot/uEnv.txt /tmp/uEnv.txt && sync
K510="1"
[[ "$(hexdump -n 15 -x "${P1}/zImage" 2>/dev/null | head -n 1 | awk '{print $7}')" == "0108" ]] && K510="0"
echo -e "K510 [ ${K510} ]"
# flippy-openwrt-release info
UBOOT_OVERLOAD=""
MAINLINE_UBOOT=""
ANDROID_UBOOT=""
env_openwrt_file=""
if [ -f "${P2}/etc/flippy-openwrt-release" ]; then
env_openwrt_file="${P2}/etc/flippy-openwrt-release"
elif [ -f "/etc/flippy-openwrt-release" ]; then
env_openwrt_file="/etc/flippy-openwrt-release"
else
env_openwrt_file=""
fi
if [ -n "${env_openwrt_file}" ]; then
source "${env_openwrt_file}" 2>/dev/null
# Update the parameters used
UBOOT_OVERLOAD=${UBOOT_OVERLOAD}
MAINLINE_UBOOT=${MAINLINE_UBOOT}
ANDROID_UBOOT=${ANDROID_UBOOT}
# Unused parameters
FDTFILE=${FDTFILE}
U_BOOT_EXT=${U_BOOT_EXT}
KERNEL_VERSION=${KERNEL_VERSION}
SOC=${SOC}
fi
#format NEW_ROOT
echo "umount [ ${NEW_ROOT_MP} ]"
umount -f "${NEW_ROOT_MP}"
if [[ "${?}" -ne "0" ]]; then
echo "Umount [ ${NEW_ROOT_MP} ] failed, Please restart and try again!"
umount -f ${P1}
umount -f ${P2}
losetup -D
exit 1
fi
# check and fix partition
function check_and_fix_partition() {
local target_dev_name=${1} # mmcblk2
local target_pt_name=${2} # p2
local target_pt_idx=${3} # 2
local safe_pt_begin_mb=${4} # 800
local safe_pt_begin_byte=$((${safe_pt_begin_mb} * 1024 * 1024))
local cur_pt_begin_sector=$(fdisk -l /dev/${target_dev_name} | grep ${target_dev_name}${target_pt_name} | awk '{printf $2}')
local cur_pt_begin_mb=$((${cur_pt_begin_sector} * 512 / 1024 / 1024))
if [ ${cur_pt_begin_mb} -ge ${safe_pt_begin_mb} ]; then
# check pass
return
fi
local cur_pt_end_sector=$(fdisk -l /dev/${target_dev_name} | grep ${target_dev_name}${target_pt_name} | awk '{printf $3}')
local cur_pt_end_byte=$(((${cur_pt_end_sector} + 1) * 512 - 1))
echo "Unsafe partition found, repairing ... "
parted /dev/${target_dev_name} rm ${target_pt_idx} ||
(
error_msg "rm partion ${target_pt_idx} failed"
)
parted /dev/${target_dev_name} mkpart primary btrfs "${safe_pt_begin_byte}b" "${cur_pt_end_byte}b" ||
(
error_msg "create new partion ${target_pt_idx} failed"
)
echo "Partition repaired"
}
# check if need fix partition
if [ "${NEW_ROOT_NAME}" == "mmcblk2p2" ]; then
if [ "${MYDEVICE_NAME}" == "Phicomm N1" ] || [ "${MYDEVICE_NAME}" == "Octopus Planet" ]; then
# 最新研究结果:
# Phicomm N1当采用官方 "天天链" 固件底包时,
# 796MB开始的 12 字节在每次重启后会被 bootloader 覆写,
# 因此把安全位置设定在800MB之后
# The latest research results:
# When Phicomm N1 uses the official "tian tian lian" firmware bottom package,
# the 12 bytes starting from 796MB will be overwritten by bootloader after each reboot,
# so the safe location is set after 800MB
SAFE_PT_BEGIN_MB=800
check_and_fix_partition "${EMMC_NAME}" "p2" 2 ${SAFE_PT_BEGIN_MB}
fi
fi
echo "Format [ ${NEW_ROOT_PATH} ]"
NEW_ROOT_UUID=$(uuidgen)
mkfs.btrfs -f -U ${NEW_ROOT_UUID} -L ${NEW_ROOT_LABEL} -m single ${NEW_ROOT_PATH}
if [ $? -ne 0 ]; then
echo "Format [ ${NEW_ROOT_PATH} ] failed!"
umount -f ${P1}
umount -f ${P2}
losetup -D
exit 1
fi
echo "Mount [ ${NEW_ROOT_PATH} ] -> [ ${NEW_ROOT_MP} ]"
mount -t btrfs -o compress=zstd:${ZSTD_LEVEL} ${NEW_ROOT_PATH} ${NEW_ROOT_MP}
if [ $? -ne 0 ]; then
echo "Mount [ ${NEW_ROOT_PATH} ] -> [ ${NEW_ROOT_MP} ] failed!"
umount -f ${P1}
umount -f ${P2}
losetup -D
exit 1
fi
# begin copy rootfs
cd ${NEW_ROOT_MP}
echo "Start copying data, From [ ${P2} ] TO [ ${NEW_ROOT_MP} ] ..."
ENTRYS=$(ls)
for entry in ${ENTRYS}; do
if [[ "${entry}" == "lost+found" ]]; then
continue
fi
echo "Remove old [ ${entry} ] ... "
rm -rf ${entry}
if [[ "${?}" -ne "0" ]]; then
error_msg "failed."
fi
done
echo "Create folder ... "
btrfs subvolume create etc
mkdir -p .snapshots .reserved bin boot dev lib opt mnt overlay proc rom root run sbin sys tmp usr www
ln -sf lib/ lib64
ln -sf tmp/ var
sync
COPY_SRC="root etc bin sbin lib opt usr www"
echo "Copy data begin ... "
for src in ${COPY_SRC}; do
echo "Copy [ ${src} ] ... "
(cd ${P2} && tar cf - ${src}) | tar xf -
sync
done
# if not backup, then force rewrite the etc/docker/daemon.json
if [ "${BR_FLAG}" -eq 0 ]; then
cat >./etc/docker/daemon.json <<EOF
{
"bip": "172.31.0.1/24",
"data-root": "${DOCKER_ROOT}",
"log-level": "warn",
"log-driver": "json-file",
"log-opts": {
"max-size": "10m",
"max-file": "5"
},
"registry-mirrors": [
"https://mirror.baidubce.com/",
"https://hub-mirror.c.163.com"
]
}
EOF
fi
cat >./etc/fstab <<EOF
UUID=${NEW_ROOT_UUID} / btrfs compress=zstd:${ZSTD_LEVEL} 0 1
LABEL=${LB_PRE}BOOT /boot vfat defaults 0 2
#tmpfs /tmp tmpfs defaults,nosuid 0 0
EOF
cat >./etc/config/fstab <<EOF
config global
option anon_swap '0'
option anon_mount '1'
option auto_swap '0'
option auto_mount '1'
option delay_root '5'
option check_fs '0'
config mount
option target '/rom'
option uuid '${NEW_ROOT_UUID}'
option enabled '1'
option enabled_fsck '1'
option fstype 'btrfs'
option options 'compress=zstd:${ZSTD_LEVEL}'
config mount
option target '/boot'
option label '${LB_PRE}BOOT'
option enabled '1'
option enabled_fsck '1'
option fstype 'vfat'
EOF
(
cd etc/rc.d
rm -f S??shortcut-fe
if grep "sfe_flow '1'" ../config/turboacc >/dev/null; then
if find ../../lib/modules -name 'shortcut-fe-cm.ko'; then
ln -sf ../init.d/shortcut-fe S99shortcut-fe
fi
fi
)
# move /etc/config/balance_irq to /etc/balance_irq
[ -f "./etc/config/balance_irq" ] && mv ./etc/config/balance_irq ./etc/
sync
echo "Create initial etc snapshot -> .snapshots/etc-000"
btrfs subvolume snapshot -r etc .snapshots/etc-000
sync
[ -d /mnt/${EMMC_NAME}${PARTITION_NAME}4/docker ] || mkdir -p /mnt/${EMMC_NAME}${PARTITION_NAME}4/docker
rm -rf opt/docker && ln -sf /mnt/${EMMC_NAME}${PARTITION_NAME}4/docker/ opt/docker
if [ -f /mnt/${NEW_ROOT_NAME}/etc/config/AdGuardHome ]; then
[ -d /mnt/${EMMC_NAME}${PARTITION_NAME}4/AdGuardHome/data ] || mkdir -p /mnt/${EMMC_NAME}${PARTITION_NAME}4/AdGuardHome/data
if [ ! -L /usr/bin/AdGuardHome ]; then
[ -d /usr/bin/AdGuardHome ] &&
cp -a /usr/bin/AdGuardHome/* /mnt/${EMMC_NAME}${PARTITION_NAME}4/AdGuardHome/
fi
ln -sf /mnt/${EMMC_NAME}${PARTITION_NAME}4/AdGuardHome /mnt/${NEW_ROOT_NAME}/usr/bin/AdGuardHome
fi
#rm -f /mnt/${NEW_ROOT_NAME}/usr/sbin/openwrt-install-amlogic
#rm -f /mnt/${NEW_ROOT_NAME}/usr/sbin/openwrt-update-amlogic
rm -f /mnt/${NEW_ROOT_NAME}/root/install-to-emmc.sh
sync
echo "Copy data complete ..."
BACKUP_LIST=$(${P2}/usr/sbin/openwrt-backup -p)
if [[ "${BR_FLAG}" -eq "1" && -n "${BACKUP_LIST}" ]]; then
echo -n "Start restoring configuration files ... "
(
cd /
eval tar czf ${NEW_ROOT_MP}/.reserved/openwrt_config.tar.gz "${BACKUP_LIST}" 2>/dev/null
)
tar xzf ${NEW_ROOT_MP}/.reserved/openwrt_config.tar.gz
[ -f ./etc/config/dockerman ] && sed -e "s/option wan_mode 'false'/option wan_mode 'true'/" -i ./etc/config/dockerman 2>/dev/null
[ -f ./etc/config/dockerd ] && sed -e "s/option wan_mode '0'/option wan_mode '1'/" -i ./etc/config/dockerd 2>/dev/null
[ -f ./etc/config/verysync ] && sed -e 's/config setting/config verysync/' -i ./etc/config/verysync 2>/dev/null
# Restore fstab
cp -f .snapshots/etc-000/fstab ./etc/fstab
cp -f .snapshots/etc-000/config/fstab ./etc/config/fstab
# 还原 luci
cp -f .snapshots/etc-000/config/luci ./etc/config/luci
# 还原/etc/config/rpcd
cp -f .snapshots/etc-000/config/rpcd ./etc/config/rpcd
sync
echo "Restore configuration information complete."
fi
echo "Modify the configuration file ... "
rm -f "./etc/rc.local.orig" "./etc/first_run.sh" "./etc/part_size"
rm -rf "./opt/docker" && ln -sf "/mnt/${EMMC_NAME}${PARTITION_NAME}4/docker" "./opt/docker"
rm -f ./etc/bench.log
cat >>./etc/crontabs/root <<EOF
37 5 * * * /etc/coremark.sh
EOF
sed -e 's/ttyAMA0/ttyAML0/' -i ./etc/inittab
sed -e 's/ttyS0/tty0/' -i ./etc/inittab
sss=$(date +%s)
ddd=$((sss / 86400))
sed -e "s/:0:0:99999:7:::/:${ddd}:0:99999:7:::/" -i ./etc/shadow
# Fix the problem of repeatedly adding amule entries after each upgrade
sed -e "/amule:x:/d" -i ./etc/shadow
# Fix the problem of repeatedly adding sshd entries after each upgrade of dropbear
sed -e "/sshd:x:/d" -i ./etc/shadow
if ! grep "sshd:x:22:sshd" ./etc/group >/dev/null; then
echo "sshd:x:22:sshd" >>./etc/group
fi
if ! grep "sshd:x:22:22:sshd:" ./etc/passwd >/dev/null; then
echo "sshd:x:22:22:sshd:/var/run/sshd:/bin/false" >>./etc/passwd
fi
if ! grep "sshd:x:" ./etc/shadow >/dev/null; then
echo "sshd:x:${ddd}:0:99999:7:::" >>./etc/shadow
fi
if [ "${BR_FLAG}" -eq "1" ]; then
if [ -x ./bin/bash ] && [ -f ./etc/profile.d/30-sysinfo.sh ]; then
sed -e 's/\/bin\/ash/\/bin\/bash/' -i ./etc/passwd
fi
sync
fi
sed -e "s/option hw_flow '1'/option hw_flow '0'/" -i ./etc/config/turboacc
(
cd etc/rc.d
rm -f S??shortcut-fe
if grep "sfe_flow '1'" ../config/turboacc >/dev/null; then
if find ../../lib/modules -name 'shortcut-fe-cm.ko'; then
ln -sf ../init.d/shortcut-fe S99shortcut-fe
fi
fi
)
eval tar czf .reserved/openwrt_config.tar.gz "${BACKUP_LIST}" 2>/dev/null
rm -f ./etc/part_size ./etc/first_run.sh
if [ -x ./usr/sbin/balethirq.pl ]; then
if grep "balethirq.pl" "./etc/rc.local"; then
echo "balance irq is enabled"
else
echo "enable balance irq"
sed -e "/exit/i\/usr/sbin/balethirq.pl" -i ./etc/rc.local
fi
fi
mv ./etc/rc.local ./etc/rc.local.orig
cat >"./etc/rc.local" <<EOF
if ! ls /etc/rc.d/S??dockerd >/dev/null 2>&1;then
/etc/init.d/dockerd enable
/etc/init.d/dockerd start
fi
if ! ls /etc/rc.d/S??dockerman >/dev/null 2>&1 && [ -f /etc/init.d/dockerman ];then
/etc/init.d/dockerman enable
/etc/init.d/dockerman start
fi
mv /etc/rc.local.orig /etc/rc.local
chmod 755 /etc/rc.local
exec /etc/rc.local
exit
EOF
chmod 755 ./etc/rc.local*
#Mainline U-BOOT detection
FLASH_MAINLINE_UBOOT=0
if [[ -n "${MAINLINE_UBOOT}" && -f "${P2}${MAINLINE_UBOOT}" ]]; then
cat <<EOF
----------------------------------------------------------------------------------
Found an available mainline bootloader (Mainline u-boot), you can flash into EMMC.
----------------------------------------------------------------------------------
EOF
while :; do
if [[ "${AUTO_MAINLINE_UBOOT}" == "yes" ]]; then
if [[ "${K510}" -eq "1" ]]; then
yn="y"
else
yn="n"
fi
elif [[ "${AUTO_MAINLINE_UBOOT}" == "no" ]]; then
yn="n"
else
read -p "Please choose whether to write the mainline bootloader to EMMC? y/n " yn
fi
case ${yn} in
y | Y)
FLASH_MAINLINE_UBOOT=1
break
;;
n | N)
FLASH_MAINLINE_UBOOT=0
break
;;
esac
done
fi
if [[ "${FLASH_MAINLINE_UBOOT}" -eq "1" ]]; then
echo -e "Write Mainline bootloader: [ ${MAINLINE_UBOOT} ]"
dd if=${P2}${MAINLINE_UBOOT} of=/dev/${EMMC_NAME} bs=1 count=444 conv=fsync
dd if=${P2}${MAINLINE_UBOOT} of=/dev/${EMMC_NAME} bs=512 skip=1 seek=1 conv=fsync
elif [[ -n "${ANDROID_UBOOT}" && -f "${P2}${ANDROID_UBOOT}" ]]; then
echo -e "Write Android bootloader: [ ${ANDROID_UBOOT} ]"
dd if=${P2}${ANDROID_UBOOT} of=/dev/${EMMC_NAME} bs=1 count=444 conv=fsync
dd if=${P2}${ANDROID_UBOOT} of=/dev/${EMMC_NAME} bs=512 skip=1 seek=1 conv=fsync
else
echo "Did not change the original bootloader."
fi
# move /etc/config/balance_irq to /etc/balance_irq
[ -f "./etc/config/balance_irq" ] && mv ./etc/config/balance_irq ./etc/
echo "Create etc snapshot -> .snapshots/etc-001"
btrfs subvolume snapshot -r etc .snapshots/etc-001
cd ${WORK_DIR}
echo "Change the label of ${BOOT_PATH} ... "
fatlabel ${BOOT_PATH} "${LB_PRE}BOOT"
echo "Start copying data, from [ ${P1} ] to [ /boot ] ..."
cd /boot
echo "Delete the old boot file ..."
rm -rf * && sync
echo "Copy the new boot file ... "
(cd ${P1} && tar cf - .) | tar xf - 2>/dev/null
sync
if [ -f ${P1}/uInitrd ]; then
i=1
max_try=10
while [ "${i}" -le "${max_try}" ]; do
uInitrd_original=$(md5sum ${P1}/uInitrd | awk '{print $1}')
uInitrd_new=$(md5sum uInitrd | awk '{print $1}')
if [ "${uInitrd_original}" = "${uInitrd_new}" ]; then
break
else
rm -f uInitrd && sync
cp -f ${P1}/uInitrd uInitrd 2>/dev/null && sync
let i++
continue
fi
done
[ "${i}" -eq "10" ] && error_msg "uInitrd file copy failed."
else
echo "uInitrd file is missing."
fi
if [ -f ${P1}/zImage ]; then
i=1
max_try=10
while [ "${i}" -le "${max_try}" ]; do
zImage_original=$(md5sum ${P1}/zImage | awk '{print $1}')
zImage_new=$(md5sum zImage | awk '{print $1}')
if [ "${zImage_original}" = "${zImage_new}" ]; then
break
else
rm -f zImage && sync
cp -f ${P1}/zImage zImage 2>/dev/null && sync
let i++
continue
fi
done
[ "${i}" -eq "10" ] && error_msg "zImage file copy failed."
else
error_msg "zImage file is missing."
fi
if [ ${ROOT_DISK_TYPE} == "EMMC" ]; then
rm -f s905_autoscript* aml_autoscript*
mv -f boot-emmc.ini boot.ini
mv -f boot-emmc.cmd boot.cmd
mv -f boot-emmc.scr boot.scr
fi
if [ "${K510}" -eq "1" ]; then
if [ -f "u-boot.ext" ]; then
cp -vf u-boot.ext u-boot.emmc
elif [ -f ${P1}/${UBOOT_OVERLOAD} ]; then
cp -vf ${P1}/${UBOOT_OVERLOAD} ${UBOOT_OVERLOAD}
cp -vf ${P1}/${UBOOT_OVERLOAD} u-boot.ext
cp -vf ${P1}/${UBOOT_OVERLOAD} u-boot.emmc
chmod +x u-boot*
fi
else
rm -f u-boot.ext 2>/dev/null
rm -f u-boot.emmc 2>/dev/null
fi
sync
echo "Update boot parameters ... "
if [ -f /tmp/uEnv.txt ]; then
lines=$(wc -l </tmp/uEnv.txt)
lines=$((lines - 1))
head -n $lines /tmp/uEnv.txt >uEnv.txt
cat >>uEnv.txt <<EOF
APPEND=root=UUID=${NEW_ROOT_UUID} rootfstype=btrfs rootflags=compress=zstd:${ZSTD_LEVEL} console=ttyAML0,115200n8 console=tty0 no_console_suspend consoleblank=0 fsck.fix=yes fsck.repair=yes net.ifnames=0 cgroup_enable=cpuset cgroup_memory=1 cgroup_enable=memory swapaccount=1
EOF
else
cat >uEnv.txt <<EOF
LINUX=/zImage
INITRD=/uInitrd
FDT=${CUR_FDTFILE}
APPEND=root=UUID=${NEW_ROOT_UUID} rootfstype=btrfs rootflags=compress=zstd:${ZSTD_LEVEL} console=ttyAML0,115200n8 console=tty0 no_console_suspend consoleblank=0 fsck.fix=yes fsck.repair=yes net.ifnames=0 cgroup_enable=cpuset cgroup_memory=1 cgroup_enable=memory swapaccount=1
EOF
fi
sync
# Replace the UUID for extlinux/extlinux.conf if it exists
[[ -f "extlinux/extlinux.conf" ]] && {
sed -i -E "s|UUID=[^ ]*|UUID=${NEW_ROOT_UUID}|" extlinux/extlinux.conf 2>/dev/null
}
cd $WORK_DIR
umount -f ${P1} ${P2} 2>/dev/null
losetup -D 2>/dev/null
rm -rf ${P1} ${P2} 2>/dev/null
rm -f ${IMG_NAME} 2>/dev/null
rm -f sha256sums 2>/dev/null
sync
wait
echo "Successfully updated, automatic restarting..."
sleep 3
reboot
exit 0
+674
View File
@@ -0,0 +1,674 @@
#!/bin/bash
#======================================================================================
# Function: Update the QEMU AARCH64 KVM vitual machine openwrt firmware
# Copyright (C) 2022-- https://github.com/unifreq/openwrt_packit
# Copyright (C) 2022-- https://github.com/ophub
#======================================================================================
#
# The script supports directly setting parameters for update, skipping interactive selection
# openwrt-update-amlogic ${OPENWRT_FILE} ${AUTO_MAINLINE_UBOOT} ${RESTORE_CONFIG} ${WORK_DIR}
# E.g: openwrt-update-kvm openwrt_qemu-aarch64.img.gz no restore /mnt/vda4
# E.g: openwrt-update-kvm openwrt_qemu-aarch64.img.gz no no-restore /mnt/data
# You can also execute the script directly, and interactively select related functions
# E.g: openwrt-update-kvm
#
#======================================================================================
# Encountered a serious error, abort the script execution
error_msg() {
echo -e "[ERROR] ${1}"
exit 1
}
# Get the partition name of the /boot file system
get_boot_partition_name() {
local paths="/boot"
local partition_name
partition_name=$(df "${paths}" | awk 'NR==2 {print $1}' | awk -F '/' '{print $3}')
echo "${partition_name}"
}
# Get the partition name of the root file system
get_root_partition_name() {
local paths=("/" "/overlay" "/rom")
local partition_name
for path in "${paths[@]}"; do
partition_name=$(df "${path}" | awk 'NR==2 {print $1}' | awk -F '/' '{print $3}')
[[ -n "${partition_name}" ]] && break
done
echo "${partition_name}"
}
# Get the partition message of the root file system
get_root_partition_msg() {
local paths=("/" "/overlay" "/rom")
local partition_name
for path in "${paths[@]}"; do
partition_msg=$(lsblk -l -o NAME,PATH,TYPE,UUID,MOUNTPOINT | awk '$3~/^part$/ && $5 ~ "^" "'"${path}"'" "$" {print $0}')
[[ -n "${partition_msg}" ]] && break
done
[[ -z "${partition_msg}" ]] && error_msg "Cannot find the root partition message!"
echo "${partition_msg}"
}
# Receive one-key command related parameters
IMG_NAME="${1}"
AUTO_MAINLINE_UBOOT="${2}"
BACKUP_RESTORE_CONFIG="${3}"
WORK_DIR="${4}"
# Check the necessary dependencies
DEPENDS="lsblk uuidgen grep awk btrfs mkfs.fat mkfs.btrfs md5sum fatlabel jq"
echo "Check the necessary dependencies..."
for dep in ${DEPENDS}; do
WITCH=$(busybox which ${dep})
if [ "${WITCH}" == "" ]; then
error_msg "Dependent command: ${dep} does not exist, upgrade cannot be performed!"
else
echo "${dep} path: ${WITCH}"
fi
done
echo "Check passed"
# Current device model
source /etc/flippy-openwrt-release
if [[ -z "${PLATFORM}" ]]; then
error_msg "The platform is empty."
elif [[ "${PLATFORM}" != "qemu-aarch64" ]]; then
error_msg "The platform is missing, only support qemu-aarch64."
else
echo -e "Current platform: [ ${PLATFORM} ]"
sleep 3
fi
# Check and repair partition mount points
[[ -z "$(get_boot_partition_name)" || -z "$(get_root_partition_name)" ]] && {
echo -e "Partition mount point error, start repairing..."
openwrt-backup -g
}
# Find the partition where root is located
# vda2 or vda3
ROOT_PTNAME="$(get_root_partition_name)"
# Find the disk where the partition is located, only supports sd?? hd?? vd??
case ${ROOT_PTNAME} in
[hsv]d[a-z][1-4])
DISK_NAME=$(echo ${ROOT_PTNAME} | awk '{print substr($1, 1, length($1)-1)}')
PART_PRESTR=""
LABEL_PRESTR=""
;;
*)
error_msg "Unable to recognize the disk type of ${ROOT_PTNAME}!"
;;
esac
function get_docker_root {
local data_root
if [[ -f /etc/config/dockerd ]]; then
data_root=$(uci get dockerd.globals.data_root)
fi
if [[ -z "${data_root}" ]] && [[ -f /etc/docker/daemon.json ]]; then
data_root=$(jq -r '."data-root"' /etc/docker/daemon.json)
fi
echo "$data_root"
}
DOCKER_ROOT=$(get_docker_root)
if [[ -z "${WORK_DIR}" ]]; then
WORK_DIR="/mnt/${DISK_NAME}${PART_PRESTR}4/"
fi
if [[ ! -d "${WORK_DIR}" ]]; then
error_msg "the work directory is not exists. [ ${WORK_DIR} ]"
fi
cd "${WORK_DIR}"
if [[ -d "/tmp/upload" ]] && [[ -f "/tmp/upload/*img*" ]]; then
mv -f /tmp/upload/*img* .
if [[ $? -ne 0 ]]; then
error_msg "move file failed."
fi
fi
sync
if [[ "${IMG_NAME}" == *.img ]]; then
echo -e "Update using [ ${IMG_NAME} ] file. Please wait a moment ..."
elif [ $(ls *.img -l 2>/dev/null | grep "^-" | wc -l) -ge 1 ]; then
IMG_NAME=$(ls *.img | head -n 1)
echo -e "Update using [ ${IMG_NAME} ] ] file. Please wait a moment ..."
elif [ $(ls *.img.xz -l 2>/dev/null | grep "^-" | wc -l) -ge 1 ]; then
xz_file=$(ls *.img.xz | head -n 1)
echo -e "Update using [ ${xz_file} ] file. Please wait a moment ..."
xz -d ${xz_file} 2>/dev/null
IMG_NAME=$(ls *.img | head -n 1)
elif [ $(ls *.img.gz -l 2>/dev/null | grep "^-" | wc -l) -ge 1 ]; then
gz_file=$(ls *.img.gz | head -n 1)
echo -e "Update using [ ${gz_file} ] file. Please wait a moment ..."
gzip -df ${gz_file} 2>/dev/null
IMG_NAME=$(ls *.img | head -n 1)
elif [ $(ls *.7z -l 2>/dev/null | grep "^-" | wc -l) -ge 1 ]; then
gz_file=$(ls *.7z | head -n 1)
echo -e "Update using [ ${gz_file} ] file. Please wait a moment ..."
bsdtar -xmf ${gz_file} 2>/dev/null
[ $? -eq 0 ] || 7z x ${gz_file} -aoa -y 2>/dev/null
IMG_NAME=$(ls *.img | head -n 1)
elif [ $(ls *.zip -l 2>/dev/null | grep "^-" | wc -l) -ge 1 ]; then
zip_file=$(ls *.zip | head -n 1)
echo -e "Update using [ ${zip_file} ] file. Please wait a moment ..."
unzip -o ${zip_file} 2>/dev/null
IMG_NAME=$(ls *.img | head -n 1)
else
echo -e "Please upload or specify the update openwrt firmware file."
#echo -e "Upload method: system menu → Amlogic Service → Manually Upload Update"
echo -e "Specify method: Place the openwrt firmware file in [ ${WORK_DIR} ]"
echo -e "The supported file suffixes are: *.img, *.img.xz, *.img.gz, *.7z, *.zip"
echo -e "After upload the openwrt firmware file, run again."
exit 1
fi
sync
# check file
if [ ! -f "${IMG_NAME}" ]; then
error_msg "No update file found."
else
echo "Start update from [ ${IMG_NAME} ]"
fi
# find efi partition
EFI_PART_MSG=$(lsblk -l -o NAME,PATH,TYPE,UUID,MOUNTPOINT | awk '$3~/^part$/ && $5 ~ /^\/boot\/efi$/ {print $0}')
if [ "${EFI_PART_MSG}" == "" ]; then
error_msg "The EFI partition does not exist, so the update cannot be continued!"
fi
EFI_NAME=$(echo $EFI_PART_MSG | awk '{print $1}')
EFI_DEV=$(echo $EFI_PART_MSG | awk '{print $2}')
EFI_UUID=$(echo $EFI_PART_MSG | awk '{print $4}')
BR_FLAG=1
if [[ ${BACKUP_RESTORE_CONFIG} == "restore" ]]; then
BR_FLAG=1
elif [[ ${BACKUP_RESTORE_CONFIG} == "no-restore" ]]; then
BR_FLAG=0
else
echo -ne "Whether to backup and restore the current config files? y/n [y]\b\b"
read yn
case $yn in
n* | N*) BR_FLAG=0 ;;
esac
fi
# find root partition
ROOT_PART_MSG="$(get_root_partition_msg)"
ROOT_NAME=$(echo ${ROOT_PART_MSG} | awk '{print $1}')
ROOT_DEV=$(echo ${ROOT_PART_MSG} | awk '{print $2}')
ROOT_UUID=$(echo ${ROOT_PART_MSG} | awk '{print $4}')
case ${ROOT_NAME} in
${DISK_NAME}${PART_PRESTR}2)
NEW_ROOT_NAME="${DISK_NAME}${PART_PRESTR}3"
NEW_ROOT_LABEL="${LABEL_PRESTR}ROOTFS2"
;;
${DISK_NAME}${PART_PRESTR}3)
NEW_ROOT_NAME="${DISK_NAME}${PART_PRESTR}2"
NEW_ROOT_LABEL="${LABEL_PRESTR}ROOTFS1"
;;
*)
error_msg "ROOTFS The partition location is incorrect, so the update cannot continue!"
;;
esac
echo "NEW_ROOT_NAME: [ ${NEW_ROOT_NAME} ]"
# find new root partition
NEW_ROOT_PART_MSG=$(lsblk -l -o NAME,PATH,TYPE,UUID,MOUNTPOINT | grep "${NEW_ROOT_NAME}" | awk '$3 ~ /^part$/ && $5 !~ /^\/$/ && $5 !~ /^\/boot$/ {print $0}')
if [ "${NEW_ROOT_PART_MSG}" == "" ]; then
error_msg "The new ROOTFS partition does not exist, so the update cannot continue!"
fi
NEW_ROOT_NAME=$(echo $NEW_ROOT_PART_MSG | awk '{print $1}')
NEW_ROOT_DEV=$(echo $NEW_ROOT_PART_MSG | awk '{print $2}')
NEW_ROOT_UUID=$(echo $NEW_ROOT_PART_MSG | awk '{print $4}')
NEW_ROOT_MOUNTPOINT=$(echo $NEW_ROOT_PART_MSG | awk '{print $5}')
echo "NEW_ROOT_MOUNTPOINT: [ ${NEW_ROOT_MOUNTPOINT} ]"
# losetup
losetup -f -P $IMG_NAME
if [ $? -eq 0 ]; then
LOOP_DEV=$(losetup | grep "$IMG_NAME" | awk '{print $1}')
if [ "$LOOP_DEV" == "" ]; then
error_msg "loop device not found!"
fi
else
error_msg "losetup [ $IMG_FILE ] failed!"
fi
# fix loopdev issue in kernel 5.19
function fix_loopdev() {
local parentdev=${1##*/}
if [ ! -d /sys/block/${parentdev} ]; then
return
fi
subdevs=$(lsblk -l -o NAME | grep -E "^${parentdev}.+\$")
for subdev in $subdevs; do
if [ ! -d /sys/block/${parentdev}/${subdev} ]; then
return
elif [ -b /dev/${sub_dev} ]; then
continue
fi
source /sys/block/${parentdev}/${subdev}/uevent
mknod /dev/${subdev} b ${MAJOR} ${MINOR}
unset MAJOR MINOR DEVNAME DEVTYPE DISKSEQ PARTN PARTNAME
done
}
fix_loopdev ${LOOP_DEV}
WAIT=3
echo "The loopdev is [ $LOOP_DEV ], wait [ ${WAIT} ] seconds. "
while [ $WAIT -ge 1 ]; do
sleep 1
WAIT=$((WAIT - 1))
done
# umount loop devices (openwrt will auto mount some partition)
MOUNTED_DEVS=$(lsblk -l -o NAME,PATH,MOUNTPOINT | grep "$LOOP_DEV" | awk '$3 !~ /^$/ {print $2}')
for dev in $MOUNTED_DEVS; do
while :; do
echo "umount [ $dev ] ... "
umount -f $dev
sleep 1
mnt=$(lsblk -l -o NAME,PATH,MOUNTPOINT | grep "$dev" | awk '$3 !~ /^$/ {print $2}')
if [ "$mnt" == "" ]; then
break
else
echo "Retry ..."
fi
done
done
# mount src part
P1=${WORK_DIR}/efi
P2=${WORK_DIR}/root
mkdir -p $P1 $P2
echo "Mount [ ${LOOP_DEV}p1 ] -> [ ${P1} ] ... "
mount -t vfat -o ro ${LOOP_DEV}p1 ${P1}
if [ $? -ne 0 ]; then
echo "Mount p1 [ ${LOOP_DEV}p1 ] failed!"
losetup -D
exit 1
fi
echo "Mount [ ${LOOP_DEV}p2 ] -> [ ${P2} ] ... "
ZSTD_LEVEL="6"
mount -t btrfs -o ro,compress=zstd:${ZSTD_LEVEL} ${LOOP_DEV}p2 ${P2}
if [ $? -ne 0 ]; then
echo "Mount p2 [ ${LOOP_DEV}p2 ] failed!"
umount -f ${P1}
losetup -D
exit 1
fi
# Prepare the dockerman config file
if [ -f ${P2}/etc/init.d/dockerman ] && [ -f ${P2}/etc/config/dockerd ]; then
flg=0
# get current docker data root
data_root=$(uci get dockerd.globals.data_root 2>/dev/null)
if [ "$data_root" == "" ]; then
flg=1
# get current config from /etc/docker/daemon.json
if [ -f "/etc/docker/daemon.json" ] && [ -x "/usr/bin/jq" ]; then
data_root=$(jq -r '."data-root"' /etc/docker/daemon.json)
bip=$(jq -r '."bip"' /etc/docker/daemon.json)
[ "$bip" == "null" ] && bip="172.31.0.1/24"
log_level=$(jq -r '."log-level"' /etc/docker/daemon.json)
[ "$log_level" == "null" ] && log_level="warn"
_iptables=$(jq -r '."iptables"' /etc/docker/daemon.json)
[ "$_iptables" == "null" ] && _iptables="true"
registry_mirrors=$(jq -r '."registry-mirrors"[]' /etc/docker/daemon.json 2>/dev/null)
fi
fi
if [ "$data_root" == "" ]; then
data_root="/opt/docker/" # the default data root
fi
if ! uci get dockerd.globals >/dev/null 2>&1; then
uci set dockerd.globals='globals'
uci commit
fi
# delete alter config , use inner config
if uci get dockerd.globals.alt_config_file >/dev/null 2>&1; then
uci delete dockerd.globals.alt_config_file
uci commit
fi
if [ $flg -eq 1 ]; then
uci set dockerd.globals.data_root=$data_root
[ "$bip" != "" ] && uci set dockerd.globals.bip=$bip
[ "$log_level" != "" ] && uci set dockerd.globals.log_level=$log_level
[ "$_iptables" != "" ] && uci set dockerd.globals.iptables=$_iptables
if [ "$registry_mirrors" != "" ]; then
for reg in $registry_mirrors; do
uci add_list dockerd.globals.registry_mirrors=$reg
done
fi
uci set dockerd.globals.auto_start='1'
uci commit
fi
fi
#format NEW_ROOT
echo "umount [ ${NEW_ROOT_MOUNTPOINT} ]"
umount -f "${NEW_ROOT_MOUNTPOINT}"
if [ $? -ne 0 ]; then
echo "Umount [ ${NEW_ROOT_MOUNTPOINT} ] failed, Please restart and try again!"
umount -f ${P1}
umount -f ${P2}
losetup -D
exit 1
fi
echo "Format [ ${NEW_ROOT_DEV} ]"
NEW_ROOT_UUID=$(uuidgen)
mkfs.btrfs -f -U ${NEW_ROOT_UUID} -L ${NEW_ROOT_LABEL} ${NEW_ROOT_DEV}
if [ $? -ne 0 ]; then
echo "Format [ ${NEW_ROOT_DEV} ] failed!"
umount -f ${P1}
umount -f ${P2}
losetup -D
exit 1
fi
echo "Mount [ ${NEW_ROOT_DEV} ] -> [ ${NEW_ROOT_MOUNTPOINT} ]"
mount -t btrfs -o compress=zstd:${ZSTD_LEVEL} ${NEW_ROOT_DEV} ${NEW_ROOT_MOUNTPOINT}
if [ $? -ne 0 ]; then
echo "Mount [ ${NEW_ROOT_DEV} ] -> [ ${NEW_ROOT_MOUNTPOINT} ] failed!"
umount -f ${P1}
umount -f ${P2}
losetup -D
exit 1
fi
# begin copy rootfs
cd ${NEW_ROOT_MOUNTPOINT}
echo "Start copying data, From [ ${P2} ] TO [ ${NEW_ROOT_MOUNTPOINT} ] ..."
ENTRYS=$(ls)
for entry in $ENTRYS; do
if [ "$entry" == "lost+found" ]; then
continue
fi
echo "Remove old [ $entry ] ... "
rm -rf $entry
if [ $? -ne 0 ]; then
error_msg "failed."
fi
done
echo "Create folder ... "
btrfs subvolume create etc
mkdir -p .snapshots .reserved bin boot dev lib opt mnt overlay proc rom root run sbin sys tmp usr www
ln -sf lib/ lib64
ln -sf tmp/ var
sync
COPY_SRC="boot root etc bin sbin lib opt usr www"
echo "Copy data begin ... "
for src in $COPY_SRC; do
echo "Copy [ $src ] ... "
(cd ${P2} && tar cf - $src) | tar xf -
sync
done
# if not backup, then force rewrite the etc/docker/daemon.json
if [ "${BR_FLAG}" -eq 0 ]; then
cat >./etc/docker/daemon.json <<EOF
{
"bip": "172.31.0.1/24",
"data-root": "${DOCKER_ROOT}",
"log-level": "warn",
"log-driver": "json-file",
"log-opts": {
"max-size": "10m",
"max-file": "5"
},
"registry-mirrors": [
"https://mirror.baidubce.com/",
"https://hub-mirror.c.163.com"
]
}
EOF
fi
cat >./etc/fstab <<EOF
UUID=${NEW_ROOT_UUID} / btrfs compress=zstd:${ZSTD_LEVEL} 0 1
LABEL=EFI /boot/efi vfat defaults 0 2
#tmpfs /tmp tmpfs defaults,nosuid 0 0
EOF
cat >./etc/config/fstab <<EOF
config global
option anon_swap '0'
option anon_mount '1'
option auto_swap '0'
option auto_mount '1'
option delay_root '5'
option check_fs '0'
config mount
option target '/rom'
option uuid '${NEW_ROOT_UUID}'
option enabled '1'
option enabled_fsck '1'
option fstype 'btrfs'
option options 'compress=zstd:${ZSTD_LEVEL}'
config mount
option target '/boot/efi'
option label 'EFI'
option enabled '1'
option enabled_fsck '1'
option fstype 'vfat'
EOF
(
cd etc/rc.d
rm -f S??shortcut-fe
if grep "sfe_flow '1'" ../config/turboacc >/dev/null; then
if find ../../lib/modules -name 'shortcut-fe-cm.ko'; then
ln -sf ../init.d/shortcut-fe S99shortcut-fe
fi
fi
)
# move /etc/config/balance_irq to /etc/balance_irq
[ -f "./etc/config/balance_irq" ] && mv ./etc/config/balance_irq ./etc/
sync
echo "Create initial etc snapshot -> .snapshots/etc-000"
btrfs subvolume snapshot -r etc .snapshots/etc-000
sync
[ -d /mnt/${DISK_NAME}${PART_PRESTR}4/docker ] || mkdir -p /mnt/${DISK_NAME}${PART_PRESTR}4/docker
rm -rf opt/docker && ln -sf /mnt/${DISK_NAME}${PART_PRESTR}4/docker/ opt/docker
if [ -f /mnt/${NEW_ROOT_NAME}/etc/config/AdGuardHome ]; then
[ -d /mnt/${DISK_NAME}${PART_PRESTR}4/AdGuardHome/data ] || mkdir -p /mnt/${DISK_NAME}${PART_PRESTR}4/AdGuardHome/data
if [ ! -L /usr/bin/AdGuardHome ]; then
[ -d /usr/bin/AdGuardHome ] &&
cp -a /usr/bin/AdGuardHome/* /mnt/${DISK_NAME}${PART_PRESTR}4/AdGuardHome/
fi
ln -sf /mnt/${DISK_NAME}${PART_PRESTR}4/AdGuardHome /mnt/${NEW_ROOT_NAME}/usr/bin/AdGuardHome
fi
sync
echo "Copy data complete ..."
BACKUP_LIST=$(${P2}/usr/sbin/openwrt-backup -p)
if [[ "${BR_FLAG}" -eq "1" && -n "${BACKUP_LIST}" ]]; then
echo -n "Start restoring configuration files ... "
(
cd /
eval tar czf ${NEW_ROOT_MOUNTPOINT}/.reserved/openwrt_config.tar.gz "${BACKUP_LIST}" 2>/dev/null
)
tar xzf ${NEW_ROOT_MOUNTPOINT}/.reserved/openwrt_config.tar.gz
[ -f ./etc/config/dockerman ] && sed -e "s/option wan_mode 'false'/option wan_mode 'true'/" -i ./etc/config/dockerman 2>/dev/null
[ -f ./etc/config/dockerd ] && sed -e "s/option wan_mode '0'/option wan_mode '1'/" -i ./etc/config/dockerd 2>/dev/null
[ -f ./etc/config/verysync ] && sed -e 's/config setting/config verysync/' -i ./etc/config/verysync 2>/dev/null
# Restore fstab
cp -f .snapshots/etc-000/fstab ./etc/fstab
cp -f .snapshots/etc-000/config/fstab ./etc/config/fstab
# 还原 luci
cp -f .snapshots/etc-000/config/luci ./etc/config/luci
# 还原/etc/config/rpcd
cp -f .snapshots/etc-000/config/rpcd ./etc/config/rpcd
sync
echo "Restore configuration information complete."
fi
echo "Modify the configuration file ... "
rm -f "./etc/rc.local.orig" "./etc/first_run.sh" "./etc/part_size"
rm -rf "./opt/docker" && ln -sf "/mnt/${DISK_NAME}${PART_PRESTR}4/docker" "./opt/docker"
rm -f ./etc/bench.log
cat >>./etc/crontabs/root <<EOF
37 5 * * * /etc/coremark.sh
EOF
sss=$(date +%s)
ddd=$((sss / 86400))
sed -e "s/:0:0:99999:7:::/:${ddd}:0:99999:7:::/" -i ./etc/shadow
# Fix the problem of repeatedly adding amule entries after each upgrade
sed -e "/amule:x:/d" -i ./etc/shadow
# Fix the problem of repeatedly adding sshd entries after each upgrade of dropbear
sed -e "/sshd:x:/d" -i ./etc/shadow
if ! grep "sshd:x:22:sshd" ./etc/group >/dev/null; then
echo "sshd:x:22:sshd" >>./etc/group
fi
if ! grep "sshd:x:22:22:sshd:" ./etc/passwd >/dev/null; then
echo "sshd:x:22:22:sshd:/var/run/sshd:/bin/false" >>./etc/passwd
fi
if ! grep "sshd:x:" ./etc/shadow >/dev/null; then
echo "sshd:x:${ddd}:0:99999:7:::" >>./etc/shadow
fi
if [ "${BR_FLAG}" -eq "1" ]; then
if [ -x ./bin/bash ] && [ -f ./etc/profile.d/30-sysinfo.sh ]; then
sed -e 's/\/bin\/ash/\/bin\/bash/' -i ./etc/passwd
fi
sync
fi
sed -e "s/option hw_flow '1'/option hw_flow '0'/" -i ./etc/config/turboacc
(
cd etc/rc.d
rm -f S??shortcut-fe
if grep "sfe_flow '1'" ../config/turboacc >/dev/null; then
if find ../../lib/modules -name 'shortcut-fe-cm.ko'; then
ln -sf ../init.d/shortcut-fe S99shortcut-fe
fi
fi
)
eval tar czf .reserved/openwrt_config.tar.gz "${BACKUP_LIST}" 2>/dev/null
rm -f ./etc/part_size ./etc/first_run.sh
if [ -x ./usr/sbin/balethirq.pl ]; then
if grep "balethirq.pl" "./etc/rc.local"; then
echo "balance irq is enabled"
else
echo "enable balance irq"
sed -e "/exit/i\/usr/sbin/balethirq.pl" -i ./etc/rc.local
fi
fi
mv ./etc/rc.local ./etc/rc.local.orig
cat >"./etc/rc.local" <<EOF
if ! ls /etc/rc.d/S??dockerd >/dev/null 2>&1;then
/etc/init.d/dockerd enable
/etc/init.d/dockerd start
fi
if ! ls /etc/rc.d/S??dockerman >/dev/null 2>&1 && [ -f /etc/init.d/dockerman ];then
/etc/init.d/dockerman enable
/etc/init.d/dockerman start
fi
mv /etc/rc.local.orig /etc/rc.local
chmod 755 /etc/rc.local
exec /etc/rc.local
exit
EOF
chmod 755 ./etc/rc.local*
# move /etc/config/balance_irq to /etc/balance_irq
[ -f "./etc/config/balance_irq" ] && mv ./etc/config/balance_irq ./etc/
echo "Create etc snapshot -> .snapshots/etc-001"
btrfs subvolume snapshot -r etc .snapshots/etc-001
cd ${WORK_DIR}
echo "Copy efi files ..."
fatlabel ${EFI_DEV} "EFI"
cd /boot/efi
mv ./EFI/BOOT/grub.cfg /tmp/grub.cfg.prev
rm -rf *
cp -a ${P1}/* .
# 如果想启动上一个版本的openwrt,可以把 /boot/efi/EFI/BOOT/grub.cfg.prev 复制成 /boot/efi/EFI/BOOT/grub.cfg
mv /tmp/grub.cfg.prev ./EFI/BOOT/
echo "Modify efi configuration ... "
cd /boot/efi/EFI/BOOT
cat >grub.cfg <<EOF
echo "search fs_uuid ${NEW_ROOT_UUID} ..."
search.fs_uuid ${NEW_ROOT_UUID} root
echo "root=\$root"
echo "set prefix ... "
set prefix=(\$root)'/boot/grub2'
echo "prefix=\$prefix"
source \${prefix}/grub.cfg
EOF
echo "Modify boot configuration ... "
cd ${NEW_ROOT_MOUNTPOINT}/boot/grub2
cat >grub.cfg <<EOF
insmod gzio
insmod part_gpt
insmod zstd
insmod btrfs
terminal_input console
terminal_output console
set default="0"
set timeout=3
menuentry "OpenWrt" {
echo 'Loading linux kernel ...'
linux /boot/vmlinuz root=UUID=${NEW_ROOT_UUID} rootfstype=btrfs rootflags=compress=zstd:${ZSTD_LEVEL} console=ttyAMA0,115200n8 no_console_suspend consoleblank=0 fsck.fix=yes fsck.repair=yes net.ifnames=0 cgroup_enable=cpuset cgroup_memory=1 cgroup_enable=memory swapaccount=1
echo 'Loading initial ramdisk ...'
initrd /boot/initrd.img
}
EOF
sync
cd $WORK_DIR
umount -f ${P1} ${P2} 2>/dev/null
losetup -D 2>/dev/null
rm -rf ${P1} ${P2} 2>/dev/null
rm -f ${IMG_NAME} 2>/dev/null
rm -f sha256sums 2>/dev/null
sync
wait
echo "Successfully updated, automatic restarting..."
sleep 3
reboot
exit 0
+916
View File
@@ -0,0 +1,916 @@
#!/bin/bash
#======================================================================================
# Function: Update openwrt to emmc for Rockchip STB
# Copyright (C) 2020-- https://github.com/unifreq/openwrt_packit
# Copyright (C) 2021-- https://github.com/ophub/luci-app-amlogic
#======================================================================================
#
# The script supports directly setting parameters for update, skipping interactive selection
# openwrt-update-rockchip ${OPENWRT_FILE} ${AUTO_MAINLINE_UBOOT} ${RESTORE_CONFIG}
# E.g: openwrt-update-rockchip openwrt_s905d.img.gz yes restore
# E.g: openwrt-update-rockchip openwrt_s905d.img.gz no no-restore
# You can also execute the script directly, and interactively select related functions
# E.g: openwrt-update-rockchip
#
#======================================================================================
# Encountered a serious error, abort the script execution
error_msg() {
echo -e "[ERROR] ${1}"
exit 1
}
# Get the partition name of the /boot file system
get_boot_partition_name() {
local paths="/boot"
local partition_name
partition_name=$(df "${paths}" | awk 'NR==2 {print $1}' | awk -F '/' '{print $3}')
echo "${partition_name}"
}
# Get the partition name of the root file system
get_root_partition_name() {
local paths=("/" "/overlay" "/rom")
local partition_name
for path in "${paths[@]}"; do
partition_name=$(df "${path}" | awk 'NR==2 {print $1}' | awk -F '/' '{print $3}')
[[ -n "${partition_name}" ]] && break
done
echo "${partition_name}"
}
# Get the partition message of the root file system
get_root_partition_msg() {
local paths=("/" "/overlay" "/rom")
local partition_name
for path in "${paths[@]}"; do
partition_msg=$(lsblk -l -o NAME,PATH,TYPE,UUID,MOUNTPOINT | awk '$3~/^part$/ && $5 ~ "^" "'"${path}"'" "$" {print $0}')
[[ -n "${partition_msg}" ]] && break
done
[[ -z "${partition_msg}" ]] && error_msg "Cannot find the root partition message!"
echo "${partition_msg}"
}
# Receive one-key command related parameters
IMG_NAME="${1}"
AUTO_MAINLINE_UBOOT="${2}"
BACKUP_RESTORE_CONFIG="${3}"
# Current device model
if [ -f /boot/armbianEnv.txt ]; then
source /boot/armbianEnv.txt 2>/dev/null
CURRENT_FDTFILE=$(basename ${fdtfile})
fi
MYDEVICE_NAME=$(cat /proc/device-tree/model | tr -d '\000')
case $MYDEVICE_NAME in
"")
error_msg "The device name is empty and cannot be recognized."
;;
"Chainedbox L1 Pro")
if [ -n "${CURRENT_FDTFILE}" ]; then
MYDTB_FDTFILE="${CURRENT_FDTFILE}"
else
MYDTB_FDTFILE="rk3328-l1pro-1296mhz.dtb"
fi
SOC="l1pro"
;;
"BeikeYun")
if [ -n "${CURRENT_FDTFILE}" ]; then
MYDTB_FDTFILE="${CURRENT_FDTFILE}"
else
MYDTB_FDTFILE="rk3328-beikeyun-1296mhz.dtb"
fi
SOC="beikeyun"
;;
"ZCuble1 Max")
if [ -n "${CURRENT_FDTFILE}" ]; then
MYDTB_FDTFILE="${CURRENT_FDTFILE}"
else
MYDTB_FDTFILE="rk3399-zcube1-max.dtb"
fi
SOC="zcube1 max"
;;
"JP TVbox 3566")
if [ -n "${CURRENT_FDTFILE}" ]; then
MYDTB_FDTFILE="${CURRENT_FDTFILE}"
else
MYDTB_FDTFILE="rk3566-jp-tvbox.dtb"
fi
SOC="jp-tvbox"
;;
"Radxa CM3 RPI CM4 IO")
if [ -n "${CURRENT_FDTFILE}" ]; then
MYDTB_FDTFILE="${CURRENT_FDTFILE}"
else
MYDTB_FDTFILE="rk3566-radxa-cm3-rpi-cm4-io.dtb"
fi
SOC="radxa-cm3-rpi-cm4-io"
;;
"FastRhino R66S" | "Lunzn FastRhino R66S")
if [ -n "${CURRENT_FDTFILE}" ]; then
MYDTB_FDTFILE="${CURRENT_FDTFILE}"
else
MYDTB_FDTFILE="rk3568-fastrhino-r66s.dtb"
fi
SOC="r66s"
;;
"FastRhino R68S" | "Lunzn FastRhino R68S")
if [ -n "${CURRENT_FDTFILE}" ]; then
MYDTB_FDTFILE="${CURRENT_FDTFILE}"
else
MYDTB_FDTFILE="rk3568-fastrhino-r68s.dtb"
fi
SOC="r68s"
;;
"RK3568 EC-X")
if [ -n "${CURRENT_FDTFILE}" ]; then
MYDTB_FDTFILE="${CURRENT_FDTFILE}"
else
MYDTB_FDTFILE="rk3568-ec-x.dtb"
fi
SOC="ec-x"
;;
"HINLINK OPC-H66K Board" | "Hlink H66K")
if [ -n "${CURRENT_FDTFILE}" ] && [ "${CURRENT_FDTFILE}" != "rk3568-opc-h66k.dtb" ]; then
MYDTB_FDTFILE="${CURRENT_FDTFILE}"
else
MYDTB_FDTFILE="rk3568-hlink-h66k.dtb"
fi
SOC="h66k"
;;
"HINLINK OPC-H68K Board" | "Hlink H68K")
if [ -n "${CURRENT_FDTFILE}" ] && [ "${CURRENT_FDTFILE}" != "rk3568-opc-h68k.dtb" ]; then
MYDTB_FDTFILE="${CURRENT_FDTFILE}"
else
MYDTB_FDTFILE="rk3568-hlink-h68k.dtb"
fi
SOC="h68k"
;;
"HINLINK OPC-H69K Board" | "Hlink H69K")
if [ -n "${CURRENT_FDTFILE}" ] && [ "${CURRENT_FDTFILE}" != "rk3568-opc-h69k.dtb" ]; then
MYDTB_FDTFILE="${CURRENT_FDTFILE}"
else
MYDTB_FDTFILE="rk3568-hlink-h69k.dtb"
fi
SOC="h69k"
;;
"Radxa E25" | "Radxa E25 Carrier Board")
if [ -n "${CURRENT_FDTFILE}" ]; then
MYDTB_FDTFILE="${CURRENT_FDTFILE}"
else
MYDTB_FDTFILE="rk3568-radxa-e25.dtb"
fi
SOC="e25"
;;
"HINLINK OWL H88K-V3 Board" | "Hlink H88K-V3")
if [ -n "${CURRENT_FDTFILE}" ] && [ "${CURRENT_FDTFILE}" != "rk3568-hinlink-h88k-v3.dtb" ]; then
MYDTB_FDTFILE="${CURRENT_FDTFILE}"
else
MYDTB_FDTFILE="rk3588-hlink-h88k-v3.dtb"
fi
SOC="h88k-v3"
;;
"Hlink H88K V3.1")
if [ -n "${CURRENT_FDTFILE}" ] && [ "${CURRENT_FDTFILE}" != "rk3568-hinlink-h88k-v31.dtb" ]; then
MYDTB_FDTFILE="${CURRENT_FDTFILE}"
else
MYDTB_FDTFILE="rk3588-hlink-h88k-v31.dtb"
fi
SOC="h88k-v3"
;;
"HINLINK OWL H88K Board" | "Hlink H88K")
if [ -n "${CURRENT_FDTFILE}" ] && [ "${CURRENT_FDTFILE}" != "rk3568-hinlink-h88k.dtb" ]; then
MYDTB_FDTFILE="${CURRENT_FDTFILE}"
else
MYDTB_FDTFILE="rk3588-hlink-h88k.dtb"
fi
SOC="ak88/h88k"
;;
"Hlink H28K")
if [ -n "${CURRENT_FDTFILE}" ]; then
MYDTB_FDTFILE="${CURRENT_FDTFILE}"
else
MYDTB_FDTFILE="rk3528-hlink-h28k.dtb"
fi
SOC="h28k"
;;
"Hlink HT2")
if [ -n "${CURRENT_FDTFILE}" ]; then
MYDTB_FDTFILE="${CURRENT_FDTFILE}"
else
MYDTB_FDTFILE="rk3528-hlink-ht2.dtb"
fi
SOC="ht2"
;;
"Radxa E20C")
if [ -n "${CURRENT_FDTFILE}" ]; then
MYDTB_FDTFILE="${CURRENT_FDTFILE}"
else
MYDTB_FDTFILE="rk3528-radxa-e20c.dtb"
fi
SOC="e20c"
;;
"Radxa E24C")
if [ -n "${CURRENT_FDTFILE}" ]; then
MYDTB_FDTFILE="${CURRENT_FDTFILE}"
else
MYDTB_FDTFILE="rk3528-radxa-e24c.dtb"
fi
SOC="e24c"
;;
"YiXun Rs6Pro")
if [ -n "${CURRENT_FDTFILE}" ]; then
MYDTB_FDTFILE="${CURRENT_FDTFILE}"
else
MYDTB_FDTFILE="rk3528-yixun-rs6pro.dtb"
fi
SOC="rs6pro"
;;
"Ariaboard Photonicat")
if [ -n "${CURRENT_FDTFILE}" ]; then
MYDTB_FDTFILE="${CURRENT_FDTFILE}"
else
MYDTB_FDTFILE="rk3568-photonicat.dtb"
fi
SOC="photonicat"
;;
"NLnet Watermelon Pi V3")
if [ -n "${CURRENT_FDTFILE}" ]; then
MYDTB_FDTFILE="${CURRENT_FDTFILE}"
else
MYDTB_FDTFILE="rk3568-watermelon-pi-v3.dtb"
fi
SOC="watermelon-pi-v3"
;;
"NLnet Watermelon Pi")
if [ -n "${CURRENT_FDTFILE}" ]; then
MYDTB_FDTFILE="${CURRENT_FDTFILE}"
else
MYDTB_FDTFILE="rk3568-watermelon-pi.dtb"
fi
SOC="watermelon-pi"
;;
"Rockchip RK3576 DshanPi A1 Board")
if [ -n "${CURRENT_FDTFILE}" ]; then
MYDTB_FDTFILE="${CURRENT_FDTFILE}"
else
MYDTB_FDTFILE="rk3576-100ask-dshanpi-a1.dtb"
fi
SOC="100ask-dshanpi-a1"
;;
"Radxa ROCK 5B" | "Radxa ROCK 5 Model B")
if [ -n "${CURRENT_FDTFILE}" ]; then
MYDTB_FDTFILE="${CURRENT_FDTFILE}"
else
MYDTB_FDTFILE="rk3588-rock-5b.dtb"
fi
SOC="rock5b"
;;
"Radxa ROCK 5C" | "Radxa ROCK 5 Model C")
if [ -n "${CURRENT_FDTFILE}" ]; then
MYDTB_FDTFILE="${CURRENT_FDTFILE}"
else
MYDTB_FDTFILE="rk3588s-rock-5c.dtb"
fi
SOC="rock5c"
;;
"Radxa E52C")
if [ -n "${CURRENT_FDTFILE}" ]; then
MYDTB_FDTFILE="${CURRENT_FDTFILE}"
else
MYDTB_FDTFILE="rk3588s-radxa-e52c.dtb"
fi
SOC="e52c"
;;
"Radxa E54C")
if [ -n "${CURRENT_FDTFILE}" ]; then
MYDTB_FDTFILE="${CURRENT_FDTFILE}"
else
MYDTB_FDTFILE="rk3588s-radxa-e54c.dtb"
fi
SOC="e54c"
;;
*) #default
if [ -f "/etc/flippy-openwrt-release" ]; then
source /etc/flippy-openwrt-release 2>/dev/null
if [ -n "${CURRENT_FDTFILE}" ]; then
MYDTB_FDTFILE="${CURRENT_FDTFILE}"
else
MYDTB_FDTFILE="${FDTFILE}"
fi
SOC="${SOC}"
else
error_msg "Unknown device: [ ${MYDEVICE_NAME} ], Not supported."
fi
;;
esac
[[ -z "${MYDTB_FDTFILE}" || -z "${SOC}" ]] && {
error_msg "Invalid FDTFILE or SOC: [ ${MYDTB_FDTFILE} / ${SOC} ]"
}
echo -e "Current device: ${MYDEVICE_NAME} [ ${SOC} ]"
sleep 3
# Check and repair partition mount points
[[ -z "$(get_boot_partition_name)" || -z "$(get_root_partition_name)" ]] && {
echo -e "Partition mount point error, start repairing..."
openwrt-backup -g
}
# Find the partition where root is located
ROOT_PTNAME="$(get_root_partition_name)"
# Find the disk where the partition is located, only supports mmcblk?p? sd?? hd?? vd?? and other formats
case ${ROOT_PTNAME} in
mmcblk?p[1-4])
EMMC_NAME=$(echo ${ROOT_PTNAME} | awk '{print substr($1, 1, length($1)-2)}')
PARTITION_NAME="p"
LB_PRE="EMMC_"
;;
nvme?n?p?)
EMMC_NAME=$(echo ${ROOT_PTNAME} | awk '{print substr($1, 1, length($1)-2)}')
PARTITION_NAME="p"
LB_PRE="NVME_"
;;
[hsv]d[a-z][1-4])
EMMC_NAME=$(echo ${ROOT_PTNAME} | awk '{print substr($1, 1, length($1)-1)}')
PARTITION_NAME=""
LB_PRE="USB_"
;;
*)
error_msg "Unable to recognize the disk type of ${ROOT_PTNAME}!"
;;
esac
cd /mnt/${EMMC_NAME}${PARTITION_NAME}4/
mv -f /tmp/upload/* . 2>/dev/null && sync
if [[ "${IMG_NAME}" == *.img ]]; then
echo -e "Update using [ ${IMG_NAME} ] file. Please wait a moment ..."
elif [ $(ls *.img -l 2>/dev/null | grep "^-" | wc -l) -ge 1 ]; then
IMG_NAME=$(ls *.img | head -n 1)
echo -e "Update using [ ${IMG_NAME} ] ] file. Please wait a moment ..."
elif [ $(ls *.img.xz -l 2>/dev/null | grep "^-" | wc -l) -ge 1 ]; then
xz_file=$(ls *.img.xz | head -n 1)
echo -e "Update using [ ${xz_file} ] file. Please wait a moment ..."
xz -d ${xz_file} 2>/dev/null
IMG_NAME=$(ls *.img | head -n 1)
elif [ $(ls *.img.gz -l 2>/dev/null | grep "^-" | wc -l) -ge 1 ]; then
gz_file=$(ls *.img.gz | head -n 1)
echo -e "Update using [ ${gz_file} ] file. Please wait a moment ..."
gzip -df ${gz_file} 2>/dev/null
IMG_NAME=$(ls *.img | head -n 1)
elif [ $(ls *.7z -l 2>/dev/null | grep "^-" | wc -l) -ge 1 ]; then
gz_file=$(ls *.7z | head -n 1)
echo -e "Update using [ ${gz_file} ] file. Please wait a moment ..."
bsdtar -xmf ${gz_file} 2>/dev/null
[ $? -eq 0 ] || 7z x ${gz_file} -aoa -y 2>/dev/null
IMG_NAME=$(ls *.img | head -n 1)
elif [ $(ls *.zip -l 2>/dev/null | grep "^-" | wc -l) -ge 1 ]; then
zip_file=$(ls *.zip | head -n 1)
echo -e "Update using [ ${zip_file} ] file. Please wait a moment ..."
unzip -o ${zip_file} 2>/dev/null
IMG_NAME=$(ls *.img | head -n 1)
else
echo -e "Please upload or specify the update openwrt firmware file."
echo -e "Upload method: system menu → Amlogic Service → Manually Upload Update"
echo -e "Specify method: Place the openwrt firmware file in [ /mnt/${EMMC_NAME}${PARTITION_NAME}4/ ]"
echo -e "The supported file suffixes are: *.img, *.img.xz, *.img.gz, *.7z, *.zip"
echo -e "After upload the openwrt firmware file, run again."
exit 1
fi
sync
# check file
if [ ! -f "${IMG_NAME}" ]; then
error_msg "No update file found."
else
echo "Start update from [ ${IMG_NAME} ]"
fi
# find boot partition
BOOT_PART_MSG=$(lsblk -l -o NAME,PATH,TYPE,UUID,MOUNTPOINT | awk '$3~/^part$/ && $5 ~ /^\/boot$/ {print $0}')
if [ "${BOOT_PART_MSG}" == "" ]; then
error_msg "The boot partition is not exists or not mounted, so it cannot be upgraded with this script!"
fi
BR_FLAG=1
echo -ne "Whether to backup and restore the current config files? y/n [y]\b\b"
if [[ ${BACKUP_RESTORE_CONFIG} == "restore" ]]; then
yn="y"
elif [[ ${BACKUP_RESTORE_CONFIG} == "no-restore" ]]; then
yn="n"
else
read yn
fi
case ${yn} in
n* | N*)
BR_FLAG=0
;;
esac
BOOT_NAME=$(echo ${BOOT_PART_MSG} | awk '{print $1}')
BOOT_PATH=$(echo ${BOOT_PART_MSG} | awk '{print $2}')
BOOT_UUID=$(echo ${BOOT_PART_MSG} | awk '{print $4}')
# find root partition
ROOT_PART_MSG="$(get_root_partition_msg)"
ROOT_NAME=$(echo ${ROOT_PART_MSG} | awk '{print $1}')
ROOT_PATH=$(echo ${ROOT_PART_MSG} | awk '{print $2}')
ROOT_UUID=$(echo ${ROOT_PART_MSG} | awk '{print $4}')
case ${ROOT_NAME} in
${EMMC_NAME}${PARTITION_NAME}2)
NEW_ROOT_NAME="${EMMC_NAME}${PARTITION_NAME}3"
NEW_ROOT_LABEL="${LB_PRE}ROOTFS2"
;;
${EMMC_NAME}${PARTITION_NAME}3)
NEW_ROOT_NAME="${EMMC_NAME}${PARTITION_NAME}2"
NEW_ROOT_LABEL="${LB_PRE}ROOTFS1"
;;
*)
error_msg "The root partition location is invalid, so it cannot be upgraded with this script!"
;;
esac
# find new root partition
NEW_ROOT_PART_MSG=$(lsblk -l -o NAME,PATH,TYPE,UUID,MOUNTPOINT | grep "${NEW_ROOT_NAME}" | awk '$3 ~ /^part$/ && $5 !~ /^\/$/ && $5 !~ /^\/boot$/ {print $0}')
if [ "${NEW_ROOT_PART_MSG}" == "" ]; then
error_msg "The new root partition is not exists, so it cannot be upgraded with this script!"
fi
NEW_ROOT_NAME=$(echo ${NEW_ROOT_PART_MSG} | awk '{print $1}')
NEW_ROOT_PATH=$(echo ${NEW_ROOT_PART_MSG} | awk '{print $2}')
NEW_ROOT_UUID=$(echo ${NEW_ROOT_PART_MSG} | awk '{print $4}')
NEW_ROOT_MP=$(echo ${NEW_ROOT_PART_MSG} | awk '{print $5}')
# losetup
losetup -f -P ${IMG_NAME}
if [[ "${?}" -eq "0" ]]; then
LOOP_DEV=$(losetup | grep "${IMG_NAME}" | awk '{print $1}')
if [ "$LOOP_DEV" == "" ]; then
error_msg "loop device not found!"
fi
else
error_msg "losetup ${IMG_FILE} failed!"
fi
# fix loopdev issue in kernel 5.19
function fix_loopdev() {
local parentdev=${1##*/}
if [ ! -d /sys/block/${parentdev} ]; then
return
fi
subdevs=$(lsblk -l -o NAME | grep -E "^${parentdev}.+\$")
for subdev in ${subdevs}; do
if [ ! -d /sys/block/${parentdev}/${subdev} ]; then
return
elif [ -b /dev/${sub_dev} ]; then
continue
fi
source /sys/block/${parentdev}/${subdev}/uevent
mknod /dev/${subdev} b ${MAJOR} ${MINOR}
unset MAJOR MINOR DEVNAME DEVTYPE DISKSEQ PARTN PARTNAME
done
}
fix_loopdev ${LOOP_DEV}
WAIT=3
echo -n "The loopdev is ${LOOP_DEV}, wait ${WAIT} seconds "
while [ ${WAIT} -ge 1 ]; do
echo -n "."
sleep 1
WAIT=$((WAIT - 1))
done
echo
# umount loop devices (openwrt will auto mount some partition)
MOUNTED_DEVS=$(lsblk -l -o NAME,PATH,MOUNTPOINT | grep "${LOOP_DEV}" | awk '$3 !~ /^$/ {print $2}')
for dev in ${MOUNTED_DEVS}; do
while :; do
echo -n "umount ${dev} ... "
umount -f ${dev}
sleep 1
mnt=$(lsblk -l -o NAME,PATH,MOUNTPOINT | grep "${dev}" | awk '$3 !~ /^$/ {print $2}')
if [ "${mnt}" == "" ]; then
echo "ok"
break
else
echo "try again ..."
fi
done
done
# mount src part
WORK_DIR=${PWD}
P1=${WORK_DIR}/boot
P2=${WORK_DIR}/root
mkdir -p $P1 $P2
echo -n "mount ${LOOP_DEV}p1 -> ${P1} ... "
mount -t ext4 -o ro ${LOOP_DEV}p1 ${P1}
if [[ "${?}" -ne "0" ]]; then
echo "mount failed"
losetup -D
exit 1
else
echo "ok"
fi
echo -n "mount ${LOOP_DEV}p2 -> ${P2} ... "
ZSTD_LEVEL=6
mount -t btrfs -o ro,compress=zstd:${ZSTD_LEVEL} ${LOOP_DEV}p2 ${P2}
if [[ "${?}" -ne "0" ]]; then
echo "mount failed"
umount -f ${P1}
losetup -D
exit 1
else
echo "ok"
fi
# Prepare the dockerman config file
if [ -f ${P2}/etc/init.d/dockerman ] && [ -f ${P2}/etc/config/dockerd ]; then
flg=0
# get current docker data root
data_root=$(uci get dockerd.globals.data_root 2>/dev/null)
if [ "${data_root}" == "" ]; then
flg=1
# get current config from /etc/docker/daemon.json
if [ -f "/etc/docker/daemon.json" ] && [ -x "/usr/bin/jq" ]; then
data_root=$(jq -r '."data-root"' /etc/docker/daemon.json)
bip=$(jq -r '."bip"' /etc/docker/daemon.json)
[ "${bip}" == "null" ] && bip="172.31.0.1/24"
log_level=$(jq -r '."log-level"' /etc/docker/daemon.json)
[ "${log_level}" == "null" ] && log_level="warn"
_iptables=$(jq -r '."iptables"' /etc/docker/daemon.json)
[ "${_iptables}" == "null" ] && _iptables="true"
registry_mirrors=$(jq -r '."registry-mirrors"[]' /etc/docker/daemon.json 2>/dev/null)
fi
fi
if [ "${data_root}" == "" ]; then
data_root="/opt/docker/" # the default data root
fi
if ! uci get dockerd.globals >/dev/null 2>&1; then
uci set dockerd.globals='globals'
uci commit
fi
# delete alter config , use inner config
if uci get dockerd.globals.alt_config_file >/dev/null 2>&1; then
uci delete dockerd.globals.alt_config_file
uci commit
fi
if [[ "${flg}" -eq "1" ]]; then
uci set dockerd.globals.data_root=${data_root}
[ "${bip}" != "" ] && uci set dockerd.globals.bip=${bip}
[ "${log_level}" != "" ] && uci set dockerd.globals.log_level=${log_level}
[ "${_iptables}" != "" ] && uci set dockerd.globals.iptables=${_iptables}
if [ "${registry_mirrors}" != "" ]; then
for reg in ${registry_mirrors}; do
uci add_list dockerd.globals.registry_mirrors=${reg}
done
fi
uci set dockerd.globals.auto_start='1'
uci commit
fi
fi
#format NEW_ROOT
echo "umount ${NEW_ROOT_MP}"
umount -f "${NEW_ROOT_MP}"
if [[ "${?}" -ne "0" ]]; then
echo "umount failed, please reboot and try again!"
umount -f ${P1}
umount -f ${P2}
losetup -D
exit 1
fi
echo "format ${NEW_ROOT_PATH}"
NEW_ROOT_UUID=$(uuidgen)
mkfs.btrfs -f -U ${NEW_ROOT_UUID} -L ${NEW_ROOT_LABEL} -m single ${NEW_ROOT_PATH}
if [[ "${?}" -ne "0" ]]; then
echo "format ${NEW_ROOT_PATH} failed!"
umount -f ${P1}
umount -f ${P2}
losetup -D
exit 1
fi
echo "mount ${NEW_ROOT_PATH} to ${NEW_ROOT_MP}"
mount -t btrfs -o compress=zstd:${ZSTD_LEVEL} ${NEW_ROOT_PATH} ${NEW_ROOT_MP}
if [[ "${?}" -ne "0" ]]; then
echo "mount ${NEW_ROOT_PATH} to ${NEW_ROOT_MP} failed!"
umount -f ${P1}
umount -f ${P2}
losetup -D
exit 1
fi
# begin copy rootfs
cd ${NEW_ROOT_MP}
echo "Start copy data from ${P2} to ${NEW_ROOT_MP} ..."
ENTRYS=$(ls)
for entry in ${ENTRYS}; do
if [ "${entry}" == "lost+found" ]; then
continue
fi
echo -n "remove old ${entry} ... "
rm -rf ${entry}
if [ $? -eq 0 ]; then
echo "ok"
else
echo "failed"
exit 1
fi
done
echo
echo "create etc subvolume ..."
btrfs subvolume create etc
echo -n "make dirs ... "
mkdir -p .snapshots .reserved bin boot dev lib opt mnt overlay proc rom root run sbin sys tmp usr www
ln -sf lib/ lib64
ln -sf tmp/ var
echo "done"
echo
COPY_SRC="root etc bin sbin lib opt usr www"
echo "copy data ... "
for src in ${COPY_SRC}; do
echo -n "copy ${src} ... "
(cd ${P2} && tar cf - ${src}) | tar xf -
sync
echo "done"
done
SHFS="/mnt/${EMMC_NAME}${PARTITION_NAME}4"
echo "Modify config files ... "
if [ -x ./usr/sbin/balethirq.pl ]; then
if grep "balethirq.pl" "./etc/rc.local"; then
echo "balance irq is enabled"
else
echo "enable balance irq"
sed -e "/exit/i\/usr/sbin/balethirq.pl" -i ./etc/rc.local
fi
fi
rm -f ./etc/bench.log
cat >./etc/fstab <<EOF
UUID=${NEW_ROOT_UUID} / btrfs compress=zstd:${ZSTD_LEVEL} 0 1
UUID=${BOOT_UUID} /boot ext4 defaults 0 2
#tmpfs /tmp tmpfs defaults,nosuid 0 0
EOF
cat >./etc/config/fstab <<EOF
config global
option anon_swap '0'
option anon_mount '1'
option auto_swap '0'
option auto_mount '1'
option delay_root '5'
option check_fs '0'
config mount
option target '/rom'
option uuid '${NEW_ROOT_UUID}'
option enabled '1'
option enabled_fsck '1'
option fstype 'btrfs'
option options 'compress=zstd:${ZSTD_LEVEL}'
config mount
option target '/boot'
option uuid '${BOOT_UUID}'
option enabled '1'
option enabled_fsck '0'
option fstype 'ext4'
EOF
(
cd etc/rc.d
rm -f S??shortcut-fe
if grep "sfe_flow '1'" ../config/turboacc >/dev/null; then
if find ../../lib/modules -name 'shortcut-fe-cm.ko'; then
ln -sf ../init.d/shortcut-fe S99shortcut-fe
fi
fi
)
# move /etc/config/balance_irq to /etc/balance_irq
[ -f "./etc/config/balance_irq" ] && mv ./etc/config/balance_irq ./etc/
sync
echo "create the first etc snapshot -> .snapshots/etc-000"
btrfs subvolume snapshot -r etc .snapshots/etc-000
[ -d ${SHFS}/docker ] || mkdir -p ${SHFS}/docker
rm -rf opt/docker && ln -sf ${SHFS}/docker/ opt/docker
if [ -f /mnt/${NEW_ROOT_NAME}/etc/config/AdGuardHome ]; then
[ -d ${SHFS}/AdGuardHome/data ] || mkdir -p ${SHFS}/AdGuardHome/data
if [ ! -L /usr/bin/AdGuardHome ]; then
[ -d /usr/bin/AdGuardHome ] &&
cp -a /usr/bin/AdGuardHome/* ${SHFS}/AdGuardHome/
fi
ln -sf ${SHFS}/AdGuardHome /mnt/${NEW_ROOT_NAME}/usr/bin/AdGuardHome
fi
sync
echo "copy done"
echo
BACKUP_LIST=$(${P2}/usr/sbin/openwrt-backup -p)
if [ $BR_FLAG -eq 1 ]; then
echo -n "Restore your old config files ... "
(
cd /
eval tar czf ${NEW_ROOT_MP}/.reserved/openwrt_config.tar.gz "${BACKUP_LIST}" 2>/dev/null
)
tar xzf ${NEW_ROOT_MP}/.reserved/openwrt_config.tar.gz
[ -f ./etc/config/dockerman ] && sed -e "s/option wan_mode 'false'/option wan_mode 'true'/" -i ./etc/config/dockerman 2>/dev/null
[ -f ./etc/config/dockerd ] && sed -e "s/option wan_mode '0'/option wan_mode '1'/" -i ./etc/config/dockerd 2>/dev/null
[ -f ./etc/config/verysync ] && sed -e 's/config setting/config verysync/' -i ./etc/config/verysync
# 还原 fstab
cp -f .snapshots/etc-000/fstab ./etc/fstab
cp -f .snapshots/etc-000/config/fstab ./etc/config/fstab
# 还原 luci
cp -f .snapshots/etc-000/config/luci ./etc/config/luci
# 还原/etc/config/rpcd
cp -f .snapshots/etc-000/config/rpcd ./etc/config/rpcd
sync
echo "done"
echo
fi
cat >>./etc/crontabs/root <<EOF
17 3 * * * /etc/coremark.sh
EOF
sed -e 's/ttyAMA0/ttyS2/' -i ./etc/inittab
[ "${SOC}" != "h28k" ] && \
[ "${SOC}" != "h29k" ] && \
[ "${SOC}" != "ht2" ] && \
[ "${SOC}" != "e20c" ] && \
[ "${SOC}" != "e24c" ] && \
sed -e 's/ttyS0/tty1/' -i ./etc/inittab
sss=$(date +%s)
ddd=$((sss / 86400))
sed -e "s/:0:0:99999:7:::/:${ddd}:0:99999:7:::/" -i ./etc/shadow
# 修复amule每次升级后重复添加条目的问题
sed -e "/amule:x:/d" -i ./etc/shadow
# 修复dropbear每次升级后重复添加sshd条目的问题
sed -e "/sshd:x:/d" -i ./etc/shadow
if ! grep "sshd:x:22:sshd" ./etc/group >/dev/null; then
echo "sshd:x:22:sshd" >>./etc/group
fi
if ! grep "sshd:x:22:22:sshd:" ./etc/passwd >/dev/null; then
echo "sshd:x:22:22:sshd:/var/run/sshd:/bin/false" >>./etc/passwd
fi
if ! grep "sshd:x:" ./etc/shadow >/dev/null; then
echo "sshd:x:${ddd}:0:99999:7:::" >>./etc/shadow
fi
if [ $BR_FLAG -eq 1 ]; then
if [ -x ./bin/bash ] && [ -f ./etc/profile.d/30-sysinfo.sh ]; then
sed -e 's/\/bin\/ash/\/bin\/bash/' -i ./etc/passwd
fi
sync
echo "done"
echo
fi
sed -e "s/option hw_flow '1'/option hw_flow '0'/" -i ./etc/config/turboacc
(
cd etc/rc.d
rm -f S??shortcut-fe
if grep "sfe_flow '1'" ../config/turboacc >/dev/null; then
if find ../../lib/modules -name 'shortcut-fe-cm.ko'; then
ln -sf ../init.d/shortcut-fe S99shortcut-fe
fi
fi
)
# move /etc/config/balance_irq to /etc/balance_irq
[ -f "./etc/config/balance_irq" ] && mv ./etc/config/balance_irq ./etc/
rm -f "./etc/rc.local.orig" "./etc/first_run.sh" "./etc/part_size"
eval tar czf .reserved/openwrt_config.tar.gz "${BACKUP_LIST}" 2>/dev/null
sync
mv ./etc/rc.local ./etc/rc.local.orig
cat >"./etc/rc.local" <<EOF
if ! ls /etc/rc.d/S??dockerd >/dev/null 2>&1;then
/etc/init.d/dockerd enable
/etc/init.d/dockerd start
fi
if ! ls /etc/rc.d/S??dockerman >/dev/null 2>&1 && [ -f /etc/init.d/dockerman ];then
/etc/init.d/dockerman enable
/etc/init.d/dockerman start
fi
mv /etc/rc.local.orig /etc/rc.local
chmod 755 /etc/rc.local
exec /etc/rc.local
exit
EOF
chmod 755 ./etc/rc.local*
echo "create the second etc snapshot -> .snapshots/etc-001"
btrfs subvolume snapshot -r etc .snapshots/etc-001
# 2021.04.01添加
# 强制锁定fstab,防止用户擅自修改挂载点
# 开启了快照功能之后,不再需要锁定fstab
#chattr +ia ./etc/config/fstab
cd ${WORK_DIR}
echo "Start copy data from ${P2} to /boot ..."
cd /boot
echo -n "backup armbianEnv.txt ..."
cp armbianEnv.txt /tmp/
echo -n "backup current dtb file ..."
cp -v dtb/rockchip/${CURRENT_FDTFILE} /tmp/
echo -n "remove old boot files ..."
rm -rf *
echo "done"
echo -n "copy new boot files ... "
(cd ${P1} && tar cf - .) | tar xf -
sync
echo "done"
echo
echo -n "Update boot args ... "
if [ -f /tmp/armbianEnv.txt ]; then
ORIG_OVERLAYS=$(grep '^overlays=' /tmp/armbianEnv.txt)
ORIG_USER_OVERLAYS=$(grep '^user_overlays=' /tmp/armbianEnv.txt)
sed -e '/user_overlays=/d' -i armbianEnv.txt
sed -e '/overlays=/d' -i armbianEnv.txt
echo "$ORIG_OVERLAYS" >>armbianEnv.txt
echo "$ORIG_USER_OVERLAYS" >>armbianEnv.txt
fi
sed -e '/fdtfile=/d' -i armbianEnv.txt
sed -e '/rootdev=/d' -i armbianEnv.txt
sed -e '/rootfstype=/d' -i armbianEnv.txt
sed -e '/rootflags=/d' -i armbianEnv.txt
case $SOC in
l1pro | beikeyun)
echo "fdtfile=/dtb/rockchip/${MYDTB_FDTFILE}" >>armbianEnv.txt
;;
*)
echo "fdtfile=rockchip/${MYDTB_FDTFILE}" >>armbianEnv.txt
;;
esac
cat >>armbianEnv.txt <<EOF
rootdev=UUID=${NEW_ROOT_UUID}
rootfstype=btrfs
rootflags=compress=zstd:${ZSTD_LEVEL}
EOF
# Replace the UUID for extlinux/extlinux.conf if it exists
[[ -f "extlinux/extlinux.conf" ]] && {
sed -i -E "s|UUID=[^ ]*|UUID=${NEW_ROOT_UUID}|" extlinux/extlinux.conf 2>/dev/null
}
# 如果新的dtb文件不存在,则用旧的代替
if [ ! -f "dtb/rockchip/${MYDTB_FDTFILE}" ]; then
echo "The new dtb file does not exist, replace it with the old one."
cp -v /tmp/${CURRENT_FDTFILE} dtb/rockchip/${MYDTB_FDTFILE}
fi
sync
echo "done"
echo
cd $WORK_DIR
umount -f ${P1} ${P2} 2>/dev/null
losetup -D 2>/dev/null
rmdir ${P1} ${P2} 2>/dev/null
rm -f ${IMG_NAME} 2>/dev/null
rm -f sha256sums 2>/dev/null
sync
echo "Successfully updated, automatic restarting..."
sleep 3
reboot
exit 0
@@ -0,0 +1,299 @@
#!/bin/bash
#==================================================================
# This file is licensed under the terms of the GNU General Public
# License version 2. This program is licensed "as is" without any
# warranty of any kind, whether express or implied.
#
# This file is a part of the luci-app-amlogic plugin
# https://github.com/ophub/luci-app-amlogic
#
# Description: Check and update OpenWrt firmware
# Copyright (C) 2021- https://github.com/unifreq/openwrt_packit
# Copyright (C) 2021- https://github.com/ophub/luci-app-amlogic
#==================================================================
# Set a fixed value
check_option="${1}"
download_version="${2}"
TMP_CHECK_DIR="/tmp/amlogic"
AMLOGIC_SOC_FILE="/etc/flippy-openwrt-release"
START_LOG="${TMP_CHECK_DIR}/amlogic_check_firmware.log"
RUNNING_LOG="${TMP_CHECK_DIR}/amlogic_running_script.log"
LOG_FILE="${TMP_CHECK_DIR}/amlogic.log"
support_platform=("allwinner" "rockchip" "amlogic" "qemu-aarch64")
LOGTIME="$(date "+%Y-%m-%d %H:%M:%S")"
[[ -d ${TMP_CHECK_DIR} ]] || mkdir -p ${TMP_CHECK_DIR}
# Clean the running log
clean_running() {
echo -e '' >${RUNNING_LOG} 2>/dev/null && sync
}
# Add log
tolog() {
echo -e "${1}" >${START_LOG}
echo -e "${LOGTIME} ${1}" >>${LOG_FILE}
[[ -n "${2}" && "${2}" -eq "1" ]] && clean_running && exit 1
}
# Get the partition name of the root file system
get_root_partition_name() {
local paths=("/" "/overlay" "/rom")
local partition_name
for path in "${paths[@]}"; do
partition_name=$(df "${path}" | awk 'NR==2 {print $1}' | awk -F '/' '{print $3}')
[[ -n "${partition_name}" ]] && break
done
[[ -z "${partition_name}" ]] && tolog "Cannot find the root partition!" "1"
echo "${partition_name}"
}
# Check running scripts, prohibit running concurrently
this_running_log="3@OpenWrt update in progress, try again later!"
running_script="$(cat ${RUNNING_LOG} 2>/dev/null | xargs)"
if [[ -n "${running_script}" ]]; then
run_num="$(echo "${running_script}" | awk -F "@" '{print $1}')"
run_log="$(echo "${running_script}" | awk -F "@" '{print $2}')"
fi
if [[ -n "${run_log}" && "${run_num}" -ne "3" ]]; then
echo -e "${run_log}" >${START_LOG} 2>/dev/null && sync && exit 1
else
echo -e "${this_running_log}" >${RUNNING_LOG} 2>/dev/null && sync
fi
# Find the partition where root is located
ROOT_PTNAME="$(get_root_partition_name)"
# Find the disk where the partition is located, only supports mmcblk?p? sd?? hd?? vd?? and other formats
case "${ROOT_PTNAME}" in
mmcblk?p[1-4])
EMMC_NAME="$(echo ${ROOT_PTNAME} | awk '{print substr($1, 1, length($1)-2)}')"
PARTITION_NAME="p"
;;
[hsv]d[a-z][1-4])
EMMC_NAME="$(echo ${ROOT_PTNAME} | awk '{print substr($1, 1, length($1)-1)}')"
PARTITION_NAME=""
;;
nvme?n?p[1-4])
EMMC_NAME="$(echo ${ROOT_PTNAME} | awk '{print substr($1, 1, length($1)-2)}')"
PARTITION_NAME="p"
;;
*)
tolog "Unable to recognize the disk type of ${ROOT_PTNAME}!" "1"
;;
esac
# Set the default download path
FIRMWARE_DOWNLOAD_PATH="/mnt/${EMMC_NAME}${PARTITION_NAME}4"
[ -d "${FIRMWARE_DOWNLOAD_PATH}/.luci-app-amlogic" ] || mkdir -p "${FIRMWARE_DOWNLOAD_PATH}/.luci-app-amlogic"
# Check release file
if [[ -s "${AMLOGIC_SOC_FILE}" ]]; then
source "${AMLOGIC_SOC_FILE}" 2>/dev/null
PLATFORM="${PLATFORM}"
BOARD="${BOARD}"
else
tolog "${AMLOGIC_SOC_FILE} file is missing!" "1"
fi
if [[ -z "${PLATFORM}" || -z "$(echo "${support_platform[@]}" | grep -w "${PLATFORM}")" || -z "${BOARD}" ]]; then
tolog "Missing [ PLATFORM / BOARD ] value in ${AMLOGIC_SOC_FILE} file." "1"
fi
tolog "PLATFORM: [ ${PLATFORM} ], BOARD: [ ${BOARD} ], Use in [ ${EMMC_NAME} ]"
sleep 2
# 01. Query local version information
tolog "01. Query version information..."
# 01.01 Query the current version
current_kernel_v="$(uname -r 2>/dev/null | grep -oE '^[1-9].[0-9]{1,3}.[0-9]+')"
tolog "01.01 current version: ${current_kernel_v}"
sleep 2
# 01.01 Version comparison
main_line_version="$(echo ${current_kernel_v} | awk -F '.' '{print $1"."$2}')"
# 01.02. Query the selected branch in the settings
server_kernel_branch="$(uci get amlogic.config.amlogic_kernel_branch 2>/dev/null | grep -oE '^[1-9].[0-9]{1,3}')"
if [[ -z "${server_kernel_branch}" ]]; then
server_kernel_branch="${main_line_version}"
uci set amlogic.config.amlogic_kernel_branch="${main_line_version}" 2>/dev/null
uci commit amlogic 2>/dev/null
fi
if [[ "${server_kernel_branch}" != "${main_line_version}" ]]; then
main_line_version="${server_kernel_branch}"
tolog "01.02 Select branch: ${main_line_version}"
sleep 2
fi
# 01.03. Download server version documentation
server_firmware_url="$(uci get amlogic.config.amlogic_firmware_repo 2>/dev/null)"
[[ ! -z "${server_firmware_url}" ]] || tolog "01.03 The custom firmware download repo is invalid." "1"
releases_tag_keywords="$(uci get amlogic.config.amlogic_firmware_tag 2>/dev/null)"
[[ ! -z "${releases_tag_keywords}" ]] || tolog "01.04 The custom firmware tag keywords is invalid." "1"
firmware_suffix="$(uci get amlogic.config.amlogic_firmware_suffix 2>/dev/null)"
[[ ! -z "${firmware_suffix}" ]] || tolog "01.05 The custom firmware suffix is invalid." "1"
if [[ "${server_firmware_url}" == http* ]]; then
server_firmware_url="${server_firmware_url#*com\/}"
fi
# 02. Check Updated
check_updated() {
tolog "02.01 Search for tags in the first 5 pages of releases..."
# Get the tags list
firmware_tags_array=()
for i in {1..5}; do
while IFS= read -r firmware_tags_name; do
firmware_tags_name="$(echo "${firmware_tags_name}" | sed 's/releases\/tag\///g')"
if [[ -n "${firmware_tags_name}" ]]; then
firmware_tags_array+=("${firmware_tags_name}")
fi
done < <(
curl -fsSL -m 10 \
https://github.com/${server_firmware_url}/releases?page=${i} |
grep -oE 'releases/tag/([^" ]+)'
)
done
if [[ "${#firmware_tags_array[*]}" -eq "0" ]]; then
tolog "02.01.01 Unable to retrieve a list of firmware tags." "1"
fi
tolog "02.02 Search for tags containing the keyword..."
# Search for tags containing the keyword
for i in "${firmware_tags_array[@]}"; do
if [[ "${i}" == *"${releases_tag_keywords}"* ]]; then
firmware_releases_tag="${i}"
break
fi
done
if [[ -n "${firmware_releases_tag}" ]]; then
tolog "02.02.01 Tags: ${firmware_releases_tag}"
sleep 2
else
tolog "02.02.01 No matching tags found." "1"
fi
tolog "02.03 Start searching for firmware download links..."
# Retrieve the HTML code of the tags list page
html_code="$(
curl -fsSL -m 10 \
https://github.com/${server_firmware_url}/releases/expanded_assets/${firmware_releases_tag}
)"
# Set the regular expression for the OpenWrt filename
op_file_pattern=".*_${BOARD}_.*k${main_line_version}\.[0-9]+.*${firmware_suffix}"
# Find the <li> list item where the OpenWrt file is located
li_block=$(awk -v pattern="${op_file_pattern}" -v RS='</li>' '$0 ~ pattern { print $0 "</li>"; exit }' <<<"${html_code}")
[[ -z "${li_block}" ]] && tolog "02.03.01 No matching download links found." "1"
# Find the OpenWrt filename
latest_url=$(echo "${li_block}" | grep -oE "/[^\"]*_${BOARD}_.*k${main_line_version}\.[0-9]+[^\"]*${firmware_suffix}" | sort -urV | head -n 1 | xargs basename 2>/dev/null)
tolog "02.03.02 OpenWrt file: ${latest_url}"
# Find the date of the latest update
latest_updated_at=$(echo "${li_block}" | grep -o 'datetime="[^"]*"' | sed 's/datetime="//; s/"//')
tolog "02.03.03 Latest updated at: ${latest_updated_at}"
# Format the date for display
date_display_format="$(echo ${latest_updated_at} | tr 'T' '(' | tr 'Z' ')')"
[[ -z "${latest_url}" || -z "${latest_updated_at}" ]] && tolog "02.03.04 The download URL or date is invalid." "1"
# Find the firmware sha256 value
latest_firmware_sha256="$(echo "${li_block}" | grep -o 'value="sha256:[^"]*' | sed 's/value="sha256://')"
tolog "02.03.05 OpenWrt sha256: ${latest_firmware_sha256}"
# Check the firmware update code
down_check_code="${latest_updated_at}.${main_line_version}"
op_release_code="${FIRMWARE_DOWNLOAD_PATH}/.luci-app-amlogic/op_release_code"
if [[ -s "${op_release_code}" ]]; then
update_check_code="$(cat ${op_release_code} | xargs)"
if [[ -n "${update_check_code}" && "${update_check_code}" == "${down_check_code}" ]]; then
tolog "02.04 Already the latest version, no need to update." "1"
fi
fi
# Prompt to update
if [[ -n "${latest_url}" ]]; then
tolog '<input type="button" class="cbi-button cbi-button-reload" value="Download" onclick="return b_check_firmware(this, '"'download_${latest_updated_at}@${firmware_releases_tag}/${latest_url}@${latest_firmware_sha256}'"')"/> Latest updated: '${date_display_format}'' "1"
else
tolog "02.05 No OpenWrt available, please use another kernel branch." "1"
fi
exit 0
}
# 03. Download Openwrt
download_firmware() {
tolog "03. Start download the Openwrt..."
# Get the openwrt firmware download path
if [[ "${download_version}" == "download_"* ]]; then
tolog "03.01 Start downloading..."
else
tolog "03.01 Invalid parameter." "1"
fi
# Delete other residual firmware files
rm -f ${FIRMWARE_DOWNLOAD_PATH}/*${firmware_suffix} 2>/dev/null && sync
rm -f ${FIRMWARE_DOWNLOAD_PATH}/*.img 2>/dev/null && sync
rm -f ${FIRMWARE_DOWNLOAD_PATH}/sha256sums 2>/dev/null && sync
# OpenWrt make data
latest_updated_at="$(echo ${download_version} | awk -F'@' '{print $1}' | sed -e s'|download_||'g)"
down_check_code="${latest_updated_at}.${main_line_version}"
# Download firmware
opfile_path="$(echo ${download_version} | awk -F'@' '{print $2}')"
# Restore converted characters in file names(%2B to +)
firmware_download_oldname="${opfile_path//%2B/+}"
latest_url="https://github.com/${server_firmware_url}/releases/download/${firmware_download_oldname}"
# Find the firmware sha256 value
releases_firmware_sha256sums="$(echo ${download_version} | awk -F'@' '{print $3}')"
# Download to OpenWrt file
firmware_download_name="openwrt_${BOARD}_k${main_line_version}_github${firmware_suffix}"
curl -fsSL "${latest_url}" -o "${FIRMWARE_DOWNLOAD_PATH}/${firmware_download_name}"
if [[ "$?" -eq "0" && -s "${FIRMWARE_DOWNLOAD_PATH}/${firmware_download_name}" ]]; then
tolog "03.02 OpenWrt downloaded successfully."
else
tolog "03.02 OpenWrt download failed." "1"
fi
# Verify sha256sums if available
if [[ -n "${releases_firmware_sha256sums}" ]]; then
tolog "03.03 Perform sha256 checksum verification."
# If there is a sha256sum file, compare it
download_firmware_sha256sums="$(sha256sum ${FIRMWARE_DOWNLOAD_PATH}/${firmware_download_name} | awk '{print $1}')"
if [[ "${releases_firmware_sha256sums}" != "${download_firmware_sha256sums}" ]]; then
tolog "03.03.01 sha256sum verification mismatched." "1"
else
tolog "03.03.02 sha256sum verification succeeded."
fi
fi
sync && sleep 3
tolog "You can update."
tolog '<input type="button" class="cbi-button cbi-button-reload" value="Update" onclick="return amlogic_update(this, '"'${firmware_download_name}@${down_check_code}@${FIRMWARE_DOWNLOAD_PATH}'"')"/>' "1"
exit 0
}
getopts 'cd' opts
case "${opts}" in
c | check)
check_updated
;;
* | download)
download_firmware
;;
esac
@@ -0,0 +1,275 @@
#!/bin/bash
#==================================================================
# This file is licensed under the terms of the GNU General Public
# License version 2. This program is licensed "as is" without any
# warranty of any kind, whether express or implied.
#
# This file is a part of the luci-app-amlogic plugin
# https://github.com/ophub/luci-app-amlogic
#
# Description: Check and update OpenWrt Kernel
# Copyright (C) 2021- https://github.com/unifreq/openwrt_packit
# Copyright (C) 2021- https://github.com/ophub/luci-app-amlogic
#==================================================================
# Set a fixed value
check_option="${1}"
download_version="${2}"
TMP_CHECK_DIR="/tmp/amlogic"
AMLOGIC_SOC_FILE="/etc/flippy-openwrt-release"
START_LOG="${TMP_CHECK_DIR}/amlogic_check_kernel.log"
RUNNING_LOG="${TMP_CHECK_DIR}/amlogic_running_script.log"
LOG_FILE="${TMP_CHECK_DIR}/amlogic.log"
support_platform=("allwinner" "rockchip" "amlogic" "qemu-aarch64")
LOGTIME="$(date "+%Y-%m-%d %H:%M:%S")"
[[ -d ${TMP_CHECK_DIR} ]] || mkdir -p ${TMP_CHECK_DIR}
# Clean the running log
clean_running() {
echo -e '' >${RUNNING_LOG} 2>/dev/null && sync
}
# Add log
tolog() {
echo -e "${1}" >${START_LOG}
echo -e "${LOGTIME} ${1}" >>${LOG_FILE}
[[ -n "${2}" && "${2}" -eq "1" ]] && clean_running && exit 1
}
# Get the partition name of the root file system
get_root_partition_name() {
local paths=("/" "/overlay" "/rom")
local partition_name
for path in "${paths[@]}"; do
partition_name=$(df "${path}" | awk 'NR==2 {print $1}' | awk -F '/' '{print $3}')
[[ -n "${partition_name}" ]] && break
done
[[ -z "${partition_name}" ]] && tolog "Cannot find the root partition!" "1"
echo "${partition_name}"
}
# Check running scripts, prohibit running concurrently
this_running_log="2@Kernel update in progress, try again later!"
running_script="$(cat ${RUNNING_LOG} 2>/dev/null | xargs)"
if [[ -n "${running_script}" ]]; then
run_num="$(echo "${running_script}" | awk -F "@" '{print $1}')"
run_log="$(echo "${running_script}" | awk -F "@" '{print $2}')"
fi
if [[ -n "${run_log}" && "${run_num}" -ne "2" ]]; then
echo -e "${run_log}" >${START_LOG} 2>/dev/null && sync && exit 1
else
echo -e "${this_running_log}" >${RUNNING_LOG} 2>/dev/null && sync
fi
# Find the partition where root is located
ROOT_PTNAME="$(get_root_partition_name)"
# Find the disk where the partition is located, only supports mmcblk?p? sd?? hd?? vd?? and other formats
case "${ROOT_PTNAME}" in
mmcblk?p[1-4])
EMMC_NAME="$(echo ${ROOT_PTNAME} | awk '{print substr($1, 1, length($1)-2)}')"
PARTITION_NAME="p"
;;
[hsv]d[a-z][1-4])
EMMC_NAME="$(echo ${ROOT_PTNAME} | awk '{print substr($1, 1, length($1)-1)}')"
PARTITION_NAME=""
;;
nvme?n?p[1-4])
EMMC_NAME="$(echo ${ROOT_PTNAME} | awk '{print substr($1, 1, length($1)-2)}')"
PARTITION_NAME="p"
;;
*)
tolog "Unable to recognize the disk type of ${ROOT_PTNAME}!" "1"
;;
esac
# Set the default download path
KERNEL_DOWNLOAD_PATH="/mnt/${EMMC_NAME}${PARTITION_NAME}4"
# Check release file
if [[ -s "${AMLOGIC_SOC_FILE}" ]]; then
source "${AMLOGIC_SOC_FILE}" 2>/dev/null
PLATFORM="${PLATFORM}"
else
tolog "${AMLOGIC_SOC_FILE} file is missing!" "1"
fi
if [[ -z "${PLATFORM}" || -z "$(echo "${support_platform[@]}" | grep -w "${PLATFORM}")" ]]; then
tolog "Missing [ PLATFORM ] value in ${AMLOGIC_SOC_FILE} file." "1"
fi
tolog "PLATFORM: [ ${PLATFORM} ], Use in [ ${EMMC_NAME} ]"
sleep 2
# Step 1. Set the kernel query api
tolog "01. Start checking the kernel repository."
firmware_repo="$(uci get amlogic.config.amlogic_firmware_repo 2>/dev/null)"
[[ -n "${firmware_repo}" ]] || tolog "01.01 The custom kernel download repo is invalid." "1"
kernel_repo="$(uci get amlogic.config.amlogic_kernel_path 2>/dev/null)"
[[ -n "${kernel_repo}" ]] || tolog "01.02 The custom kernel download repo is invalid." "1"
if [[ "${kernel_repo}" == "opt/kernel" ]]; then
uci set amlogic.config.amlogic_kernel_path="${firmware_repo}" 2>/dev/null
uci commit amlogic 2>/dev/null
kernel_repo="${firmware_repo}"
fi
# Convert kernel repo to api format
[[ "${kernel_repo}" =~ ^https: ]] && kernel_repo="$(echo ${kernel_repo} | awk -F'/' '{print $4"/"$5}')"
kernel_api="https://github.com/${kernel_repo}"
tolog "01.03 Kernel repo: ${kernel_repo}"
# Get the current kernel uname
kernel_uname="$(uname -r 2>/dev/null)"
tolog "01.04 Current kernel uname: ${kernel_uname}"
# Get the kernel tag from uci config
op_kernel_tags="$(uci get amlogic.config.amlogic_kernel_tags 2>/dev/null)"
# Determine the kernel tag
if [[ -n "${op_kernel_tags}" ]]; then
kernel_tag="${op_kernel_tags/kernel_/}"
else
# Determine the kernel tag based on the current kernel uname
if [[ "${kernel_uname}" =~ -rk3588 ]]; then
kernel_tag="rk3588"
elif [[ "${kernel_uname}" =~ -rk35xx ]]; then
kernel_tag="rk35xx"
elif [[ "${kernel_uname}" =~ -h6|-zicai ]]; then
kernel_tag="h6"
else
kernel_tag="stable"
fi
# Save the kernel tag to uci config
uci set amlogic.config.amlogic_kernel_tags="kernel_${kernel_tag}" 2>/dev/null
uci commit amlogic 2>/dev/null
fi
tolog "01.05 Kernel tag: kernel_${kernel_tag}"
sleep 2
# Step 2: Check if there is the latest kernel version
check_kernel() {
# 02. Query local version information
tolog "02. Start checking the kernel version."
# 02.01 Get current kernel version
[[ ! "${kernel_tag}" =~ ^(rk3588|rk35xx)$ ]] && kernel_uname="$(echo "${kernel_uname}" | cut -d'-' -f1)"
[[ -n "${kernel_uname}" ]] || tolog "02.01 The current kernel version is not detected." "1"
tolog "02.01 current version: ${kernel_uname}"
sleep 2
# 02.02 Version comparison
main_line_version="$(echo ${kernel_uname} | awk -F '.' '{print $1"."$2}')"
# 02.03 Query the selected branch in the settings
server_kernel_branch="$(uci get amlogic.config.amlogic_kernel_branch 2>/dev/null | grep -oE '^[1-9].[0-9]{1,3}')"
if [[ -z "${server_kernel_branch}" ]]; then
server_kernel_branch="${main_line_version}"
uci set amlogic.config.amlogic_kernel_branch="${main_line_version}" 2>/dev/null
uci commit amlogic 2>/dev/null
fi
if [[ "${server_kernel_branch}" != "${main_line_version}" ]]; then
main_line_version="${server_kernel_branch}"
main_line_now="0"
tolog "02.02 Select branch: ${main_line_version}"
sleep 2
fi
# Check the version on the server
latest_version="$(
curl -fsSL -m 10 \
${kernel_api}/releases/expanded_assets/kernel_${kernel_tag} |
grep -oE "${main_line_version}\.[0-9]+[^\"]*\.tar\.gz" | sed 's/.tar.gz//' |
sort -urV | head -n 1
)"
[[ -n "${latest_version}" ]] || tolog "02.03 No kernel available, please use another kernel branch." "1"
tolog "02.04 current version: ${kernel_uname}, Latest version: ${latest_version}"
sleep 2
# Get the sha256 value of the latest version
latest_kernel_sha256="$(
curl -fsSL -m 10 \
${kernel_api}/releases/expanded_assets/kernel_${kernel_tag} |
awk -v pattern="${latest_version}\.tar\.gz" -v RS='</li>' '$0 ~ pattern { print $0 "</li>"; exit }' |
grep -o 'value="sha256:[^"]*' | sed 's/value="sha256://'
)"
[[ -n "${latest_kernel_sha256}" ]] && tolog "02.05 Kernel sha256: ${latest_kernel_sha256}"
if [[ "${latest_version}" == "${kernel_uname}" ]]; then
tolog "02.06 Already the latest version, no need to update." "1"
sleep 2
else
tolog '<input type="button" class="cbi-button cbi-button-reload" value="Download" onclick="return b_check_kernel(this, '"'download_${latest_version}_${latest_kernel_sha256}'"')"/> Latest version: '${latest_version}'' "1"
fi
exit 0
}
# Step 3: Download the latest kernel version
download_kernel() {
tolog "03. Start download the kernel file."
if [[ "${download_version}" == "download_"* ]]; then
tolog "03.01 Start downloading..."
else
tolog "03.01 Invalid parameter" "1"
fi
# Get the kernel file name
kernel_file_name="$(echo "${download_version}" | cut -d '_' -f2)"
# Restore converted characters in file names(%2B to +)
kernel_file_name="${kernel_file_name//%2B/+}"
# Get the sha256 value
kernel_file_sha256="$(echo "${download_version}" | cut -d '_' -f3)"
# Delete other residual kernel files
rm -f ${KERNEL_DOWNLOAD_PATH}/*.tar.gz
rm -f ${KERNEL_DOWNLOAD_PATH}/sha256sums
rm -rf ${KERNEL_DOWNLOAD_PATH}/${kernel_file_name}*
kernel_down_from="https://github.com/${kernel_repo}/releases/download/kernel_${kernel_tag}/${kernel_file_name}.tar.gz"
curl -fsSL "${kernel_down_from}" -o ${KERNEL_DOWNLOAD_PATH}/${kernel_file_name}.tar.gz
[[ "${?}" -ne "0" ]] && tolog "03.02 The kernel download failed." "1"
# Verify sha256
if [[ -n "${kernel_file_sha256}" ]]; then
tolog "03.03 Perform sha256 checksum verification."
download_kernel_sha256sums="$(sha256sum ${KERNEL_DOWNLOAD_PATH}/${kernel_file_name}.tar.gz | awk '{print $1}')"
if [[ "${kernel_file_sha256}" != "${download_kernel_sha256sums}" ]]; then
tolog "03.03.01 sha256sum verification mismatched." "1"
else
tolog "03.03.02 sha256sum verification succeeded."
fi
fi
# Decompress the kernel package
tolog "03.04 Start decompressing the kernel package..."
tar -xf ${KERNEL_DOWNLOAD_PATH}/${kernel_file_name}.tar.gz -C ${KERNEL_DOWNLOAD_PATH}
[[ "${?}" -ne "0" ]] && tolog "03.05 Kernel decompression failed." "1"
mv -f ${KERNEL_DOWNLOAD_PATH}/${kernel_file_name}/* ${KERNEL_DOWNLOAD_PATH}/
sync && sleep 3
# Delete the downloaded kernel file
rm -f ${KERNEL_DOWNLOAD_PATH}/${kernel_file_name}.tar.gz
rm -rf ${KERNEL_DOWNLOAD_PATH}/${kernel_file_name}
tolog "03.06 The kernel is ready, you can update."
sleep 2
#echo '<a href="javascript:;" onclick="return amlogic_kernel(this)">Update</a>' >$START_LOG
tolog '<input type="button" class="cbi-button cbi-button-reload" value="Update" onclick="return amlogic_kernel(this)"/>' "1"
exit 0
}
getopts 'cd' opts
case "${opts}" in
c | check)
check_kernel
;;
* | download)
download_kernel
;;
esac
@@ -0,0 +1,170 @@
#!/bin/bash
#==================================================================
# This file is licensed under the terms of the GNU General Public
# License version 2. This program is licensed "as is" without any
# warranty of any kind, whether express or implied.
#
# This file is a part of the luci-app-amlogic plugin
# https://github.com/ophub/luci-app-amlogic
#
# Description: Check and update luci-app-amlogic plugin
# Copyright (C) 2021- https://github.com/unifreq/openwrt_packit
# Copyright (C) 2021- https://github.com/ophub/luci-app-amlogic
#==================================================================
# Set a fixed value
TMP_CHECK_DIR="/tmp/amlogic"
AMLOGIC_SOC_FILE="/etc/flippy-openwrt-release"
START_LOG="${TMP_CHECK_DIR}/amlogic_check_plugin.log"
RUNNING_LOG="${TMP_CHECK_DIR}/amlogic_running_script.log"
LOG_FILE="${TMP_CHECK_DIR}/amlogic.log"
support_platform=("allwinner" "rockchip" "amlogic" "qemu-aarch64")
LOGTIME="$(date "+%Y-%m-%d %H:%M:%S")"
[[ -d ${TMP_CHECK_DIR} ]] || mkdir -p ${TMP_CHECK_DIR}
rm -f ${TMP_CHECK_DIR}/*.ipk 2>/dev/null && sync
rm -f ${TMP_CHECK_DIR}/sha256sums 2>/dev/null && sync
# Clean the running log
clean_running() {
echo -e '' >${RUNNING_LOG} 2>/dev/null && sync
}
# Add log
tolog() {
echo -e "${1}" >${START_LOG}
echo -e "${LOGTIME} ${1}" >>${LOG_FILE}
[[ -n "${2}" && "${2}" -eq "1" ]] && clean_running && exit 1
}
# Check running scripts, prohibit running concurrently
this_running_log="1@Plugin update in progress, try again later!"
running_script="$(cat ${RUNNING_LOG} 2>/dev/null | xargs)"
if [[ -n "${running_script}" ]]; then
run_num="$(echo "${running_script}" | awk -F "@" '{print $1}')"
run_log="$(echo "${running_script}" | awk -F "@" '{print $2}')"
fi
if [[ -n "${run_log}" && "${run_num}" -ne "1" ]]; then
echo -e "${run_log}" >${START_LOG} 2>/dev/null && sync && exit 1
else
echo -e "${this_running_log}" >${RUNNING_LOG} 2>/dev/null && sync
fi
# Check release file
if [[ -s "${AMLOGIC_SOC_FILE}" ]]; then
source "${AMLOGIC_SOC_FILE}" 2>/dev/null
PLATFORM="${PLATFORM}"
else
tolog "${AMLOGIC_SOC_FILE} file is missing!" "1"
fi
if [[ -z "${PLATFORM}" || -z "$(echo "${support_platform[@]}" | grep -w "${PLATFORM}")" ]]; then
tolog "Missing [ PLATFORM ] value in ${AMLOGIC_SOC_FILE} file." "1"
fi
tolog "PLATFORM: [ ${PLATFORM} ]"
sleep 2
# 01. Query local version information
tolog "01. Query current version information."
# If neither opkg nor apk found, set package_manager to empty
package_manager=""
current_plugin_v=""
if command -v opkg >/dev/null 2>&1; then
# System has opkg
package_manager="ipk"
# Important: Add cut to handle versions like X.Y.Z-r1, ensuring consistent output
current_plugin_v="$(opkg list-installed | grep '^luci-app-amlogic' | awk '{print $3}' | cut -d'-' -f1)"
elif command -v apk >/dev/null 2>&1; then
# System has apk
package_manager="apk"
current_plugin_v="$(apk list --installed | grep '^luci-app-amlogic' | awk '{print $1}' | cut -d'-' -f4)"
fi
# Check if we successfully found the plugin
if [[ -z "${package_manager}" || -z "${current_plugin_v}" ]]; then
tolog "01.01 Plugin 'luci-app-amlogic' not found or package manager unknown." "1"
else
tolog "01.01 Using [${package_manager}]. Current version: ${current_plugin_v}"
fi
sleep 2
# 02. Check the version on the server
tolog "02. Start querying plugin version..."
# Get the latest version
latest_version="$(
curl -fsSL -m 10 \
https://github.com/ophub/luci-app-amlogic/releases |
grep -oE 'expanded_assets/[0-9]+.[0-9]+.[0-9]+(-[0-9]+)?' | sed 's|expanded_assets/||g' |
sort -urV | head -n 1
)"
if [[ -z "${latest_version}" ]]; then
tolog "02.01 Query failed, please try again." "1"
else
tolog "02.01 current version: ${current_plugin_v}, Latest version: ${latest_version}"
sleep 2
fi
# Compare the version and download the latest version
if [[ "${current_plugin_v}" == "${latest_version}" ]]; then
tolog "02.02 Already the latest version, no need to update." "1"
else
tolog "02.03 New version found. Preparing to download for [${package_manager}]..."
download_repo="https://github.com/ophub/luci-app-amlogic/releases/download"
# Intelligent File Discovery
plugin_file_name=""
lang_file_list=""
# Method 1: Use GitHub API if 'jq' is installed (Preferred Method)
if command -v jq >/dev/null 2>&1; then
tolog "Using GitHub API with jq to find package files."
api_url="https://api.github.com/repos/ophub/luci-app-amlogic/releases/tags/${latest_version}"
# Fetch all asset names from the API
asset_list="$(curl -fsSL -m 15 "${api_url}" | jq -r '.assets[].name' | xargs)"
if [[ -n "${asset_list}" ]]; then
# Discover exact filenames using regular expressions from the asset list
plugin_file_name="$(echo "${asset_list}" | tr ' ' '\n' | grep -oE "^luci-app-amlogic.*${package_manager}$" | head -n 1)"
lang_file_list=($(echo "${asset_list}" | tr ' ' '\n' | grep -oE "^luci-i18n-amlogic.*${package_manager}$"))
else
tolog "Warning: Failed to fetch data from GitHub API." "1"
fi
else
tolog "jq not found, Aborting." "1"
fi
# Validation and Download
if [[ -z "${plugin_file_name}" || "${#lang_file_list[@]}" -eq "0" ]]; then
tolog "02.03.2 Could not discover plugin(.${package_manager}) in the release. Aborting." "1"
fi
tolog "Found plugin file: ${plugin_file_name}"
tolog "Found language file: $(echo ${lang_file_list[@]} | xargs)"
# Download the main plugin file
plugin_full_url="${download_repo}/${latest_version}/${plugin_file_name}"
tolog "02.04 Downloading main plugin..."
curl -fsSL "${plugin_full_url}" -o "${TMP_CHECK_DIR}/${plugin_file_name}"
[[ "${?}" -ne "0" ]] && tolog "02.04 Plugin [ ${plugin_file_name} ] download failed." "1"
# Download language packs
for langfile in "${lang_file_list[@]}"; do
lang_full_url="${download_repo}/${latest_version}/${langfile}"
tolog "02.05 Downloading language pack [ ${langfile} ]..."
curl -fsSL "${lang_full_url}" -o "${TMP_CHECK_DIR}/${langfile}"
[[ "${?}" -ne "0" ]] && tolog "02.05 Language pack [ ${langfile} ] download failed." "1"
done
sync && sleep 2
fi
tolog "03. The plug is ready, you can update."
sleep 2
tolog '<input type="button" class="cbi-button cbi-button-reload" value="Update" onclick="return amlogic_plugin(this)"/> Latest version: '${latest_version}'' "1"
exit 0
@@ -0,0 +1,11 @@
{
"luci-app-amlogic": {
"description": "Grant UCI access for luci-app-amlogic",
"read": {
"uci": [ "amlogic" ]
},
"write": {
"uci": [ "amlogic" ]
}
}
}
@@ -0,0 +1,4 @@
{
"config": "amlogic",
"init": "amlogic"
}