forked from Mirror/pmbootstrap
Add install flag to generate separate boot and system images (#1442)
* Usage: pmbootstrap install --split * Make obvious that export is the next step when split images are created * Fix note for missing rootfs image on export * Change wording from "system image" to "rootfs image" * The idea was to show the note only when the rootfs image was not generated yet. But this was broken, because the path we checked for was missing the chroot path prefix (which is added now). * Also don't display the message, when the split image files exist
This commit is contained in:
parent
4e665a2190
commit
827a60cd25
5 changed files with 79 additions and 46 deletions
|
@ -1,3 +1,4 @@
|
||||||
|
import glob
|
||||||
import logging
|
import logging
|
||||||
import os
|
import os
|
||||||
|
|
||||||
|
@ -13,10 +14,11 @@ def frontend(args):
|
||||||
if not os.path.exists(target):
|
if not os.path.exists(target):
|
||||||
pmb.helpers.run.user(args, ["mkdir", "-p", target])
|
pmb.helpers.run.user(args, ["mkdir", "-p", target])
|
||||||
|
|
||||||
# System image note
|
# Rootfs image note
|
||||||
img_path = "/home/pmos/rootfs/" + args.device + ".img"
|
chroot = args.work + "/chroot_native"
|
||||||
if not os.path.exists(args.work + "/chroot_native" + img_path):
|
pattern = chroot + "/home/pmos/rootfs/" + args.device + "*.img"
|
||||||
logging.info("NOTE: To export the system image, run 'pmbootstrap"
|
if not glob.glob(pattern):
|
||||||
|
logging.info("NOTE: To export the rootfs image, run 'pmbootstrap"
|
||||||
" install' first (without the 'sdcard' parameter).")
|
" install' first (without the 'sdcard' parameter).")
|
||||||
|
|
||||||
# Rebuild the initramfs, just to make sure (see #69)
|
# Rebuild the initramfs, just to make sure (see #69)
|
||||||
|
|
|
@ -42,6 +42,8 @@ def symlinks(args, flavor, folder):
|
||||||
"uImage-" + flavor: "Kernel, legacy u-boot image format",
|
"uImage-" + flavor: "Kernel, legacy u-boot image format",
|
||||||
"vmlinuz-" + flavor: "Linux kernel",
|
"vmlinuz-" + flavor: "Linux kernel",
|
||||||
args.device + ".img": "Rootfs with partitions for /boot and /",
|
args.device + ".img": "Rootfs with partitions for /boot and /",
|
||||||
|
args.device + "-boot.img": "Boot partition image",
|
||||||
|
args.device + "-root.img": "Root partition image",
|
||||||
"pmos-" + args.device + ".zip": "Android recovery flashable zip",
|
"pmos-" + args.device + ".zip": "Android recovery flashable zip",
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -51,6 +53,8 @@ def symlinks(args, flavor, folder):
|
||||||
path_buildroot = args.work + "/chroot_buildroot_" + args.deviceinfo["arch"]
|
path_buildroot = args.work + "/chroot_buildroot_" + args.deviceinfo["arch"]
|
||||||
patterns = [path_boot + "/*-" + flavor,
|
patterns = [path_boot + "/*-" + flavor,
|
||||||
path_native + "/home/pmos/rootfs/" + args.device + ".img",
|
path_native + "/home/pmos/rootfs/" + args.device + ".img",
|
||||||
|
path_native + "/home/pmos/rootfs/" + args.device + "-boot.img",
|
||||||
|
path_native + "/home/pmos/rootfs/" + args.device + "-root.img",
|
||||||
path_buildroot +
|
path_buildroot +
|
||||||
"/var/lib/postmarketos-android-recovery-installer/pmos-" +
|
"/var/lib/postmarketos-android-recovery-installer/pmos-" +
|
||||||
args.device + ".zip"]
|
args.device + ".zip"]
|
||||||
|
|
|
@ -46,9 +46,9 @@ def mount_device_rootfs(args, suffix="native"):
|
||||||
|
|
||||||
def get_subpartitions_size(args):
|
def get_subpartitions_size(args):
|
||||||
"""
|
"""
|
||||||
Calculate the size of the whole image and boot subpartition.
|
Calculate the size of the boot and root subpartition.
|
||||||
|
|
||||||
:returns: (full, boot) the size of the full image and boot
|
:returns: (boot, root) the size of the boot and root
|
||||||
partition as integer in bytes
|
partition as integer in bytes
|
||||||
"""
|
"""
|
||||||
# Calculate required sizes first
|
# Calculate required sizes first
|
||||||
|
@ -66,7 +66,7 @@ def get_subpartitions_size(args):
|
||||||
full *= 1.20
|
full *= 1.20
|
||||||
full += 50 * 1024 * 1024
|
full += 50 * 1024 * 1024
|
||||||
boot += 15 * 1024 * 1024
|
boot += 15 * 1024 * 1024
|
||||||
return (full, boot)
|
return (boot, full - boot)
|
||||||
|
|
||||||
|
|
||||||
def get_nonfree_packages(args, device):
|
def get_nonfree_packages(args, device):
|
||||||
|
@ -284,11 +284,13 @@ def install_system_image(args):
|
||||||
# Partition and fill image/sdcard
|
# Partition and fill image/sdcard
|
||||||
logging.info("*** (3/5) PREPARE INSTALL BLOCKDEVICE ***")
|
logging.info("*** (3/5) PREPARE INSTALL BLOCKDEVICE ***")
|
||||||
pmb.chroot.shutdown(args, True)
|
pmb.chroot.shutdown(args, True)
|
||||||
(size_image, size_boot) = get_subpartitions_size(args)
|
(size_boot, size_root) = get_subpartitions_size(args)
|
||||||
if not args.rsync:
|
if not args.rsync:
|
||||||
pmb.install.blockdevice.create(args, size_image)
|
pmb.install.blockdevice.create(args, size_boot, size_root)
|
||||||
pmb.install.partition(args, size_boot)
|
if not args.split:
|
||||||
pmb.install.partitions_mount(args)
|
pmb.install.partition(args, size_boot)
|
||||||
|
if not args.split:
|
||||||
|
pmb.install.partitions_mount(args)
|
||||||
|
|
||||||
if args.full_disk_encryption:
|
if args.full_disk_encryption:
|
||||||
logging.info("WARNING: Full disk encryption is enabled!")
|
logging.info("WARNING: Full disk encryption is enabled!")
|
||||||
|
@ -309,7 +311,7 @@ def install_system_image(args):
|
||||||
pmb.chroot.shutdown(args, True)
|
pmb.chroot.shutdown(args, True)
|
||||||
|
|
||||||
# Convert system image to sparse using img2simg
|
# Convert system image to sparse using img2simg
|
||||||
if args.deviceinfo["flash_sparse"] == "true":
|
if args.deviceinfo["flash_sparse"] == "true" and not args.split:
|
||||||
logging.info("(native) make sparse system image")
|
logging.info("(native) make sparse system image")
|
||||||
pmb.chroot.apk.install(args, ["libsparse"])
|
pmb.chroot.apk.install(args, ["libsparse"])
|
||||||
sys_image = args.device + ".img"
|
sys_image = args.device + ".img"
|
||||||
|
@ -325,7 +327,7 @@ def install_system_image(args):
|
||||||
" target device:")
|
" target device:")
|
||||||
|
|
||||||
# System flash information
|
# System flash information
|
||||||
if not args.sdcard:
|
if not args.sdcard and not args.split:
|
||||||
logging.info("* pmbootstrap flasher flash_rootfs")
|
logging.info("* pmbootstrap flasher flash_rootfs")
|
||||||
logging.info(" Flashes the generated rootfs image to your device:")
|
logging.info(" Flashes the generated rootfs image to your device:")
|
||||||
logging.info(" " + args.work + "/chroot_native/home/pmos/rootfs/" +
|
logging.info(" " + args.work + "/chroot_native/home/pmos/rootfs/" +
|
||||||
|
@ -346,9 +348,14 @@ def install_system_image(args):
|
||||||
" Use 'pmbootstrap flasher boot' to do that.)")
|
" Use 'pmbootstrap flasher boot' to do that.)")
|
||||||
|
|
||||||
# Export information
|
# Export information
|
||||||
logging.info("* If the above steps do not work, you can also create"
|
if args.split:
|
||||||
" symlinks to the generated files with 'pmbootstrap export'"
|
logging.info("* Boot and root image files have been generated, run"
|
||||||
" and flash outside of pmbootstrap.")
|
" 'pmbootstrap export' to create symlinks and flash"
|
||||||
|
" outside of pmbootstrap.")
|
||||||
|
else:
|
||||||
|
logging.info("* If the above steps do not work, you can also create"
|
||||||
|
" symlinks to the generated files with 'pmbootstrap export'"
|
||||||
|
" and flash outside of pmbootstrap.")
|
||||||
|
|
||||||
|
|
||||||
def install_recovery_zip(args):
|
def install_recovery_zip(args):
|
||||||
|
|
|
@ -70,56 +70,73 @@ def mount_sdcard(args):
|
||||||
raise RuntimeError("Aborted.")
|
raise RuntimeError("Aborted.")
|
||||||
|
|
||||||
|
|
||||||
def create_and_mount_image(args, size):
|
def create_and_mount_image(args, size_boot, size_root):
|
||||||
"""
|
"""
|
||||||
Create a new image file, and mount it as /dev/install.
|
Create a new image file, and mount it as /dev/install.
|
||||||
|
|
||||||
:param size: of the whole image in bytes
|
:param size_boot: size of the boot partition in bytes
|
||||||
|
:param size_root: size of the root partition in bytes
|
||||||
"""
|
"""
|
||||||
# Short variables for paths
|
# Short variables for paths
|
||||||
chroot = args.work + "/chroot_native"
|
chroot = args.work + "/chroot_native"
|
||||||
img_path = "/home/pmos/rootfs/" + args.device + ".img"
|
img_path_prefix = "/home/pmos/rootfs/" + args.device
|
||||||
img_path_outside = chroot + img_path
|
img_path_full = img_path_prefix + ".img"
|
||||||
|
img_path_boot = img_path_prefix + "-boot.img"
|
||||||
|
img_path_root = img_path_prefix + "-root.img"
|
||||||
|
|
||||||
# Umount and delete existing image
|
# Umount and delete existing images
|
||||||
if os.path.exists(img_path_outside):
|
for img_path in [img_path_full, img_path_boot, img_path_root]:
|
||||||
pmb.helpers.mount.umount_all(args, chroot + "/mnt")
|
outside = chroot + img_path
|
||||||
pmb.install.losetup.umount(args, img_path)
|
if os.path.exists(outside):
|
||||||
pmb.chroot.root(args, ["rm", img_path])
|
pmb.helpers.mount.umount_all(args, chroot + "/mnt")
|
||||||
if os.path.exists(img_path_outside):
|
pmb.install.losetup.umount(args, img_path)
|
||||||
raise RuntimeError("Failed to remove old image file: " +
|
pmb.chroot.root(args, ["rm", img_path])
|
||||||
img_path_outside)
|
|
||||||
|
|
||||||
# Make sure there is enough free space
|
# Make sure there is enough free space
|
||||||
size_mb = round(size / (1024**2))
|
size_mb = round((size_boot + size_root) / (1024**2))
|
||||||
disk_data = os.statvfs(args.work)
|
disk_data = os.statvfs(args.work)
|
||||||
free = round((disk_data.f_bsize * disk_data.f_bavail) / (1024**2))
|
free = round((disk_data.f_bsize * disk_data.f_bavail) / (1024**2))
|
||||||
if size_mb > free:
|
if size_mb > free:
|
||||||
raise RuntimeError("Not enough free space to create rootfs image! (free: " + str(free) + "M, required: " + str(size_mb) + "M)")
|
raise RuntimeError("Not enough free space to create rootfs image! (free: " + str(free) + "M, required: " + str(size_mb) + "M)")
|
||||||
mb = str(size_mb) + "M"
|
|
||||||
|
|
||||||
# Create empty image file
|
# Create empty image files
|
||||||
logging.info("(native) create " + args.device + ".img (" + mb + ")")
|
|
||||||
pmb.chroot.user(args, ["mkdir", "-p", "/home/pmos/rootfs"])
|
pmb.chroot.user(args, ["mkdir", "-p", "/home/pmos/rootfs"])
|
||||||
pmb.chroot.root(args, ["truncate", "-s", mb, img_path])
|
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"
|
||||||
|
images = {img_path_full: size_mb_full}
|
||||||
|
if args.split:
|
||||||
|
images = {img_path_boot: size_mb_boot,
|
||||||
|
img_path_root: size_mb_root}
|
||||||
|
for img_path, size_mb in images.items():
|
||||||
|
logging.info("(native) create " + os.path.basename(img_path) + " (" + size_mb + ")")
|
||||||
|
pmb.chroot.root(args, ["truncate", "-s", size_mb, img_path])
|
||||||
|
|
||||||
# Mount to /dev/install
|
# Mount to /dev/install
|
||||||
logging.info("(native) mount /dev/install (" + args.device + ".img)")
|
mount_image_paths = {img_path_full: "/dev/install"}
|
||||||
pmb.install.losetup.mount(args, img_path)
|
if args.split:
|
||||||
device = pmb.install.losetup.device_by_back_file(args, img_path)
|
mount_image_paths = {img_path_boot: "/dev/installp1",
|
||||||
pmb.helpers.mount.bind_blockdevice(args, device, args.work +
|
img_path_root: "/dev/installp2"}
|
||||||
"/chroot_native/dev/install")
|
|
||||||
|
for img_path, mount_point in mount_image_paths.items():
|
||||||
|
logging.info("(native) mount " + mount_point +
|
||||||
|
" (" + os.path.basename(img_path) + ")")
|
||||||
|
pmb.install.losetup.mount(args, img_path)
|
||||||
|
device = pmb.install.losetup.device_by_back_file(args, img_path)
|
||||||
|
pmb.helpers.mount.bind_blockdevice(args, device, args.work +
|
||||||
|
"/chroot_native" + mount_point)
|
||||||
|
|
||||||
|
|
||||||
def create(args, size):
|
def create(args, size_boot, size_root):
|
||||||
"""
|
"""
|
||||||
Create /dev/install (the "install blockdevice").
|
Create /dev/install (the "install blockdevice").
|
||||||
|
|
||||||
:param size: of the whole image in bytes
|
:param size_boot: size of the boot partition in bytes
|
||||||
|
:param size_root: size of the root partition in bytes
|
||||||
"""
|
"""
|
||||||
pmb.helpers.mount.umount_all(
|
pmb.helpers.mount.umount_all(
|
||||||
args, args.work + "/chroot_native/dev/install")
|
args, args.work + "/chroot_native/dev/install")
|
||||||
if args.sdcard:
|
if args.sdcard:
|
||||||
mount_sdcard(args)
|
mount_sdcard(args)
|
||||||
else:
|
else:
|
||||||
create_and_mount_image(args, size)
|
create_and_mount_image(args, size_boot, size_root)
|
||||||
|
|
|
@ -321,8 +321,14 @@ def arguments():
|
||||||
# Action: install
|
# Action: install
|
||||||
install = sub.add_parser("install", help="set up device specific" +
|
install = sub.add_parser("install", help="set up device specific" +
|
||||||
" chroot and install to sdcard or image file")
|
" chroot and install to sdcard or image file")
|
||||||
install.add_argument("--sdcard", help="path to the sdcard device,"
|
group = install.add_mutually_exclusive_group()
|
||||||
" eg. /dev/mmcblk0")
|
group.add_argument("--sdcard", help="path to the sdcard device,"
|
||||||
|
" eg. /dev/mmcblk0")
|
||||||
|
group.add_argument("--split", help="install the boot and root partition"
|
||||||
|
" in separated image files", action="store_true")
|
||||||
|
group.add_argument("--android-recovery-zip",
|
||||||
|
help="generate TWRP flashable zip",
|
||||||
|
action="store_true", dest="android_recovery_zip")
|
||||||
install.add_argument("--rsync", help="update the sdcard using rsync,"
|
install.add_argument("--rsync", help="update the sdcard using rsync,"
|
||||||
" only works with --no-fde", action="store_true")
|
" only works with --no-fde", action="store_true")
|
||||||
install.add_argument("--cipher", help="cryptsetup cipher used to"
|
install.add_argument("--cipher", help="cryptsetup cipher used to"
|
||||||
|
@ -337,9 +343,6 @@ def arguments():
|
||||||
install.add_argument("--flavor",
|
install.add_argument("--flavor",
|
||||||
help="Specify kernel flavor to include in recovery"
|
help="Specify kernel flavor to include in recovery"
|
||||||
" flashable zip", default=None)
|
" flashable zip", default=None)
|
||||||
install.add_argument("--android-recovery-zip",
|
|
||||||
help="generate TWRP flashable zip",
|
|
||||||
action="store_true", dest="android_recovery_zip")
|
|
||||||
install.add_argument("--recovery-install-partition", default="system",
|
install.add_argument("--recovery-install-partition", default="system",
|
||||||
help="partition to flash from recovery,"
|
help="partition to flash from recovery,"
|
||||||
" eg. external_sd",
|
" eg. external_sd",
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue