Skip to main content

Creating a Remote Reimage Utility

Creating a Remote Reimage Utility

There are various ways you can go about creating a bootable utility for this purpose, but I'm willing to bet that if you're reading this, you probably have a copy of Ukit handy on a flash drive somewhere. We're going to cheat a little (but only a little) and modify Ukit instead of building something from scratch.

Once we're done modifying Ukit, we'll add in our image and zip everything up into an archive that we can easily deploy.

This process requires a Bash shell. If you don't have Windows Subsystem for Linux installed, you can do this on ThinPro or on another Linux computer.

Preparation

Definitions

Let's get some basic terminology out of the way so we're all on the same page:

  • ThinState: ThinPro utility that writes Ukit to a flash drive
  • Ukit: HP's Bootable imaging utility. This is an Ubuntu live image with custom scripts packed into a cpio archive
  • ThinUpdate: HP's Windows utility for creating Ukit drives, downloading images, etc
  • Initial Ramdisk (initrd): Temporary filesystem loaded into memory during boot
  • Tarball: An archive created using the tar command

Be aware that the version of Ukit installed by ThinUpdate generally lags behind the version installed by ThinState. This can impact what binaries are available when Ukit boots. For this guide, we'll be using the Ukit version produced by ThinState on ThinPro 7.2.

Prep Work

If you don't have a Ukit drive, please consult HP's documentation on how to use ThinState. A copy of the ThinPro 7.2 Admin Guide is attached to this page for reference.

We have a few prep tasks to run through. First, let's set up a folder structure that we can work in. Name the main folder Remote Reimage Utility and create the following subfolders:

  • init\ for working on init.sh
  • initrd\ for working on initrd.gz
  • tarball\ for storing our finished tar archive 
  • ukit-final\ for storing completed copies of our modified files
  • ukit-source\ for original copies of Ukit files

image.png

Now copy the contents of your Ukit drive to ukit-source\

image.png

File paths for the remainder of this page are relative to the Remote Reimage Utility folder

Modifying Ukit

Initrd

We need to make some changes to the files inside initrd.gz. Copy the file from ukit-source\ to initrd\, then run zcat to decompress it and cpio to extract the files from the archive.

zcat initrd.gz | cpio -idmv

When you're done extracting files, you'll see the Ubuntu filesystem that Ukit boots to.

image.png

The first file we need to modify is init.ukit. Open it up and comment out echo Please remove the USB key and press Enter... and read. This will prevent Ukit from asking for user input before restarting the computer. The commented version of the file is provided below.

#!/bin/bash
# put local startup commands in here

mkdir -p /mnt/usbkey

export USB_DEV=$BOOTDISK
export USBKEY=/mnt/usbkey
# don't pass SYSDISK into ukit, let ukit figure it out
#export flash_device=$SYSDISK

mount $BOOTPART $USBKEY >/dev/null 2>&1

if ! `grep -q usbkey /proc/mounts`; then
	echo "ERROR: Unable to mount USB Key"
	echo "Press Enter to reboot..."
	read
	/bin/bash
	exit 1
fi

clear
cat $USBKEY/init.sh | /usr/bin/tr -d '\r' > /tmp/init.sh
chmod +x /tmp/init.sh
eval /tmp/init.sh

cd /
umount -l /mnt/usbkey
#echo Please remove the USB key and press Enter...
#read
reboot -f

We also need to install a couple extra binaries.

  • mkfs.vfat: Formats volumes
  • md5sum: Validates file integrity

You'll find them on a running ThinPro instance at the locations listed below. Copy them over from ThinPro to the Ukit folder. You don't need to paste them to the exact same paths, but it is good practice to stay consistent with where they are expected to be installed.

  • /sbin/mkfs.vfat
  • /usr/bin/md5sum

Paste mkfs.vfat to initrd\sbin\

image.png

Paste md5sum to initrd\usr\bin\

image.png

The last thing we need to do is create a new-image folder at initrd\. This is where we'll stash our new image during the reimage operation.

image.png

We're all done making changes to initrd.gz, so let's repack and recompress it. We should delete the original initrd.gz file from the folder so it doesn't get packed in with the rest of the files we need.

image.png

Run this command from within initrd\

find . | cpio -o -H newc | gzip > initrd.gz

When you're done, copy the new initrd.gz file to ukit-final\.

image.png

Init Script

Init.sh runs after Ukit boots. This is what usually displays all the normal options (write image, capture image, etc) you're probably used to seeing. Let's hijack it!

Copy init.sh from ukit-source\ to init\ and replace the entire contents of the copy with the below script. This is how we hook into Ukit and make it do what we want.

If you create a new text file instead of copying the original, you will need to change the end of line (EOL) formatting from Windows to Unix. You can do this with Notepad++

init.sh (click to expand)
#! /bin/bash

## This is a workaround for HP Device Manager limitations regarding reimage over wireless networks
## This script replaces init.sh inside HP's ukit utility and allows the utility to work as a recovery partition (sort of)
## Script assumes the 'please remove media' reboot prompt has been removed from init.ukit inside initrd.gz
## Additional binaries (mkfs.vfat, md5sum) have been installed to initrd.gz
## Author: Newb

