自动选择要引导的QNX分区

huangapple go评论127阅读模式
英文:

Picking which QNX partition to boot into automatically

问题

我目前有一个嵌入式设备,其中有一个带有3个QNX 6.5.0SP1分区的闪存卡 - 两个可引导分区(文件系统类型79),一个数据分区(文件系统类型78)。我想根据数据分区上的某种标志(可能是一个touch命令创建的文件),在关机前通过用户交互来编程选择要引导的两个可引导分区中的哪一个。这种做法可行吗?理想情况下,选择的分区的文件系统在引导后会被挂载到根目录。

我尝试修改.boot文件,但我相信在执行交给.boot之前,分区已经被引导了。我相信我需要修改IPL,但我不确定如何在IPL期间从任何文件系统中读取数据。

英文:

I currently have an embedded device with a flash card that has 3 QNX 6.5.0SP1 partitions - two bootable partitions (fs type 79), one data partition (fs type 78). I would like to programmatically choose which of these two bootable partitions to boot into, based on a flag of some sort on the data partition (perhaps a touch'd file) set by user interaction before shutdown. Is this possible? Ideally, the end result would have the chosen partition's file system mounted to root once booted.

I have tried modifying the .boot file, but I believe the partition has already been booted by the time execution is handed to .boot. I believe I need to modify the IPL, but I'm unsure how to read from any file system during the IPL.

答案1

得分: 1

最简单的解决方案是通过确保只有一个带有.diskroot文件的“活动”可引导分区,该文件指示diskboot将其挂载为/。切换过程如下:使用fdisk boot将新的根分区标记为可引导;然后将/.diskroot移动到该分区。

如果要求可引导分区不可写入,您需要为系统设计一个替代的启动脚本,该脚本启动关键驱动程序并执行自己的挂载操作,因为diskboot不支持复杂的挂载行为(它不支持重复的.diskroot挂载点)。您可以使用mkifs将更新的脚本链接到.boot文件的替代品中。

关键参考文档:

最后,作为帮助,我可以提供这个Shell脚本“fsscan”,这是我们公司在QNX 6.3时代用于此目的的脚本。该脚本会查找具有与IFS中包含的“bootkey”文件匹配的“.bootkey”文件的分区;该文件的内容是一个简短的版本和日期戳。这样,我们就可以仅使用fdisk boot选择引导分区,它会找到并挂载匹配的根分区。

  1. #/proc/boot/sh
  2. # fsscan for QNX - scans for and mounts filesystems
  3. # includes analysis of .diskroot for QNX filesystems for use at boot.
  4. # Options
  5. do_mount=0
  6. build_fstab=1
  7. parse_diskroot=0
  8. commit_string=""
  9. keyfile="/proc/boot/bootkey"
  10. ## Parse commandline
  11. while getopts "mndck:" opt ; do
  12. case $opt in
  13. m)
  14. do_mount=1
  15. ;;
  16. n)
  17. build_fstab=0
  18. ;;
  19. d)
  20. parse_diskroot=1
  21. ;;
  22. k)
  23. keyfile="$OPTARG"
  24. ;;
  25. c)
  26. commit_string="commit=none"
  27. ;;
  28. esac
  29. done
  30. if [ -r "$keyfile" ]; then
  31. keydata=`cat $keyfile`
  32. else
  33. keyfile=""
  34. fi
  35. echo "Scanning available disk partitions..."
  36. if [ "$build_fstab" -eq 1 ]; then
  37. echo "# fstab build by fsscan on `date`" > /etc/fstab
  38. fi
  39. # Get QNX devices
  40. # We use two passes to figure out what to do. First pass pre-mounts devices
  41. # and locates .bootkey, second pass manages other .diskroots.
  42. UD=`ls /dev/ud*t79 /dev/ud*t78 /dev/ud*t77 2>/dev/null`
  43. HD=`ls /dev/hd*t79 /dev/hd*t78 /dev/hd*t77 2>/dev/null`
  44. QDEVS="$UD $HD"
  45. # First pass
  46. did_mount=""
  47. was_mounted=""
  48. for device in $QDEVS; do
  49. disk=`echo $device | sed -e "s/\/dev\/[hu]d\(.*\)t7[789]/\1/"`
  50. type=`echo $device | sed -n -e "s/\/dev\/\([hu]\)d.*t7[789]/\1/p"`
  51. id=`echo $device | sed -n -e "s/\/dev\/[hu]d.*t\(7[789]\)/\1/p"`
  52. mountopts="rw"
  53. if [ ! -z "$commit_string" ]; then
  54. mountopts="$mountopts,$commit_string"
  55. fi
  56. # Check if already mounted
  57. mountpt=`df $device | awk "\$1 == \"$device\" {print \$6}"`
  58. is_mounted=0
  59. if [ -z "$mountpt" ]; then
  60. num=$((80 - $id))
  61. mountpt="/fs/${type}d$disk-qnx4-$num"
  62. if [ "$do_mount" -eq 1 ]; then
  63. echo "Found QNX filesystem at $device, mounting as $mountpt"
  64. mount -t qnx4 -o $mountopts $device $mountpt
  65. is_mounted=1
  66. did_mount="$did_mount $device"
  67. fi;
  68. else
  69. is_mounted=1
  70. was_mounted="$was_mounted $device"
  71. echo "Found QNX filesystem at $device already mounted as $mountpt"
  72. fi
  73. if [ "$is_mounted" -eq 1 ]; then
  74. if [ -n "$keyfile" -a "$parse_diskroot" -eq 1 -a -r $mountpt/.diskroot -a -r $mountpt/.bootkey ]; then
  75. # Check boot key.
  76. fskeydata=`cat $mountpt/.bootkey`
  77. if [ "$keydata" = "$fskeydata" ]; then
  78. # Handle diskroot RIGHT NOW
  79. diskroot=`awk 'BEGIN { mp = "/" }
  80. (NR == 1) && /\// { mp = $0; }
  81. /^[ \t]*mount[ \t]*=/ { split($0,parts,/=/); mp = parts[2]; gsub(/^[ \t]*/,"",mp); gsub(/[ \t]*$/,"",mp); }
  82. END { print mp; }' <$mountpt/.diskroot`
  83. # echo "$device: Diskroot mountpoint is '$diskroot'"
  84. if [ -z "$diskroot" ]; then
  85. diskroot="/"
  86. fi
  87. # Check for existing partition there
  88. if df $diskroot | awk "\$6 != \"$diskroot\" {exit 0} {exit 1}"; then
  89. echo "Relocating QNX filesystem with matching key at $device to $diskroot"
  90. umount $mountpt
  91. if [ "$do_mount" -eq 1 ]; then
  92. mount -t qnx4 -o $mountopts $device $diskroot
  93. fi
  94. mountpt="$diskroot"
  95. fi
  96. fi
  97. fi;
  98. else
  99. echo "Found QNX filesystem at $device, mountable as $mountpt"
  100. fi
  101. done;
  102. #echo "Did mount: '$did_mount' Was mounted: '$was_mounted'"
  103. # Second pass
  104. for device in $QDEVS; do
  105. disk=`echo $device | sed -e "s/\/dev\/[hu]d\(.*\)t7[789]/\1/"`
  106. type=`echo $device | sed -n -e "s/\/dev\/\([hu]\)d.*t7[789]/\1/p"`
  107. id=`echo $device | sed -n -e "s/\/dev\/[hu]d.*t\(7[789]\)/\1/p"`
  108. mountopts="rw"
  109. if [ ! -z "$commit_string" ]; then
  110. mountopts="$mountopts,$commit_string"
  111. fi
  112. # Check if already mounted
  113. mountpt=`df $device | awk "\$1 == \"$device\" {print \$6}"`
  114. if echo $was_mounted | grep -q $device || echo $did_mount | grep -q $device; then
  115. # Process diskroot
  116. #echo "Considering $device for diskroot"
  117. # Read .diskroot
  118. if [ "$parse_diskroot" -eq 1 -a -r $mountpt/.diskroot ]; then
  119. diskroot=`awk 'BEGIN { mp = "/" }
  120. (NR == 1) && /\// { mp = $0; }
  121. /^[ \t]*mount[ \t]*=/ { split($0,parts,/=/); mp = parts[2]; gsub(/^[ \t]*/,"",mp); gsub(/[ \t]*$/,"",mp); }
  122. END { print mp; }' <$mountpt/.diskroot`
  123. # echo "$device: Diskroot mountpoint is '$diskroot'"
  124. if [ -z "$diskroot" ]; then
  125. diskroot="/"
  126. fi
  127. # echo "Using '$diskroot' for $device"
  128. # Check for existing partition there
  129. if df $diskroot | awk "\$6 != \"$diskroot\" {exit 0} {exit 1}"; then
  130. echo "Relocating QNX filesystem at $device to $diskroot"
  131. echo "umount $mountpt"
  132. umount $mountpt
  133. if [ "$do_mount" -eq 1 ]; then
  134. echo "mount -t qnx4 -o $mountopts $device $diskroot"
  135. mount -t qnx4 -o $mountopts $device $diskroot
  136. fi
  137. mountpt="$diskroot"
  138. fi
  139. fi
  140. else
  141. # Check is now mounted == bootkey
  142. if [ -z "$mountpt" ]; then
  143. num=$((80 - $id))
  144. mountpt="/fs/${type}d$disk-qnx4-$num"
  145. fi
  146. fi
  147. if [ "$build_fstab" -eq 1 ]; then
  148. echo "$device $mountpt qnx4 $mountopts 0 0" >> /etc/fstab
  149. fi;
  150. done;
  151. # Grab DOS devices.
  152. lastdisk=""
  153. for id in 1 4 6 11 12; do
  154. for device in `ls /dev/hd*t$id /dev/hd*t$id.* /dev/ud*t$id /dev/ud*t$id.* 2>/dev/null`; do
  155. disk=`echo $device | sed -e "s/\/dev\/\([hu]d.*\)t$id.*/\1/"`
  156. # Check if already mounted
  157. mountpt=`df $device | awk "\$1 == \"$device\" {print \$6}"`
  158. mountopts="rw"
  159. if [ -z "$mountpt" ]; then
  160. is_mounted=0
  161. # Find mountpoint
  162. if [ "X$lastdisk" != "X$disk" ]; then
  163. lastdisk="$disk"
  164. num=0
  165. fi
  166. while [ -z "$mountpt" ]; do
  167. num=$(($num + 1))
  168. mountpt="/fs/$disk-dos-$num"
  169. if [ -e "$mountpt" ]; then
  170. mountpt=""
  171. fi
  172. done;
  173. if [ "$do_mount" -eq 1 ]; then
  174. echo "Found DOS filesystem at $device, mounting as $mountpt"
  175. mount -t dos -o $mountopts $device $mountpt
  176. else
  177. echo "Found DOS filesystem at $device, mountable as $mountpt"
  178. fi
  179. else
  180. echo "Found DOS filesystem at $device, already mounted as $mountpt"
  181. fi
  182. if [ "$build_fstab" -eq 1 ]; then
  183. echo "$device $mountpt dos $mountopts 0 0" >> /etc/fstab
  184. fi
  185. done;
  186. done;
  187. echo "Partition scan complete."

