cros-kernel-install 6.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287
  1. #!/usr/bin/env bash
  2. # Copyright (C) 2016 Paul Kocialkowski <contact@paulk.fr>
  3. #
  4. # This program is free software: you can redistribute it and/or modify
  5. # it under the terms of the GNU General Public License as published by
  6. # the Free Software Foundation, either version 3 of the License, or
  7. # (at your option) any later version.
  8. #
  9. # This program is distributed in the hope that it will be useful,
  10. # but WITHOUT ANY WARRANTY; without even the implied warranty of
  11. # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  12. # GNU General Public License for more details.
  13. #
  14. # You should have received a copy of the GNU General Public License
  15. # along with this program. If not, see <http://www.gnu.org/licenses/>.
  16. SYS_BLOCK_PATH="/sys/class/block"
  17. DEV_PATH="/dev"
  18. DEVICE="device"
  19. VENDOR="vendor"
  20. MODEL="model"
  21. NAME="name"
  22. usage() {
  23. printf '%s\n' "$executable [action] [storage] [kernel image|kernel modules]" >&2
  24. printf '\n%s\n' 'Actions:' >&2
  25. printf '%s\n' ' backup - Backup kernel image' >&2
  26. printf '%s\n' ' image - Install kernel image' >&2
  27. printf '%s\n' ' modules - Install kernel modules' >&2
  28. usage_storage
  29. printf '\n%s\n' 'Environment variables:' >&2
  30. printf '%s\n' ' VBOOT_KEYS_PATH - Path to the vboot keys' >&2
  31. printf '%s\n' ' VBOOT_TOOLS_PATH - Path to vboot tools' >&2
  32. }
  33. usage_storage() {
  34. printf '\n%s\n' 'Storage:' >&2
  35. local nodes=$( ls "$SYS_BLOCK_PATH" )
  36. local node_path
  37. local name
  38. for node in $nodes
  39. do
  40. node_path="$DEV_PATH/$node"
  41. if ! [ -b "$node_path" ]
  42. then
  43. continue
  44. fi
  45. name=$( storage_name "$node_path" )
  46. if [ -z "$name" ]
  47. then
  48. continue
  49. fi
  50. printf '%s\n' " $node_path - $name" >&2
  51. done
  52. }
  53. storage_affect_confirm() {
  54. local storage_path=$1
  55. local name=$( storage_name "$storage_path" )
  56. local confirm
  57. printf '%s\n' 'This is going to affect the following storage:'
  58. printf '%s\n' " $storage_path - $name"
  59. printf '%s' 'Press enter to confirm: '
  60. read confirm
  61. }
  62. storage_name() {
  63. local storage_path=$1
  64. local node=$( basename "$storage_path" )
  65. local vendor_path="$SYS_BLOCK_PATH/$node/$DEVICE/$VENDOR"
  66. local model_path="$SYS_BLOCK_PATH/$node/$DEVICE/$MODEL"
  67. local name_path="$SYS_BLOCK_PATH/$node/$DEVICE/$NAME"
  68. local vendor
  69. local name
  70. if [ -f "$model_path" ]
  71. then
  72. name=$( cat "$model_path" )
  73. elif [ -f "$name_path" ]
  74. then
  75. name=$( cat "$name_path" )
  76. else
  77. return 0
  78. fi
  79. name=$( printf '%s\n' "$name" | sed -e "s/^[[:space:]]*//;s/[[:space:]]*$//" )
  80. if [ -f "$vendor_path" ]
  81. then
  82. vendor=$( cat "$vendor_path" )
  83. vendor=$( printf '%s\n' "$vendor" | sed -e "s/^[[:space:]]*//;s/[[:space:]]*$//" )
  84. name="$vendor $name"
  85. fi
  86. printf '%s\n' "$name"
  87. }
  88. storage_partition_path() {
  89. local storage_path=$1
  90. local index=$2
  91. storage_partition_path="$storage_path$index"
  92. if ! [ -b "$storage_partition_path" ]
  93. then
  94. storage_partition_path="$storage_path""p$index"
  95. fi
  96. if ! [ -b "$storage_partition_path" ]
  97. then
  98. return 1
  99. fi
  100. printf '%s\n' "$storage_partition_path"
  101. }
  102. storage_partition_mount_path() {
  103. local storage_partition_path=$1
  104. local storage_partition_mount_path=$( udisksctl info -b "$storage_partition_path" | grep "MountPoints" | sed "s/.*MountPoints:[[:space:]]*\(.*\)/\1/g" )
  105. printf '%s\n' "$storage_partition_mount_path"
  106. }
  107. storage_kernel_path() {
  108. local storage_path=$1
  109. cgpt find -t kernel "$storage_path" | head -n 1
  110. }
  111. storage_rootfs_path() {
  112. local storage_path=$1
  113. cgpt find -t rootfs "$storage_path" | head -n 1
  114. }
  115. backup() {
  116. local storage_path=$1
  117. local kernel_image_path=$2
  118. local storage_kernel_path=$( storage_kernel_path "$storage_path" )
  119. if [ -z "$storage_kernel_path" ]
  120. then
  121. printf '%s\n' "No kernel partition found on storage $storage_path" >&2
  122. return 1
  123. fi
  124. cat "$storage_kernel_path" > "$kernel_image_path"
  125. printf '\n%s\n' "Backed up kernel image to $kernel_image_path"
  126. }
  127. image() {
  128. local storage_path=$1
  129. local kernel_image_path=$2
  130. local storage_kernel_path=$( storage_kernel_path "$storage_path" )
  131. if [ -z "$storage_kernel_path" ]
  132. then
  133. printf '%s\n' "No kernel partition found on storage $storage_path" >&2
  134. return 1
  135. fi
  136. storage_affect_confirm "$storage_path"
  137. cat "$kernel_image_path" > "$storage_kernel_path"
  138. sync
  139. printf '\n%s\n' "Installed kernel image on storage $storage_path"
  140. }
  141. modules() {
  142. local storage_path=$1
  143. local kernel_modules_path=$2
  144. local storage_rootfs_path=$( storage_rootfs_path "$storage_path" )
  145. if [ -z "$storage_rootfs_path" ]
  146. then
  147. printf '%s\n' "No rootfs partition found on storage $storage_path" >&2
  148. return 1
  149. fi
  150. storage_affect_confirm "$storage_path"
  151. # Partition may already be mounted.
  152. udisksctl mount -b "$storage_rootfs_path" || true
  153. storage_rootfs_mount_path=$( storage_partition_mount_path "$storage_rootfs_path" )
  154. rsync -a --keep-dirlinks "$kernel_modules_path" "$storage_rootfs_mount_path/"
  155. sync
  156. udisksctl unmount -b "$storage_rootfs_path"
  157. printf '\n%s\n' "Installed kernel modules on storage $storage_path"
  158. }
  159. requirements() {
  160. local requirement
  161. local requirement_path
  162. for requirement in "$@"
  163. do
  164. requirement_path=$( which "$requirement" || true )
  165. if [ -z "$requirement_path" ]
  166. then
  167. printf '%s\n' "Missing requirement: $requirement" >&2
  168. exit 1
  169. fi
  170. done
  171. }
  172. setup() {
  173. root=$(readlink -f "$( dirname "$0" )" )
  174. executable=$( basename "$0" )
  175. if ! [ -z "$VBOOT_TOOLS_PATH" ]
  176. then
  177. PATH="$PATH:$VBOOT_TOOLS_PATH"
  178. fi
  179. if [ -z "$VBOOT_KEYS_PATH" ]
  180. then
  181. if ! [ -z "$VBOOT_TOOLS_PATH" ] && [ -d "$VBOOT_TOOLS_PATH/devkeys" ]
  182. then
  183. VBOOT_KEYS_PATH="$VBOOT_TOOLS_PATH/devkeys"
  184. else
  185. VBOOT_KEYS_PATH="/usr/share/vboot/devkeys"
  186. fi
  187. fi
  188. }
  189. cros_kernel_install() {
  190. local action=$1
  191. local storage_path=$2
  192. local kernel_image_path=$3
  193. local kernel_modules_path=$3
  194. set -e
  195. setup "$@"
  196. if [ -z "$action" ] || [ -z "$storage_path" ] || [ -z "$kernel_image_path" ] || [ -z "$kernel_modules_path" ]
  197. then
  198. usage
  199. exit 1
  200. fi
  201. case $action in
  202. "backup")
  203. requirements "cgpt"
  204. backup "$storage_path" "$kernel_image_path"
  205. ;;
  206. "image")
  207. requirements "cgpt"
  208. image "$storage_path" "$kernel_image_path"
  209. ;;
  210. "modules")
  211. requirements "cgpt"
  212. modules "$storage_path" "$kernel_modules_path"
  213. ;;
  214. *)
  215. usage
  216. exit 1
  217. ;;
  218. esac
  219. }
  220. cros_kernel_install "$@"