@Paul-Freeman Please try this for your script:
#!/bin/bash
## FOG post-download script -- copy model-matched drivers into the imaged OS.
##
## Sourced, not executed: funcs.sh completeTasking() does
## . ${postdownpath}fog.postdownload
## so use `return` here, never `exit` -- an exit aborts the whole imaging init
## and the task never completes.
##
## Install to /images/postdownloadscripts/drivers.sh, then add this line to
## /images/postdownloadscripts/fog.postdownload:
## . ${postdownpath}drivers.sh
##
## Server layout expected (extracted .inf trees, not CABs):
## /images/drivers/<model>/... e.g. /images/drivers/Latitude E5410/
## Lands in the image as:
## C:\Windows\DRV\...
driverbase="/images/drivers"
clientdriverdir="Windows/DRV" # relative to the mounted Windows volume
#############################################
# Work out the model name
#############################################
# Lenovo is the only real special case: it puts the marketing model
# ("ThinkPad T14 Gen 3") in system-version and a bare machine type ("21AH") in
# system-product-name. Dell and everyone else use system-product-name, so Dell
# needs no branch of its own -- it is the default.
manufacturer=$(dmidecode -s system-manufacturer 2>/dev/null)
case $manufacturer in
[Ll][Ee][Nn][Oo][Vv][Oo])
machine=$(dmidecode -s system-version 2>/dev/null)
;;
*)
machine=$(dmidecode -s system-product-name 2>/dev/null)
;;
esac
# Strip leading and trailing whitespace. Dell in particular pads its DMI
# strings, and " Latitude 5420 " will not match the folder on the server.
machine="${machine#"${machine%%[![:space:]]*}"}"
machine="${machine%"${machine##*[![:space:]]}"}"
dots "Preparing drivers"
# Placeholder junk dmidecode returns on whiteboxes, VMs and unflashed boards.
# Treat these the same as "no model" rather than looking for a folder named
# "To Be Filled By O.E.M.".
case $machine in
""|[Tt]o[[:space:]][Bb]e[[:space:]][Ff]illed*|[Ss]ystem[[:space:]][Pp]roduct[[:space:]][Nn]ame*|[Dd]efault[[:space:]]string*)
echo "Skipped (no usable model name)"
debugPause
return
;;
esac
#############################################
# Bail out before mounting anything if there are no drivers to copy
#############################################
# -d, not -f: these are directories. The original used -f, which is false for a
# directory, so the copy could never run.
remotedriverpath="$driverbase/$machine"
if [[ ! -d $remotedriverpath ]]; then
echo "Skipped (no drivers for $machine)"
debugPause
return
fi
#############################################
# Find and mount the Windows volume
#############################################
# /ntfs is NOT mounted when post-download scripts run -- every funcs.sh helper
# that touches it mounts and unmounts for itself (see mountOSPartition and
# clearMountedDevices). Without this, mkdir -p /ntfs/Windows/DRV just creates a
# directory in the ramdisk that disappears at reboot, which is the usual reason
# this script "succeeds" and no drivers appear.
[[ -z $disks ]] && disks="$hd"
[[ -d /ntfs ]] || mkdir -p /ntfs >/dev/null 2>&1
umount /ntfs >/dev/null 2>&1
winpart=""
for disk in $disks; do
getPartitions "$disk"
for part in $parts; do
fsTypeSetting "$part"
[[ $fstype == ntfs ]] || continue
ntfs-3g -o remove_hiberfile,rw "$part" /ntfs >/dev/null 2>&1 || continue
# WinRE/recovery partitions are NTFS too. \Windows\System32 is what
# distinguishes the actual OS volume from them.
if [[ -d /ntfs/Windows/System32 ]]; then
winpart="$part"
break 2
fi
umount /ntfs >/dev/null 2>&1
done
done
if [[ -z $winpart ]]; then
echo "Skipped (no Windows partition found)"
debugPause
return
fi
#############################################
# Copy the drivers
#############################################
# -rt, not -a: ntfs-3g mounted without a permissions map cannot honour chown or
# chmod, so rsync -a fails on every file and returns 23 -- a spurious "Failed"
# even though the data copied fine. -r -t gives recursion and mtimes, which is
# all a driver tree needs. -z is dropped too: it is a local copy, so
# compression costs CPU and buys nothing.
#
# Trailing slash on the source copies the CONTENTS of the model folder into
# DRV. Without it you get C:\Windows\DRV\<model>\... and the DevicePath below
# no longer points at the .inf files.
mkdir -p "/ntfs/$clientdriverdir" >/dev/null 2>&1
rsync -rt "$remotedriverpath/" "/ntfs/$clientdriverdir/" >/dev/null 2>&1
errStat=$?
#############################################
# Point sysprep at the drivers
#############################################
# NOTE: this block is still commented out, as in the original. Without it the
# files are copied but nothing ever reads them -- DevicePath is what makes
# sysprep/PnP search C:\Windows\DRV. Uncomment to actually inject. It must stay
# ABOVE the umount below, because it edits a file on the mounted volume.
# Keep %SystemRoot%\inf in the list; separate extra locations with ;
#
#regfile="/ntfs/Windows/System32/config/SOFTWARE"
#key="\Microsoft\Windows\CurrentVersion\DevicePath"
#devpath="%SystemRoot%\DRV;%SystemRoot%\inf;";
#reged -e "$regfile" &>/dev/null <<EOFREG
#ed $key
#$devpath
#q
#y
#EOFREG
umount /ntfs >/dev/null 2>&1
#############################################
# Report
#############################################
# A driver copy that fails must not fail the imaging task, so this never calls
# handleError. handleWarning is used only for a genuine copy failure -- note it
# sleeps 60 seconds, which is why the "no drivers for this model" cases above
# just echo and return instead.
if [[ $errStat -ne 0 ]]; then
echo "Failed"
debugPause
handleWarning "Failed to copy drivers for [$machine] (rsync exit $errStat)"
return
fi
echo "Done"
debugPause