From 776a5adc2cc513b86df5b35715e1d10ef21f3e26 Mon Sep 17 00:00:00 2001 From: vasilito Date: Tue, 30 Jun 2026 14:31:04 +0300 Subject: [PATCH] Add installer source: Hiperiso2Disk, WebUI, Plugson launchers --- src/installer/CreatePersistentImg.sh | 140 ++++ src/installer/ExtendPersistentImg.sh | 145 ++++ src/installer/Hiperiso.sh | 49 ++ src/installer/Hiperiso2Disk.sh | 104 +++ src/installer/HiperisoGtk.sh | 27 + src/installer/HiperisoPlugson.sh | 227 ++++++ src/installer/HiperisoQt.sh | 32 + src/installer/HiperisoWeb.sh | 130 ++++ src/installer/hisocli | 10 + src/installer/hisolnk | 10 + src/installer/tool/HiperisoWorker.sh | 650 ++++++++++++++++++ .../tool/create_hiperiso_iso_part_dm.sh | 38 + src/installer/tool/hiperiso_lib.sh | 516 ++++++++++++++ 13 files changed, 2078 insertions(+) create mode 100644 src/installer/CreatePersistentImg.sh create mode 100644 src/installer/ExtendPersistentImg.sh create mode 100755 src/installer/Hiperiso.sh create mode 100644 src/installer/Hiperiso2Disk.sh create mode 100755 src/installer/HiperisoGtk.sh create mode 100644 src/installer/HiperisoPlugson.sh create mode 100755 src/installer/HiperisoQt.sh create mode 100644 src/installer/HiperisoWeb.sh create mode 100755 src/installer/hisocli create mode 100755 src/installer/hisolnk create mode 100644 src/installer/tool/HiperisoWorker.sh create mode 100644 src/installer/tool/create_hiperiso_iso_part_dm.sh create mode 100644 src/installer/tool/hiperiso_lib.sh diff --git a/src/installer/CreatePersistentImg.sh b/src/installer/CreatePersistentImg.sh new file mode 100644 index 0000000..1d1eb66 --- /dev/null +++ b/src/installer/CreatePersistentImg.sh @@ -0,0 +1,140 @@ +#!/bin/bash + +size=1024 +fstype=ext4 +label=casper-rw +config='' +outputfile=persistence.dat + +print_usage() { + echo 'Usage: sudo ./CreatePersistentImg.sh [ -s size ] [ -t fstype ] [ -l LABEL ] [ -c CFG ] [ -e ]' + echo ' OPTION: (optional)' + echo ' -s size in MB, default is 1024' + echo ' -t filesystem type, default is ext4 ext2/ext3/ext4/xfs are supported now' + echo ' -l label, default is casper-rw' + echo ' -c configfile name inside the persistence file. File content is "/ union"' + echo ' -o outputfile name, default is persistence.dat' + echo ' -e enable encryption, disabled by default (only few distros support this)' + echo '' +} + +print_err() { + echo "" + echo "$*" + echo "" +} + +uid=$(id -u) +if [ $uid -ne 0 ]; then + print_err "Please use sudo or run the script as root." + exit 1 +fi + +while [ -n "$1" ]; do + if [ "$1" = "-s" ]; then + shift + size=$1 + elif [ "$1" = "-t" ]; then + shift + fstype=$1 + elif [ "$1" = "-l" ]; then + shift + label=$1 + elif [ "$1" = "-c" ]; then + shift + config=$1 + elif [ "$1" = "-o" ]; then + shift + outputfile=$1 + elif [ "$1" = "-e" ]; then + read -s -p "Encryption passphrase: " passphrase + echo + elif [ "$1" = "-h" ] || [ "$1" = "--help" ]; then + print_usage + exit 0 + else + print_usage + exit 1 + fi + shift +done + + +# check label +if [ -z "$label" ]; then + echo "The label can NOT be empty." + exit 1 +fi + +# check size +if echo $size | grep -q "^[0-9][0-9]*$"; then + vtMinSize=1 + if echo $fstype | grep -q '^xfs$'; then + vtMinSize=16 + fi + + if [ $size -lt $vtMinSize ]; then + echo "size too small ($size)" + exit 1 + fi +else + echo "Invalid size $size" + exit 1 +fi + + +# check file system type +# nodiscard must be set for ext2/3/4 +# -K must be set for xfs +if echo $fstype | grep -q '^ext[234]$'; then + fsopt='-E nodiscard' +elif [ "$fstype" = "xfs" ]; then + fsopt='-K' +else + echo "unsupported file system $fstype" + exit 1 +fi + +if [ "$outputfile" != "persistence.dat" ]; then + mkdir -p "$(dirname "$outputfile")" +fi + +# 00->ff avoid sparse file +dd if=/dev/zero bs=1M count=$size | tr '\000' '\377' > "$outputfile" +sync + +freeloop=$(losetup -f) + +losetup $freeloop "$outputfile" + +if [ ! -z "$passphrase" ]; then + printf "$passphrase" | cryptsetup -q --verbose luksFormat $freeloop - + printf "$passphrase" | cryptsetup -q --verbose luksOpen $freeloop persist_decrypted - + _freeloop=$freeloop + freeloop="/dev/mapper/persist_decrypted" +fi + +mkfs -t $fstype $fsopt -L $label $freeloop + +sync + +if [ -n "$config" ]; then + if [ -d ./persist_tmp_mnt ]; then + rm -rf ./persist_tmp_mnt + fi + + mkdir ./persist_tmp_mnt + if mount $freeloop ./persist_tmp_mnt; then + echo '/ union' > ./persist_tmp_mnt/$config + sync + umount ./persist_tmp_mnt + fi + rm -rf ./persist_tmp_mnt +fi + +if [ ! -z "$passphrase" ]; then + cryptsetup luksClose $freeloop + freeloop=$_freeloop +fi + +losetup -d $freeloop diff --git a/src/installer/ExtendPersistentImg.sh b/src/installer/ExtendPersistentImg.sh new file mode 100644 index 0000000..5f8b852 --- /dev/null +++ b/src/installer/ExtendPersistentImg.sh @@ -0,0 +1,145 @@ +#!/bin/bash + +print_usage() { + echo 'Usage: ExtendPersistentImg.sh file size' + echo ' file persistent dat file' + echo ' size extend size in MB' + echo 'Examples:' + echo ' sh ExtendPersistentImg.sh ubuntu.dat 2048 - This command would extend ubuntu.dat by 2048MB (2GB)' + echo ' sh ExtendPersistentImg.sh ubuntu.dat -2048 - This command reduces ubuntu.dat by 2048MB (-2GB)' + echo '' +} + +if [ -z "$1" -o "$1" = "-h" ]; then + print_usage + exit 1 +fi + +if [ -z "$2" ]; then + print_usage + exit 1 +fi + +uid=$(id -u) +if [ $uid -ne 0 ]; then + print_err "Please use sudo or run the script as root." + exit 1 +fi + +if [ "$1" = "__vbash__" ]; then + shift +else + if readlink /bin/sh | grep -q bash; then + : + else + exec /bin/bash $0 "__vbash__" "$@" + fi +fi + + +file=$1 +size=$2 + +if [ ! -f "$file" ]; then + echo "$file not exist." + exit 1 +fi + +if echo $size | grep -q "^-"; then + mode="Shrink" + size=${size:1} +else + mode="Extend" +fi + +if echo $size | grep -q "[^0-9]"; then + print_usage + exit 1 +fi + +fsize=$(stat -c '%s' $file) + +fsmod=$(expr $fsize % 1024) +if [ $fsmod -ne 0 ]; then + echo "File size of $file is not aligned by 1MB, please check." + exit 1 +fi + + +fsMB=$(expr $fsize / 1024 / 1024) + +if [ "$mode" = "Extend" ]; then + total=$(expr $fsMB + $size) +else + if [ $fsMB -le $size ]; then + echo "File size of $file is less than ${size}MB." + exit 1 + fi + total=$(expr $fsMB - $size) +fi + + +magic=$(hexdump -n3 -e '3/1 "%02X"' $file) +if [ "$magic" = "584653" ]; then + if [ "$mode" = "Shrink" ]; then + echo "Shrink is not supported for XFS filesystem." + exit 1 + fi + + if which xfs_growfs >/dev/null 2>&1; then + cmd=xfs_growfs + else + echo 'xfs_growfs not found, please install xfsprogs first' + exit 1 + fi +else + if which resize2fs >/dev/null 2>&1; then + cmd=resize2fs + else + echo 'resize2fs not found, please install e2fsprogs first' + exit 1 + fi +fi + +if [ "$mode" = "Extend" ]; then + echo "$mode dat file... (current is ${fsMB}MB, append ${size}MB, total ${total}MB)" + dd if=/dev/zero bs=1M count=$size status=none >> "$file" + sync +else + echo "$mode dat file... (current is ${fsMB}MB, reduce ${size}MB, finally ${total}MB)" +fi + + +freeloop=$(losetup -f) +losetup $freeloop "$file" + +if [ "$cmd" = "resize2fs" ]; then + echo "$mode ext filesystem by resize2fs ..." + echo "resize2fs $freeloop ${total}M" + e2fsck -f $freeloop + resize2fs $freeloop ${total}M + ret=$? +else + echo "$mode xfs filesystem by xfs_growfs ..." + tmpdir=$(mktemp -d) + mount $freeloop $tmpdir + xfs_growfs $freeloop + ret=$? + umount $tmpdir && rm -rf $tmpdir +fi + +losetup -d $freeloop + +if [ $ret -eq 0 -a "$mode" = "Shrink" ]; then + echo "truncate persistent file ..." + truncate "$file" -s ${total}M + ret=$? +fi + +echo "" +if [ $ret -eq 0 ]; then + echo "======= SUCCESS =========" +else + echo "======= FAILED =========" +fi +echo "" diff --git a/src/installer/Hiperiso.sh b/src/installer/Hiperiso.sh new file mode 100755 index 0000000..df4829e --- /dev/null +++ b/src/installer/Hiperiso.sh @@ -0,0 +1,49 @@ +#!/bin/sh +set -e + +SCRIPT_PATH="$0" +case "$SCRIPT_PATH" in + /*) : ;; + *) SCRIPT_PATH="$(pwd)/$SCRIPT_PATH" ;; +esac + +SCRIPT_DIR=$(dirname "$SCRIPT_PATH") +cd "$SCRIPT_DIR" + +if uname -m | grep -E -q 'aarch64|arm64'; then + TOOLDIR=aarch64 +else + TOOLDIR=x86_64 +fi + +GUI_BIN="" +if [ -x "$SCRIPT_DIR/tool/$TOOLDIR/Hiperiso2Disk.qt5" ]; then + GUI_BIN="$SCRIPT_DIR/tool/$TOOLDIR/Hiperiso2Disk.qt5" +elif [ -x "$SCRIPT_DIR/tool/$TOOLDIR/Hiperiso2Disk.gtk3" ]; then + GUI_BIN="$SCRIPT_DIR/tool/$TOOLDIR/Hiperiso2Disk.gtk3" +fi + +if [ -z "$GUI_BIN" ]; then + printf '%s\n' 'No GUI launcher found in this package.' >&2 + exit 1 +fi + +if [ "$(id -u)" -eq 0 ]; then + if [ -z "$XDG_RUNTIME_DIR" ] || [ ! -d "$XDG_RUNTIME_DIR" ] || [ ! -O "$XDG_RUNTIME_DIR" ]; then + export XDG_RUNTIME_DIR=/tmp/runtime-root + mkdir -p "$XDG_RUNTIME_DIR" + chmod 700 "$XDG_RUNTIME_DIR" 2>/dev/null || true + fi + exec "$GUI_BIN" "$@" +fi + +if command -v pkexec >/dev/null 2>&1; then + exec pkexec env DISPLAY="$DISPLAY" XAUTHORITY="$XAUTHORITY" XDG_RUNTIME_DIR=/tmp/runtime-root "$GUI_BIN" "$@" +fi + +if command -v sudo >/dev/null 2>&1; then + exec sudo env DISPLAY="$DISPLAY" XAUTHORITY="$XAUTHORITY" XDG_RUNTIME_DIR=/tmp/runtime-root "$GUI_BIN" "$@" +fi + +printf '%s\n' 'Need pkexec or sudo to start the GUI with root privileges.' >&2 +exit 1 diff --git a/src/installer/Hiperiso2Disk.sh b/src/installer/Hiperiso2Disk.sh new file mode 100644 index 0000000..b54c798 --- /dev/null +++ b/src/installer/Hiperiso2Disk.sh @@ -0,0 +1,104 @@ +#!/bin/sh + +OLDDIR=$(pwd) + +if ! [ -f ./tool/hiperiso_lib.sh ]; then + if [ -f ${0%Hiperiso2Disk.sh}/tool/hiperiso_lib.sh ]; then + cd ${0%Hiperiso2Disk.sh} + fi +fi + +if [ -f ./hiperiso/version ]; then + curver=$(cat ./hiperiso/version) +fi + +if uname -m | grep -E -q 'aarch64|arm64'; then + export TOOLDIR=aarch64 +elif uname -m | grep -E -q 'x86_64|amd64'; then + export TOOLDIR=x86_64 +elif uname -m | grep -E -q 'mips64'; then + export TOOLDIR=mips64el +else + export TOOLDIR=i386 +fi +export PATH="$OLDDIR/tool/$TOOLDIR:$PATH" + + +echo '' +echo '**********************************************' +echo " Hiperiso: $curver $TOOLDIR" +echo " longpanda admin@hiperiso.net" +echo " https://www.hiperiso.net" +echo '**********************************************' +echo '' + + +if ! [ -f ./boot/boot.img ]; then + if [ -d ./grub ]; then + echo "Don't run Hiperiso2Disk.sh here, please download the released install package, and run the script in it." + else + echo "Please run under the correct directory!" + fi + exit 1 +fi + +for req in ./boot/core.img.xz ./hiperiso/hiperiso.disk.img.xz ./tool/HiperisoWorker.sh; do + if ! [ -f "$req" ]; then + echo "Required file missing: $req" + exit 1 + fi +done + +echo "############# Hiperiso2Disk $* [$TOOLDIR] ################" >> ./log.txt +date >> ./log.txt + +#decompress tool +echo "decompress tools" >> ./log.txt +cd ./tool/$TOOLDIR + +ls *.xz > /dev/null 2>&1 +if [ $? -eq 0 ]; then + [ -f ./xzcat ] && chmod +x ./xzcat + + for file in $(ls *.xz); do + echo "decompress $file" >> ./log.txt + xzcat $file > ${file%.xz} + [ -f ./${file%.xz} ] && chmod +x ./${file%.xz} + [ -f ./$file ] && rm -f ./$file + done +fi + +#use static linked mkexfatfs for musl-libc environment +if [ -f mkexfatfs_static ]; then + if ldd --version 2>&1 | grep -qi musl; then + mv mkexfatfs mkexfatfs_shared + mv mkexfatfs_static mkexfatfs + else + if ./mkexfatfs -V > /dev/null 2>&1; then + echo "mkexfatfs can not run, check static version" >> ./log.txt + else + if ./mkexfatfs_static -V > /dev/null 2>&1; then + echo "Use static version of mkexfatfs" >> ./log.txt + mv mkexfatfs mkexfatfs_shared + mv mkexfatfs_static mkexfatfs + fi + fi + fi +fi + +cd ../../ +chmod +x -R ./tool/$TOOLDIR + + +if [ -f /bin/bash ]; then + /bin/bash ./tool/HiperisoWorker.sh $* +else + ash ./tool/HiperisoWorker.sh $* +fi + +if [ -n "$OLDDIR" ]; then + CURDIR=$(pwd) + if [ "$CURDIR" != "$OLDDIR" ]; then + cd "$OLDDIR" + fi +fi diff --git a/src/installer/HiperisoGtk.sh b/src/installer/HiperisoGtk.sh new file mode 100755 index 0000000..32856c8 --- /dev/null +++ b/src/installer/HiperisoGtk.sh @@ -0,0 +1,27 @@ +#!/bin/sh +set -e +SCRIPT_PATH="$0" +case "$SCRIPT_PATH" in + /*) : ;; + *) SCRIPT_PATH="$(pwd)/$SCRIPT_PATH" ;; +esac +SCRIPT_DIR=$(dirname "$SCRIPT_PATH") +cd "$SCRIPT_DIR" + +if uname -m | grep -E -q 'aarch64|arm64'; then + TOOLDIR=aarch64 +else + TOOLDIR=x86_64 +fi + +if [ "$(id -u)" -eq 0 ]; then + exec ./tool/$TOOLDIR/Hiperiso2Disk.gtk3 "$@" +fi +if command -v pkexec >/dev/null 2>&1; then + exec pkexec env DISPLAY="$DISPLAY" XAUTHORITY="$XAUTHORITY" "$SCRIPT_DIR/tool/$TOOLDIR/Hiperiso2Disk.gtk3" "$@" +fi +if command -v sudo >/dev/null 2>&1; then + exec sudo env DISPLAY="$DISPLAY" XAUTHORITY="$XAUTHORITY" "$SCRIPT_DIR/tool/$TOOLDIR/Hiperiso2Disk.gtk3" "$@" +fi +printf '%s\n' 'Need pkexec or sudo to start the GTK GUI with root privileges.' >&2 +exit 1 diff --git a/src/installer/HiperisoPlugson.sh b/src/installer/HiperisoPlugson.sh new file mode 100644 index 0000000..e97e1b2 --- /dev/null +++ b/src/installer/HiperisoPlugson.sh @@ -0,0 +1,227 @@ +#!/bin/bash + +. ./tool/hiperiso_lib.sh + +print_usage() { + echo 'Usage: sudo bash HiperisoPlugson.sh [OPTION] /dev/sdX' + echo ' OPTION: (optional)' + echo ' -H x.x.x.x http server IP address (default is 127.0.0.1)' + echo ' -P PORT http server PORT (default is 24681)' + echo ' -h print this help' + echo '' +} + +uid=$(id -u) +if [ $uid -ne 0 ]; then + echo "Please use sudo or run the script as root." + exit 1 +fi + +if [ "$1" = "__vbash__" ]; then + shift +else + if readlink /bin/sh | grep -q bash; then + : + else + exec /bin/bash $0 "__vbash__" "$@" + fi +fi + +OLDDIR=$(pwd) + +machine=$(uname -m) +if echo $machine | grep -E -q 'aarch64|arm64'; then + TOOLDIR=aarch64 +elif echo $machine | grep -E -q 'x86_64|amd64'; then + TOOLDIR=x86_64 +elif echo $machine | grep -E -q 'mips64'; then + TOOLDIR=mips64el +elif echo $machine | grep -E -q 'i[3-6]86'; then + TOOLDIR=i386 +else + echo "Unsupported machine type $machine" + exit 1 +fi + + +if ! [ -f "$OLDDIR/tool/$TOOLDIR/Plugson" ]; then + echo "Please run under the correct directory!" + exit 1 +fi + +echo "############# HiperisoPlugson $* [$TOOLDIR] ################" >> ./HiperisoPlugson.log +date >> ./HiperisoPlugson.log + +echo "decompress tools" >> ./HiperisoPlugson.log +cd ./tool/$TOOLDIR + +ls *.xz > /dev/null 2>&1 +if [ $? -eq 0 ]; then + [ -f ./xzcat ] && chmod +x ./xzcat + + for file in $(ls *.xz); do + echo "decompress $file" >> ./HiperisoPlugson.log + xzcat $file > ${file%.xz} + [ -f ./${file%.xz} ] && chmod +x ./${file%.xz} + [ -f ./$file ] && rm -f ./$file + done +fi + +cd ../../ +chmod +x -R ./tool/$TOOLDIR + +if ! [ -f "$OLDDIR/tool/$TOOLDIR/Plugson" ]; then + echo "$OLDDIR/tool/$TOOLDIR/Plugson does not exist!" + exit 1 +fi + + +PATH=./tool/$TOOLDIR:$PATH + +HOST="127.0.0.1" +PORT=24681 + +while [ -n "$1" ]; do + if [ "$1" = "-h" ] || [ "$1" = "--help" ]; then + print_usage + exit 0 + elif [ "$1" = "-H" ]; then + shift + if echo $1 | grep -q '[0-9]*\.[0-9]*\.[0-9]*\.[0-9]*'; then + HOST="$1" + else + echo "Invalid host $1" + exit 1 + fi + elif [ "$1" = "-P" ]; then + shift + if [ $1 -gt 0 -a $1 -le 65535 ]; then + PORT="$1" + else + echo "Invalid port $1" + exit 1 + fi + else + DISK=$1 + fi + + shift +done + +if [ -z "$DISK" ]; then + print_usage + exit 0 +fi + +if ps -ef | grep "tool/$TOOLDIR/Plugson.*$HOST.*$PORT" | grep -q -v grep; then + echo "Another hiperiso server is running now, please close it first." + exit 1 +fi + +if echo $DISK | grep -q "[a-z]d[a-z][1-9]"; then + DISK=${DISK:0:-1} +fi + +if echo $DISK | grep -E -q "/dev/nvme|/dev/mmcblk/dev/nbd"; then + if echo $DISK | grep -q "p[1-9]$"; then + DISK=${DISK:0:-2} + fi +fi + + +if [ ! -b "$DISK" ]; then + echo "$DISK does NOT exist." + exit 1 +fi + + +version=$(get_disk_hiperiso_version $DISK) +if [ $? -eq 0 ]; then + echo "Hiperiso version in Disk: $version" + + vtPart1Type=$(dd if=$DISK bs=1 count=1 skip=450 status=none | hexdump -n1 -e '1/1 "%02X"') + if [ "$vtPart1Type" = "EE" ]; then + echo "Disk Partition Style : GPT" + partstyle=1 + else + echo "Disk Partition Style : MBR" + partstyle=0 + fi + + if check_disk_secure_boot $DISK; then + echo "Secure Boot Support : YES" + secureboot=1 + else + echo "Secure Boot Support : NO" + secureboot=0 + fi +else + echo "$DISK is NOT Hiperiso disk." + exit 1 +fi + +PART1=$(get_disk_part_name $DISK 1) + +if grep -q "^$PART1 " /proc/mounts; then + mtpnt=$(grep "^$PART1 " /proc/mounts | awk '{print $2}' | sed 's/\\040/ /g') + fstype=$(grep "^$PART1 " /proc/mounts | awk '{print $3}') + + if echo $fstype | grep -q -i 'fuse'; then + if hexdump -C -n 16 $PART1 | grep -q -i "EXFAT"; then + fstype="exFAT" + elif hexdump -C -n 16 $PART1 | grep -q -i "NTFS"; then + fstype="NTFS" + fi + fi + + echo "$PART1 is mounted at $mtpnt $fstype" +else + echo "$PART1 is NOT mounted, please mount it first!" + exit 1 +fi + +if [ -d "$mtpnt/hiperiso" ]; then + echo "hiperiso directory exist OK" +else + echo "create hiperiso directory" + mkdir -p "$mtpnt/hiperiso" + if [ -d "$mtpnt/hiperiso" ]; then + chmod -R 0755 "$mtpnt/hiperiso" + else + echo "Failed to create directory $mtpnt/hiperiso" + exit 1 + fi +fi + + +#change current directory to Hiperiso disk +cd "$mtpnt" +"$OLDDIR/tool/$TOOLDIR/Plugson" "$HOST" "$PORT" "$OLDDIR" "$DISK" $version "$fstype" $partstyle $secureboot & +wID=$! +sleep 1 + +if [ -f /proc/$wID/maps ]; then + echo "" + echo "===============================================================" + if [ "$LANG" = "zh_CN.UTF-8" ]; then + echo " Hiperiso Plugson Server 已经启动 ..." + echo " 请打开浏览器,访问 http://${HOST}:${PORT}" + else + echo " Hiperiso Plugson Server is running ..." + echo " Please open your browser and visit http://${HOST}:${PORT}" + fi + echo "===============================================================" + echo "" + echo "################## Press Ctrl + C to exit #####################" + echo "" + + wait $wID +fi + + +if [ -n "$OLDDIR" ]; then + CURDIR=$(pwd) + if [ "$CURDIR" != "$OLDDIR" ]; then + cd "$OLDDIR" + fi +fi diff --git a/src/installer/HiperisoQt.sh b/src/installer/HiperisoQt.sh new file mode 100755 index 0000000..6f933c7 --- /dev/null +++ b/src/installer/HiperisoQt.sh @@ -0,0 +1,32 @@ +#!/bin/sh +set -e +SCRIPT_PATH="$0" +case "$SCRIPT_PATH" in + /*) : ;; + *) SCRIPT_PATH="$(pwd)/$SCRIPT_PATH" ;; +esac +SCRIPT_DIR=$(dirname "$SCRIPT_PATH") +cd "$SCRIPT_DIR" + +if uname -m | grep -E -q 'aarch64|arm64'; then + TOOLDIR=aarch64 +else + TOOLDIR=x86_64 +fi + +if [ "$(id -u)" -eq 0 ]; then + if [ -z "$XDG_RUNTIME_DIR" ] || [ ! -d "$XDG_RUNTIME_DIR" ] || [ ! -O "$XDG_RUNTIME_DIR" ]; then + export XDG_RUNTIME_DIR=/tmp/runtime-root + mkdir -p "$XDG_RUNTIME_DIR" + chmod 700 "$XDG_RUNTIME_DIR" 2>/dev/null || true + fi + exec ./tool/$TOOLDIR/Hiperiso2Disk.qt5 "$@" +fi +if command -v pkexec >/dev/null 2>&1; then + exec pkexec env DISPLAY="$DISPLAY" XAUTHORITY="$XAUTHORITY" XDG_RUNTIME_DIR=/tmp/runtime-root "$SCRIPT_DIR/tool/$TOOLDIR/Hiperiso2Disk.qt5" "$@" +fi +if command -v sudo >/dev/null 2>&1; then + exec sudo env DISPLAY="$DISPLAY" XAUTHORITY="$XAUTHORITY" XDG_RUNTIME_DIR=/tmp/runtime-root "$SCRIPT_DIR/tool/$TOOLDIR/Hiperiso2Disk.qt5" "$@" +fi +printf '%s\n' 'Need pkexec or sudo to start the Qt GUI with root privileges.' >&2 +exit 1 diff --git a/src/installer/HiperisoWeb.sh b/src/installer/HiperisoWeb.sh new file mode 100644 index 0000000..cee2c89 --- /dev/null +++ b/src/installer/HiperisoWeb.sh @@ -0,0 +1,130 @@ +#!/bin/bash + +print_usage() { + echo 'Usage: HiperisoWeb.sh [ OPTION ]' + echo ' OPTION: (optional)' + echo ' -H x.x.x.x http server IP address (default is 127.0.0.1)' + echo ' -p PORT http server PORT (default is 24680)' + echo ' -h print this help' + echo '' +} + +print_err() { + echo "" + echo "$*" + echo "" +} + +uid=$(id -u) +if [ $uid -ne 0 ]; then + print_err "Please use sudo or run the script as root." + exit 1 +fi + +OLDDIR=$(pwd) + +if uname -m | grep -E -q 'aarch64|arm64'; then + TOOLDIR=aarch64 +elif uname -m | grep -E -q 'x86_64|amd64'; then + TOOLDIR=x86_64 +elif uname -m | grep -E -q 'mips64'; then + TOOLDIR=mips64el +else + TOOLDIR=i386 +fi + +if [ ! -f ./tool/$TOOLDIR/HiperisoWeb ]; then + if [ -f ${0%HiperisoWeb.sh}/tool/$TOOLDIR/HiperisoWeb ]; then + cd ${0%HiperisoWeb.sh} + fi +fi + +PATH=./tool/$TOOLDIR:$PATH + +if [ ! -f ./boot/boot.img ]; then + if [ -d ./grub ]; then + echo "Don't run HiperisoWeb.sh here, please download the released install package, and run the script in it." + else + echo "Current directory is $PWD" + echo "Please run under the correct directory!" + fi + exit 1 +fi + +HOST="127.0.0.1" +PORT=24680 + +while [ -n "$1" ]; do + if [ "$1" = "-h" ] || [ "$1" = "--help" ]; then + print_usage + exit 0 + elif [ "$1" = "-H" ]; then + shift + if echo $1 | grep -q '[0-9]*\.[0-9]*\.[0-9]*\.[0-9]*'; then + HOST="$1" + else + print_err "Invalid host $1" + exit 1 + fi + elif [ "$1" = "-p" ]; then + shift + if [ $1 -gt 0 -a $1 -le 65535 ]; then + PORT="$1" + else + print_err "Invalid port $1" + exit 1 + fi + fi + + shift +done + + +if ps -ef | grep "HiperisoWeb.*$HOST.*$PORT" | grep -q -v grep; then + print_err "Another hiperiso server is running now, please close it first." + exit 1 +fi + +LOGFILE=log.txt +#delete the log.txt if it's more than 8MB +if [ -f $LOGFILE ]; then + logsize=$(stat -c '%s' $LOGFILE) + if [ $logsize -gt 8388608 ]; then + rm -f $LOGFILE + fi +fi + + +if [ -f ./tool/$TOOLDIR/HiperisoWeb.xz ]; then + xz -d ./tool/$TOOLDIR/HiperisoWeb.xz + chmod +x ./tool/$TOOLDIR/HiperisoWeb +fi + + +HiperisoWeb "$HOST" "$PORT" & +wID=$! +sleep 1 + +vtVer=$(cat hiperiso/version) +echo "" +echo "===============================================================" +if [ "$LANG" = "zh_CN.UTF-8" ]; then + echo " Hiperiso Server $vtVer 已经启动 ..." + echo " 请打开浏览器,访问 http://${HOST}:${PORT}" +else + echo " Hiperiso Server $vtVer is running ..." + echo " Please open your browser and visit http://${HOST}:${PORT}" +fi +echo "===============================================================" +echo "" +echo "################## Press Ctrl + C to exit #####################" +echo "" + +wait $wID + +if [ -n "$OLDDIR" ]; then + CURDIR=$(pwd) + if [ "$CURDIR" != "$OLDDIR" ]; then + cd "$OLDDIR" + fi +fi diff --git a/src/installer/hisocli b/src/installer/hisocli new file mode 100755 index 0000000..8a750ac --- /dev/null +++ b/src/installer/hisocli @@ -0,0 +1,10 @@ +#!/bin/sh +set -e +SCRIPT_PATH="$0" +case "$SCRIPT_PATH" in + /*) : ;; + *) SCRIPT_PATH="$(pwd)/$SCRIPT_PATH" ;; +esac +SCRIPT_DIR=$(dirname "$SCRIPT_PATH") +cd "$SCRIPT_DIR" +exec ./tool/x86_64/hisocli "$@" diff --git a/src/installer/hisolnk b/src/installer/hisolnk new file mode 100755 index 0000000..4ce3b13 --- /dev/null +++ b/src/installer/hisolnk @@ -0,0 +1,10 @@ +#!/bin/sh +set -e +SCRIPT_PATH="$0" +case "$SCRIPT_PATH" in + /*) : ;; + *) SCRIPT_PATH="$(pwd)/$SCRIPT_PATH" ;; +esac +SCRIPT_DIR=$(dirname "$SCRIPT_PATH") +cd "$SCRIPT_DIR" +exec ./tool/x86_64/hisolnk "$@" diff --git a/src/installer/tool/HiperisoWorker.sh b/src/installer/tool/HiperisoWorker.sh new file mode 100644 index 0000000..9603684 --- /dev/null +++ b/src/installer/tool/HiperisoWorker.sh @@ -0,0 +1,650 @@ +#!/bin/sh + +. ./tool/hiperiso_lib.sh + +print_usage() { + + echo 'Usage: Hiperiso2Disk.sh CMD [ OPTION ] /dev/sdX' + echo ' CMD:' + echo ' -i install Hiperiso to sdX (fails if disk already installed with Hiperiso)' + echo ' -I force install Hiperiso to sdX (no matter if installed or not)' + echo ' -u update Hiperiso in sdX' + echo ' -l list Hiperiso information in sdX' + echo '' + echo ' OPTION: (optional)' + echo ' -r SIZE_MiB preserve some space (MiB) at the bottom of the disk (only for install)' + echo ' -s/-S enable/disable secure boot support (default is enabled)' + echo ' -g use GPT partition style, default is MBR (only for install)' + echo ' -L Label of the 1st exfat partition (default is Hiperiso)' + echo ' -n try non-destructive installation (only for install)' + echo '' +} + + +SECUREBOOT="YES" +VTNEW_LABEL='Hiperiso' +RESERVE_SIZE_MB=0 +while [ -n "$1" ]; do + if [ "$1" = "-i" ]; then + MODE="install" + elif [ "$1" = "-I" ]; then + MODE="install" + FORCE="Y" + elif [ "$1" = "-n" ]; then + NONDESTRUCTIVE="Y" + elif [ "$1" = "-u" ]; then + MODE="update" + elif [ "$1" = "-l" ]; then + MODE="list" + elif [ "$1" = "-s" ]; then + SECUREBOOT="YES" + elif [ "$1" = "-S" ]; then + SECUREBOOT="NO" + elif [ "$1" = "-g" ]; then + VTGPT="YES" + elif [ "$1" = "-L" ]; then + shift + VTNEW_LABEL=$1 + elif [ "$1" = "-r" ]; then + RESERVE_SPACE="YES" + shift + RESERVE_SIZE_MB=$1 + elif [ "$1" = "-V" ] || [ "$1" = "--version" ]; then + exit 0 + elif [ "$1" = "-h" ] || [ "$1" = "--help" ]; then + print_usage + exit 0 + else + if ! [ -b "$1" ]; then + hisoerr "$1 is NOT a valid device" + print_usage + exit 1 + fi + DISK=$1 + # Resolve symlinks now, will be needed to look up information about the device in + # the /sys/ filesystem, for example /sys/class/block/${DISK#/dev/}/start + # The main use case is supporting /dev/disk/by-id/ symlinks instead of raw devices + if [ -L "$DISK" ]; then + DISK=$(readlink -e -n "$DISK") + fi + fi + + shift +done + +if [ -z "$MODE" ]; then + print_usage + exit 1 +fi + +if ! [ -b "$DISK" ]; then + hisoerr "Disk $DISK does not exist" + exit 1 +fi + +if [ -e /sys/class/block/${DISK#/dev/}/start ]; then + hisoerr "$DISK is a partition, please use the whole disk." + echo "For example:" + hisoerr " sudo sh Hiperiso2Disk.sh -i /dev/sdb1 <=== This is wrong" + hisoinfo " sudo sh Hiperiso2Disk.sh -i /dev/sdb <=== This is right" + echo "" + exit 1 +fi + +if [ -n "$RESERVE_SPACE" -a "$MODE" = "install" ]; then + if echo $RESERVE_SIZE_MB | grep -q '^[0-9][0-9]*$'; then + hisodebug "User will reserve $RESERVE_SIZE_MB MiB disk space" + else + hisoerr "$RESERVE_SIZE_MB is invalid for reserved space" + exit 1 + fi +fi + +hisodebug "MODE=$MODE FORCE=$FORCE RESERVE_SPACE=$RESERVE_SPACE RESERVE_SIZE_MB=$RESERVE_SIZE_MB" + +#check tools +if check_tool_work_ok; then + hisodebug "check tool work ok" +else + hisoerr "Some tools can not run on current system. Please check log.txt for details." + exit 1 +fi + +if [ "$MODE" = "list" ]; then + version=$(get_disk_hiperiso_version $DISK) + if [ $? -eq 0 ]; then + echo "Hiperiso Version in Disk: $version" + + vtPart1Type=$(dd if=$DISK bs=1 count=1 skip=450 status=none | hexdump -n1 -e '1/1 "%02X"') + if [ "$vtPart1Type" = "EE" ]; then + echo "Disk Partition Style : GPT" + else + echo "Disk Partition Style : MBR" + fi + + if check_disk_secure_boot $DISK; then + echo "Secure Boot Support : YES" + else + echo "Secure Boot Support : NO" + fi + else + echo "Hiperiso Version: NA" + fi + echo "" + exit 0 +fi + +#check mountpoint +check_umount_disk "$DISK" + +if grep -q "$DISK" /proc/mounts; then + hisoerr "$DISK is already mounted, please umount it first!" + exit 1 +fi + +#check swap partition +if swapon --help 2>&1 | grep -q '^ -s,'; then + if swapon -s | grep -q "^${DISK}[0-9]"; then + hisoerr "$DISK is used as swap, please swapoff it first!" + exit 1 + fi +fi + +#check access +if dd if="$DISK" of=/dev/null bs=1 count=1 >/dev/null 2>&1; then + hisodebug "root permission check ok ..." +else + hisoerr "Failed to access $DISK, maybe root privilege is needed!" + echo '' + exit 1 +fi + + +#check tmp_mnt directory +if [ -d ./tmp_mnt ]; then + hisodebug "There is a tmp_mnt directory, now delete it." + umount ./tmp_mnt >/dev/null 2>&1 + rm -rf ./tmp_mnt + if [ -d ./tmp_mnt ]; then + hisoerr "tmp_mnt directory exists, please delete it first." + exit 1 + fi +fi + + +if [ "$MODE" = "install" -a -z "$NONDESTRUCTIVE" ]; then + hisodebug "install Hiperiso ..." + + if [ -n "$VTGPT" ]; then + if parted -v > /dev/null 2>&1; then + PARTTOOL='parted' + else + hisoerr "parted is not found in the system, Hiperiso can't create new partitions without it." + hisoerr "You should install \"GNU parted\" first." + exit 1 + fi + else + if parted -v > /dev/null 2>&1; then + PARTTOOL='parted' + elif fdisk -v >/dev/null 2>&1; then + PARTTOOL='fdisk' + else + hisoerr "Both parted and fdisk are not found in the system, Hiperiso can't create new partitions." + exit 1 + fi + fi + + if [ "$PARTTOOL" = "parted" ]; then + if parted -s $DISK p 2>&1 | grep -i -q 'sector size.*4096.*4096'; then + hisoerr "Currently Hiperiso does not support 4K native device." + exit 1 + fi + else + if fdisk -l $DISK | grep -i -q 'sector size.*4096.*4096'; then + hisoerr "Currently Hiperiso does not support 4K native device." + exit 1 + fi + fi + + + version=$(get_disk_hiperiso_version $DISK) + if [ $? -eq 0 ]; then + if [ -z "$FORCE" ]; then + hisowarn "$DISK already contains a Hiperiso with version $version" + hisowarn "Use -u option to do a safe upgrade operation." + hisowarn "OR if you really want to reinstall Hiperiso to $DISK, please use -I option." + hisowarn "" + exit 1 + fi + fi + + disk_sector_num=$(cat /sys/block/${DISK#/dev/}/size) + disk_size_gb=$(expr $disk_sector_num / 2097152) + + if [ $disk_sector_num -gt 4294967296 ] && [ -z "$VTGPT" ]; then + hisoerr "$DISK is over 2TB size, MBR will not work on it." + exit 1 + fi + + if [ -n "$RESERVE_SPACE" ]; then + sum_size_mb=$(expr $RESERVE_SIZE_MB + $HIPERISO_PART_SIZE_MB) + reserve_sector_num=$(expr $sum_size_mb \* 2048) + + if [ $disk_sector_num -le $reserve_sector_num ]; then + hisoerr "Can't reserve $RESERVE_SIZE_MB MiB space from $DISK" + exit 1 + fi + fi + + #Print disk info + echo "Disk : $DISK" + parted -s $DISK p 2>&1 | grep Model + echo "Size : $disk_size_gb GiB" + if [ -n "$VTGPT" ]; then + echo "Style: GPT" + else + echo "Style: MBR" + fi + echo '' + + if [ -n "$RESERVE_SPACE" ]; then + echo "You will reserve $RESERVE_SIZE_MB MiB disk space " + fi + echo '' + + hisowarn "Attention:" + hisowarn "You will install Hiperiso to $DISK." + hisowarn "All the data on the disk $DISK will be lost!!!" + echo "" + + read -p 'Continue? (y/n) ' Answer + if [ "$Answer" != "y" ]; then + if [ "$Answer" != "Y" ]; then + exit 0 + fi + fi + + echo "" + hisowarn "All the data on the disk $DISK will be lost!!!" + read -p 'Double-check. Continue? (y/n) ' Answer + if [ "$Answer" != "y" ]; then + if [ "$Answer" != "Y" ]; then + exit 0 + fi + fi + + if [ $disk_sector_num -le $HIPERISO_SECTOR_NUM ]; then + hisoerr "No enough space in disk $DISK" + exit 1 + fi + + # check and umount + check_umount_disk "$DISK" + + if ! dd if=/dev/zero of=$DISK bs=64 count=512 status=none conv=fsync; then + hisoerr "Write data to $DISK failed, please check whether it's in use." + exit 1 + fi + + if [ -n "$VTGPT" ]; then + hisodebug "format_hiperiso_disk_gpt $RESERVE_SIZE_MB $DISK $PARTTOOL ..." + format_hiperiso_disk_gpt $RESERVE_SIZE_MB $DISK $PARTTOOL + else + hisodebug "format_hiperiso_disk_mbr $RESERVE_SIZE_MB $DISK $PARTTOOL ..." + format_hiperiso_disk_mbr $RESERVE_SIZE_MB $DISK $PARTTOOL + fi + + # format part1 + + # DiskSize > 32GB Cluster Size use 128KB + # DiskSize < 32GB Cluster Size use 32KB + if [ $disk_size_gb -gt 32 ]; then + cluster_sectors=256 + else + cluster_sectors=64 + fi + + PART1=$(get_disk_part_name $DISK 1) + PART2=$(get_disk_part_name $DISK 2) + + #clean part2 + dd status=none conv=fsync if=/dev/zero of=$DISK bs=512 count=32 seek=$part2_start_sector + + #format part1 + wait_and_create_part ${PART1} ${PART2} + if [ -b ${PART1} ]; then + hisoinfo "Format partition 1 ${PART1} ..." + mkexfatfs -n "$VTNEW_LABEL" -s $cluster_sectors ${PART1} + if [ $? -ne 0 ]; then + echo "mkexfatfs failed, now retry..." + mkexfatfs -n "$VTNEW_LABEL" -s $cluster_sectors ${PART1} + if [ $? -ne 0 ]; then + echo "######### mkexfatfs failed, exit ########" + exit 1 + fi + else + echo "mkexfatfs success" + fi + else + hisoerr "${PART1} NOT exist" + fi + + hisoinfo "writing data to disk ..." + dd status=none conv=fsync if=./boot/boot.img of=$DISK bs=1 count=446 + + if [ -n "$VTGPT" ]; then + echo -en '\x22' | dd status=none of=$DISK conv=fsync bs=1 count=1 seek=92 + xzcat ./boot/core.img.xz | dd status=none conv=fsync of=$DISK bs=512 count=2014 seek=34 + echo -en '\x23' | dd of=$DISK conv=fsync bs=1 count=1 seek=17908 status=none + else + xzcat ./boot/core.img.xz | dd status=none conv=fsync of=$DISK bs=512 count=2047 seek=1 + fi + + # check and umount + check_umount_disk "$DISK" + + xzcat ./hiperiso/hiperiso.disk.img.xz | dd status=none conv=fsync of=$DISK bs=512 count=$HIPERISO_SECTOR_NUM seek=$part2_start_sector + + #test UUID + testUUIDStr=$(hiso_gen_uuid | hexdump -C) + hisodebug "test uuid: $testUUIDStr" + + #disk uuid + hiso_gen_uuid | dd status=none conv=fsync of=${DISK} seek=384 bs=1 count=16 + + #disk signature + hiso_gen_uuid | dd status=none conv=fsync of=${DISK} skip=12 seek=440 bs=1 count=4 + + hisoinfo "sync data ..." + sync + + hisoinfo "esp partition processing ..." + + if [ "$SECUREBOOT" != "YES" ]; then + sleep 2 + check_umount_disk "$DISK" + hisocli partresize -s $DISK $part2_start_sector + fi + + echo "" + hisoinfo "Install Hiperiso to $DISK successfully finished." + sync + check_umount_disk "$DISK" + echo "You can now safely remove $DISK." + echo "" + +elif [ "$MODE" = "install" -a -n "$NONDESTRUCTIVE" ]; then + hisodebug "non-destructive install Hiperiso ..." + + version=$(get_disk_hiperiso_version $DISK) + if [ $? -eq 0 ]; then + if [ -z "$FORCE" ]; then + hisowarn "$DISK already contains a Hiperiso with version $version." + hisowarn "You can not do and don not need non-destructive installation." + hisowarn "" + exit 1 + fi + fi + + disk_sector_num=$(cat /sys/block/${DISK#/dev/}/size) + disk_size_gb=$(expr $disk_sector_num / 2097152) + + if hisocli partresize -t $DISK; then + OldStyle="GPT" + else + OldStyle="MBR" + fi + + #Print disk info + echo "Disk : $DISK" + parted -s $DISK p 2>&1 | grep Model + echo "Size : $disk_size_gb GiB" + echo "Style: $OldStyle" + echo '' + + hisowarn "Attention:" + hisowarn "Hiperiso will try non-destructive installation on $DISK if possible." + echo "" + + read -p 'Continue? (y/n) ' Answer + if [ "$Answer" != "y" ]; then + if [ "$Answer" != "Y" ]; then + exit 0 + fi + fi + + if [ $disk_sector_num -le $HIPERISO_SECTOR_NUM ]; then + hisoerr "No enough space in disk $DISK" + exit 1 + fi + + PART1=$(get_disk_part_name $DISK 1) + PART2=$(get_disk_part_name $DISK 2) + + #Part1 size in MB aligned with 4KB + PART1_SECTORS=$(cat /sys/class/block/${PART1#/dev/}/size) + PART1_4K=$(expr $PART1_SECTORS / 8) + PART1_MB=$(expr $PART1_4K / 256) + PART1_NEW_MB=$(expr $PART1_MB - 32) + + echo "$PART1 is ${PART1_MB}MiB" + + #check partition layout + echo "check partition layout ..." + hisocli partresize -c $DISK + vtRet=$? + if [ $vtRet -eq 0 ]; then + exit 1 + else + # check and umount + check_umount_disk "$DISK" + sleep 1 + check_umount_disk "$DISK" + + if [ $vtRet -eq 1 ]; then + echo "Free space enough, start install..." + part2_start_sector=$(expr $PART1_SECTORS + 2048) + elif [ $vtRet -eq 2 ]; then + echo "We need to shrink partition 1 firstly ..." + + PART1_BLKID=$(blkid $PART1) + blkid $PART1 + + if echo $PART1_BLKID | grep -E -q -i 'TYPE=ntfs|TYPE=.ntfs'; then + echo "Partition 1 contains NTFS filesystem" + + which ntfsresize + if [ $? -ne 0 ]; then + echo "###[FAIL] ntfsresize not found. Please install ntfs-3g package." + exit 1 + fi + + echo "ntfsfix -b -d $PART1 ..." + ntfsfix -b -d $PART1 + + echo "ntfsresize --size ${PART1_NEW_MB}Mi $PART1 ..." + ntfsresize -f --size ${PART1_NEW_MB}Mi $PART1 + if [ $? -ne 0 ]; then + echo "###[FAIL] ntfsresize failed." + exit 1 + fi + elif echo $PART1_BLKID | grep -E -q -i 'TYPE=ext[2-4]|TYPE=.ext[2-4]'; then + echo "Partition 1 contains EXT filesystem" + + which resize2fs + if [ $? -ne 0 ]; then + echo "###[FAIL] resize2fs not found. Please install e2fsprogs package." + exit 1 + fi + + echo "e2fsck -f $PART1 ..." + e2fsck -f $PART1 + + echo "resize2fs $PART1 ${PART1_NEW_MB}M ..." + resize2fs $PART1 ${PART1_NEW_MB}M + if [ $? -ne 0 ]; then + echo "###[FAIL] resize2fs failed." + exit 1 + fi + else + echo "###[FAIL] Unsupported filesystem in partition 1." + exit 1 + fi + + sync + PART1_NEW_END_MB=$(expr $PART1_NEW_MB + 1) + part2_start_sector=$(expr $PART1_NEW_END_MB \* 2048) + fi + fi + + hisoinfo "writing data to disk part2_start=$part2_start_sector ..." + + dd status=none conv=fsync if=./boot/boot.img of=$DISK bs=1 count=440 + + if [ "$OldStyle" = "GPT" ]; then + echo -en '\x22' | dd status=none of=$DISK conv=fsync bs=1 count=1 seek=92 + xzcat ./boot/core.img.xz | dd status=none conv=fsync of=$DISK bs=512 count=2014 seek=34 + echo -en '\x23' | dd of=$DISK conv=fsync bs=1 count=1 seek=17908 status=none + else + xzcat ./boot/core.img.xz | dd status=none conv=fsync of=$DISK bs=512 count=2047 seek=1 + fi + + xzcat ./hiperiso/hiperiso.disk.img.xz | dd status=none conv=fsync of=$DISK bs=512 count=$HIPERISO_SECTOR_NUM seek=$part2_start_sector + + #test UUID + testUUIDStr=$(hiso_gen_uuid | hexdump -C) + hisodebug "test uuid: $testUUIDStr" + + #disk uuid + hiso_gen_uuid | dd status=none conv=fsync of=${DISK} seek=384 bs=1 count=16 + + hisoinfo "sync data ..." + sync + + hisoinfo "esp partition processing ..." + if [ "$SECUREBOOT" != "YES" ]; then + sleep 2 + check_umount_disk "$DISK" + hisocli partresize -s $DISK $part2_start_sector + fi + + hisoinfo "update partition table $DISK $part2_start_sector ..." + hisocli partresize -p $DISK $part2_start_sector + if [ $? -eq 0 ]; then + sync + echo "" + hisoinfo "Hiperiso non-destructive installation on $DISK successfully finished." + check_umount_disk "$DISK" + echo "You can now safely remove $DISK." + echo "" + else + echo "" + hisoerr "Hiperiso non-destructive installation on $DISK failed." + echo "" + fi + +else + hisodebug "update Hiperiso ..." + + oldver=$(get_disk_hiperiso_version $DISK) + if [ $? -ne 0 ]; then + if is_disk_contains_hiperiso $DISK; then + oldver="Unknown" + else + hisowarn "$DISK does not contain Hiperiso or data corrupted" + echo "" + hisowarn "Please use -i option if you want to install hiperiso to $DISK" + echo "" + exit 1 + fi + fi + + #reserve secure boot option + if [ -z "$SECUREBOOT" ]; then + if check_disk_secure_boot $DISK; then + SECUREBOOT="YES" + else + SECUREBOOT="NO" + fi + fi + + curver=$(cat ./hiperiso/version) + + hisoinfo "Upgrade operation is safe, all the data in the 1st partition (iso files and other) will be unchanged!" + echo "" + + read -p "Update Hiperiso $oldver ===> $curver Continue? (y/n) " Answer + if [ "$Answer" != "y" ]; then + if [ "$Answer" != "Y" ]; then + exit 0 + fi + fi + + PART2=$(get_disk_part_name $DISK 2) + SHORT_PART2=${PART2#/dev/} + part2_start=$(cat /sys/class/block/$SHORT_PART2/start) + + PART1_TYPE=$(dd if=$DISK bs=1 count=1 skip=450 status=none | hexdump -n1 -e '1/1 "%02X"') + + #reserve disk uuid + rm -f ./diskuuid.bin + dd status=none conv=fsync if=${DISK} skip=384 bs=1 count=16 of=./diskuuid.bin + + dd status=none conv=fsync if=./boot/boot.img of=$DISK bs=1 count=440 + dd status=none conv=fsync if=./diskuuid.bin of=$DISK bs=1 count=16 seek=384 + rm -f ./diskuuid.bin + + #reserve data + rm -f ./rsvdata.bin + dd status=none conv=fsync if=${DISK} skip=2040 bs=512 count=8 of=./rsvdata.bin + + if [ "$PART1_TYPE" = "EE" ]; then + hisodebug "This is GPT partition style ..." + echo -en '\x22' | dd status=none of=$DISK conv=fsync bs=1 count=1 seek=92 + xzcat ./boot/core.img.xz | dd status=none conv=fsync of=$DISK bs=512 count=2014 seek=34 + echo -en '\x23' | dd of=$DISK conv=fsync bs=1 count=1 seek=17908 status=none + else + hisodebug "This is MBR partition style ..." + + PART1_ACTIVE=$(dd if=$DISK bs=1 count=1 skip=446 status=none | hexdump -n1 -e '1/1 "%02X"') + PART2_ACTIVE=$(dd if=$DISK bs=1 count=1 skip=462 status=none | hexdump -n1 -e '1/1 "%02X"') + + hisodebug "PART1_ACTIVE=$PART1_ACTIVE PART2_ACTIVE=$PART2_ACTIVE" + if [ "$PART1_ACTIVE" = "00" ] && [ "$PART2_ACTIVE" = "80" ]; then + hisodebug "change 1st partition active, 2nd partition inactive ..." + echo -en '\x80' | dd of=$DISK conv=fsync bs=1 count=1 seek=446 status=none + echo -en '\x00' | dd of=$DISK conv=fsync bs=1 count=1 seek=462 status=none + fi + xzcat ./boot/core.img.xz | dd status=none conv=fsync of=$DISK bs=512 count=2047 seek=1 + fi + + dd status=none conv=fsync if=./rsvdata.bin seek=2040 bs=512 count=8 of=${DISK} + rm -f ./rsvdata.bin + + check_umount_disk "$DISK" + + xzcat ./hiperiso/hiperiso.disk.img.xz | dd status=none conv=fsync of=$DISK bs=512 count=$HIPERISO_SECTOR_NUM seek=$part2_start + sync + + hisoinfo "esp partition processing ..." + if [ "$SECUREBOOT" != "YES" ]; then + sleep 2 + check_umount_disk "$DISK" + hisocli partresize -s $DISK $part2_start + fi + + + if [ "$PART1_TYPE" = "EE" ]; then + hisoinfo "update esp partition attribute" + hisocli gpt -f $DISK + sync + fi + + + echo "" + hisoinfo "Update Hiperiso on $DISK successfully finished." + echo "" + +fi + + diff --git a/src/installer/tool/create_hiperiso_iso_part_dm.sh b/src/installer/tool/create_hiperiso_iso_part_dm.sh new file mode 100644 index 0000000..adc544b --- /dev/null +++ b/src/installer/tool/create_hiperiso_iso_part_dm.sh @@ -0,0 +1,38 @@ +#!/bin/sh + +if [ "$(id -u)" -ne 0 ]; then + echo "Please run with sudo ..." + exit 1 +fi + +oldpwd=$(pwd) +VPART="" + +if dmsetup -h > /dev/null 2>&1; then + VPART_MAJOR_MINOR=$(dmsetup table hiperiso | head -n 1 | awk '{print $4}') + cd /sys/class/block/ + for t in *; do + if grep -q "^${VPART_MAJOR_MINOR}$" $t/dev; then + VPART=$t + echo 0 $(cat /sys/class/block/$VPART/size) linear /dev/$VPART 0 | dmsetup create $VPART + dmsetup mknodes "$VPART" > /dev/null 2>&1 + break + fi + done + cd $oldpwd + + if [ -z "$VPART" ]; then + echo "$VPART_MAJOR_MINOR not found" + dmsetup ls; dmsetup info hiperiso; dmsetup table hiperiso + exit 1 + else + if [ ! -b "/dev/mapper/$VPART" ]; then + udevadm trigger --type=devices --action=add > /dev/null 2>&1 + udevadm settle > /dev/null 2>&1 + fi + echo "Create /dev/mapper/$VPART success" + fi +else + echo "dmsetup program not avaliable" + exit 1 +fi diff --git a/src/installer/tool/hiperiso_lib.sh b/src/installer/tool/hiperiso_lib.sh new file mode 100644 index 0000000..e3caa4b --- /dev/null +++ b/src/installer/tool/hiperiso_lib.sh @@ -0,0 +1,516 @@ +#!/bin/sh + +#Hiperiso partition 32MB +HIPERISO_PART_SIZE=33554432 +HIPERISO_PART_SIZE_MB=32 +HIPERISO_SECTOR_SIZE=512 +HIPERISO_SECTOR_NUM=65536 + +hiperiso_false() { + [ "1" = "2" ] +} + +hiperiso_true() { + [ "1" = "1" ] +} + + +hisoinfo() { + echo -e "\033[32m$*\033[0m" +} + +hisowarn() { + echo -e "\033[33m$*\033[0m" +} + + +hisoerr() { + echo -e "\033[31m$*\033[0m" +} + +hisodebug() { + echo "$*" >> ./log.txt +} + +hiso_gen_uuid() { + if uuid -F BIN > /dev/null 2>&1; then + uuid -F BIN + elif uuidgen -V > /dev/null 2>&1; then + a=$(uuidgen | sed 's/-//g') + echo -en "\x${a:0:2}\x${a:2:2}\x${a:4:2}\x${a:6:2}\x${a:8:2}\x${a:10:2}\x${a:12:2}\x${a:14:2}\x${a:16:2}\x${a:18:2}\x${a:20:2}\x${a:22:2}\x${a:24:2}\x${a:26:2}\x${a:28:2}\x${a:30:2}" + elif python3 -V > /dev/null 2>&1; then + a=$(python3 -c 'import sys,uuid; sys.stdout.write(uuid.uuid4().hex)') + echo -en "\x${a:0:2}\x${a:2:2}\x${a:4:2}\x${a:6:2}\x${a:8:2}\x${a:10:2}\x${a:12:2}\x${a:14:2}\x${a:16:2}\x${a:18:2}\x${a:20:2}\x${a:22:2}\x${a:24:2}\x${a:26:2}\x${a:28:2}\x${a:30:2}" + elif python -V > /dev/null 2>&1; then + a=$(python -c 'import sys,uuid; sys.stdout.write(uuid.uuid4().hex)') + echo -en "\x${a:0:2}\x${a:2:2}\x${a:4:2}\x${a:6:2}\x${a:8:2}\x${a:10:2}\x${a:12:2}\x${a:14:2}\x${a:16:2}\x${a:18:2}\x${a:20:2}\x${a:22:2}\x${a:24:2}\x${a:26:2}\x${a:28:2}\x${a:30:2}" + elif [ -e /dev/urandom ]; then + dd if=/dev/urandom bs=1 count=16 status=none + else + datestr=$(date +%N%N%N%N%N) + a=${datestr:0:32} + echo -en "\x${a:0:2}\x${a:2:2}\x${a:4:2}\x${a:6:2}\x${a:8:2}\x${a:10:2}\x${a:12:2}\x${a:14:2}\x${a:16:2}\x${a:18:2}\x${a:20:2}\x${a:22:2}\x${a:24:2}\x${a:26:2}\x${a:28:2}\x${a:30:2}" + fi +} + +check_tool_work_ok() { + + if echo 1 | hexdump > /dev/null; then + hisodebug "hexdump test ok ..." + else + hisodebug "hexdump test fail ..." + hiperiso_false + return + fi + + if mkexfatfs -V > /dev/null; then + hisodebug "mkexfatfs test ok ..." + else + hisodebug "mkexfatfs test fail ..." + hiperiso_false + return + fi + + if hisocli fat -T; then + hisodebug "hisocli fat test ok ..." + else + hisodebug "hisocli fat test fail ..." + hiperiso_false + return + fi + + hisodebug "tool check success ..." + hiperiso_true +} + + +get_disk_part_name() { + DISK=$1 + + if echo $DISK | grep -q "/dev/loop"; then + echo ${DISK}p${2} + elif echo $DISK | grep -q "/dev/nvme[0-9][0-9]*n[0-9]"; then + echo ${DISK}p${2} + elif echo $DISK | grep -q "/dev/mmcblk[0-9]"; then + echo ${DISK}p${2} + elif echo $DISK | grep -q "/dev/nbd[0-9]"; then + echo ${DISK}p${2} + elif echo $DISK | grep -q "/dev/zd[0-9]"; then + echo ${DISK}p${2} + elif echo $DISK | grep -q "/dev/md[0-9]"; then + echo ${DISK}p${2} + else + echo ${DISK}${2} + fi +} + +check_umount_disk() { + DiskOrPart="$1" + grep "^${DiskOrPart}" /proc/mounts | while read mtline; do + mtpnt=$(echo $mtline | awk '{print $2}') + hisodebug "Trying to umount $mtpnt ..." + umount $mtpnt >/dev/null 2>&1 + done +} + +get_hiperiso_version_from_cfg() { + if grep -q 'set.*HIPERISO_VERSION=' $1; then + grep 'set.*HIPERISO_VERSION=' $1 | awk -F'"' '{print $2}' + else + echo 'none' + fi +} + +is_disk_contains_hiperiso() { + DISK=$1 + + PART1=$(get_disk_part_name $1 1) + PART2=$(get_disk_part_name $1 2) + + if [ -e /sys/class/block/${PART2#/dev/}/size ]; then + SIZE=$(cat /sys/class/block/${PART2#/dev/}/size) + else + SIZE=0 + fi + + if ! [ -b $PART1 ]; then + hisodebug "$PART1 not exist" + hiperiso_false + return + fi + + if ! [ -b $PART2 ]; then + hisodebug "$PART2 not exist" + hiperiso_false + return + fi + + PART1_TYPE=$(dd if=$DISK bs=1 count=1 skip=450 status=none | hexdump -n1 -e '1/1 "%02X"') + PART2_TYPE=$(dd if=$DISK bs=1 count=1 skip=466 status=none | hexdump -n1 -e '1/1 "%02X"') + + # if [ "$PART1_TYPE" != "EE" ]; then + # if [ "$PART2_TYPE" != "EF" ]; then + # hisodebug "part2 type is $PART2_TYPE not EF" + # hiperiso_false + # return + # fi + # fi + + # PART1_TYPE=$(dd if=$DISK bs=1 count=1 skip=450 status=none | hexdump -n1 -e '1/1 "%02X"') + # if [ "$PART1_TYPE" != "07" ]; then + # hisodebug "part1 type is $PART2_TYPE not 07" + # hiperiso_false + # return + # fi + + if [ -e /sys/class/block/${PART1#/dev/}/start ]; then + PART1_START=$(cat /sys/class/block/${PART1#/dev/}/start) + fi + + if [ "$PART1_START" != "2048" ]; then + hisodebug "part1 start is $PART1_START not 2048" + hiperiso_false + return + fi + + if [ "$HIPERISO_SECTOR_NUM" != "$SIZE" ]; then + hisodebug "part2 size is $SIZE not $HIPERISO_SECTOR_NUM" + hiperiso_false + return + fi + + hiperiso_true +} + +check_disk_secure_boot() { + if ! is_disk_contains_hiperiso $1; then + hiperiso_false + return + fi + + PART2=$(get_disk_part_name $1 2) + + hisocli fat -s $PART2 +} + +get_disk_hiperiso_version() { + + if ! is_disk_contains_hiperiso $1; then + hiperiso_false + return + fi + + PART2=$(get_disk_part_name $1 2) + + ParseVer=$(hisocli fat $PART2) + if [ $? -eq 0 ]; then + hisodebug "Hiperiso version in $PART2 is $ParseVer" + echo $ParseVer + hiperiso_true + return + fi + + hiperiso_false +} + +wait_and_create_part() { + vPART1=$1 + vPART2=$2 + echo "Wait for partitions $vPART1 and $vPART2 ..." + for i in 0 1 2 3 4 5 6 7 8 9; do + if ls -l $vPART1 2>/dev/null | grep -q '^b'; then + if ls -l $vPART2 2>/dev/null | grep -q '^b'; then + break + fi + else + echo "Wait for $vPART1 and $vPART2 ..." + sleep 1 + fi + done + + if ls -l $vPART1 2>/dev/null | grep -q '^b'; then + echo "$vPART1 exist OK" + else + MajorMinor=$(sed "s/:/ /" /sys/class/block/${vPART1#/dev/}/dev) + echo "mknod -m 0660 $vPART1 b $MajorMinor ..." + mknod -m 0660 $vPART1 b $MajorMinor + fi + + if ls -l $vPART2 2>/dev/null | grep -q '^b'; then + echo "$vPART2 exist OK" + else + MajorMinor=$(sed "s/:/ /" /sys/class/block/${vPART2#/dev/}/dev) + echo "mknod -m 0660 $vPART2 b $MajorMinor ..." + mknod -m 0660 $vPART2 b $MajorMinor + fi + + if ls -l $vPART1 2>/dev/null | grep -q '^b'; then + if ls -l $vPART2 2>/dev/null | grep -q '^b'; then + echo "partition exist OK" + fi + else + echo "[FAIL] $vPART1/$vPART2 does not exist" + exit 1 + fi +} + + +format_hiperiso_disk_mbr() { + reserve_mb=$1 + DISK=$2 + PARTTOOL=$3 + + PART1=$(get_disk_part_name $DISK 1) + PART2=$(get_disk_part_name $DISK 2) + + sector_num=$(cat /sys/block/${DISK#/dev/}/size) + + part1_start_sector=2048 + + if [ $reserve_mb -gt 0 ]; then + reserve_sector_num=$(expr $reserve_mb \* 2048) + part1_end_sector=$(expr $sector_num - $reserve_sector_num - $HIPERISO_SECTOR_NUM - 1) + else + part1_end_sector=$(expr $sector_num - $HIPERISO_SECTOR_NUM - 1) + fi + + part2_start_sector=$(expr $part1_end_sector + 1) + + modsector=$(expr $part2_start_sector % 8) + if [ $modsector -gt 0 ]; then + hisodebug "modsector:$modsector need to be aligned with 4KB" + part1_end_sector=$(expr $part1_end_sector - $modsector) + part2_start_sector=$(expr $part1_end_sector + 1) + fi + + part2_end_sector=$(expr $part2_start_sector + $HIPERISO_SECTOR_NUM - 1) + + export part2_start_sector + + hisodebug "part1_start_sector=$part1_start_sector part1_end_sector=$part1_end_sector" + hisodebug "part2_start_sector=$part2_start_sector part2_end_sector=$part2_end_sector" + + if [ -e $PART1 ]; then + echo "delete $PART1" + rm -f $PART1 + fi + + if [ -e $PART2 ]; then + echo "delete $PART2" + rm -f $PART2 + fi + + echo "" + echo "Create partitions on $DISK by $PARTTOOL in MBR style ..." + + if [ "$PARTTOOL" = "parted" ]; then + hisodebug "format disk by parted ..." + parted -a none --script $DISK \ + mklabel msdos \ + unit s \ + mkpart primary ntfs $part1_start_sector $part1_end_sector \ + mkpart primary fat16 $part2_start_sector $part2_end_sector \ + set 1 boot on \ + quit + + sync + echo -en '\xEF' | dd of=$DISK conv=fsync bs=1 count=1 seek=466 > /dev/null 2>&1 + else + hisodebug "format disk by fdisk ..." + +fdisk $DISK >>./log.txt 2>&1 </dev/null 2>&1 + partprobe >/dev/null 2>&1 + partx -u $DISK >/dev/null 2>&1 + sleep 3 + echo "Done" + + + echo 'Wait for partitions ...' + for i in 0 1 2 3 4 5 6 7 8 9; do + if [ -b $PART1 -a -b $PART2 ]; then + break + else + echo "Wait for $PART1/$PART2 ..." + sleep 1 + fi + done + + if ! [ -b $PART1 ]; then + MajorMinor=$(sed "s/:/ /" /sys/class/block/${PART1#/dev/}/dev) + echo "mknod -m 0660 $PART1 b $MajorMinor ..." + mknod -m 0660 $PART1 b $MajorMinor + fi + + if ! [ -b $PART2 ]; then + MajorMinor=$(sed "s/:/ /" /sys/class/block/${PART2#/dev/}/dev) + echo "mknod -m 0660 $PART2 b $MajorMinor ..." + mknod -m 0660 $PART2 b $MajorMinor + fi + + if [ -b $PART1 -a -b $PART2 ]; then + echo "partition exist OK" + else + echo "[FAIL] $PART1/$PART2 does not exist" + exit 1 + fi + + echo "create efi fat fs $PART2 ..." + for i in 0 1 2 3 4 5 6 7 8 9; do + check_umount_disk "$PART2" + + if mkfs.vfat -F 16 -n HISOEFI -s 1 $PART2; then + echo 'success' + break + else + echo "$? retry ..." + sleep 2 + fi + done +} + + +format_hiperiso_disk_gpt() { + reserve_mb=$1 + DISK=$2 + PARTTOOL=$3 + + PART1=$(get_disk_part_name $DISK 1) + PART2=$(get_disk_part_name $DISK 2) + + sector_num=$(cat /sys/block/${DISK#/dev/}/size) + + part1_start_sector=2048 + + if [ $reserve_mb -gt 0 ]; then + reserve_sector_num=$(expr $reserve_mb \* 2048 + 33) + part1_end_sector=$(expr $sector_num - $reserve_sector_num - $HIPERISO_SECTOR_NUM - 1) + else + part1_end_sector=$(expr $sector_num - $HIPERISO_SECTOR_NUM - 34) + fi + + part2_start_sector=$(expr $part1_end_sector + 1) + + modsector=$(expr $part2_start_sector % 8) + if [ $modsector -gt 0 ]; then + hisodebug "modsector:$modsector need to be aligned with 4KB" + part1_end_sector=$(expr $part1_end_sector - $modsector) + part2_start_sector=$(expr $part1_end_sector + 1) + fi + + part2_end_sector=$(expr $part2_start_sector + $HIPERISO_SECTOR_NUM - 1) + + export part2_start_sector + + hisodebug "part1_start_sector=$part1_start_sector part1_end_sector=$part1_end_sector" + hisodebug "part2_start_sector=$part2_start_sector part2_end_sector=$part2_end_sector" + + if [ -e $PART1 ]; then + echo "delete $PART1" + rm -f $PART1 + fi + + if [ -e $PART2 ]; then + echo "delete $PART2" + rm -f $PART2 + fi + + echo "" + echo "Create partitions on $DISK by $PARTTOOL in GPT style ..." + + hisodebug "format disk by parted ..." + + if [ "$TOOLDIR" != "aarch64" ]; then + vt_set_efi_type="set 2 msftdata on" + fi + + parted -a none --script $DISK \ + mklabel gpt \ + unit s \ + mkpart Hiperiso ntfs $part1_start_sector $part1_end_sector \ + mkpart HISOEFI fat16 $part2_start_sector $part2_end_sector \ + $vt_set_efi_type \ + quit + + sync + + hisocli gpt -f $DISK + sync + + udevadm trigger --name-match=$DISK >/dev/null 2>&1 + partprobe >/dev/null 2>&1 + partx -u $DISK >/dev/null 2>&1 + sleep 3 + echo "Done" + + echo 'Wait for partitions ...' + for i in 0 1 2 3 4 5 6 7 8 9; do + if [ -b $PART1 -a -b $PART2 ]; then + break + else + echo "Wait for $PART1/$PART2 ..." + sleep 1 + fi + done + + if ! [ -b $PART1 ]; then + MajorMinor=$(sed "s/:/ /" /sys/class/block/${PART1#/dev/}/dev) + echo "mknod -m 0660 $PART1 b $MajorMinor ..." + mknod -m 0660 $PART1 b $MajorMinor + fi + + if ! [ -b $PART2 ]; then + MajorMinor=$(sed "s/:/ /" /sys/class/block/${PART2#/dev/}/dev) + echo "mknod -m 0660 $PART2 b $MajorMinor ..." + mknod -m 0660 $PART2 b $MajorMinor + fi + + if [ -b $PART1 -a -b $PART2 ]; then + echo "partition exist OK" + else + echo "[FAIL] $PART1/$PART2 does not exist" + exit 1 + fi + + echo "create efi fat fs $PART2 ..." + + for i in 0 1 2 3 4 5 6 7 8 9; do + check_umount_disk "$PART2" + + if mkfs.vfat -F 16 -n HISOEFI -s 1 $PART2; then + echo 'success' + break + else + echo "$? retry ..." + sleep 2 + fi + done +} + + + + +