diff --git a/pmb/helpers/frontend.py b/pmb/helpers/frontend.py index 544f6f35..b5998fe2 100644 --- a/pmb/helpers/frontend.py +++ b/pmb/helpers/frontend.py @@ -137,8 +137,9 @@ def chroot(args): 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_root, size_reserve) # Run the command as user/root if args.user: diff --git a/pmb/install/_install.py b/pmb/install/_install.py index c06219e8..b15ac350 100644 --- a/pmb/install/_install.py +++ b/pmb/install/_install.py @@ -366,17 +366,22 @@ 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=0): + """ + :param size_reserve: empty partition between root and boot in MB (pma#463) + """ # Partition and fill image/sdcard logging.info("*** (3/5) PREPARE INSTALL BLOCKDEVICE ***") pmb.chroot.shutdown(args, True) (size_boot, size_root) = get_subpartitions_size(args) if not args.rsync: - pmb.install.blockdevice.create(args, size_boot, size_root) + pmb.install.blockdevice.create(args, size_boot, size_root, + size_reserve) if not args.split: - pmb.install.partition(args, size_boot) + pmb.install.partition(args, size_boot, size_reserve) if not args.split: - pmb.install.partitions_mount(args) + root_id = 3 if size_reserve else 2 + pmb.install.partitions_mount(args, root_id) if args.full_disk_encryption: logging.info("WARNING: Full disk encryption is enabled!") @@ -386,7 +391,7 @@ def install_system_image(args): logging.info("FDE by re-running the install command without '--fde' until") logging.info("you have properly configured osk-sdl. More information:") logging.info("") - pmb.install.format(args) + pmb.install.format(args, size_reserve) # Just copy all the files logging.info("*** (4/5) FILL INSTALL BLOCKDEVICE ***") diff --git a/pmb/install/blockdevice.py b/pmb/install/blockdevice.py index 1608a861..a73b7fd7 100644 --- a/pmb/install/blockdevice.py +++ b/pmb/install/blockdevice.py @@ -54,12 +54,14 @@ def mount_sdcard(args): raise RuntimeError("Aborted.") -def create_and_mount_image(args, size_boot, size_root, split=False): +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 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 """ @@ -79,7 +81,7 @@ def create_and_mount_image(args, size_boot, size_root, split=False): pmb.chroot.root(args, ["rm", img_path]) # Make sure there is enough free space - size_mb = round(size_boot + size_root) + 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: @@ -113,16 +115,18 @@ def create_and_mount_image(args, size_boot, size_root, split=False): args.work + "/chroot_native" + mount_point) -def create(args, size_boot, size_root): +def create(args, size_boot, size_root, size_reserve): """ Create /dev/install (the "install blockdevice"). :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) """ pmb.helpers.mount.umount_all( args, args.work + "/chroot_native/dev/install") if args.sdcard: mount_sdcard(args) else: - create_and_mount_image(args, size_boot, size_root, args.split) + create_and_mount_image(args, size_boot, size_root, size_reserve, + args.split) diff --git a/pmb/install/format.py b/pmb/install/format.py index 94222f9f..4fde0860 100644 --- a/pmb/install/format.py +++ b/pmb/install/format.py @@ -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,13 @@ 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): + """ + :param device: root partition on install block device (e.g. /dev/installp2) + """ # Block device if args.full_disk_encryption: device = "/dev/mapper/pm_crypt" - else: - device = "/dev/installp2" # Format if not args.rsync: @@ -72,7 +75,11 @@ 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): + """ + :param size_reserve: empty partition between root and boot in MB (pma#463) + """ + 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) format_and_mount_boot(args) diff --git a/pmb/install/partition.py b/pmb/install/partition.py index 71bc697d..b71baadb 100644 --- a/pmb/install/partition.py +++ b/pmb/install/partition.py @@ -8,9 +8,10 @@ import pmb.config import pmb.install.losetup -def partitions_mount(args): +def partitions_mount(args, root_id): """ Mount blockdevices of partitions inside native chroot + :param root_id: root partition id (3 with --reserve-space, otherwise 2) """ prefix = args.sdcard if not args.sdcard: @@ -35,22 +36,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) :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)) + "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 +70,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)