cros-firmware-prepare 7.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321
  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. KEYBLOCK="keyblock"
  17. VBPRIVK="vbprivk"
  18. VBPUBK="vbpubk"
  19. GBB_FLAGS="dev_screen_short_delay load_option_roms enable_alternate_os force_dev_switch_on force_dev_boot_usb disable_fw_rollback_check enter_triggers_tonorm force_dev_boot_legacy faft_key_overide disable_ec_software_sync default_dev_boot_lefacy disable_pd_software_sync disable_lid_shutdown dev_boot_fastboot_full_cap enable_serial"
  20. usage() {
  21. printf 1>&2 '%s\n' "$executable [action] [firmware image] [gbb action|vpd action] [gbb file|gbb flag|vpd file]"
  22. printf 1>&2 '\n%s\n' 'Actions:'
  23. printf 1>&2 '%s\n' ' sign - Sign firmware image'
  24. printf 1>&2 '%s\n' ' verify - Verify firmware image'
  25. printf 1>&2 '%s\n' ' gbb - Google Binary Block'
  26. printf 1>&2 '\n%s\n' 'GBB actions:'
  27. printf 1>&2 '%s\n' ' extract - Extract GBB from firmware image to path'
  28. printf 1>&2 '%s\n' ' replace - Replace GBB from path to firmware image'
  29. printf 1>&2 '%s\n' ' list - List enabled GBB flags'
  30. printf 1>&2 '%s\n' ' enable - Enable GBB flag'
  31. printf 1>&2 '%s\n' ' disable - Disable GBB flag'
  32. printf 1>&2 '\n%s\n' 'GBB flags:'
  33. for flag in $GBB_FLAGS
  34. do
  35. printf 1>&2 '%s\n' " $flag"
  36. done
  37. printf 1>&2 '\n%s\n' 'VPD actions:'
  38. printf 1>&2 '%s\n' ' extract - Extract VPD from firmware image to path'
  39. printf 1>&2 '%s\n' ' replace - Replace VPD from path to firmware image'
  40. printf 1>&2 '\n%s\n' 'Environment variables:'
  41. printf 1>&2 '%s\n' ' VBOOT_KEYS_PATH - Path to the vboot keys'
  42. printf 1>&2 '%s\n' ' VBOOT_TOOLS_PATH - Path to vboot tools'
  43. }
  44. sign() {
  45. local firmware_image_path=$1
  46. futility sign --signprivate="$VBOOT_KEYS_PATH/firmware_data_key.$VBPRIVK" --keyblock "$VBOOT_KEYS_PATH/firmware.$KEYBLOCK" --kernelkey "$VBOOT_KEYS_PATH/kernel_subkey.$VBPUBK" --infile "$firmware_image_path"
  47. futility gbb_utility -s --recoverykey="$VBOOT_KEYS_PATH/recovery_key.$VBPUBK" --rootkey="$VBOOT_KEYS_PATH/root_key.$VBPUBK" "$firmware_image_path" "$firmware_image_path"
  48. printf '\n%s\n' "Signed firmwares image $firmware_image_path"
  49. }
  50. verify() {
  51. local firmware_image_path=$1
  52. futility verify -k "$VBOOT_KEYS_PATH/root_key.$VBPUBK" "$firmware_image_path" || ( printf '\n%s\n' "Bad firmware image signature!" >&2 && return 1 )
  53. printf '\n%s\n' "Verified firmware image $firmware_image_path"
  54. }
  55. gbb() {
  56. local firmware_image_path=$1
  57. local gbb_action=$2
  58. local gbb_file_path=$3
  59. local gbb_flag=$3
  60. local i=0
  61. local flags
  62. local flag
  63. local flag_value
  64. case $gbb_action in
  65. "extract")
  66. if [ -z "$gbb_file_path" ]
  67. then
  68. usage
  69. exit 1
  70. fi
  71. futility dump_fmap -x "$firmware_image_path" "GBB:$gbb_file_path"
  72. printf '\n%s\n' "Extracted GBB from $firmware_image_path to $gbb_file_path"
  73. ;;
  74. "replace")
  75. if [ -z "$gbb_file_path" ]
  76. then
  77. usage
  78. exit 1
  79. fi
  80. futility load_fmap "$firmware_image_path" "GBB:$gbb_file_path"
  81. printf '\n%s\n' "Replaced GBB from $gbb_file_path to $firmware_image_path"
  82. ;;
  83. "list")
  84. printf '%s\n' "GBB flags in $firmware_image_path:"
  85. flags=$( gbb_flags_get "$firmware_image_path" )
  86. for flag in $GBB_FLAGS
  87. do
  88. flag_value=$(( 1 << $i ))
  89. if (( $flags & $flag_value ))
  90. then
  91. printf '%s\n' " $flag"
  92. fi
  93. i=$(( $i + 1 ))
  94. done
  95. ;;
  96. "enable")
  97. if [ -z "$gbb_flag" ]
  98. then
  99. usage
  100. exit 1
  101. fi
  102. flags=$( gbb_flags_get "$firmware_image_path" )
  103. flag_value=$( gbb_flag_value "$gbb_flag" )
  104. if [ -z "$flag_value" ]
  105. then
  106. printf 1>&2 '%s\n' "Invalid GBB flag: $gbb_flag"
  107. exit 1
  108. fi
  109. flags=$( printf "0x%x\n" $(( $flags | $flag_value )) )
  110. gbb_flags_set "$firmware_image_path" "$flags"
  111. printf '\n%s\n' "Enabled GBB flag $gbb_flag in $firmware_image_path"
  112. ;;
  113. "disable")
  114. if [ -z "$gbb_flag" ]
  115. then
  116. usage
  117. exit 1
  118. fi
  119. flags=$( gbb_flags_get "$firmware_image_path" )
  120. flag_value=$( gbb_flag_value "$gbb_flag" )
  121. if [ -z "$flag_value" ]
  122. then
  123. printf 1>&2 '%s\n' "Invalid GBB flag: $gbb_flag"
  124. exit 1
  125. fi
  126. flags=$( printf "0x%x\n" $(( $flags & ~$flag_value )) )
  127. gbb_flags_set "$firmware_image_path" "$flags"
  128. printf '\n%s\n' "Disabled GBB flag $gbb_flag in $firmware_image_path"
  129. ;;
  130. *)
  131. usage
  132. exit 1
  133. ;;
  134. esac
  135. }
  136. gbb_flags_get() {
  137. local firmware_image_path=$1
  138. futility gbb_utility -g --flags "$firmware_image_path" | sed "s/^[^:]*: //g"
  139. }
  140. gbb_flags_set() {
  141. local firmware_image_path=$1
  142. local gbb_flags=$2
  143. futility gbb_utility -s --flags="$gbb_flags" "$firmware_image_path"
  144. }
  145. gbb_flag_value() {
  146. local gbb_flag=$1
  147. local i=0
  148. for flag in $GBB_FLAGS
  149. do
  150. if [ "$gbb_flag" = "$flag" ]
  151. then
  152. printf '%d\n' $(( 1 << $i ))
  153. return
  154. fi
  155. i=$(( $i + 1 ))
  156. done
  157. }
  158. vpd() {
  159. local firmware_image_path=$1
  160. local vpd_action=$2
  161. local vpd_file_path=$3
  162. case $vpd_action in
  163. "extract")
  164. futility dump_fmap -x "$firmware_image_path" "RO_VPD:$vpd_file_path"
  165. printf '\n%s\n' "Extracted VPD from $firmware_image_path to $vpd_file_path"
  166. ;;
  167. "replace")
  168. futility load_fmap "$firmware_image_path" "RO_VPD:$vpd_file_path"
  169. printf '\n%s\n' "Replaced VPD from $vpd_file_path to $firmware_image_path"
  170. ;;
  171. *)
  172. usage
  173. exit 1
  174. ;;
  175. esac
  176. }
  177. requirements() {
  178. local requirement
  179. local requirement_path
  180. for requirement in "$@"
  181. do
  182. requirement_path=$( which "$requirement" || true )
  183. if [ -z "$requirement_path" ]
  184. then
  185. printf 1>&2 '%s\n' "Missing requirement: $requirement"
  186. exit 1
  187. fi
  188. done
  189. }
  190. setup() {
  191. root=$(readlink -f "$( dirname "$0" )" )
  192. executable=$( basename "$0" )
  193. if ! [ -z "$VBOOT_TOOLS_PATH" ]
  194. then
  195. PATH="$PATH:$VBOOT_TOOLS_PATH"
  196. fi
  197. if [ -z "$VBOOT_KEYS_PATH" ]
  198. then
  199. if ! [ -z "$VBOOT_TOOLS_PATH" ] && [ -d "$VBOOT_TOOLS_PATH/devkeys" ]
  200. then
  201. VBOOT_KEYS_PATH="$VBOOT_TOOLS_PATH/devkeys"
  202. else
  203. VBOOT_KEYS_PATH="/usr/share/vboot/devkeys"
  204. fi
  205. fi
  206. }
  207. cros_firmware_prepare() {
  208. local action=$1
  209. local firmware_image_path=$2
  210. local gbb_action=$3
  211. local vpd_action=$3
  212. local gbb_file_path_flag=$4
  213. local vpd_file_path=$4
  214. set -e
  215. setup "$@"
  216. if [ -z "$action" ] || [ -z "$firmware_image_path" ]
  217. then
  218. usage
  219. exit 1
  220. fi
  221. case $action in
  222. "sign")
  223. if ! [ -f "$firmware_image_path" ]
  224. then
  225. usage
  226. exit 1
  227. fi
  228. requirements "futility"
  229. sign "$firmware_image_path"
  230. ;;
  231. "verify")
  232. requirements "futility"
  233. verify "$firmware_image_path"
  234. ;;
  235. "gbb")
  236. requirements "futility"
  237. gbb "$firmware_image_path" "$gbb_action" "$gbb_file_path_flag"
  238. ;;
  239. "vpd")
  240. if [ -z "$vpd_file_path" ]
  241. then
  242. usage
  243. exit 1
  244. fi
  245. requirements "futility"
  246. vpd "$firmware_image_path" "$vpd_action" "$vpd_file_path"
  247. ;;
  248. *)
  249. usage
  250. exit 1
  251. ;;
  252. esac
  253. }
  254. cros_firmware_prepare "$@"