我目前有一个带有闪存卡的嵌入式设备,该设备有 3 个 QNX 6.5.0SP1 分区 - 两个可引导分区(fs 类型 79),一个数据分区(fs 类型 78)。我想以编程方式选择启动这两个可启动分区中的哪一个,基于数据分区上的某种标志(可能是一个
touch
'd 文件),在关闭之前由用户交互设置。这可能吗?理想情况下,最终结果是将所选分区的文件系统在启动后安装到根目录。
我尝试修改
.boot
文件,但我相信在执行交给.boot
时分区已经启动。我相信我需要修改 IPL,但我不确定如何在 IPL 期间从任何文件系统读取。
最简单的解决方案是标记“活动”可启动分区,确保它是唯一一个带有
.diskroot
文件的分区,指示 diskboot
将其安装为 /
。切换过程是:使用 fdisk boot
将新的根分区标记为可启动;然后mv /.diskroot
就可以了。
如果严格要求可启动分区不可写,则需要为系统设计一个替换启动脚本来启动关键驱动程序并进行自己的安装,因为
diskboot
不支持复杂的安装行为(它不支持重复的 .diskroot 安装点)。您可以使用 mkifs将更新后的脚本链接到
.boot
文件的替换版本。
关键参考文档:
最后,作为一个优势,我可以提供这个 shell 脚本“fsscan”,我的公司在 QNX 6.3 天时曾用于此目的。该脚本查找具有“.bootkey”文件的分区,该文件与 IFS 中包含的“bootkey”文件相匹配;该文件的内容是简短版本和日期戳。这让我们选择一个启动分区,除了
fdisk boot
,它会找到并挂载匹配的根分区。
#/proc/boot/sh
# fsscan for QNX - scans for and mounts filesystems
# includes analysis of .diskroot for QNX filesystems for use at boot.
# Options
do_mount=0
build_fstab=1
parse_diskroot=0
commit_string=""
keyfile="/proc/boot/bootkey"
## Parse commandline
while getopts "mndck:" opt ; do
case $opt in
m)
do_mount=1
;;
n)
build_fstab=0
;;
d)
parse_diskroot=1
;;
k)
keyfile="$OPTARG"
;;
c)
commit_string="commit=none"
;;
esac
done
if [ -r "$keyfile" ]; then
keydata=`cat $keyfile`
else
keyfile=""
fi
echo "Scanning available disk partitions..."
if [ "$build_fstab" -eq 1 ]; then
echo "# fstab build by fsscan on `date`" > /etc/fstab
fi
# Get QNX devices
# We use two passes to figure out what to do. First pass pre-mounts devices
# and locates .bootkey, second pass manages other .diskroots.
UD=`ls /dev/ud*t79 /dev/ud*t78 /dev/ud*t77 2>/dev/null`
HD=`ls /dev/hd*t79 /dev/hd*t78 /dev/hd*t77 2>/dev/null`
QDEVS="$UD $HD"
# First pass
did_mount=""
was_mounted=""
for device in $QDEVS; do
disk=`echo $device | sed -e "s/\/dev\/[hu]d\(.*\)t7[789]/\1/"`
type=`echo $device | sed -n -e "s/\/dev\/\([hu]\)d.*t7[789]/\1/p"`
id=`echo $device | sed -n -e "s/\/dev\/[hu]d.*t\(7[789]\)/\1/p"`
mountopts="rw"
if [ ! -z "$commit_string" ]; then
mountopts="$mountopts,$commit_string"
fi
# Check if already mounted
mountpt=`df $device | awk "\\$1 == \"$device\" {print \\$6}"`
is_mounted=0
if [ -z "$mountpt" ]; then
num=$((80 - $id))
mountpt="/fs/${type}d$disk-qnx4-$num"
if [ "$do_mount" -eq 1 ]; then
echo "Found QNX filesystem at $device, mounting as $mountpt"
mount -t qnx4 -o $mountopts $device $mountpt
is_mounted=1
did_mount="$did_mount $device"
fi;
else
is_mounted=1
was_mounted="$was_mounted $device"
echo "Found QNX filesystem at $device already mounted as $mountpt"
fi
if [ "$is_mounted" -eq 1 ]; then
if [ -n "$keyfile" -a "$parse_diskroot" -eq 1 -a -r $mountpt/.diskroot -a -r $mountpt/.bootkey ]; then
# Check boot key.
fskeydata=`cat $mountpt/.bootkey`
if [ "$keydata" = "$fskeydata" ]; then
# Handle diskroot RIGHT NOW
diskroot=`awk 'BEGIN { mp = "/" }
(NR == 1) && /\// { mp = $0; }
/^[ \t]*mount[ \t]*=/ { split($0,parts,/=/); mp = parts[2]; gsub(/^[ \t]*/,"",mp); gsub(/[ \t]*$/,"",mp); }
END { print mp; }' <$mountpt/.diskroot`
# echo "$device: Diskroot mountpoint is '$diskroot'"
if [ -z "$diskroot" ]; then
diskroot="/"
fi
# Check for existing partition there
if df $diskroot | awk "\$6 != \"$diskroot\" {exit 0} {exit 1}"; then
echo "Relocating QNX filesystem with matching key at $device to $diskroot"
umount $mountpt
if [ "$do_mount" -eq 1 ]; then
mount -t qnx4 -o $mountopts $device $diskroot
fi
mountpt="$diskroot"
fi
fi
fi;
else
echo "Found QNX filesystem at $device, mountable as $mountpt"
fi
done;
#echo "Did mount: '$did_mount' Was mounted: '$was_mounted'"
# Second pass
for device in $QDEVS; do
disk=`echo $device | sed -e "s/\/dev\/[hu]d\(.*\)t7[789]/\1/"`
type=`echo $device | sed -n -e "s/\/dev\/\([hu]\)d.*t7[789]/\1/p"`
id=`echo $device | sed -n -e "s/\/dev\/[hu]d.*t\(7[789]\)/\1/p"`
mountopts="rw"
if [ ! -z "$commit_string" ]; then
mountopts="$mountopts,$commit_string"
fi
# Check if already mounted
mountpt=`df $device | awk "\\$1 == \"$device\" {print \\$6}"`
if echo $was_mounted | grep -q $device || echo $did_mount | grep -q $device; then
# Process diskroot
#echo "Considering $device for diskroot"
# Read .diskroot
if [ "$parse_diskroot" -eq 1 -a -r $mountpt/.diskroot ]; then
diskroot=`awk 'BEGIN { mp = "/" }
(NR == 1) && /\// { mp = $0; }
/^[ \t]*mount[ \t]*=/ { split($0,parts,/=/); mp = parts[2]; gsub(/^[ \t]*/,"",mp); gsub(/[ \t]*$/,"",mp); }
END { print mp; }' <$mountpt/.diskroot`
# echo "$device: Diskroot mountpoint is '$diskroot'"
if [ -z "$diskroot" ]; then
diskroot="/"
fi
# echo "Using '$diskroot' for $device"
# Check for existing partition there
if df $diskroot | awk "\$6 != \"$diskroot\" {exit 0} {exit 1}"; then
echo "Relocating QNX filesystem at $device to $diskroot"
echo "umount $mountpt"
umount $mountpt
if [ "$do_mount" -eq 1 ]; then
echo "mount -t qnx4 -o $mountopts $device $diskroot"
mount -t qnx4 -o $mountopts $device $diskroot
fi
mountpt="$diskroot"
fi
fi
else
# Check is now mounted == bootkey
if [ -z "$mountpt" ]; then
num=$((80 - $id))
mountpt="/fs/${type}d$disk-qnx4-$num"
fi
fi
if [ "$build_fstab" -eq 1 ]; then
echo "$device $mountpt qnx4 $mountopts 0 0" >> /etc/fstab
fi;
done;
# Grab DOS devices.
lastdisk=""
for id in 1 4 6 11 12; do
for device in `ls /dev/hd*t$id /dev/hd*t$id.* /dev/ud*t$id /dev/ud*t$id.* 2>/dev/null`; do
disk=`echo $device | sed -e "s/\/dev\/\([hu]d.*\)t$id.*/\1/"`
# Check if already mounted
mountpt=`df $device | awk "\\$1 == \"$device\" {print \\$6}"`
mountopts="rw"
if [ -z "$mountpt" ]; then
is_mounted=0
# Find mountpoint
if [ "X$lastdisk" != "X$disk" ]; then
lastdisk="$disk"
num=0
fi
while [ -z "$mountpt" ]; do
num=$(($num + 1))
mountpt="/fs/$disk-dos-$num"
if [ -e "$mountpt" ]; then
mountpt=""
fi
done;
if [ "$do_mount" -eq 1 ]; then
echo "Found DOS filesystem at $device, mounting as $mountpt"
mount -t dos -o $mountopts $device $mountpt
else
echo "Found DOS filesystem at $device, mountable as $mountpt"
fi
else
echo "Found DOS filesystem at $device, already mounted as $mountpt"
fi
if [ "$build_fstab" -eq 1 ]; then
echo "$device $mountpt dos $mountopts 0 0" >> /etc/fstab
fi
done;
done;
echo "Partition scan complete."
注意:此脚本需要完整的 shell 和一些 UNIX 文本处理实用程序,才能包含在 .boot IFS 中。 QNX 努力使其默认 IFS 尽可能小;这不是我们应用程序的限制。
mount
umount
sleep
sh
awk
sed
ls
cat
echo
df
grep