Score:0

How to change rootfs UUID or device name in the grub boot options to switch between rootfs device partitions?

cn flag

I am currently working on the software update framework swupdate. As an update scheme, I chose the dual copy approach. I have installed Ubuntu 20.04 on my target device (desktop pc -->i5,32GB SSD,BIOS,..) to test and partitioned it accordingly.

 /dev/sda1 --/boot 
 /dev/sda2 --/
 /dev/sda3 --/root2
 /dev/sda4 --/data

For testing purposes I created a root file system image from the host system (/dev/sda2) using the "dd" command. I assigned a new UUID and label to the image using "tune2fs" and "e2label" commands.

dd if=/dev/sda2 of=rootfs.img status=progress 

e2label rootfs.img root2

e2fsck -fy rootfs.img

tune2fs -U random rootfs.img

It is necessary to have a mechanism for coordination between the boot loader and the update agent in order to boot the system with the secondary rootfs partition after a successful update. The bootloader should be assure which rootfs partition (A or B) is loaded.

Ubuntu uses GRUB as the standard boot loader. GRUB provides an "environment block" which can be used to save a small amount of state (/boot/grub/grubenv). The update agent "SWUpdate" has a bootloader handler to manage this file. SWupdate is able to add environment variables to this file. SWupdate can call scripts before and after installing the images (pre-postinstall). I have written a bash script that reads the current rootfs partition from the kernel command line (/proc/cmdline) and the environment variables from the GRUB environment block (/boot/grub/grubenv) in order to update the rootfs partition after the update process through the default bootloader configuration file (/etc/default/grub) with which the system is booted.

CONFIG_FILE=/etc/default/grub
ROOTFS1_UUID=$(blkid -o value -s UUID /dev/sda2)
ROOTFS2_UUID=$(blkid -o value -s UUID /dev/sda3) 
function get_UUID_of_current_boot_device() {
    for i in `cat /proc/cmdline`; do
        case "$i" in
            root=*)
                ROOT="${i#root=UUID=}"
                ;;
        esac
    done
}
function get_partition_number_of_current_boot_device() {
    if [[ $ROOT = $ROOTFS1_UUID ]]; then
        CURRENT_PARTITION="2";
    elif [[ $ROOT = $ROOTFS2_UUID ]]; then
        CURRENT_PARTITION="3";
    else
        echo "Error by Partitionshema!!"
    fi
}
function get_bootloader_env() {
        for i in `cat /boot/grub/grubenv`; do
                case "$i" in
                    bootpart=*)
                            BOOT_DEVICE="${i#bootpart=}"
                            ;;
                esac
        done
}
function set_boot_device_UUID() {
    if [ $BOOT_DEVICE = "2" ]; then
        BOOT_DEVICE_UUID="$ROOTFS1_UUID";
    elif [ $BOOT_DEVICE = "3" ]; then
        BOOT_DEVICE_UUID="$ROOTFS2_UUID";
    else
        echo "";
        BOOT_DEVICE_UUID="$ROOT";
    fi
}

As far as I have read so far, in order to permanently modify the kernel command line parameters, the required parameters must be configured in the GRUB_CMDLINE_LINUX_DEFAULT line or in the GRUB_CMDLINE_LINUX line. In my script I modified this line so that the $BOOT_DEVICE_UUID variable should always be the rootfs partition that should be booted after the reboot.

sed -i "s/\(GRUB_CMDLINE_LINUX *= *\).*/\1\"$BOOT_DEVICE_UUID\"/" $CONFIG_FILE;

Unfortunately that didn't work, I thought that the value of the existing variable "root" in the command line would be replaced with the value that I passed. The boot loader should somehow select via environment variables which Rootfs partition, which contains the Linux system, should be loaded. Could someone please explain to me where my mistake is and could someone give me a concrete example about this topic?

mangohost

Post an answer

Most people don’t grasp that asking a lot of questions unlocks learning and improves interpersonal bonding. In Alison’s studies, for example, though people could accurately recall how many questions had been asked in their conversations, they didn’t intuit the link between questions and liking. Across four studies, in which participants were engaged in conversations themselves or read transcripts of others’ conversations, people tended not to realize that question asking would influence—or had influenced—the level of amity between the conversationalists.