Blob Blame History Raw
#!/usr/bin/python3
# -*- coding: utf-8 -*-
# Author: KaratekHD <karatekhd@opensuse.org>
#
# Copyright (c) 2021 KaratekHD.
# is program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License along
# with this program; if not, see <http://www.gnu.org/licenses/>.
#

import argparse
import os
import sys
import tarfile

from termcolor import colored

parser = argparse.ArgumentParser(
    description="Deploy openSUSE Tumbleweed to the Mars MA3.")
parser.add_argument("-r", "--rootfs", help="Path to rottfs.tar", required=True)
parser.add_argument(
    "-d",
    "--device",
    help="Deviceprefix to deploy to (e.g. /dev/mmcblk0p)",
    required=True)
parser.add_argument(
    "-i",
    "--input_dir",
    help="Build files generated by build.sh",
    required=True)
args = parser.parse_args()
rootfs_path = args.rootfs
block = args.device


# Check if script is run as root
if os.geteuid() != 0:
    print(colored("Script must be run as root, relaunching...", "cyan"))
    # Relaunch script as root
    # Get all args to one string
    os.system("sudo python3 " + " ".join(sys.argv))
    # Exit script
    sys.exit(1)

# Check if args.input-dir is a directory
if not os.path.isdir(args.input_dir):
    print(colored("Input directory is invalid!", "red"))
    sys.exit(1)
os.chdir(args.input_dir)
# Check if block device exists
if not os.path.exists(block):
    print(colored("Block device does not exist", "red"))
    sys.exit(1)

# Check if something is mounted on /mnt abort if so
if os.path.ismount("/mnt"):
    print(colored("Please unmount /mnt before running this script", "red"))
    sys.exit(1)

# Check if /mnt/boot exists and create if not
if not os.path.exists("/mnt/boot"):
    os.makedirs("/mnt/boot")
# Check if /mnt/rootfs exists and create if not
if not os.path.exists("/mnt/rootfs"):
    os.makedirs("/mnt/rootfs")

# Umount all partitions
# Check if /mnt/rootfs is mounted
if os.path.ismount("/mnt/rootfs"):
    print(colored("Unmounting /mnt/rootfs", "yellow"))
    os.system("umount -l /mnt/rootfs")
# Check if /mnt/boot is mounted
if os.path.ismount("/mnt/boot"):
    print(colored("Unmounting /mnt/boot"))
    os.system("umount -l /mnt/boot")

# TODO: Partitioning of the SD card

# Format the SD card
print(colored("Formatting partition 1 with fat32...", "yellow"))
os.system("mkfs.vfat -F 32 -n BOOT {}1".format(block))
print(colored("Formatted partition 1", "green"))
print(colored("Formatting partition 3 with ext2...", "yellow"))
os.system("mkfs.ext2 -L rootfs {}3".format(block))
print(colored("Formatted partition 3", "green"))

# Flash preloader
print(colored("Flashing preloader...", "yellow"))
os.system("dd if=preloader-mkpimage.bin of={}2 status=progress".format(block))
print(colored("Preloader flashed!", "green"))
print(colored("Syncing...", "yellow"))
os.system("sync")
print(colored("Synced!", "green"))

# Check if device is mounted
if not os.path.ismount("/mnt/rootfs"):
    print(colored("Mounting /mnt/rootfs", "yellow"))
    os.system("sudo mount {}3 /mnt/rootfs".format(block))
if not os.path.ismount("/mnt/boot"):
    print(colored("Mounting /mnt/boot", "yellow"))
    os.system("sudo mount {}1 /mnt/boot".format(block))

print(colored("Copying files to /mnt/boot", "yellow"))

# List of files to copy
files = ["uImage", "devicetree.dtb", "fpga.rbf", "u-boot.img", "uboot.scr"]

# Copy files to /mnt/boot with progress bar
for file in files:
    print(colored("- " + file, "green"))
    with open(file, "rb") as f:
        with open("/mnt/boot/" + file, "wb") as f2:
            while True:
                data = f.read(1024)
                if not data:
                    break
                f2.write(data)

# Remove everything from /mnt/rootfs
print(colored("Removing everything from /mnt/rootfs...", "yellow"))
os.system("rm -rf /mnt/rootfs/*")

# Extract rootfs from tarfile to /mnt/rootfs
# Check wether tarfile is .gz or .xz
compression = ""
if rootfs_path.endswith(".gz") or rootfs_path.endswith(".xz"):
    if rootfs_path.endswith(".gz"):
        compression = "gz"
    elif rootfs_path.endswith(".xz"):
        compression = "xz"
    print(
        colored(
            "Extracting rootfs from {} to /mnt/rootfs...".format(rootfs_path),
            "yellow"))
    with tarfile.open(rootfs_path, "r:" + compression) as tar:
        tar.extractall("/mnt/rootfs")
    print(colored("Extracted {} to /mnt/rootfs".format(rootfs_path), "green"))
else:
    # Extract .tar
    print(colored("Extracting {} to /mnt/rootfs...".format(rootfs_path), "yellow"))
    with tarfile.open(rootfs_path) as tar:
        tar.extractall("/mnt/rootfs")
    print(colored("Extracted {} to /mnt/rootfs".format(rootfs_path), "green"))
print(colored("Syncing...", "yellow"))
os.system("sync")
print(colored("Umounting devices...", "yellow"))
os.system("umount /mnt/boot")
os.system("umount /mnt/rootfs")

print(colored("Done", "green"))