Commit 29eada26 authored by Chebanov Kostiantyn's avatar Chebanov Kostiantyn

Key Changes Made:

1. Shebang line: Changed from #!/usr/bin/env python to #!/usr/bin/env python3

2. Print statements: Converted all print statements to
function calls with parentheses

3. String formatting: Used f-strings (Python 3.6+) for cleaner string formatting

4. subprocess.check_output: Updated error handling to use
stderr=subprocess.DEVNULL

5. Device naming fix:
Added logic to handle both /dev/sdX and /dev/mmcblkX devices correctly
(mmcblk devices use p1, p2 for partitions)

6. Better progress indication: Added dots while waiting for devices

7. Cleaner error messages: Improved error handling and messages

Issue-ID: 1

Signed-off-by: Chebanov Kostiantyn
parent 026d36a1
#!/usr/bin/env python #!/usr/bin/env python3
''' '''
# Copyright (C) 2020, Elphel.inc. # Copyright (C) 2020, Elphel.inc.
# Usage: known # Usage: known
...@@ -16,7 +16,7 @@ ...@@ -16,7 +16,7 @@
# You should have received a copy of the GNU General Public License # You should have received a copy of the GNU General Public License
# along with this program. If not, see <http:#www.gnu.org/licenses/>. # along with this program. If not, see <http:#www.gnu.org/licenses/>.
@author: Oleg K Dzhimiev @author: Oleg K Dzhimiev, Konstantyn Chebanov
@copyright: 2016 Elphel, Inc. @copyright: 2016 Elphel, Inc.
@license: GPLv3.0+ @license: GPLv3.0+
@contact: oleg@elphel.com @contact: oleg@elphel.com
...@@ -27,7 +27,7 @@ ...@@ -27,7 +27,7 @@
__author__ = "Elphel" __author__ = "Elphel"
__copyright__ = "Copyright 2020, Elphel, Inc." __copyright__ = "Copyright 2020, Elphel, Inc."
__license__ = "GPL" __license__ = "GPL"
__version__ = "3.0+" __version__ = "4.0"
__maintainer__ = "Oleg K Dzhimiev" __maintainer__ = "Oleg K Dzhimiev"
__email__ = "oleg@elphel.com" __email__ = "oleg@elphel.com"
__status__ = "Development" __status__ = "Development"
...@@ -43,11 +43,13 @@ import time ...@@ -43,11 +43,13 @@ import time
# (?) useful link 3: http://unix.stackexchange.com/questions/53890/partitioning-disk-image-file # (?) useful link 3: http://unix.stackexchange.com/questions/53890/partitioning-disk-image-file
def shout(cmd): def shout(cmd):
#subprocess.call prints to console """Execute shell command and print to console"""
subprocess.call(cmd,shell=True) subprocess.call(cmd, shell=True)
def print_help(): def print_help():
print("\nDesctiption:\n") """Print help information"""
print(" * Required programs: kpartx") print("\nDescription:\n")
print(" * Required programs: kpartx, parted")
print(" * Run under superuser. Make sure the correct device is provided.") print(" * Run under superuser. Make sure the correct device is provided.")
print(" * Erases partition table on the provided device") print(" * Erases partition table on the provided device")
print(" * If given someimage.img file - burns the sd card from it") print(" * If given someimage.img file - burns the sd card from it")
...@@ -56,50 +58,55 @@ def print_help(): ...@@ -56,50 +58,55 @@ def print_help():
print(" * Creates EXT4 partition labeled 'root' and extracts rootfs.tar.gz") print(" * Creates EXT4 partition labeled 'root' and extracts rootfs.tar.gz")
print("\nExamples:\n") print("\nExamples:\n")
print(" * Use files (names are hardcoded) from the current dir ('build/tmp/deploy/images/elphel393/mmc/'):") print(" * Use files (names are hardcoded) from the current dir ('build/tmp/deploy/images/elphel393/mmc/'):")
print(" ~$ python make_sdcard.py /dev/sdz") print(" ~$ sudo python3 make_sdcard.py /dev/sdz")
print(" * Use someimage.img file:") print(" * Use someimage.img file:")
print(" ~$ python make_sdcard.py /dev/sdz someimage.img") print(" ~$ sudo python3 make_sdcard.py /dev/sdz someimage.img")
print(" * To write *.iso use a standard os tool that burns bootable USB drives") print(" * To write *.iso use a standard OS tool that burns bootable USB drives")
print("") print("")
def check_program_installed(program): def check_program_installed(program):
try: """Check if a program is installed"""
result = subprocess.check_output("which "+program,shell=True) try:
except subprocess.CalledProcessError: result = subprocess.check_output(["which", program], stderr=subprocess.DEVNULL)
print("Program missing: "+program) return True
return False except subprocess.CalledProcessError:
return True print(f"Program missing: {program}")
return False
# Check required programs
required_programs = ( required_programs = (
"parted", "parted",
"kpartx" "kpartx"
) )
something_is_missing = False something_is_missing = False
for i in required_programs: for program in required_programs:
tmpres = check_program_installed(i) if not check_program_installed(program):
something_is_missing = something_is_missing or (not tmpres) something_is_missing = True
if something_is_missing:
sys.exit()
if something_is_missing:
print("\nPlease install missing programs and run again.")
sys.exit(1)
# Parse command line arguments
if len(sys.argv) > 1: if len(sys.argv) > 1:
DEVICE = sys.argv[1] DEVICE = sys.argv[1]
else: else:
DEVICE = "" DEVICE = ""
print_help() print_help()
sys.exit() sys.exit(0)
if len(sys.argv) > 2: if len(sys.argv) > 2:
IMAGE_FILE = sys.argv[2] IMAGE_FILE = sys.argv[2]
if not IMAGE_FILE.endswith(".img"): if not IMAGE_FILE.endswith(".img"):
print("ERROR: Please, provide *.img file or leave argument empty to use certain image files in the current dir") print("ERROR: Please provide *.img file or leave argument empty to use certain image files in the current dir")
sys.exit() sys.exit(1)
else: else:
IMAGE_FILE = "" IMAGE_FILE = ""
print("NOTE: if plasma crash do not worry") print("NOTE: If plasma crashes, do not worry")
#params # Parameters
SDCARD_SIZE = 4000 SDCARD_SIZE = 4000
PT_TYPE = "msdos" PT_TYPE = "msdos"
...@@ -112,7 +119,7 @@ BOOT_FILE_LIST = ( ...@@ -112,7 +119,7 @@ BOOT_FILE_LIST = (
"u-boot-dtb.img", "u-boot-dtb.img",
"devicetree.dtb", "devicetree.dtb",
"uImage" "uImage"
) )
ROOT_LABEL = "root" ROOT_LABEL = "root"
ROOT_FS = "ext4" ROOT_FS = "ext4"
...@@ -120,101 +127,119 @@ ROOT_ARCHIVE = "rootfs.tar.gz" ...@@ -120,101 +127,119 @@ ROOT_ARCHIVE = "rootfs.tar.gz"
something_is_missing = False something_is_missing = False
if IMAGE_FILE=="": # Check if required files exist
print("Preparing SD card using files: "+str(BOOT_FILE_LIST + (ROOT_ARCHIVE,))) if IMAGE_FILE == "":
print(f"Preparing SD card using files: {BOOT_FILE_LIST + (ROOT_ARCHIVE,)}")
for f in BOOT_FILE_LIST + (ROOT_ARCHIVE,): for f in BOOT_FILE_LIST + (ROOT_ARCHIVE,):
if not os.path.isfile(f): if not os.path.isfile(f):
print("file "+f+" is missing") print(f"File {f} is missing")
something_is_missing = True something_is_missing = True
else: else:
print("Preparing SD card from "+IMAGE_FILE) print(f"Preparing SD card from {IMAGE_FILE}")
if not os.path.isfile(IMAGE_FILE): if not os.path.isfile(IMAGE_FILE):
print("No such file") print("No such file")
something_is_missing = True something_is_missing = True
if not os.path.exists(DEVICE): if not os.path.exists(DEVICE):
print("No such device") print(f"No such device: {DEVICE}")
something_is_missing = True something_is_missing = True
if something_is_missing: if something_is_missing:
sys.exit() sys.exit(1)
print("= Erase partition table on "+DEVICE+" and everything else")
#shout("dd if=/dev/zero of="+DEVICE+" bs=1M count="+str(BOOT_SIZE+2))
shout("dd if=/dev/zero of="+DEVICE+" bs=512 count=2")
shout("dd if=/dev/zero of="+DEVICE+" bs=1MB count=1 seek=1") # Main execution
shout("dd if=/dev/zero of="+DEVICE+" bs=1MB count=1 seek="+str(BOOT_SIZE)) print(f"= Erase partition table on {DEVICE} and everything else")
shout(f"dd if=/dev/zero of={DEVICE} bs=512 count=2")
shout(f"dd if=/dev/zero of={DEVICE} bs=1MB count=1 seek=1")
shout(f"dd if=/dev/zero of={DEVICE} bs=1MB count=1 seek={BOOT_SIZE}")
print("= Create partition table") print("= Create partition table")
shout("parted -s "+DEVICE+" mktable "+PT_TYPE) shout(f"parted -s {DEVICE} mktable {PT_TYPE}")
print("= Create FAT partition")
shout("parted -s "+DEVICE+" mkpart primary "+BOOT_FS+" 1 "+str(BOOT_SIZE))
shout("parted -s "+DEVICE+" mkpart primary "+ROOT_FS+" "+str(BOOT_SIZE+1)+" 100%")
# no need?
shout("parted -s "+DEVICE+" align-check optimal 1")
shout("parted -s "+DEVICE+" align-check optimal 2")
#sys.exit() print("= Create partitions")
shout(f"parted -s {DEVICE} mkpart primary {BOOT_FS} 1 {BOOT_SIZE}")
shout(f"parted -s {DEVICE} mkpart primary {ROOT_FS} {BOOT_SIZE + 1} 100%")
# Check alignment
shout(f"parted -s {DEVICE} align-check optimal 1")
shout(f"parted -s {DEVICE} align-check optimal 2")
# Wait for device nodes to be created
devs_created = False devs_created = False
partition1 = f"{DEVICE}1" if not "mmcblk" in DEVICE else f"{DEVICE}p1"
partition2 = f"{DEVICE}2" if not "mmcblk" in DEVICE else f"{DEVICE}p2"
print("= Waiting for device nodes...")
while not devs_created: while not devs_created:
if (os.path.exists(DEVICE+"1")) and (os.path.exists(DEVICE+"2")): if os.path.exists(partition1) and os.path.exists(partition2):
devs_created = True devs_created = True
else: else:
print("waiting") print(".", end="", flush=True)
time.sleep(0.5) time.sleep(0.5)
print()
time.sleep(1) time.sleep(1)
print("= Format") print("= Format partitions")
shout("mkfs.vfat "+DEVICE+"1 -F 32 -n "+BOOT_LABEL) shout(f"mkfs.vfat {partition1} -F 32 -n {BOOT_LABEL}")
shout("mkfs.ext4 "+DEVICE+"2 -F -L "+ROOT_LABEL) shout(f"mkfs.ext4 {partition2} -F -L {ROOT_LABEL}")
shout("mkdir tmp") # Create temporary mount point
shout("mkdir -p tmp")
if IMAGE_FILE=="": if IMAGE_FILE == "":
shout("mount "+DEVICE+"1 tmp") # Copy boot files
print("= Copying boot files...")
shout(f"mount {partition1} tmp")
for i in BOOT_FILE_LIST: for i in BOOT_FILE_LIST:
print(" "+i) print(f" {i}")
shout("cp "+i+" tmp") shout(f"cp {i} tmp")
shout("umount tmp") shout("umount tmp")
shout("mount "+DEVICE+"2 tmp") # Extract root filesystem
shout("tar -C tmp/ -xzpf "+ROOT_ARCHIVE) print("= Extracting root filesystem...")
shout(f"mount {partition2} tmp")
shout(f"tar -C tmp/ -xzpf {ROOT_ARCHIVE}")
shout("umount tmp") shout("umount tmp")
else: else:
# Copy from image file
print("= Copying from image file...")
shout("modprobe dm-mod") shout("modprobe dm-mod")
shout("kpartx -av "+IMAGE_FILE) shout(f"kpartx -av {IMAGE_FILE}")
#wait for devices # Wait for mapper devices
devs_created = False devs_created = False
print("= Waiting for mapper devices...")
while not devs_created: while not devs_created:
if (os.path.exists("/dev/mapper/loop0p1")) and (os.path.exists("/dev/mapper/loop0p2")): if os.path.exists("/dev/mapper/loop0p1") and os.path.exists("/dev/mapper/loop0p2"):
devs_created = True devs_created = True
else: else:
print("waiting") print(".", end="", flush=True)
time.sleep(0.5) time.sleep(0.5)
print()
shout("mkdir tmp2") shout("mkdir -p tmp2")
shout("mount "+DEVICE+"1 tmp") # Copy boot partition
print("= Copying boot partition...")
shout(f"mount {partition1} tmp")
shout("mount /dev/mapper/loop0p1 tmp2") shout("mount /dev/mapper/loop0p1 tmp2")
shout("rsync -a tmp2/ tmp") shout("rsync -a tmp2/ tmp")
shout("umount tmp") shout("umount tmp")
shout("umount tmp2") shout("umount tmp2")
shout("mount "+DEVICE+"2 tmp") # Copy root partition
print("= Copying root partition...")
shout(f"mount {partition2} tmp")
shout("mount /dev/mapper/loop0p2 tmp2") shout("mount /dev/mapper/loop0p2 tmp2")
shout("rsync -a tmp2/ tmp") shout("rsync -a tmp2/ tmp")
shout("umount tmp") shout("umount tmp")
shout("umount tmp2") shout("umount tmp2")
shout("rm -rf tmp2") shout("rm -rf tmp2")
shout(f"kpartx -dv {IMAGE_FILE}")
shout("kpartx -dv "+IMAGE_FILE)
# Clean up
shout("rm -rf tmp") shout("rm -rf tmp")
print("Done") print("\nDone! SD card is ready for use.")
print(f"You can now safely remove {DEVICE}")
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment