Some initial partitioning
This commit is contained in:
@@ -1,5 +1,7 @@
|
|||||||
#!/bin/bash
|
#!/bin/bash
|
||||||
|
|
||||||
|
set -euo pipefail
|
||||||
|
|
||||||
/preload-k8s-images.sh || exit 1
|
/preload-k8s-images.sh || exit 1
|
||||||
|
|
||||||
REGISTRY_DATA_DIR="${KUBE_IMG_CACHE}/registry-data/${ARCH}/${KUBE_VERSION}"
|
REGISTRY_DATA_DIR="${KUBE_IMG_CACHE}/registry-data/${ARCH}/${KUBE_VERSION}"
|
||||||
@@ -11,6 +13,7 @@ cp -a "${REGISTRY_DATA_DIR}/." "${ROOTFS}/var/lib/registry/"
|
|||||||
|
|
||||||
mkdir -p "$ROOTFS/var/cache/apk"
|
mkdir -p "$ROOTFS/var/cache/apk"
|
||||||
mkdir -p "$ROOTFS/var/cache/k8s-images"
|
mkdir -p "$ROOTFS/var/cache/k8s-images"
|
||||||
|
mkdir -p "$ROOTFS/opt/monok8s/config"
|
||||||
mkdir -p "$ROOTFS/build"
|
mkdir -p "$ROOTFS/build"
|
||||||
|
|
||||||
mount --bind /var/cache/apk "$ROOTFS/var/cache/apk"
|
mount --bind /var/cache/apk "$ROOTFS/var/cache/apk"
|
||||||
@@ -51,12 +54,15 @@ rm -r "$ROOTFS/build"
|
|||||||
echo "##################################################### Packaging RootFS "$( du -sh "$ROOTFS/" )
|
echo "##################################################### Packaging RootFS "$( du -sh "$ROOTFS/" )
|
||||||
|
|
||||||
IMG=output.img
|
IMG=output.img
|
||||||
SIZE=3072MB
|
SIZE=8GB
|
||||||
|
|
||||||
dd if=/dev/zero of="$IMG" bs=1 count=0 seek=$SIZE
|
dd if=/dev/zero of="$IMG" bs=1 count=0 seek=$SIZE
|
||||||
|
|
||||||
sgdisk -o "$IMG" \
|
sgdisk -o "$IMG" \
|
||||||
-n 1:65536:-1M -t 1:8300
|
-n 1:2048:+64M -t 1:0700 -c 1:config \
|
||||||
|
-n 2:0:+3G -t 2:8300 -c 2:rootfsA \
|
||||||
|
-n 3:0:+3G -t 3:8300 -c 3:rootfsB \
|
||||||
|
-n 4:0:0 -t 4:8300 -c 4:data
|
||||||
|
|
||||||
losetup -D
|
losetup -D
|
||||||
LOOP=$(losetup --find --show -P "$IMG")
|
LOOP=$(losetup --find --show -P "$IMG")
|
||||||
@@ -64,11 +70,14 @@ LOOP=$(losetup --find --show -P "$IMG")
|
|||||||
/sync-loop.sh "$LOOP"
|
/sync-loop.sh "$LOOP"
|
||||||
|
|
||||||
TMP_LOOP="/tmp$LOOP"
|
TMP_LOOP="/tmp$LOOP"
|
||||||
mkfs.ext4 -F "${TMP_LOOP}p1"
|
mkfs.vfat -F 32 -n MONOK8S_CFG "${TMP_LOOP}p1"
|
||||||
|
mkfs.ext4 -F "${TMP_LOOP}p2"
|
||||||
|
mkfs.ext4 -F "${TMP_LOOP}p3"
|
||||||
|
mkfs.ext4 -F "${TMP_LOOP}p4"
|
||||||
|
|
||||||
mkdir -p /mnt/img-root
|
mkdir -p /mnt/img-root
|
||||||
|
|
||||||
mount "${TMP_LOOP}p1" /mnt/img-root
|
mount "${TMP_LOOP}p2" /mnt/img-root
|
||||||
|
|
||||||
cp -a "$ROOTFS"/. /mnt/img-root/
|
cp -a "$ROOTFS"/. /mnt/img-root/
|
||||||
|
|
||||||
|
|||||||
2
alpine/rootfs-extra/etc/fstab
Normal file
2
alpine/rootfs-extra/etc/fstab
Normal file
@@ -0,0 +1,2 @@
|
|||||||
|
PARTLABEL=config /opt/monok8s/config vfat defaults,noatime 0 0
|
||||||
|
PARTLABEL=data /data ext4 defaults,noatime 0 21
|
||||||
70
docs/uboot.md
Normal file
70
docs/uboot.md
Normal file
@@ -0,0 +1,70 @@
|
|||||||
|
Booting release image with bootusb
|
||||||
|
- Use this if you are flashing image from macos/flashusb.sh
|
||||||
|
```
|
||||||
|
setenv bootusb '
|
||||||
|
usb start;
|
||||||
|
setenv bootargs "console=ttyS0,115200 root=/dev/sda2 rw rootwait";
|
||||||
|
ext4load usb 0:2 ${kernel_addr_r} /boot/Image.gz;
|
||||||
|
ext4load usb 0:2 ${fdt_addr_r} /boot/mono-gateway-dk-sdk.dtb;
|
||||||
|
booti ${kernel_addr_r} - ${fdt_addr_r}
|
||||||
|
'
|
||||||
|
|
||||||
|
run bootusb
|
||||||
|
```
|
||||||
|
|
||||||
|
Booting into initramfs (board.itb in usb drive root)
|
||||||
|
```
|
||||||
|
setenv bootusb 'usb start; ext4load usb 0:2 ${mks_loadaddr} /boot/kernel.itb; bootm ${mks_loadaddr}'
|
||||||
|
run bootusb
|
||||||
|
```
|
||||||
|
|
||||||
|
|
||||||
|
Original uboot env from mono
|
||||||
|
```
|
||||||
|
arch=arm
|
||||||
|
baudrate=115200
|
||||||
|
board=gateway_dk
|
||||||
|
board_name=gateway_dk
|
||||||
|
bootargs_console=console=ttyS0,115200 earlycon=uart8250,mmio,0x21c0500 mtdparts=${mtdparts}
|
||||||
|
bootcmd=run emmc || run recovery
|
||||||
|
bootdelay=5
|
||||||
|
cpu=armv8
|
||||||
|
emmc=setenv bootargs "${bootargs_console} root=/dev/mmcblk0p1 rw rootwait rootfstype=ext4 ${bootargs_hwtest}"; \
|
||||||
|
ext4load mmc 0:1 ${kernel_addr_r} /boot/Image.gz && \
|
||||||
|
ext4load mmc 0:1 ${fdt_addr_r} /boot/mono-gateway-dk-sdk.dtb && \
|
||||||
|
booti ${kernel_addr_r} - ${fdt_addr_r} || \
|
||||||
|
ext4load mmc 0:1 ${kernel_addr_r} /boot/kernel.itb && \
|
||||||
|
bootm ${kernel_addr_r}
|
||||||
|
eth1addr=E8:F6:D7:00:1E:93
|
||||||
|
eth2addr=E8:F6:D7:00:1E:94
|
||||||
|
eth3addr=E8:F6:D7:00:1E:95
|
||||||
|
eth4addr=E8:F6:D7:00:1E:96
|
||||||
|
ethact=fm1-mac5
|
||||||
|
ethaddr=E8:F6:D7:00:1E:92
|
||||||
|
ethprime=fm1-mac5
|
||||||
|
fdt_addr=0x500000
|
||||||
|
fdt_addr_r=0x88000000
|
||||||
|
fdt_size=0x100000
|
||||||
|
fdtcontroladdr=fbc01220
|
||||||
|
fman_ucode=fbc12d40
|
||||||
|
fsl_bootcmd_mcinitcmd_set=y
|
||||||
|
kernel_addr=0xA00000
|
||||||
|
kernel_addr_r=0x82000000
|
||||||
|
kernel_comp_addr_r=0x90000000
|
||||||
|
kernel_comp_size=0x1600000
|
||||||
|
kernel_size=0x1600000
|
||||||
|
load_addr=0xa0000000
|
||||||
|
loadaddr=0xa0000000
|
||||||
|
mks_loadaddr=0x80000000
|
||||||
|
model=Mono Gateway Development Kit
|
||||||
|
mtdparts=1550000.spi:1M(rcw-bl2),2M(uboot),1M(uboot-env),1M(fman-ucode),1M(recovery-dtb),4M(unallocated),-(kernel-initramfs)
|
||||||
|
netmask=255.255.255.0
|
||||||
|
ramdisk_addr_r=0x88080000
|
||||||
|
recovery=setenv bootargs "${bootargs_console} rw rootwait quiet ${bootargs_hwtest}"; sf probe 0:0; sf read ${kernel_addr_r} ${kernel_addr} ${kernel_size}; sf read ${fdt_addr_r} ${fdt_addr} ${fdt_size}; booti ${kernel_addr_r} - ${fdt_addr_r}
|
||||||
|
serial_number=MT-R01A-0326-00747
|
||||||
|
soc=fsl-layerscape
|
||||||
|
stderr=serial@21c0500
|
||||||
|
stdin=serial@21c0500
|
||||||
|
stdout=serial@21c0500
|
||||||
|
vendor=freescale
|
||||||
|
```
|
||||||
@@ -2,16 +2,19 @@
|
|||||||
set -eu
|
set -eu
|
||||||
|
|
||||||
MNT=/mnt
|
MNT=/mnt
|
||||||
ROOT_MNT=/mnt-root
|
CONFIG_MNT=/mnt-config
|
||||||
USB_DEV=/dev/sda
|
USB_DEV=/dev/sda
|
||||||
EMMC_DEV=/dev/mmcblk0
|
EMMC_DEV=/dev/mmcblk0
|
||||||
EMMC_ROOT_PART=/dev/mmcblk0p1
|
|
||||||
CONFIG_DIR=/opt/monok8s/config
|
EMMC_CONFIG_PART=/dev/mmcblk0p1
|
||||||
|
EMMC_ROOTFS_A_PART=/dev/mmcblk0p2
|
||||||
|
EMMC_ROOTFS_B_PART=/dev/mmcblk0p3
|
||||||
|
EMMC_DATA_PART=/dev/mmcblk0p4
|
||||||
|
|
||||||
DEFAULT_GLOB="${MNT}/${BUILD_TAG}_RELEASE_IMAGE"
|
DEFAULT_GLOB="${MNT}/${BUILD_TAG}_RELEASE_IMAGE"
|
||||||
|
|
||||||
cleanup() {
|
cleanup() {
|
||||||
umount "$ROOT_MNT" 2>/dev/null || true
|
umount "$CONFIG_MNT" 2>/dev/null || true
|
||||||
umount "$MNT" 2>/dev/null || true
|
umount "$MNT" 2>/dev/null || true
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -61,7 +64,7 @@ wait_for_partition_ready() {
|
|||||||
return 1
|
return 1
|
||||||
}
|
}
|
||||||
|
|
||||||
mkdir -p "$MNT" "$ROOT_MNT"
|
mkdir -p "$MNT" "$CONFIG_MNT"
|
||||||
trap cleanup EXIT
|
trap cleanup EXIT
|
||||||
|
|
||||||
log "Mounting USB..."
|
log "Mounting USB..."
|
||||||
@@ -108,7 +111,6 @@ echo
|
|||||||
|
|
||||||
printf "Type 'YES' to continue: "
|
printf "Type 'YES' to continue: "
|
||||||
read -r CONFIRM
|
read -r CONFIRM
|
||||||
|
|
||||||
[ "$CONFIRM" = "YES" ] || die "Aborted."
|
[ "$CONFIRM" = "YES" ] || die "Aborted."
|
||||||
|
|
||||||
log "Flashing image to eMMC..."
|
log "Flashing image to eMMC..."
|
||||||
@@ -120,40 +122,45 @@ sync
|
|||||||
reread_partitions
|
reread_partitions
|
||||||
|
|
||||||
log "Waiting for partition nodes..."
|
log "Waiting for partition nodes..."
|
||||||
if ! wait_for_partition_ready "$EMMC_ROOT_PART" 15; then
|
if ! wait_for_partition_ready "$EMMC_CONFIG_PART" 15; then
|
||||||
warn "Initial partition scan did not settle; retrying after another reread..."
|
warn "Initial partition scan did not settle; retrying after another reread..."
|
||||||
reread_partitions
|
reread_partitions
|
||||||
sleep 2
|
sleep 2
|
||||||
wait_for_partition_ready "$EMMC_ROOT_PART" 15 || die "root partition not ready: $EMMC_ROOT_PART"
|
wait_for_partition_ready "$EMMC_CONFIG_PART" 15 || die "config partition not ready: $EMMC_CONFIG_PART"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
# These are useful sanity checks, but not strictly required for copying config.
|
||||||
|
wait_for_partition_ready "$EMMC_ROOTFS_A_PART" 5 || warn "rootfsA partition not ready yet: $EMMC_ROOTFS_A_PART"
|
||||||
|
wait_for_partition_ready "$EMMC_ROOTFS_B_PART" 5 || warn "rootfsB partition not ready yet: $EMMC_ROOTFS_B_PART"
|
||||||
|
wait_for_partition_ready "$EMMC_DATA_PART" 5 || warn "data partition not ready yet: $EMMC_DATA_PART"
|
||||||
|
|
||||||
log "Partition sizes:"
|
log "Partition sizes:"
|
||||||
echo " $(basename "$EMMC_DEV"): $(get_sectors "$EMMC_DEV") sectors"
|
echo " $(basename "$EMMC_DEV"): $(get_sectors "$EMMC_DEV") sectors"
|
||||||
echo " $(basename "$EMMC_ROOT_PART"): $(get_sectors "$EMMC_ROOT_PART") sectors"
|
echo " $(basename "$EMMC_CONFIG_PART"): $(get_sectors "$EMMC_CONFIG_PART") sectors"
|
||||||
|
echo " $(basename "$EMMC_ROOTFS_A_PART"): $(get_sectors "$EMMC_ROOTFS_A_PART") sectors"
|
||||||
|
echo " $(basename "$EMMC_ROOTFS_B_PART"): $(get_sectors "$EMMC_ROOTFS_B_PART") sectors"
|
||||||
|
echo " $(basename "$EMMC_DATA_PART"): $(get_sectors "$EMMC_DATA_PART") sectors"
|
||||||
|
|
||||||
if [ -n "$ENV_FILES" ]; then
|
if [ -n "$ENV_FILES" ]; then
|
||||||
log "Mounting flashed root partition..."
|
log "Mounting flashed config partition..."
|
||||||
mount "$EMMC_ROOT_PART" "$ROOT_MNT" || {
|
mount -t vfat "$EMMC_CONFIG_PART" "$CONFIG_MNT" || {
|
||||||
warn "Mount failed; retrying once after partition reread..."
|
warn "Mount failed; retrying once after partition reread..."
|
||||||
reread_partitions
|
reread_partitions
|
||||||
sleep 2
|
sleep 2
|
||||||
mount "$EMMC_ROOT_PART" "$ROOT_MNT"
|
mount -t vfat "$EMMC_CONFIG_PART" "$CONFIG_MNT"
|
||||||
}
|
}
|
||||||
|
|
||||||
log "Creating config dir: $CONFIG_DIR"
|
log "Copying env files to config partition..."
|
||||||
mkdir -p "$ROOT_MNT$CONFIG_DIR"
|
|
||||||
|
|
||||||
log "Copying env files..."
|
|
||||||
for f in $ENV_FILES; do
|
for f in $ENV_FILES; do
|
||||||
base="$(basename "$f")"
|
base="$(basename "$f")"
|
||||||
cp "$f" "$ROOT_MNT$CONFIG_DIR/$base"
|
cp "$f" "$CONFIG_MNT/$base"
|
||||||
echo " copied: $base"
|
echo " copied: $base"
|
||||||
done
|
done
|
||||||
|
|
||||||
log "Syncing copied config..."
|
log "Syncing copied config..."
|
||||||
sync
|
sync
|
||||||
|
|
||||||
umount "$ROOT_MNT"
|
umount "$CONFIG_MNT"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
log "Done."
|
log "Done."
|
||||||
|
|||||||
174
macos/flashusb.sh
Executable file
174
macos/flashusb.sh
Executable file
@@ -0,0 +1,174 @@
|
|||||||
|
#!/bin/sh
|
||||||
|
set -eu
|
||||||
|
|
||||||
|
### User-configurable vars
|
||||||
|
IMG="./out/monok8s-dev.img.gz"
|
||||||
|
DEFAULT_DISK="/dev/disk7" # whole disk, not a partition
|
||||||
|
CONFIG_PART_SUFFIX="s1" # config partition after flashing
|
||||||
|
ENV_SEARCH_DIR="./out" # optional; leave empty to use image dir
|
||||||
|
|
||||||
|
MNT="/tmp/monok8s-usb-config.$$"
|
||||||
|
|
||||||
|
cleanup() {
|
||||||
|
if mount | grep -q "on ${MNT} "; then
|
||||||
|
diskutil unmount "$MNT" >/dev/null 2>&1 || true
|
||||||
|
fi
|
||||||
|
rmdir "$MNT" >/dev/null 2>&1 || true
|
||||||
|
}
|
||||||
|
|
||||||
|
log() {
|
||||||
|
echo "[*] $*"
|
||||||
|
}
|
||||||
|
|
||||||
|
warn() {
|
||||||
|
echo "[!] $*" >&2
|
||||||
|
}
|
||||||
|
|
||||||
|
die() {
|
||||||
|
echo "[!] ERROR: $*" >&2
|
||||||
|
exit 1
|
||||||
|
}
|
||||||
|
|
||||||
|
require_cmd() {
|
||||||
|
command -v "$1" >/dev/null 2>&1 || die "Missing required command: $1"
|
||||||
|
}
|
||||||
|
|
||||||
|
wait_for_disk() {
|
||||||
|
dev="$1"
|
||||||
|
timeout="${2:-15}"
|
||||||
|
i=0
|
||||||
|
while [ "$i" -lt "$timeout" ]; do
|
||||||
|
[ -e "$dev" ] && return 0
|
||||||
|
i=$((i + 1))
|
||||||
|
sleep 1
|
||||||
|
done
|
||||||
|
return 1
|
||||||
|
}
|
||||||
|
|
||||||
|
wait_for_mountable_partition() {
|
||||||
|
dev="$1"
|
||||||
|
timeout="${2:-20}"
|
||||||
|
i=0
|
||||||
|
while [ "$i" -lt "$timeout" ]; do
|
||||||
|
if [ -e "$dev" ] && diskutil info "$dev" >/dev/null 2>&1; then
|
||||||
|
return 0
|
||||||
|
fi
|
||||||
|
i=$((i + 1))
|
||||||
|
sleep 1
|
||||||
|
done
|
||||||
|
return 1
|
||||||
|
}
|
||||||
|
|
||||||
|
### Sanity checks
|
||||||
|
require_cmd diskutil
|
||||||
|
require_cmd gunzip
|
||||||
|
require_cmd dd
|
||||||
|
require_cmd sync
|
||||||
|
require_cmd mount
|
||||||
|
require_cmd find
|
||||||
|
require_cmd cp
|
||||||
|
require_cmd sed
|
||||||
|
require_cmd stat
|
||||||
|
require_cmd pv
|
||||||
|
|
||||||
|
printf "disk ($DEFAULT_DISK): "
|
||||||
|
read -r TARGET_DISK
|
||||||
|
|
||||||
|
if [ -z "$TARGET_DISK" ]; then
|
||||||
|
TARGET_DISK="$DEFAULT_DISK"
|
||||||
|
fi
|
||||||
|
|
||||||
|
TARGET_RAW_DISK="/dev/r$(basename "$TARGET_DISK")"
|
||||||
|
TARGET_BASENAME="$(basename "$TARGET_DISK")"
|
||||||
|
|
||||||
|
### Derived vars
|
||||||
|
TARGET_CONFIG_PART="/dev/${TARGET_BASENAME}${CONFIG_PART_SUFFIX}"
|
||||||
|
IMG_DIR="$(cd "$(dirname "$IMG")" && pwd)"
|
||||||
|
SEARCH_DIR="${ENV_SEARCH_DIR:-$IMG_DIR}"
|
||||||
|
IMG_SIZE_BYTES="$(stat -f%z "$IMG")"
|
||||||
|
|
||||||
|
[ -f "$IMG" ] || die "Image not found: $IMG"
|
||||||
|
[ -b "$TARGET_DISK" ] || die "Target disk not found: $TARGET_DISK"
|
||||||
|
[ "$(id -u)" -eq 0 ] || die "Run this script with sudo"
|
||||||
|
|
||||||
|
case "$TARGET_DISK" in
|
||||||
|
/dev/disk[0-9]*)
|
||||||
|
;;
|
||||||
|
*)
|
||||||
|
die "TARGET_DISK must look like /dev/diskN"
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
|
||||||
|
mkdir -p "$MNT"
|
||||||
|
trap cleanup EXIT
|
||||||
|
|
||||||
|
log "Image: $IMG"
|
||||||
|
log "Compressed image size: $IMG_SIZE_BYTES bytes"
|
||||||
|
log "Target disk: $TARGET_DISK"
|
||||||
|
log "Raw target disk: $TARGET_RAW_DISK"
|
||||||
|
log "Expected config partition after flash: $TARGET_CONFIG_PART"
|
||||||
|
|
||||||
|
log "Target disk info:"
|
||||||
|
diskutil info "$TARGET_DISK" || die "Unable to inspect target disk"
|
||||||
|
|
||||||
|
echo
|
||||||
|
printf "Type 'YES' to continue: "
|
||||||
|
read -r CONFIRM
|
||||||
|
[ "$CONFIRM" = "YES" ] || die "Aborted."
|
||||||
|
|
||||||
|
log "Unmounting target disk..."
|
||||||
|
diskutil unmountDisk force "$TARGET_DISK" || die "Failed to unmount $TARGET_DISK"
|
||||||
|
|
||||||
|
log "Flashing image with progress..."
|
||||||
|
pv -s "$IMG_SIZE_BYTES" "$IMG" \
|
||||||
|
| gunzip \
|
||||||
|
| dd of="$TARGET_RAW_DISK" bs=1m
|
||||||
|
|
||||||
|
log "Syncing writes..."
|
||||||
|
sync
|
||||||
|
|
||||||
|
log "Ejecting and re-reading disk..."
|
||||||
|
diskutil eject "$TARGET_DISK" >/dev/null 2>&1 || true
|
||||||
|
sleep 2
|
||||||
|
|
||||||
|
log "Waiting for disk to come back..."
|
||||||
|
if ! wait_for_disk "$TARGET_DISK" 15; then
|
||||||
|
warn "Disk node did not reappear quickly. You may need to replug the drive."
|
||||||
|
fi
|
||||||
|
|
||||||
|
log "Disk layout after flashing:"
|
||||||
|
diskutil list "$TARGET_DISK" || warn "Could not list flashed disk yet"
|
||||||
|
|
||||||
|
ENV_FILES="$(find "$SEARCH_DIR" -maxdepth 1 -type f -name '*.env' | sort || true)"
|
||||||
|
|
||||||
|
if [ -n "$ENV_FILES" ]; then
|
||||||
|
log "Found env files:"
|
||||||
|
echo "$ENV_FILES" | sed 's/^/ /'
|
||||||
|
|
||||||
|
log "Waiting for config partition..."
|
||||||
|
wait_for_mountable_partition "$TARGET_CONFIG_PART" 20 || die "Config partition not ready: $TARGET_CONFIG_PART"
|
||||||
|
|
||||||
|
log "Mounting flashed config partition..."
|
||||||
|
diskutil mount -mountPoint "$MNT" "$TARGET_CONFIG_PART" >/dev/null || die "Failed to mount $TARGET_CONFIG_PART"
|
||||||
|
|
||||||
|
log "Copying env files to config partition..."
|
||||||
|
echo "$ENV_FILES" | while IFS= read -r f; do
|
||||||
|
[ -n "$f" ] || continue
|
||||||
|
base="$(basename "$f")"
|
||||||
|
cp "$f" "$MNT/$base"
|
||||||
|
echo " copied: $base"
|
||||||
|
done
|
||||||
|
|
||||||
|
log "Syncing copied config..."
|
||||||
|
sync
|
||||||
|
|
||||||
|
log "Config partition contents:"
|
||||||
|
ls -la "$MNT" || true
|
||||||
|
|
||||||
|
log "Unmounting config partition..."
|
||||||
|
diskutil unmount "$MNT" >/dev/null || warn "Unmount failed for $MNT"
|
||||||
|
else
|
||||||
|
log "No .env files found in $SEARCH_DIR"
|
||||||
|
fi
|
||||||
|
|
||||||
|
log "Done."
|
||||||
Reference in New Issue
Block a user