bootconfig.sh 3.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177
  1. . /lib/functions.sh
  2. PART_SIZE=20
  3. NAME_SIZE=16
  4. MAX_NUM_PARTS=16
  5. MAGIC_START_HEX="a0 a1 a2 a3"
  6. MAGIC_START_TRY_HEX="a1 a1 a2 a3"
  7. MAGIC_END_HEX="b0 b1 b2 b3"
  8. validate_bootconfig_magic() {
  9. local file=$1
  10. magic_start=$(hexdump -v -n 4 -e '4/1 "%02x "' "$file")
  11. magic_end=$(hexdump -v -s 332 -n 4 -e '4/1 "%02x "' "$file")
  12. if [ "$magic_start" != "$MAGIC_START_HEX" ] && \
  13. [ "$magic_start" != "$MAGIC_START_TRY_HEX" ]; then
  14. echo "Not a valid bootconfig file, start magic does not match" >&2
  15. return 1
  16. fi
  17. if [ "$magic_end" != "$MAGIC_END_HEX" ]; then
  18. echo "Not a valid bootconfig file, end magic does not match" >&2
  19. return 1
  20. fi
  21. return 0
  22. }
  23. get_bootconfig_numparts() {
  24. local file=$1
  25. numpartshex=$(hexdump -v -s 8 -n 4 -e '4/1 "%02x "' "$file")
  26. numparts=$(( 0x$(echo $numpartshex | awk '{print $4$3$2$1}') ))
  27. echo ${numparts}
  28. }
  29. get_bootconfig_partidx() {
  30. local file=$1
  31. local partname=$2
  32. local numparts=$(get_bootconfig_numparts "$file")
  33. if [ -z "$numparts" ]; then
  34. echo "Could not get number of partitions" >&2
  35. return
  36. fi
  37. if [ $numparts -gt $MAX_NUM_PARTS ]; then
  38. numparts=$MAX_NUM_PARTS
  39. fi
  40. for i in $(seq 0 $((numparts -1))); do
  41. nameoffset=$((12 + i * $PART_SIZE))
  42. nameraw=$(dd if="$file" bs=1 skip="$nameoffset" count=12 2>/dev/null)
  43. name=${nameraw//S'\x00'/}
  44. if [ "$partname" = "$name" ]; then
  45. echo $i
  46. fi
  47. done
  48. }
  49. get_bootconfig_primaryboot() {
  50. local file=$1
  51. local partname=$2
  52. local partidx=$(get_bootconfig_partidx "$file" "$partname")
  53. if ! echo "$partidx" | grep -Eq '^[0-9]+$'; then
  54. echo "Could not get partition index for $partname in $file" >&2
  55. return
  56. fi
  57. if [ "$partidx" -ge 0 ] && [ "$partidx" -lt $MAX_NUM_PARTS ]; then
  58. offset=$((12 + $partidx * $PART_SIZE + $NAME_SIZE))
  59. primaryboothex=$(hexdump -v -s "$offset" -n 4 -e '4/1 "%02x "' $file)
  60. primaryboot=$(( 0x$(echo $primaryboothex | awk '{print $4$3$2$1}') ))
  61. echo $primaryboot
  62. fi
  63. }
  64. _set_bootconfig_primaryboot() {
  65. local file=$1
  66. local partname=$2
  67. local primaryboot=$3
  68. local primaryboothex
  69. local partidx
  70. local primarybootoffset
  71. partidx=$(get_bootconfig_partidx "$file" "$partname")
  72. if ! echo "$partidx" | grep -Eq '^[0-9]+$'; then
  73. echo "Could not get partition index for $2" >&2
  74. return 1
  75. fi
  76. primarybootoffset=$((12 + $partidx * $PART_SIZE + $NAME_SIZE))
  77. case "$primaryboot" in
  78. 0)
  79. printf "\x00\x00\x00\x00" | dd of="$file" seek="$primarybootoffset" bs=1 count=4 conv=notrunc 2>/dev/null
  80. ;;
  81. 1)
  82. printf "\x01\x00\x00\x00" | dd of="$file" seek="$primarybootoffset" bs=1 count=4 conv=notrunc 2>/dev/null
  83. ;;
  84. *)
  85. echo "invalid argument: primaryboot must be 0 or 1" >&2
  86. return 1
  87. ;;
  88. esac
  89. }
  90. set_bootconfig_primaryboot() {
  91. local file=$1
  92. local partname=$2
  93. local primaryboot=$3
  94. [ -z "$file" ] || [ -z "$partname" ] || [ -z "$primaryboot" ] && {
  95. echo "usage: $0 <file> <partition name> <0|1>"
  96. return 1
  97. }
  98. [ ! -e "$file" ] && {
  99. echo "file $file not found" >&2
  100. return 1
  101. }
  102. [ ! -w $file ] && {
  103. echo "file $file not writable" >&2
  104. return 1
  105. }
  106. validate_bootconfig_magic "$file"
  107. [ $? -ne 0 ] && return 1
  108. _set_bootconfig_primaryboot $file $partname $primaryboot
  109. [ $? -ne 0 ] && return 1
  110. return 0
  111. }
  112. toggle_bootconfig_primaryboot() {
  113. local file=$1
  114. local partname=$2
  115. local primaryboot
  116. [ -z "$file" ] || [ -z "$partname" ] && {
  117. echo "usage: $0 <file> <partition name>"
  118. return 1
  119. }
  120. [ ! -e "$file" ] && {
  121. echo "file $file not found" >&2
  122. return 1
  123. }
  124. [ ! -w $file ] && {
  125. echo "file $file not writable" >&2
  126. return 1
  127. }
  128. validate_bootconfig_magic "$file"
  129. [ $? -ne 0 ] && return 1
  130. primaryboot=$(get_bootconfig_primaryboot "$1" "$2")
  131. case "$primaryboot" in
  132. 0)
  133. _set_bootconfig_primaryboot "$1" "$2" 1
  134. ;;
  135. 1)
  136. _set_bootconfig_primaryboot "$1" "$2" 0
  137. ;;
  138. *)
  139. echo "invalid value: primaryboot must be 0 or 1" >&2
  140. return 1
  141. ;;
  142. esac
  143. [ $? -ne 0 ] && return 1
  144. return 0
  145. }