注意:此脚本需要在.boot IFS中包含完整的Shell和一些UNIX文本处理实用程序。QNX努力使其默认IFS尽可能小;这对我们的应用程序来说不是一个限制。

  1. mount
  2. umount
  3. sleep
  4. sh
  5. awk
  6. sed
  7. ls
  8. cat
  9. echo
  10. df
  11. grep
英文:

The simplest solution is to mark the "active" bootable partion by ensuring it's the only one with a .diskroot file that instructs diskboot to mount it as /. The switching process would be: use fdisk boot to mark the new root partition as bootable; then mv /.diskroot to it.

If it is a strict requirement that the bootable partitions are not writable, you'll need to design a replacement boot script for your system that starts up the key drivers and does its own mounting, as diskboot does not support complex mounting behaviour (it does not support duplicate .diskroot mount points). Your updated script can be linked in to a replacment for the .boot file using mkifs.

Key reference documentation:

Finally, as a leg up, I can offer this shell script "fsscan" my company used to use for this purpose back in the QNX 6.3 days. This script looks for a partition with a ".bootkey" file that matches a "bootkey" file included in the IFS; the contents of this file were a short version and date stamp. This let us select a boot partition with nothing but fdisk boot, and it would find and mount the matching root partition.

  1. #/proc/boot/sh
  2. # fsscan for QNX - scans for and mounts filesystems
  3. # includes analysis of .diskroot for QNX filesystems for use at boot.
  4. # Options
  5. do_mount=0
  6. build_fstab=1
  7. parse_diskroot=0
  8. commit_string=&quot;&quot;
  9. keyfile=&quot;/proc/boot/bootkey&quot;
  10. ## Parse commandline
  11. while getopts &quot;mndck:&quot; opt ; do
  12. case $opt in
  13. m)
  14. do_mount=1
  15. ;;
  16. n)
  17. build_fstab=0
  18. ;;
  19. d)
  20. parse_diskroot=1
  21. ;;
  22. k)
  23. keyfile=&quot;$OPTARG&quot;
  24. ;;
  25. c)
  26. commit_string=&quot;commit=none&quot;
  27. ;;
  28. esac
  29. done
  30. if [ -r &quot;$keyfile&quot; ]; then
  31. keydata=`cat $keyfile`
  32. else
  33. keyfile=&quot;&quot;
  34. fi
  35. echo &quot;Scanning available disk partitions...&quot;
  36. if [ &quot;$build_fstab&quot; -eq 1 ]; then
  37. echo &quot;# fstab build by fsscan on `date`&quot; &gt; /etc/fstab
  38. fi
  39. # Get QNX devices
  40. # We use two passes to figure out what to do. First pass pre-mounts devices
  41. # and locates .bootkey, second pass manages other .diskroots.
  42. UD=`ls /dev/ud*t79 /dev/ud*t78 /dev/ud*t77 2&gt;/dev/null`
  43. HD=`ls /dev/hd*t79 /dev/hd*t78 /dev/hd*t77 2&gt;/dev/null`
  44. QDEVS=&quot;$UD $HD&quot;
  45. # First pass
  46. did_mount=&quot;&quot;
  47. was_mounted=&quot;&quot;
  48. for device in $QDEVS; do
  49. disk=`echo $device | sed -e &quot;s/\/dev\/[hu]d\(.*\)t7[789]/\1/&quot;`
  50. type=`echo $device | sed -n -e &quot;s/\/dev\/\([hu]\)d.*t7[789]/\1/p&quot;`
  51. id=`echo $device | sed -n -e &quot;s/\/dev\/[hu]d.*t\(7[789]\)/\1/p&quot;`
  52. mountopts=&quot;rw&quot;
  53. if [ ! -z &quot;$commit_string&quot; ]; then
  54. mountopts=&quot;$mountopts,$commit_string&quot;
  55. fi
  56. # Check if already mounted
  57. mountpt=`df $device | awk &quot;\\$1 == \&quot;$device\&quot; {print \\$6}&quot;`
  58. is_mounted=0
  59. if [ -z &quot;$mountpt&quot; ]; then
  60. num=$((80 - $id))
  61. mountpt=&quot;/fs/${type}d$disk-qnx4-$num&quot;
  62. if [ &quot;$do_mount&quot; -eq 1 ]; then
  63. echo &quot;Found QNX filesystem at $device, mounting as $mountpt&quot;
  64. mount -t qnx4 -o $mountopts $device $mountpt
  65. is_mounted=1
  66. did_mount=&quot;$did_mount $device&quot;
  67. fi;
  68. else
  69. is_mounted=1
  70. was_mounted=&quot;$was_mounted $device&quot;
  71. echo &quot;Found QNX filesystem at $device already mounted as $mountpt&quot;
  72. fi
  73. if [ &quot;$is_mounted&quot; -eq 1 ]; then
  74. if [ -n &quot;$keyfile&quot; -a &quot;$parse_diskroot&quot; -eq 1 -a -r $mountpt/.diskroot -a -r $mountpt/.bootkey ]; then
  75. # Check boot key.
  76. fskeydata=`cat $mountpt/.bootkey`
  77. if [ &quot;$keydata&quot; = &quot;$fskeydata&quot; ]; then
  78. # Handle diskroot RIGHT NOW
  79. diskroot=`awk &#39;BEGIN { mp = &quot;/&quot; }
  80. (NR == 1) &amp;&amp; /\// { mp = $0; }
  81. /^[ \t]*mount[ \t]*=/ { split($0,parts,/=/); mp = parts[2]; gsub(/^[ \t]*/,&quot;&quot;,mp); gsub(/[ \t]*$/,&quot;&quot;,mp); }
  82. END { print mp; }&#39; &lt;$mountpt/.diskroot`
  83. # echo &quot;$device: Diskroot mountpoint is &#39;$diskroot&#39;&quot;
  84. if [ -z &quot;$diskroot&quot; ]; then
  85. diskroot=&quot;/&quot;
  86. fi
  87. # Check for existing partition there
  88. if df $diskroot | awk &quot;\$6 != \&quot;$diskroot\&quot; {exit 0} {exit 1}&quot;; then
  89. echo &quot;Relocating QNX filesystem with matching key at $device to $diskroot&quot;
  90. umount $mountpt
  91. if [ &quot;$do_mount&quot; -eq 1 ]; then
  92. mount -t qnx4 -o $mountopts $device $diskroot
  93. fi
  94. mountpt=&quot;$diskroot&quot;
  95. fi
  96. fi
  97. fi;
  98. else
  99. echo &quot;Found QNX filesystem at $device, mountable as $mountpt&quot;
  100. fi
  101. done;
  102. #echo &quot;Did mount: &#39;$did_mount&#39; Was mounted: &#39;$was_mounted&#39;&quot;
  103. # Second pass
  104. for device in $QDEVS; do
  105. disk=`echo $device | sed -e &quot;s/\/dev\/[hu]d\(.*\)t7[789]/\1/&quot;`
  106. type=`echo $device | sed -n -e &quot;s/\/dev\/\([hu]\)d.*t7[789]/\1/p&quot;`
  107. id=`echo $device | sed -n -e &quot;s/\/dev\/[hu]d.*t\(7[789]\)/\1/p&quot;`
  108. mountopts=&quot;rw&quot;
  109. if [ ! -z &quot;$commit_string&quot; ]; then
  110. mountopts=&quot;$mountopts,$commit_string&quot;
  111. fi
  112. # Check if already mounted
  113. mountpt=`df $device | awk &quot;\\$1 == \&quot;$device\&quot; {print \\$6}&quot;`
  114. if echo $was_mounted | grep -q $device || echo $did_mount | grep -q $device; then
  115. # Process diskroot
  116. #echo &quot;Considering $device for diskroot&quot;
  117. # Read .diskroot
  118. if [ &quot;$parse_diskroot&quot; -eq 1 -a -r $mountpt/.diskroot ]; then
  119. diskroot=`awk &#39;BEGIN { mp = &quot;/&quot; }
  120. (NR == 1) &amp;&amp; /\// { mp = $0; }
  121. /^[ \t]*mount[ \t]*=/ { split($0,parts,/=/); mp = parts[2]; gsub(/^[ \t]*/,&quot;&quot;,mp); gsub(/[ \t]*$/,&quot;&quot;,mp); }
  122. END { print mp; }&#39; &lt;$mountpt/.diskroot`
  123. # echo &quot;$device: Diskroot mountpoint is &#39;$diskroot&#39;&quot;
  124. if [ -z &quot;$diskroot&quot; ]; then
  125. diskroot=&quot;/&quot;
  126. fi
  127. # echo &quot;Using &#39;$diskroot&#39; for $device&quot;
  128. # Check for existing partition there
  129. if df $diskroot | awk &quot;\$6 != \&quot;$diskroot\&quot; {exit 0} {exit 1}&quot;; then
  130. echo &quot;Relocating QNX filesystem at $device to $diskroot&quot;
  131. echo &quot;umount $mountpt&quot;
  132. umount $mountpt
  133. if [ &quot;$do_mount&quot; -eq 1 ]; then
  134. echo &quot;mount -t qnx4 -o $mountopts $device $diskroot&quot;
  135. mount -t qnx4 -o $mountopts $device $diskroot
  136. fi
  137. mountpt=&quot;$diskroot&quot;
  138. fi
  139. fi
  140. else
  141. # Check is now mounted == bootkey
  142. if [ -z &quot;$mountpt&quot; ]; then
  143. num=$((80 - $id))
  144. mountpt=&quot;/fs/${type}d$disk-qnx4-$num&quot;
  145. fi
  146. fi
  147. if [ &quot;$build_fstab&quot; -eq 1 ]; then
  148. echo &quot;$device $mountpt qnx4 $mountopts 0 0&quot; &gt;&gt; /etc/fstab
  149. fi;
  150. done;
  151. # Grab DOS devices.
  152. lastdisk=&quot;&quot;
  153. for id in 1 4 6 11 12; do
  154. for device in `ls /dev/hd*t$id /dev/hd*t$id.* /dev/ud*t$id /dev/ud*t$id.* 2&gt;/dev/null`; do
  155. disk=`echo $device | sed -e &quot;s/\/dev\/\([hu]d.*\)t$id.*/\1/&quot;`
  156. # Check if already mounted
  157. mountpt=`df $device | awk &quot;\\$1 == \&quot;$device\&quot; {print \\$6}&quot;`
  158. mountopts=&quot;rw&quot;
  159. if [ -z &quot;$mountpt&quot; ]; then
  160. is_mounted=0
  161. # Find mountpoint
  162. if [ &quot;X$lastdisk&quot; != &quot;X$disk&quot; ]; then
  163. lastdisk=&quot;$disk&quot;
  164. num=0
  165. fi
  166. while [ -z &quot;$mountpt&quot; ]; do
  167. num=$(($num + 1))
  168. mountpt=&quot;/fs/$disk-dos-$num&quot;
  169. if [ -e &quot;$mountpt&quot; ]; then
  170. mountpt=&quot;&quot;
  171. fi
  172. done;
  173. if [ &quot;$do_mount&quot; -eq 1 ]; then
  174. echo &quot;Found DOS filesystem at $device, mounting as $mountpt&quot;
  175. mount -t dos -o $mountopts $device $mountpt
  176. else
  177. echo &quot;Found DOS filesystem at $device, mountable as $mountpt&quot;
  178. fi
  179. else
  180. echo &quot;Found DOS filesystem at $device, already mounted as $mountpt&quot;
  181. fi
  182. if [ &quot;$build_fstab&quot; -eq 1 ]; then
  183. echo &quot;$device $mountpt dos $mountopts 0 0&quot; &gt;&gt; /etc/fstab
  184. fi
  185. done;
  186. done;
  187. echo &quot;Partition scan complete.&quot;

NB: this script requires a full shell and some UNIX text processing utilities to be included in the .boot IFS. QNX worked hard to keep their default IFS as small as possible; this wasn't a limitation for our application.

  1. mount
  2. umount
  3. sleep
  4. sh
  5. awk
  6. sed
  7. ls
  8. cat
  9. echo
  10. df
  11. grep

huangapple
  • 本文由 发表于 2023年8月8日 22:30:04
  • 转载请务必保留本文链接:https://go.coder-hub.com/76860535.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定