Compare commits
14 Commits
master
...
on-device2
Author | SHA1 | Date |
---|---|---|
Oliver Smith | ed4072956d | |
Oliver Smith | 8d0f3a1c55 | |
Oliver Smith | 9a0ef38ee3 | |
Oliver Smith | 21a6c7189b | |
Oliver Smith | 4a5137064d | |
Oliver Smith | 4bebad987d | |
Oliver Smith | fdc2fe309e | |
Oliver Smith | c940c96078 | |
Oliver Smith | 854c96f63f | |
Oliver Smith | 67e3c5ad1a | |
Oliver Smith | d8c84c8912 | |
Oliver Smith | 3f1f21add5 | |
Oliver Smith | 9da12415b8 | |
Oliver Smith | ac7d66fade |
|
@ -67,10 +67,11 @@ def shutdown(args, only_install_related=False):
|
|||
path = path_outside[len(chroot):]
|
||||
pmb.install.losetup.umount(args, path, auto_init=False)
|
||||
|
||||
# Umount device rootfs chroot
|
||||
chroot_rootfs = args.work + "/chroot_rootfs_" + args.device
|
||||
if os.path.exists(chroot_rootfs):
|
||||
pmb.helpers.mount.umount_all(args, chroot_rootfs)
|
||||
# Umount device rootfs and installer chroots
|
||||
for prefix in ["rootfs", "installer"]:
|
||||
path = f"{args.work}/chroot_{prefix}_{args.device}"
|
||||
if os.path.exists(path):
|
||||
pmb.helpers.mount.umount_all(args, path)
|
||||
|
||||
if not only_install_related:
|
||||
# Umount all folders inside args.work
|
||||
|
|
|
@ -53,6 +53,7 @@ def zap(args, confirm=True, dry=False, pkgs_local=False, http=False,
|
|||
patterns = [
|
||||
"chroot_native",
|
||||
"chroot_buildroot_*",
|
||||
"chroot_installer_*",
|
||||
"chroot_rootfs_*",
|
||||
]
|
||||
if pkgs_local:
|
||||
|
|
|
@ -25,6 +25,7 @@ import pmb.helpers.run
|
|||
import pmb.helpers.aportupgrade
|
||||
import pmb.helpers.status
|
||||
import pmb.install
|
||||
import pmb.install.blockdevice
|
||||
import pmb.parse
|
||||
import pmb.qemu
|
||||
|
||||
|
@ -132,6 +133,14 @@ def chroot(args):
|
|||
env["DISPLAY"] = os.environ.get("DISPLAY")
|
||||
env["XAUTHORITY"] = "/home/pmos/.Xauthority"
|
||||
|
||||
# Install blockdevice
|
||||
if args.install_blockdev:
|
||||
size_boot = 128 # 128 MB
|
||||
size_root = 4096 # 4 GB
|
||||
size_reserve = 2048 # 2 GB
|
||||
pmb.install.blockdevice.create_and_mount_image(args, size_boot,
|
||||
size_root, size_reserve)
|
||||
|
||||
# Run the command as user/root
|
||||
if args.user:
|
||||
logging.info("(" + suffix + ") % su pmos -c '" +
|
||||
|
@ -195,6 +204,24 @@ def install(args):
|
|||
if args.rsync and not args.sdcard:
|
||||
raise ValueError("Installation using rsync only works on sdcard.")
|
||||
|
||||
# On-device installer checks
|
||||
# Note that this can't be in the mutually exclusive group that has most of
|
||||
# the conflicting options, because then it would not work with --sdcard.
|
||||
if args.on_device_installer:
|
||||
if args.full_disk_encryption:
|
||||
raise ValueError("--on-device-installer cannot be combined with"
|
||||
" --fde. The user can choose to encrypt their"
|
||||
" installation later in the on-device installer.")
|
||||
if args.android_recovery_zip:
|
||||
raise ValueError("--on-device-installer cannot be combined with"
|
||||
" --android-recovery-zip (patches welcome)")
|
||||
if args.no_image:
|
||||
raise ValueError("--on-device-installer cannot be combined with"
|
||||
" --no-image")
|
||||
if args.rsync:
|
||||
raise ValueError("--on-device-installer cannot be combined with"
|
||||
" --rsync")
|
||||
|
||||
if not args.sdcard and args.split is None:
|
||||
# Default to split if the flash method requires it
|
||||
flasher = pmb.config.flashers.get(args.deviceinfo["flash_method"], {})
|
||||
|
|
|
@ -11,6 +11,7 @@ import pmb.chroot.apk
|
|||
import pmb.chroot.other
|
||||
import pmb.chroot.initfs
|
||||
import pmb.config
|
||||
import pmb.config.pmaports
|
||||
import pmb.helpers.devices
|
||||
import pmb.helpers.run
|
||||
import pmb.install.blockdevice
|
||||
|
@ -19,32 +20,38 @@ import pmb.install.recovery
|
|||
import pmb.install
|
||||
|
||||
|
||||
def mount_device_rootfs(args, suffix="native"):
|
||||
def mount_device_rootfs(args, suffix_rootfs, suffix_mount="native"):
|
||||
"""
|
||||
Mount the device rootfs.
|
||||
:param suffix_rootfs: the chroot suffix, where the rootfs that will be
|
||||
installed on the device has been created (e.g.
|
||||
"rootfs_qemu-amd64")
|
||||
:param suffix_mount: the chroot suffix, where the device rootfs will be
|
||||
mounted (e.g. "native")
|
||||
"""
|
||||
mountpoint = "/mnt/rootfs_" + args.device
|
||||
pmb.helpers.mount.bind(args, args.work + "/chroot_rootfs_" + args.device,
|
||||
args.work + "/chroot_" + suffix + mountpoint)
|
||||
mountpoint = f"/mnt/{suffix_rootfs}"
|
||||
pmb.helpers.mount.bind(args, f"{args.work}/chroot_{suffix_rootfs}",
|
||||
f"{args.work}/chroot_{suffix_mount}{mountpoint}")
|
||||
return mountpoint
|
||||
|
||||
|
||||
def get_subpartitions_size(args):
|
||||
def get_subpartitions_size(args, suffix):
|
||||
"""
|
||||
Calculate the size of the boot and root subpartition.
|
||||
|
||||
:param suffix: the chroot suffix, e.g. "rootfs_qemu-amd64"
|
||||
:returns: (boot, root) the size of the boot and root
|
||||
partition as integer in bytes
|
||||
partition as integer in MB
|
||||
"""
|
||||
boot = int(args.boot_size) * 1024 * 1024
|
||||
boot = int(args.boot_size)
|
||||
|
||||
# Estimate root partition size, then add some free space. The size
|
||||
# calculation is not as trivial as one may think, and depending on the
|
||||
# file system etc it seems to be just impossible to get it right.
|
||||
chroot = args.work + "/chroot_rootfs_" + args.device
|
||||
root = pmb.helpers.other.folder_size(args, chroot)
|
||||
chroot = f"{args.work}/chroot_{suffix}"
|
||||
root = pmb.helpers.other.folder_size(args, chroot) / 1024 / 1024
|
||||
root *= 1.20
|
||||
root += 50 * 1024 * 1024
|
||||
root += 50
|
||||
return (boot, root)
|
||||
|
||||
|
||||
|
@ -94,16 +101,17 @@ def get_kernel_package(args, device):
|
|||
return ["device-" + device + "-kernel-" + args.kernel]
|
||||
|
||||
|
||||
def copy_files_from_chroot(args):
|
||||
def copy_files_from_chroot(args, suffix):
|
||||
"""
|
||||
Copy all files from the rootfs chroot to /mnt/install, except
|
||||
for the home folder (because /home will contain some empty
|
||||
mountpoint folders).
|
||||
|
||||
:param suffix: the chroot suffix, e.g. "rootfs_qemu-amd64"
|
||||
"""
|
||||
# Mount the device rootfs
|
||||
logging.info("(native) copy rootfs_" + args.device + " to" +
|
||||
" /mnt/install/")
|
||||
mountpoint = mount_device_rootfs(args)
|
||||
logging.info(f"(native) copy {suffix} to /mnt/install/")
|
||||
mountpoint = mount_device_rootfs(args, suffix)
|
||||
mountpoint_outside = args.work + "/chroot_native" + mountpoint
|
||||
|
||||
# Remove empty qemu-user binary stub (where the binary was bind-mounted)
|
||||
|
@ -303,7 +311,7 @@ def embed_firmware(args):
|
|||
"deviceinfo_sd_embed_firmware_step_size "
|
||||
"is not valid: {}".format(step))
|
||||
|
||||
device_rootfs = mount_device_rootfs(args)
|
||||
device_rootfs = mount_device_rootfs(args, f"rootfs_{args.device}")
|
||||
binaries = args.deviceinfo["sd_embed_firmware"].split(",")
|
||||
|
||||
# Perform three checks prior to writing binaries to disk: 1) that binaries
|
||||
|
@ -366,31 +374,36 @@ def sanity_check_sdcard(device):
|
|||
raise RuntimeError("{} is read-only, is the sdcard locked?".format(device))
|
||||
|
||||
|
||||
def install_system_image(args):
|
||||
def install_system_image(args, size_reserve, suffix, root_label="pmOS_root",
|
||||
step=3, steps=5, split=False, sdcard=None):
|
||||
"""
|
||||
:param size_reserve: empty partition between root and boot in MB (pma#463)
|
||||
:param suffix: the chroot suffix, where the rootfs that will be installed
|
||||
on the device has been created (e.g. "rootfs_qemu-amd64")
|
||||
:param root_label: label of the root partition (e.g. "pmOS_root")
|
||||
:param step: next installation step
|
||||
:param steps: total installation steps
|
||||
:param split: create separate images for boot and root partitions
|
||||
:param sdcard: path to sdcard device (e.g. /dev/mmcblk0) or None
|
||||
"""
|
||||
# Partition and fill image/sdcard
|
||||
logging.info("*** (3/5) PREPARE INSTALL BLOCKDEVICE ***")
|
||||
logging.info(f"*** ({step}/{steps}) PREPARE INSTALL BLOCKDEVICE ***")
|
||||
pmb.chroot.shutdown(args, True)
|
||||
(size_boot, size_root) = get_subpartitions_size(args)
|
||||
(size_boot, size_root) = get_subpartitions_size(args, suffix)
|
||||
if not args.rsync:
|
||||
pmb.install.blockdevice.create(args, size_boot, size_root)
|
||||
if not args.split:
|
||||
pmb.install.partition(args, size_boot)
|
||||
if not args.split:
|
||||
pmb.install.partitions_mount(args)
|
||||
pmb.install.blockdevice.create(args, size_boot, size_root,
|
||||
size_reserve, split, sdcard)
|
||||
if not split:
|
||||
pmb.install.partition(args, size_boot, size_reserve)
|
||||
if not split:
|
||||
root_id = 3 if size_reserve else 2
|
||||
pmb.install.partitions_mount(args, root_id, sdcard)
|
||||
|
||||
if args.full_disk_encryption:
|
||||
logging.info("WARNING: Full disk encryption is enabled!")
|
||||
logging.info("Make sure that osk-sdl has been properly configured for your device")
|
||||
logging.info("or else you will be unable to unlock the rootfs on boot!")
|
||||
logging.info("If you started a device port, it is recommended you disable")
|
||||
logging.info("FDE by re-running the install command without '--fde' until")
|
||||
logging.info("you have properly configured osk-sdl. More information:")
|
||||
logging.info("<https://postmarketos.org/osk-port>")
|
||||
pmb.install.format(args)
|
||||
pmb.install.format(args, size_reserve, root_label, sdcard)
|
||||
|
||||
# Just copy all the files
|
||||
logging.info("*** (4/5) FILL INSTALL BLOCKDEVICE ***")
|
||||
copy_files_from_chroot(args)
|
||||
logging.info(f"*** ({step + 1}/{steps}) FILL INSTALL BLOCKDEVICE ***")
|
||||
copy_files_from_chroot(args, suffix)
|
||||
create_home_from_skel(args)
|
||||
configure_apk(args)
|
||||
copy_ssh_keys(args)
|
||||
|
@ -402,7 +415,7 @@ def install_system_image(args):
|
|||
if sparse is None:
|
||||
sparse = args.deviceinfo["flash_sparse"] == "true"
|
||||
|
||||
if sparse and not args.split and not args.sdcard:
|
||||
if sparse and not split and not sdcard:
|
||||
logging.info("(native) make sparse rootfs")
|
||||
pmb.chroot.apk.install(args, ["android-tools"])
|
||||
sys_image = args.device + ".img"
|
||||
|
@ -412,8 +425,13 @@ def install_system_image(args):
|
|||
pmb.chroot.user(args, ["mv", "-f", sys_image_sparse, sys_image],
|
||||
working_dir="/home/pmos/rootfs/")
|
||||
|
||||
# Kernel flash information
|
||||
logging.info("*** (5/5) FLASHING TO DEVICE ***")
|
||||
|
||||
def print_flash_info(args, step=5):
|
||||
""" Print flashing information, based on the deviceinfo data and the
|
||||
pmbootstrap arguments.
|
||||
|
||||
:param step: installation step number """
|
||||
logging.info(f"*** ({step}/{step}) FLASHING TO DEVICE ***")
|
||||
logging.info("Run the following to flash your installation to the"
|
||||
" target device:")
|
||||
|
||||
|
@ -428,16 +446,18 @@ def install_system_image(args):
|
|||
logging.info("* pmbootstrap flasher flash_rootfs")
|
||||
logging.info(" Flashes the generated rootfs image to your device:")
|
||||
if args.split:
|
||||
logging.info(" " + args.work + "/chroot_native/home/pmos/rootfs/" +
|
||||
args.device + "-rootfs.img")
|
||||
logging.info(f" {args.work}/chroot_native/home/pmos/rootfs/"
|
||||
f"{args.device}-rootfs.img")
|
||||
else:
|
||||
logging.info(" " + args.work + "/chroot_native/home/pmos/rootfs/" +
|
||||
args.device + ".img")
|
||||
logging.info(" (NOTE: This file has a partition table, which contains"
|
||||
" /boot and / subpartitions. That way we don't need to"
|
||||
" change the partition layout on your device.)")
|
||||
logging.info(f" {args.work}/chroot_native/home/pmos/rootfs/"
|
||||
f"{args.device}.img")
|
||||
logging.info(" (NOTE: This file has a partition table, which"
|
||||
" contains /boot and / subpartitions. That way we"
|
||||
" don't need to change the partition layout on your"
|
||||
" device.)")
|
||||
|
||||
# if current flasher supports vbmeta and partition is explicitly spcified in deviceinfo
|
||||
# if current flasher supports vbmeta and partition is explicitly specified
|
||||
# in deviceinfo
|
||||
if "flash_vbmeta" in flasher_actions and \
|
||||
(args.deviceinfo["flash_fastboot_partition_vbmeta"] or
|
||||
args.deviceinfo["flash_heimdall_partition_vbmeta"]):
|
||||
|
@ -448,14 +468,15 @@ def install_system_image(args):
|
|||
# (e.g. an Android boot image is generated). In that case, "flash_kernel"
|
||||
# works even when partitions are split or installing for sdcard.
|
||||
# This is not possible if the flash method requires split partitions.
|
||||
if "flash_kernel" in flasher_actions and (not requires_split or args.split):
|
||||
if "flash_kernel" in flasher_actions and \
|
||||
(not requires_split or args.split):
|
||||
logging.info("* pmbootstrap flasher flash_kernel")
|
||||
logging.info(" Flashes the kernel + initramfs to your device:")
|
||||
if requires_split:
|
||||
logging.info(" " + args.work + "/chroot_native/home/pmos/rootfs/" +
|
||||
args.device + "-boot.img")
|
||||
logging.info(f" {args.work}/chroot_native/home/pmos/rootfs/"
|
||||
f"{args.device}-boot.img")
|
||||
else:
|
||||
logging.info(" " + args.work + "/chroot_rootfs_" + args.device + "/boot")
|
||||
logging.info(f" {args.work}/chroot_rootfs_{args.device}/boot")
|
||||
|
||||
if "boot" in flasher_actions:
|
||||
logging.info(" (NOTE: " + method + " also supports booting"
|
||||
|
@ -471,7 +492,7 @@ def install_system_image(args):
|
|||
def install_recovery_zip(args):
|
||||
logging.info("*** (3/4) CREATING RECOVERY-FLASHABLE ZIP ***")
|
||||
suffix = "buildroot_" + args.deviceinfo["arch"]
|
||||
mount_device_rootfs(args, suffix)
|
||||
mount_device_rootfs(args, f"rootfs_{args.device}", suffix)
|
||||
pmb.install.recovery.create_zip(args, suffix)
|
||||
|
||||
# Flash information
|
||||
|
@ -480,6 +501,56 @@ def install_recovery_zip(args):
|
|||
logging.info("<https://postmarketos.org/recoveryzip>")
|
||||
|
||||
|
||||
def install_on_device_installer(args, step, steps):
|
||||
# Generate the rootfs image
|
||||
suffix_rootfs = f"rootfs_{args.device}"
|
||||
install_system_image(args, 0, suffix_rootfs, step=step, steps=steps,
|
||||
split=True)
|
||||
step += 2
|
||||
|
||||
# Prepare the installer chroot
|
||||
logging.info(f"*** ({step}/{steps}) CREATE ON-DEVICE INSTALLER ROOTFS ***")
|
||||
step += 1
|
||||
packages = ([f"device-{args.device}",
|
||||
"postmarketos-ondev"] +
|
||||
get_kernel_package(args, args.device) +
|
||||
get_nonfree_packages(args, args.device))
|
||||
suffix_installer = f"installer_{args.device}"
|
||||
pmb.chroot.apk.install(args, packages, suffix_installer)
|
||||
|
||||
# Move rootfs image into installer chroot
|
||||
img = f"{args.device}-root.img"
|
||||
img_path_src = f"{args.work}/chroot_native/home/pmos/rootfs/{img}"
|
||||
img_path_dest = f"{args.work}/chroot_{suffix_installer}/var/lib/rootfs.img"
|
||||
logging.info(f"({suffix_installer}) add {img} as /var/lib/rootfs.img")
|
||||
pmb.install.losetup.umount(args, img_path_src)
|
||||
pmb.helpers.run.root(args, ["mv", img_path_src, img_path_dest])
|
||||
|
||||
# Run ondev-prepare, so it may generate nice configs from the channel
|
||||
# properties (e.g. to display the version number), or transform the image
|
||||
# file into another format. This can all be done without pmbootstrap
|
||||
# changes in the postmarketos-ondev package.
|
||||
logging.info(f"({suffix_installer}) ondev-prepare-image")
|
||||
channel = pmb.config.pmaports.read_config(args)["channel"]
|
||||
channel_cfg = pmb.config.pmaports.read_config_channel(args)
|
||||
pmb.chroot.root(args, ["ondev-prepare", channel,
|
||||
channel_cfg["description"],
|
||||
channel_cfg["branch_pmaports"],
|
||||
channel_cfg["branch_aports"],
|
||||
channel_cfg["mirrordir_alpine"]], suffix_installer)
|
||||
|
||||
# Remove $DEVICE-boot.img (we will generate a new one if --split was
|
||||
# specified, otherwise the separate boot image is not needed)
|
||||
img_boot = f"{args.device}-boot.img"
|
||||
logging.info(f"(native) rm {img_boot}")
|
||||
pmb.chroot.root(args, ["rm", f"/home/pmos/rootfs/{img_boot}"])
|
||||
|
||||
# Generate installer image
|
||||
size_reserve = round(os.path.getsize(img_path_dest) / 1024 / 1024) + 200
|
||||
install_system_image(args, size_reserve, suffix_installer, "pmOS_install",
|
||||
step, steps, args.split, args.sdcard)
|
||||
|
||||
|
||||
def install(args):
|
||||
# Sanity checks
|
||||
if not args.android_recovery_zip and args.sdcard:
|
||||
|
@ -490,6 +561,8 @@ def install(args):
|
|||
steps = 2
|
||||
elif args.android_recovery_zip:
|
||||
steps = 4
|
||||
elif args.on_device_installer:
|
||||
steps = 8
|
||||
else:
|
||||
steps = 5
|
||||
|
||||
|
@ -547,7 +620,15 @@ def install(args):
|
|||
# Set the hostname as the device name
|
||||
setup_hostname(args)
|
||||
|
||||
if args.android_recovery_zip:
|
||||
install_recovery_zip(args)
|
||||
elif not args.no_image:
|
||||
install_system_image(args)
|
||||
if args.no_image:
|
||||
return
|
||||
elif args.android_recovery_zip:
|
||||
return install_recovery_zip(args)
|
||||
|
||||
if args.on_device_installer:
|
||||
# Runs install_system_image twice
|
||||
install_on_device_installer(args, 3, steps)
|
||||
else:
|
||||
install_system_image(args, 0, f"rootfs_{args.device}",
|
||||
split=args.split, sdcard=args.sdcard)
|
||||
print_flash_info(args, steps)
|
||||
|
|
|
@ -9,14 +9,15 @@ import pmb.helpers.cli
|
|||
import pmb.config
|
||||
|
||||
|
||||
def previous_install(args):
|
||||
def previous_install(args, path):
|
||||
"""
|
||||
Search the sdcard for possible existence of a previous installation of pmOS.
|
||||
We temporarily mount the possible pmOS_boot partition as /dev/sdcardp1 inside
|
||||
the native chroot to check the label from there.
|
||||
:param path: path to sdcard device (e.g. /dev/mmcblk0)
|
||||
"""
|
||||
label = ""
|
||||
for blockdevice_outside in [args.sdcard + "1", args.sdcard + "p1"]:
|
||||
for blockdevice_outside in [f"{path}1", f"{path}p1"]:
|
||||
if not os.path.exists(blockdevice_outside):
|
||||
continue
|
||||
blockdevice_inside = "/dev/sdcardp1"
|
||||
|
@ -28,39 +29,45 @@ def previous_install(args):
|
|||
return "pmOS_boot" in label
|
||||
|
||||
|
||||
def mount_sdcard(args):
|
||||
def mount_sdcard(args, path):
|
||||
"""
|
||||
:param path: path to sdcard device (e.g. /dev/mmcblk0)
|
||||
"""
|
||||
# Sanity checks
|
||||
if args.deviceinfo["external_storage"] != "true":
|
||||
raise RuntimeError("According to the deviceinfo, this device does"
|
||||
" not support a sdcard installation.")
|
||||
if not os.path.exists(args.sdcard):
|
||||
raise RuntimeError("The sdcard device does not exist: " +
|
||||
args.sdcard)
|
||||
for path in glob.glob(args.sdcard + "*"):
|
||||
if pmb.helpers.mount.ismount(path):
|
||||
raise RuntimeError(path + " is mounted! We will not attempt"
|
||||
" to format this!")
|
||||
logging.info("(native) mount /dev/install (host: " + args.sdcard + ")")
|
||||
pmb.helpers.mount.bind_file(args, args.sdcard,
|
||||
if not os.path.exists(path):
|
||||
raise RuntimeError(f"The sdcard device does not exist: {path}")
|
||||
for path_mount in glob.glob(f"{path}*"):
|
||||
if pmb.helpers.mount.ismount(path_mount):
|
||||
raise RuntimeError(f"{path_mount} is mounted! Will not attempt to"
|
||||
" format this!")
|
||||
logging.info(f"(native) mount /dev/install (host: {path})")
|
||||
pmb.helpers.mount.bind_file(args, path,
|
||||
args.work + "/chroot_native/dev/install")
|
||||
if previous_install(args):
|
||||
if previous_install(args, path):
|
||||
if not pmb.helpers.cli.confirm(args, "WARNING: This device has a"
|
||||
" previous installation of pmOS."
|
||||
" CONTINUE?"):
|
||||
raise RuntimeError("Aborted.")
|
||||
else:
|
||||
if not pmb.helpers.cli.confirm(args, "EVERYTHING ON " + args.sdcard +
|
||||
" WILL BE ERASED! CONTINUE?"):
|
||||
if not pmb.helpers.cli.confirm(args, f"EVERYTHING ON {path} WILL BE"
|
||||
" ERASED! CONTINUE?"):
|
||||
raise RuntimeError("Aborted.")
|
||||
|
||||
|
||||
def create_and_mount_image(args, size_boot, size_root):
|
||||
def create_and_mount_image(args, size_boot, size_root, size_reserve,
|
||||
split=False):
|
||||
"""
|
||||
Create a new image file, and mount it as /dev/install.
|
||||
|
||||
:param size_boot: size of the boot partition in bytes
|
||||
:param size_root: size of the root partition in bytes
|
||||
:param size_boot: size of the boot partition in MB
|
||||
:param size_root: size of the root partition in MB
|
||||
:param size_reserve: empty partition between root and boot in MB (pma#463)
|
||||
:param split: create separate images for boot and root partitions
|
||||
"""
|
||||
|
||||
# Short variables for paths
|
||||
chroot = args.work + "/chroot_native"
|
||||
img_path_prefix = "/home/pmos/rootfs/" + args.device
|
||||
|
@ -77,7 +84,7 @@ def create_and_mount_image(args, size_boot, size_root):
|
|||
pmb.chroot.root(args, ["rm", img_path])
|
||||
|
||||
# Make sure there is enough free space
|
||||
size_mb = round((size_boot + size_root) / (1024**2))
|
||||
size_mb = round(size_boot + size_reserve + size_root)
|
||||
disk_data = os.statvfs(args.work)
|
||||
free = round((disk_data.f_bsize * disk_data.f_bavail) / (1024**2))
|
||||
if size_mb > free:
|
||||
|
@ -86,10 +93,10 @@ def create_and_mount_image(args, size_boot, size_root):
|
|||
# Create empty image files
|
||||
pmb.chroot.user(args, ["mkdir", "-p", "/home/pmos/rootfs"])
|
||||
size_mb_full = str(size_mb) + "M"
|
||||
size_mb_boot = str(round(size_boot / (1024**2))) + "M"
|
||||
size_mb_root = str(round(size_root / (1024**2))) + "M"
|
||||
size_mb_boot = str(round(size_boot)) + "M"
|
||||
size_mb_root = str(round(size_root)) + "M"
|
||||
images = {img_path_full: size_mb_full}
|
||||
if args.split:
|
||||
if split:
|
||||
images = {img_path_boot: size_mb_boot,
|
||||
img_path_root: size_mb_root}
|
||||
for img_path, size_mb in images.items():
|
||||
|
@ -98,7 +105,7 @@ def create_and_mount_image(args, size_boot, size_root):
|
|||
|
||||
# Mount to /dev/install
|
||||
mount_image_paths = {img_path_full: "/dev/install"}
|
||||
if args.split:
|
||||
if split:
|
||||
mount_image_paths = {img_path_boot: "/dev/installp1",
|
||||
img_path_root: "/dev/installp2"}
|
||||
|
||||
|
@ -111,16 +118,20 @@ def create_and_mount_image(args, size_boot, size_root):
|
|||
args.work + "/chroot_native" + mount_point)
|
||||
|
||||
|
||||
def create(args, size_boot, size_root):
|
||||
def create(args, size_boot, size_root, size_reserve, split, sdcard):
|
||||
"""
|
||||
Create /dev/install (the "install blockdevice").
|
||||
|
||||
:param size_boot: size of the boot partition in bytes
|
||||
:param size_root: size of the root partition in bytes
|
||||
:param size_boot: size of the boot partition in MB
|
||||
:param size_root: size of the root partition in MB
|
||||
:param size_reserve: empty partition between root and boot in MB (pma#463)
|
||||
:param split: create separate images for boot and root partitions
|
||||
:param sdcard: path to sdcard device (e.g. /dev/mmcblk0) or None
|
||||
"""
|
||||
pmb.helpers.mount.umount_all(
|
||||
args, args.work + "/chroot_native/dev/install")
|
||||
if args.sdcard:
|
||||
mount_sdcard(args)
|
||||
if sdcard:
|
||||
mount_sdcard(args, sdcard)
|
||||
else:
|
||||
create_and_mount_image(args, size_boot, size_root)
|
||||
create_and_mount_image(args, size_boot, size_root, size_reserve,
|
||||
split)
|
||||
|
|
|
@ -23,9 +23,11 @@ def format_and_mount_boot(args):
|
|||
pmb.chroot.root(args, ["mount", device, mountpoint])
|
||||
|
||||
|
||||
def format_and_mount_root(args):
|
||||
def format_and_mount_root(args, device):
|
||||
"""
|
||||
:param device: root partition on install block device (e.g. /dev/installp2)
|
||||
"""
|
||||
mountpoint = "/dev/mapper/pm_crypt"
|
||||
device = "/dev/installp2"
|
||||
if args.full_disk_encryption:
|
||||
logging.info("(native) format " + device + " (root, luks), mount to " +
|
||||
mountpoint)
|
||||
|
@ -41,12 +43,15 @@ def format_and_mount_root(args):
|
|||
raise RuntimeError("Failed to open cryptdevice!")
|
||||
|
||||
|
||||
def format_and_mount_pm_crypt(args):
|
||||
def format_and_mount_pm_crypt(args, device, root_label, sdcard):
|
||||
"""
|
||||
:param device: root partition on install block device (e.g. /dev/installp2)
|
||||
:param root_label: label of the root partition (e.g. "pmOS_root")
|
||||
:param sdcard: path to sdcard device (e.g. /dev/mmcblk0) or None
|
||||
"""
|
||||
# Block device
|
||||
if args.full_disk_encryption:
|
||||
device = "/dev/mapper/pm_crypt"
|
||||
else:
|
||||
device = "/dev/installp2"
|
||||
|
||||
# Format
|
||||
if not args.rsync:
|
||||
|
@ -55,12 +60,12 @@ def format_and_mount_pm_crypt(args):
|
|||
# When changing the options of mkfs.ext4, also change them in the
|
||||
# recovery zip code (see 'grep -r mkfs\.ext4')!
|
||||
mkfs_ext4_args = ["mkfs.ext4", "-O", "^metadata_csum", "-F",
|
||||
"-q", "-L", "pmOS_root"]
|
||||
"-q", "-L", root_label]
|
||||
|
||||
# When we don't know the file system size before hand like
|
||||
# with non-block devices, we need to explicitely set a number of
|
||||
# inodes. See #1717 and #1845 for details
|
||||
if not args.sdcard:
|
||||
if not sdcard:
|
||||
mkfs_ext4_args = mkfs_ext4_args + ["-N", "100000"]
|
||||
|
||||
pmb.chroot.root(args, mkfs_ext4_args + [device])
|
||||
|
@ -72,7 +77,13 @@ def format_and_mount_pm_crypt(args):
|
|||
pmb.chroot.root(args, ["mount", device, mountpoint])
|
||||
|
||||
|
||||
def format(args):
|
||||
format_and_mount_root(args)
|
||||
format_and_mount_pm_crypt(args)
|
||||
def format(args, size_reserve, root_label, sdcard):
|
||||
"""
|
||||
:param size_reserve: empty partition between root and boot in MB (pma#463)
|
||||
:param root_label: label of the root partition (e.g. "pmOS_root")
|
||||
:param sdcard: path to sdcard device (e.g. /dev/mmcblk0) or None
|
||||
"""
|
||||
root_dev = "/dev/installp3" if size_reserve else "/dev/installp2"
|
||||
format_and_mount_root(args, root_dev)
|
||||
format_and_mount_pm_crypt(args, root_dev, root_label, sdcard)
|
||||
format_and_mount_boot(args)
|
||||
|
|
|
@ -8,12 +8,14 @@ import pmb.config
|
|||
import pmb.install.losetup
|
||||
|
||||
|
||||
def partitions_mount(args):
|
||||
def partitions_mount(args, root_id, sdcard):
|
||||
"""
|
||||
Mount blockdevices of partitions inside native chroot
|
||||
:param root_id: root partition id (3 with --reserve-space, otherwise 2)
|
||||
:param sdcard: path to sdcard device (e.g. /dev/mmcblk0) or None
|
||||
"""
|
||||
prefix = args.sdcard
|
||||
if not args.sdcard:
|
||||
prefix = sdcard
|
||||
if not sdcard:
|
||||
img_path = "/home/pmos/rootfs/" + args.device + ".img"
|
||||
prefix = pmb.install.losetup.device_by_back_file(args, img_path)
|
||||
|
||||
|
@ -35,22 +37,28 @@ def partitions_mount(args):
|
|||
prefix + " to be located at " + prefix +
|
||||
"1 or " + prefix + "p1!")
|
||||
|
||||
for i in [1, 2]:
|
||||
for i in [1, root_id]:
|
||||
source = prefix + partition_prefix + str(i)
|
||||
target = args.work + "/chroot_native/dev/installp" + str(i)
|
||||
pmb.helpers.mount.bind_file(args, source, target)
|
||||
|
||||
|
||||
def partition(args, size_boot):
|
||||
def partition(args, size_boot, size_reserve):
|
||||
"""
|
||||
Partition /dev/install and create /dev/install{p1,p2}
|
||||
Partition /dev/install and create /dev/install{p1,p2,p3}:
|
||||
* /dev/installp1: boot
|
||||
* /dev/installp2: root (or reserved space)
|
||||
* /dev/installp3: (root, if reserved space > 0)
|
||||
|
||||
size_boot: size of the boot partition in bytes.
|
||||
:param size_boot: size of the boot partition in MB
|
||||
:param size_reserve: empty partition between root and boot in MB (pma#463)
|
||||
"""
|
||||
# Convert to MB and print info
|
||||
mb_boot = str(round(size_boot / 1024 / 1024)) + "M"
|
||||
logging.info("(native) partition /dev/install (boot: " + mb_boot +
|
||||
", root: the rest)")
|
||||
mb_boot = f"{round(size_boot)}M"
|
||||
mb_reserved = f"{round(size_reserve)}M"
|
||||
mb_root_start = f"{round(size_boot) + round(size_reserve)}M"
|
||||
logging.info(f"(native) partition /dev/install (boot: {mb_boot},"
|
||||
f" reserved: {mb_reserved}, root: the rest)")
|
||||
|
||||
filesystem = args.deviceinfo["boot_filesystem"] or "ext2"
|
||||
|
||||
|
@ -63,9 +71,16 @@ def partition(args, size_boot):
|
|||
commands = [
|
||||
["mktable", "msdos"],
|
||||
["mkpart", "primary", filesystem, boot_part_start + 's', mb_boot],
|
||||
["mkpart", "primary", mb_boot, "100%"],
|
||||
]
|
||||
|
||||
if size_reserve:
|
||||
commands += [["mkpart", "primary", mb_boot, mb_reserved]]
|
||||
|
||||
commands += [
|
||||
["mkpart", "primary", mb_root_start, "100%"],
|
||||
["set", "1", "boot", "on"]
|
||||
]
|
||||
|
||||
for command in commands:
|
||||
pmb.chroot.root(args, ["parted", "-s", "/dev/install"] +
|
||||
command, check=False)
|
||||
|
|
|
@ -25,7 +25,7 @@ def alpine_native():
|
|||
def from_chroot_suffix(args, suffix):
|
||||
if suffix == "native":
|
||||
return args.arch_native
|
||||
if suffix == "rootfs_" + args.device:
|
||||
if suffix in [f"rootfs_{args.device}", f"installer_{args.device}"]:
|
||||
return args.deviceinfo["arch"]
|
||||
if suffix.startswith("buildroot_"):
|
||||
return suffix.split("_", 1)[1]
|
||||
|
|
|
@ -497,6 +497,10 @@ def arguments():
|
|||
help="Copy .Xauthority and set environment variables,"
|
||||
" so X11 applications can be started (native"
|
||||
" chroot only)")
|
||||
chroot.add_argument("-i", "--install-blockdev", action="store_true",
|
||||
help="Create a sparse image file and mount it as"
|
||||
" /dev/install, just like during the"
|
||||
" installation process.")
|
||||
for action in [build_init, chroot]:
|
||||
suffix = action.add_mutually_exclusive_group()
|
||||
if action == chroot:
|
||||
|
@ -553,6 +557,11 @@ def arguments():
|
|||
install.add_argument("--no-base",
|
||||
help="do not install postmarketos-base (advanced)",
|
||||
action="store_false", dest="install_base")
|
||||
install.add_argument("--on-device-installer", "--ondev",
|
||||
action="store_true",
|
||||
help="wrap the resulting image in a graphical"
|
||||
" on-device installer, so the installation can"
|
||||
" be customized after flashing")
|
||||
group = install.add_mutually_exclusive_group()
|
||||
group.add_argument("--sparse", help="generate sparse image file"
|
||||
" (even if unsupported by device)", default=None,
|
||||
|
|
Loading…
Reference in New Issue