2021-08-14 13:31:04 +02:00
import atexit
2021-09-29 02:00:59 +02:00
from constants import FLASH_PARTS , LOCATIONS
2021-08-17 20:57:31 +02:00
from fastboot import fastboot_flash
2021-08-14 13:31:04 +02:00
import shutil
2021-08-17 20:57:31 +02:00
from image import dump_bootimg , dump_lk2nd , dump_qhypstub , get_device_and_flavour , get_image_name
2021-08-05 20:26:48 +02:00
import os
import subprocess
import click
2021-08-14 13:31:04 +02:00
import tempfile
2021-09-29 23:18:12 +02:00
from wrapper import enforce_wrap
2021-09-30 05:04:42 +02:00
from image import resize_fs
2021-09-29 02:00:59 +02:00
BOOTIMG = FLASH_PARTS [ ' BOOTIMG ' ]
LK2ND = FLASH_PARTS [ ' LK2ND ' ]
QHYPSTUB = FLASH_PARTS [ ' QHYPSTUB ' ]
ROOTFS = FLASH_PARTS [ ' ROOTFS ' ]
2021-08-05 20:26:48 +02:00
2021-08-14 13:31:04 +02:00
2021-08-05 20:26:48 +02:00
@click.command ( name = ' flash ' )
@click.argument ( ' what ' )
@click.argument ( ' location ' , required = False )
2021-09-09 20:23:23 +02:00
def cmd_flash ( what , location ) :
2021-09-29 23:18:12 +02:00
enforce_wrap ( )
2021-08-05 20:26:48 +02:00
device , flavour = get_device_and_flavour ( )
image_name = get_image_name ( device , flavour )
2021-09-29 02:00:59 +02:00
if what not in FLASH_PARTS . values ( ) :
raise Exception ( f ' Unknown what " { what } " , must be one of { " , " . join ( FLASH_PARTS . values ( ) ) } ' )
2021-08-05 20:26:48 +02:00
if what == ROOTFS :
2021-09-29 02:00:59 +02:00
if location is None :
raise Exception ( f ' You need to specify a location to flash { what } to ' )
2021-08-17 20:57:31 +02:00
if location not in LOCATIONS :
2021-09-29 02:00:59 +02:00
raise Exception ( f ' Invalid location { location } . Choose one of { " , " . join ( LOCATIONS ) } ' )
2021-08-05 20:26:48 +02:00
2021-08-14 13:31:04 +02:00
path = ' '
2021-08-05 20:26:48 +02:00
dir = ' /dev/disk/by-id '
for file in os . listdir ( dir ) :
sanitized_file = file . replace ( ' - ' , ' ' ) . replace ( ' _ ' , ' ' ) . lower ( )
if f ' jumpdrive { location . split ( " - " ) [ 0 ] } ' in sanitized_file :
path = os . path . realpath ( os . path . join ( dir , file ) )
2021-08-08 18:32:42 +02:00
result = subprocess . run ( [ ' lsblk ' , path , ' -o ' , ' SIZE ' ] , capture_output = True )
2021-08-05 20:26:48 +02:00
if result . returncode != 0 :
2021-09-29 02:00:59 +02:00
raise Exception ( f ' Failed to lsblk { path } ' )
2021-08-05 20:26:48 +02:00
if result . stdout == b ' SIZE \n 0B \n ' :
2021-09-29 02:00:59 +02:00
raise Exception (
2021-08-08 18:32:42 +02:00
f ' Disk { path } has a size of 0B. That probably means it is not available (e.g. no microSD inserted or no microSD card slot installed in the device) or corrupt or defect '
)
2021-08-14 13:31:04 +02:00
if path == ' ' :
2021-09-29 02:00:59 +02:00
raise Exception ( ' Unable to discover Jumpdrive ' )
2021-08-14 13:31:04 +02:00
image_dir = tempfile . gettempdir ( )
image_path = os . path . join ( image_dir , f ' minimal- { image_name } ' )
def clean_dir ( ) :
shutil . rmtree ( image_dir )
atexit . register ( clean_dir )
shutil . copyfile ( image_name , image_path )
2021-09-30 05:04:42 +02:00
resize_fs ( image_path , shrink = True )
2021-08-05 20:26:48 +02:00
if location . endswith ( ' -file ' ) :
2021-08-14 13:31:04 +02:00
part_mount = ' /mnt/kupfer/fs '
if not os . path . exists ( part_mount ) :
os . makedirs ( part_mount )
def umount ( ) :
subprocess . run (
[
' umount ' ,
' -lc ' ,
part_mount ,
] ,
stderr = subprocess . DEVNULL ,
)
atexit . register ( umount )
result = subprocess . run ( [
' mount ' ,
path ,
part_mount ,
] )
if result . returncode != 0 :
2021-09-29 02:00:59 +02:00
raise Exception ( f ' Failed to mount { path } to { part_mount } ' )
2021-08-14 13:31:04 +02:00
dir = os . path . join ( part_mount , ' .stowaways ' )
if not os . path . exists ( dir ) :
os . makedirs ( dir )
result = subprocess . run ( [
' rsync ' ,
' --archive ' ,
' --inplace ' ,
' --partial ' ,
' --progress ' ,
' --human-readable ' ,
image_path ,
os . path . join ( dir , ' kupfer.img ' ) ,
] )
if result . returncode != 0 :
2021-09-29 02:00:59 +02:00
raise Exception ( f ' Failed to mount { path } to { part_mount } ' )
2021-08-05 20:26:48 +02:00
else :
2021-08-08 18:32:42 +02:00
result = subprocess . run ( [
' dd ' ,
2021-08-14 13:31:04 +02:00
f ' if= { image_path } ' ,
2021-08-08 18:32:42 +02:00
f ' of= { path } ' ,
' bs=20M ' ,
' iflag=direct ' ,
' oflag=direct ' ,
' status=progress ' ,
2021-08-14 13:31:04 +02:00
' conv=sync,noerror ' ,
2021-08-08 18:32:42 +02:00
] )
2021-08-05 20:26:48 +02:00
if result . returncode != 0 :
2021-09-29 02:00:59 +02:00
raise Exception ( f ' Failed to flash { image_path } to { path } ' )
2021-08-05 20:26:48 +02:00
elif what == BOOTIMG :
path = dump_bootimg ( image_name )
2021-08-17 20:57:31 +02:00
fastboot_flash ( ' boot ' , path )
elif what == LK2ND :
path = dump_lk2nd ( image_name )
fastboot_flash ( ' lk2nd ' , path )
elif what == QHYPSTUB :
path = dump_qhypstub ( image_name )
fastboot_flash ( ' qhypstub ' , path )
2021-08-05 20:26:48 +02:00
else :
2021-09-29 02:00:59 +02:00
raise Exception ( f ' Unknown what " { what } " , this must be a bug in kupferbootstrap! ' )