@@ -435,6 +435,39 @@ step::extract_boot_part_from_rootfs() {
435435 disk::umount_wait_busy " ${rootfs_mount_point} "
436436}
437437
438+ # Install zram kernel modules if needed (for Ubuntu systems)
439+ install_zram_module_if_needed () {
440+ local rootfs_mount_point=" $1 "
441+
442+ # Check if we're in an Ubuntu-like system by looking for the presence of apt
443+ if [ -x " ${rootfs_mount_point} /usr/bin/apt-get" ] && [ -x " ${rootfs_mount_point} /usr/bin/dpkg" ]; then
444+ log::info " Detecting Ubuntu-like system, attempting to install zram kernel modules"
445+
446+ # Find the kernel version from the currently installed kernel image
447+ local kernel_version
448+ kernel_version=$( chroot " ${rootfs_mount_point} " bash -c " dpkg -l | grep -oP 'linux-image-\K[0-9.-]+-generic' | head -n1" )
449+
450+ if [ -z " $kernel_version " ]; then
451+ log::error " Could not determine kernel version, zram module installation failed"
452+ return 1
453+ fi
454+
455+ log::info " Detected kernel version: $kernel_version "
456+
457+ # Install the modules package with minimal dependencies
458+ if ! chroot " ${rootfs_mount_point} " /usr/bin/env ${http_proxy: +http_proxy=$http_proxy } \
459+ ${https_proxy: +https_proxy=$https_proxy } \
460+ ${ftp_proxy: +ftp_proxy=$ftp_proxy } \
461+ ${rsync_proxy: +rsync_proxy=$rsync_proxy } \
462+ ${all_proxy: +all_proxy=$all_proxy } \
463+ ${no_proxy: +no_proxy=$no_proxy } \
464+ bash -c " apt-get update && apt-get install -y --no-install-recommends --no-install-suggests linux-modules-extra-$kernel_version " ; then
465+ log::error " Could not install zram modules, possibly due to disk space constraints or missing package"
466+ return 1
467+ fi
468+ fi
469+ }
470+
438471disk::install_rpm_on_rootfs () {
439472 local rootfs_mount_point=" $1 "
440473 shift
@@ -471,17 +504,17 @@ disk::install_rpm_on_rootfs() {
471504
472505 # Step 2: Build essential packages list
473506 local cryptpilot_fde_version=" "
474-
507+
475508 # Try to query the version of cryptpilot-fde from the current system
476509 if command -v rpm > /dev/null 2>&1 ; then
477510 cryptpilot_fde_version=$( rpm -q cryptpilot-fde --qf ' %{VERSION}-%{RELEASE}' 2> /dev/null || true)
478511 elif command -v dpkg-query > /dev/null 2>&1 ; then
479512 cryptpilot_fde_version=$( dpkg-query -W -f=' ${Version}' cryptpilot-fde 2> /dev/null || true)
480513 fi
481-
514+
482515 local essential_packages_with_version=()
483516 local essential_package_names=()
484-
517+
485518 if [ -n " ${cryptpilot_fde_version} " ]; then
486519 log::info " Detected cryptpilot-fde version: ${cryptpilot_fde_version} "
487520 essential_packages_with_version+=(" cryptpilot-fde-${cryptpilot_fde_version} " )
@@ -490,7 +523,7 @@ disk::install_rpm_on_rootfs() {
490523 essential_packages_with_version+=(" cryptpilot-fde" )
491524 fi
492525 essential_package_names+=(" cryptpilot-fde" )
493-
526+
494527 essential_packages_with_version+=(" yum-plugin-versionlock" )
495528 essential_package_names+=(" yum-plugin-versionlock" )
496529
@@ -499,7 +532,7 @@ disk::install_rpm_on_rootfs() {
499532 for i in " ${! essential_packages_with_version[@]} " ; do
500533 local pkg_with_version=" ${essential_packages_with_version[$i]} "
501534 local pkg_name=" ${essential_package_names[$i]} "
502-
535+
503536 # Check if package is already installed in chroot
504537 if chroot " ${rootfs_mount_point} " rpm -q " $pkg_name " > /dev/null 2>&1 ; then
505538 log::info " Package $pkg_name is already installed, skipping"
@@ -536,47 +569,29 @@ disk::install_deb_on_rootfs() {
536569 shift
537570 local packages=(" $@ " )
538571
539- # Essential packages for Debian/Ubuntu
540- local essential_packages=(
541- " cryptpilot-fde"
542- )
543-
544- local copied_debs=()
545- local deb_args=()
546- local packages_to_install=()
572+ local copied_debs=() # Will store the local paths inside chroot to the copied .deb files
573+ local user_packages=() # User provided packages to install
547574
575+ # Step 1: Install user-provided packages first
548576 for package in " ${packages[@]} " ; do
549577 if [[ -f " $package " && " $package " == * .deb ]]; then
578+ # This is a valid .deb file on the host
550579 base_name=$( basename " $package " )
551- cp " $package " " ${rootfs_mount_point} /tmp/"
552- copied_debs+=(" /tmp/$base_name " )
553- deb_args +=(" /tmp/$base_name " )
580+ cp " $package " " ${rootfs_mount_point} /tmp/" # Copy into rootfs /tmp/
581+ copied_debs+=(" /tmp/$base_name " ) # Record path inside rootfs
582+ user_packages +=(" /tmp/$base_name " ) # Add to installation list
554583 else
555- # For package names, we will ask apt to install after dpkg -i
556- deb_args+=(" $package " )
557- fi
558- done
559-
560- # Check which essential packages are NOT available as local .deb files
561- for essential_pkg in " ${essential_packages[@]} " ; do
562- local found=false
563- for deb in " ${copied_debs[@]} " ; do
564- if [[ " $deb " == * " ${essential_pkg} " * ]]; then
565- found=true
566- break
567- fi
568- done
569- if [ " $found " = false ]; then
570- packages_to_install+=(" $essential_pkg " )
584+ # Assume this is a regular package name (to be installed via apt)
585+ user_packages+=(" $package " )
571586 fi
572587 done
573588
574- # Try to install .deb files first, then fix dependencies via apt
575- if [ ${# deb_args [@]} -gt 0 ]; then
589+ # Install user-provided packages
590+ if [ ${# user_packages [@]} -gt 0 ]; then
576591 chroot " ${rootfs_mount_point} " bash -c " dpkg --configure -a || true"
577- chroot " ${rootfs_mount_point} " bash -c " dpkg -i $( printf ' %s ' " ${deb_args [@]} " | sed ' s/ $//' ) " || true
592+ chroot " ${rootfs_mount_point} " bash -c " dpkg -i $( printf ' %s ' " ${user_packages [@]} " | sed ' s/ $//' ) " || true
578593
579- # Fix dependencies
594+ # Fix dependencies
580595 chroot " ${rootfs_mount_point} " /usr/bin/env ${http_proxy: +http_proxy=$http_proxy } \
581596 ${https_proxy: +https_proxy=$https_proxy } \
582597 ${ftp_proxy: +ftp_proxy=$ftp_proxy } \
@@ -593,28 +608,74 @@ disk::install_deb_on_rootfs() {
593608 ${all_proxy: +all_proxy=$all_proxy } \
594609 ${no_proxy: +no_proxy=$no_proxy } \
595610 apt-get -y -f install || true
611+ fi
612+
613+ # Step 2: Build essential packages list
614+ local cryptpilot_fde_version=" "
596615
597- # Install only packages not provided as local .deb files
598- if [ ${# packages_to_install[@]} -gt 0 ]; then
599- chroot " ${rootfs_mount_point} " /usr/bin/env ${http_proxy: +http_proxy=$http_proxy } \
600- ${https_proxy: +https_proxy=$https_proxy } \
601- ${ftp_proxy: +ftp_proxy=$ftp_proxy } \
602- ${rsync_proxy: +rsync_proxy=$rsync_proxy } \
603- ${all_proxy: +all_proxy=$all_proxy } \
604- ${no_proxy: +no_proxy=$no_proxy } \
605- apt-get -y install " ${packages_to_install[@]} " || true
616+ # Try to query the version of cryptpilot-fde from the current system
617+ if command -v rpm > /dev/null 2>&1 ; then
618+ cryptpilot_fde_version=$( rpm -q cryptpilot-fde --qf ' %{VERSION}-%{RELEASE}' 2> /dev/null || true)
619+ elif command -v dpkg-query > /dev/null 2>&1 ; then
620+ # Extract version from dpkg-query output, removing epoch if present
621+ cryptpilot_fde_version=$( dpkg-query -W -f=' ${Version}' cryptpilot-fde 2> /dev/null || true)
622+ fi
623+
624+ local essential_packages_with_version=()
625+ local essential_package_names=()
626+
627+ if [ -n " ${cryptpilot_fde_version} " ]; then
628+ log::info " Detected cryptpilot-fde version: ${cryptpilot_fde_version} "
629+ essential_packages_with_version+=(" cryptpilot-fde=${cryptpilot_fde_version} " )
630+ else
631+ log::warn " Failed to detect cryptpilot-fde version, installing latest version"
632+ essential_packages_with_version+=(" cryptpilot-fde" )
633+ fi
634+ essential_package_names+=(" cryptpilot-fde" )
635+
636+ # Also include apt-utils for better apt handling
637+ if ! chroot " ${rootfs_mount_point} " dpkg -l apt-utils > /dev/null 2>&1 ; then
638+ essential_packages_with_version+=(" apt-utils" )
639+ essential_package_names+=(" apt-utils" )
640+ fi
641+
642+ # Step 3: Check and install missing essential packages
643+ local packages_to_install=()
644+ for i in " ${! essential_packages_with_version[@]} " ; do
645+ local pkg_with_version=" ${essential_packages_with_version[$i]} "
646+ local pkg_name=" ${essential_package_names[$i]} "
647+
648+ # Check if package is already installed in chroot
649+ if chroot " ${rootfs_mount_point} " dpkg -l " $pkg_name " 2> /dev/null | grep -q " ^ii" ; then
650+ log::info " Package $pkg_name is already installed, skipping"
651+ else
652+ log::info " Package $pkg_name is not installed, will install: $pkg_with_version "
653+ packages_to_install+=(" $pkg_with_version " )
606654 fi
655+ done
607656
608- # Hold package versions for essential packages
609- for p in " ${essential_packages[@]} " ; do
610- chroot " ${rootfs_mount_point} " apt-mark hold " $p " || true
611- done
612- chroot " ${rootfs_mount_point} " apt-get clean || true
657+ # Install missing essential packages
658+ if [ ${# packages_to_install[@]} -gt 0 ]; then
659+ chroot " ${rootfs_mount_point} " /usr/bin/env ${http_proxy: +http_proxy=$http_proxy } \
660+ ${https_proxy: +https_proxy=$https_proxy } \
661+ ${ftp_proxy: +ftp_proxy=$ftp_proxy } \
662+ ${rsync_proxy: +rsync_proxy=$rsync_proxy } \
663+ ${all_proxy: +all_proxy=$all_proxy } \
664+ ${no_proxy: +no_proxy=$no_proxy } \
665+ apt-get -y install " ${packages_to_install[@]} "
613666 fi
614667
615- # cleanup copied debs
616- for d in " ${copied_debs[@]} " ; do
617- rm -f " ${rootfs_mount_point}${d} "
668+ # Step 4: Install zram kernel module for Ubuntu
669+ install_zram_module_if_needed " ${rootfs_mount_point} "
670+
671+ # Step 5: Lock version for all essential packages (using base package name)
672+ chroot " ${rootfs_mount_point} " apt-mark hold " ${essential_package_names[@]} "
673+
674+ chroot " ${rootfs_mount_point} " apt-get clean
675+
676+ # Remove the copied .deb files from the chroot after installation
677+ for deb in " ${copied_debs[@]} " ; do
678+ rm -f " ${rootfs_mount_point}${deb} "
618679 done
619680}
620681
@@ -779,6 +840,41 @@ step:update_rootfs() {
779840 local boot_file_path=$2
780841 local uki=$3
781842
843+ # Expand the rootfs partition to utilize available disk space before update
844+ # This ensures sufficient space for package installations that may trigger scripts
845+ log::info " Expanding rootfs partition to utilize available disk space before update"
846+
847+ # Get current rootfs partition size information
848+ local original_size_in_bytes
849+ original_size_in_bytes=$( blockdev --getsize64 " ${rootfs_orig_part} " )
850+ local original_size_mb=$(( original_size_in_bytes / 1024 / 1024 ))
851+
852+ log::info " Original rootfs partition size: ${original_size_mb} MB (${original_size_in_bytes} bytes)"
853+
854+ # Use growpart to expand the partition to maximum available space
855+ # This is more reliable than manual calculations
856+ if command -v growpart > /dev/null 2>&1 ; then
857+ log::info " Using growpart to expand partition ${rootfs_orig_part_num} on device $device "
858+ if growpart " $device " " $rootfs_orig_part_num " ; then
859+ # Resize the filesystem to fill the new partition size
860+ log::info " Resizing filesystem to fill new partition size..."
861+ e2fsck -f " ${rootfs_orig_part} " -p || true # Run e2fsck first to ensure filesystem integrity
862+ resize2fs " ${rootfs_orig_part} "
863+
864+ # Verify the new size
865+ local new_size_in_bytes
866+ new_size_in_bytes=$( blockdev --getsize64 " ${rootfs_orig_part} " )
867+ local new_size_mb=$(( new_size_in_bytes / 1024 / 1024 ))
868+
869+ log::info " New rootfs partition size: ${new_size_mb} MB (${new_size_in_bytes} bytes)"
870+ log::info " Rootfs partition and filesystem resized successfully"
871+ else
872+ log::warn " growpart failed, proceeding with original partition size"
873+ fi
874+ else
875+ log::warn " growpart command not found, proceeding with original partition size"
876+ fi
877+
782878 update_rootfs_inner () {
783879 local rootfs_mount_point=$1
784880 local uki=$2
0 commit comments