#### Define Variables ####
blk_dev=$(lsblk -lf | sort | sed '/boot/d' | grep -i btrfs -B 2 | head -n 1) # <-- System disk
image_path=/mnt/usbkey/images # <-- Location of new image and checksum. This is in the initrd file
image_name=$(ls $image_path | grep dd.gz) # <-- Image to be applied to disk
md5sum=$(ls $image_path | grep md5) # <-- Checksum for new image
image_path_on_ram=/new-image # <-- Where new image will be copied to once ukit boots. This is in the initrd file
ukit_part=$(lsblk -lf | grep -i usbkey | cut -d " " -f 1) # <-- Ukit partition on disk

#### Define Echo Colors ####
red='\033[0;31m'; green='\033[0;32m'; yellow='\033[0;33m'
blue='\033[1;34m'; white='\033[1;37m'
nc='\033[0m' # <-- No color (needs to be added after messages to reset back to white)

#### Define Functions ####
perform_reimage () # Reimage disk
{
	echo -e "${blue}Preparing for reimage${nc}"
	echo -ne "[ INFO ] Copying image to RAM \r"
	cp $image_path/$image_name $image_path_on_ram &&
	echo -e "${green}[	OK	]${nc} Copying image to RAM" ||
	echo -e "${red}[FAILED]${nc} Copying image to RAM"
	cleanup_ukit
	echo -e "${blue}Writing new image to disk. This will take a few minutes${nc}"
	gunzip -c $image_path_on_ram/$image_name | dd of=/dev/$blk_dev status=progress &&
	echo -e "${green}Image operation was successful${nc}"
}

abort_reimage () # Abort reimage operation
{
	echo -e "${red}New image $image_name absent or does not match checksum. Aborting operation${nc}"
	cleanup_ukit
}

cleanup_ukit () # Remove ukit from the disk. It'll leave residual data structures otherwise
{
	echo -ne "[ INFO ] Removing ukit from disk \r"
	umount /dev/$ukit_part &&
	mkfs.vfat -F32 /dev/$ukit_part > /dev/null &&
	echo -e "${green}[	OK	]${nc} Removing ukit from disk" ||
	echo -e "${red}[FAILED]${nc} Removing uikit from disk"
}

reboot_timer () # Displays a countdown timer
{
	for i in {30..1}
	do
		echo -ne "Rebooting in ${yellow}$i${nc} seconds \r"
		sleep 1
	done
	echo -e "Rebooting in 0 seconds"
}

#### Run Script ####
echo -e "${red}Operating system reimage in progress. Rebooting the computer will cause irreversible damage${nc}"
echo -e "Local disk label is ${blue}$blk_dev${nc}"
echo -ne "[ INFO ] Verifying files \r"
cd $image_path
if test -f $image_path/$image_name && md5sum -c --quiet $md5sum
then
	cd /
	echo -e "${green}[	OK	]${nc} Verifying files"
	perform_reimage
else
	cd /
	echo -e "${red}[FAILED]${nc} Verifying files"
	abort_reimage
fi
reboot_timer

As you read through the new script (which you should always do with scripts you find on the internet), you will see that it does these things for us:

  • Confirms the integrity of our image using the md5sum binary we installed
  • Copies the new image to the new-image/ folder we created
  • Deletes Ukit from the disk and formats it using the mkfs.vfat binary we installed
  • Writes the new image to the disk using the dd command

While the script executes, it will output information to the user. If the integrity of the new image can not be verified, the utility will exit and the computer will then boot back into the old ThinPro installation as if nothing had happened.

Copy the new init.sh to ukit-final\

image.png

Now copy the remaining files from ukit-source\ to ukit-final\.

image.png

Grub.cfg

This last file change isn't really necessary, but it is helpful to have a way to visually identify whether or not the modified utility is booting. Go to ukit-final\EFI\Boot\ and edit grub.cfg. We're just going to replace Loading Ukit with Loading reimage utility

set default=0
set timeout=0

set menu_color_normal=cyan/blue
set menu_color_highlight=white/blue

search.file /ukit-ukit.ver root

menuentry 'ThinPro UKit' {
        echo    'Loading reimage utility'
        linux   /Linux edd=off ramdisk_size=262144 vga=788 mode=ukit modprobe.blacklist=amdgpu
        initrd  /initrd.gz
}

Adding an Image

This part is pretty straightforward. Boot to an unmodified Ukit drive on a ThinPro computer you want to grab an image from.

You should use a Ukit drive created by ThinUpdate to capture the image. Drives created with ThinState on ThinPro 7.2 will (probably) fail

image.png

Select Image Record Mode and follow the on-screen instructions. Give the image a descriptive name in line with your naming convention. I'm just going to name mine Dummy. The final filename will be Dummy.dd.gz. When you're done capturing the new image, shut the computer back down and remove the drive.

Copy the captured image from the unmodified Ukit drive to ukit-final\images\.

image.png

Now we need to calculate a checksum for the image. This allows our new init.sh script to verify the file's integrity before applying it to the target machine(s). You can name the checksum file whatever you want, just make sure it has an .md5 file extension.

md5sum Dummy.dd.gz > Dummy.md5

You'll see the checksum file once md5sum is done.

image.png

The new init.sh script will not work correctly if you have more than one image and checksum in this folder

Creating the Tarball

At this point, we just need to add everything in ukit-final\ to a tarball for easy transportation. Run the following command from within ukit-final\. This will create a tarbomb, which is not exactly best practice, but it is appropriate for this scenario.

If you want to extract this tarball later, extract it to an empty folder.

tar cfz Dummy.ukit.tar *

Create a checksum for the tarball

md5sum Dummy.ukit.tar > Dummy.ukit.md5

Move both files to tarball\.

image.png