download 5.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227
  1. #!/usr/bin/env sh
  2. # SPDX-FileCopyrightText: 2022 Caleb La Grange <thonkpeasant@protonmail.com>
  3. # SPDX-FileCopyrightText: 2022 Ferass El Hafidi <vitali64pmemail@protonmail.com>
  4. # SPDX-FileCopyrightText: 2023 Leah Rowe <info@minifree.org>
  5. # SPDX-License-Identifier: GPL-3.0-only
  6. blobdir="blobs"
  7. dl_path="${blobdir}/vendorupdate"
  8. appdir="${blobdir}/app"
  9. _7ztest="a"
  10. mecleaner="$(pwd)/me_cleaner/me_cleaner.py"
  11. me7updateparser="$(pwd)/resources/blobs/me7_update_parser.py"
  12. board="${1}"
  13. # A shorthand for each board, to avoid duplicating configs per flash size
  14. board_short=${board%%_*mb}
  15. set -- "resources/coreboot/${board}/config/*"
  16. . ${1} 2>/dev/null
  17. . "resources/coreboot/${board}/board.cfg"
  18. if [ "${CONFIG_HAVE_MRC}" = "y" ]; then
  19. printf 'haswell board detected, downloading mrc\n'
  20. needs="${needs} MRC"
  21. fi
  22. if [ "${CONFIG_HAVE_IFD_BIN}" = "y" ]; then
  23. printf 'board needs intel firmware descriptor\n'
  24. needs="${needs} IFD"
  25. fi
  26. if [ "${CONFIG_HAVE_ME_BIN}" = "y" ]; then
  27. printf 'board needs intel management engine\n'
  28. needs="${needs} ME"
  29. fi
  30. if [ "${CONFIG_HAVE_GBE_BIN}" = "y" ]; then
  31. printf 'board needs gigabit ethernet firmware\n'
  32. needs="${needs} GBE"
  33. fi
  34. # Quickly exit without wasting more time if there are no blobs needed (GM45)
  35. if [ -z ${needs+x} ]; then
  36. printf 'No binary blobs needed for this board\n'
  37. exit 0
  38. fi
  39. while read -r line ; do
  40. case ${line} in
  41. DL_hash*)
  42. set ${line}
  43. dl_hash=${2}
  44. ;;
  45. DL_url*)
  46. set ${line}
  47. dl_url=${2}
  48. ;;
  49. DL_url_bkup*)
  50. set ${line}
  51. dl_url_bkup=${2}
  52. ;;
  53. esac
  54. done << EOF
  55. $(eval "awk ' /\{.*${board_short}.*}{/ {flag=1;next} /\}/{flag=0} flag { print }' resources/blobs/sources")
  56. EOF
  57. Main() {
  58. Build_deps
  59. Download_needed
  60. }
  61. Fail(){
  62. printf "\nERROR: $@\n"
  63. exit 1
  64. }
  65. Build_deps(){
  66. if [ ! -d me_cleaner ]; then
  67. printf "downloading me_cleaner\n"
  68. ./download me_cleaner || Fail 'could not download me_cleaner'
  69. fi
  70. if [ ! -d coreboot/default ]; then
  71. printf "downloading coreboot\n"
  72. ./download coreboot default || Fail 'could not download coreboot'
  73. fi
  74. if [ ! -f "coreboot/default/util/ifdtool/ifdtool" ]; then
  75. printf "building ifdtool from coreboot\n"
  76. make -C coreboot/default/util/ifdtool || Fail 'could not build ifdtool'
  77. fi
  78. }
  79. Download_needed(){
  80. for need in ${needs}; do
  81. case ${need} in
  82. *ME*)
  83. Download_me || _failed="${_failed} me"
  84. ;;
  85. *MRC*)
  86. ./download mrc || _failed="${_failed} mrc"
  87. ;;
  88. esac
  89. done
  90. if [ ! -z ${_failed+x} ]; then
  91. Fail "failed to obtain ${_failed}\nYou may try manually extracting blobs with './blobutil extract'"
  92. fi
  93. }
  94. Download_me() {
  95. printf "Downloading neutered ME for board: `%s`\n" ${board}
  96. Fetch_update || return 1
  97. Extract_me || return 1
  98. return 0
  99. }
  100. Fetch_update() {
  101. printf "Fetching vendor update for board: `%s`\n" ${board}
  102. if [ -z "${dl_url+x}" ]; then
  103. printf "No vendor update specified for board: `%s`\n" ${board}
  104. return 1
  105. fi
  106. Vendor_checksum ${dl_path} || \
  107. curl ${dl_url} > ${dl_path} || curl ${dl_url_bkup} > ${dl_path}
  108. Vendor_checksum ${dl_path} || Fail \
  109. "Cannot guarantee intergity of vendor update for board: `${board}`"
  110. return 0
  111. }
  112. Vendor_checksum() {
  113. if [ ! -f "${dl_path}" ]; then
  114. printf "Vendor update not found on disk for board: `%s`\n" ${board}
  115. return 1
  116. fi
  117. if [ "$(sha1sum ${dl_path} | awk '{print $1}')" != "${dl_hash}" ]; then
  118. printf "Bad checksum on vendor update for board: `%s`\n" ${board}
  119. rm ${dl_path}
  120. return 1
  121. fi
  122. return 0
  123. }
  124. Extract_me(){
  125. printf "Extracting neutered ME for ${board}\n"
  126. _me_destination=${CONFIG_ME_BIN_PATH#../../}
  127. if [ ! -d "${_me_destination%/*}" ]; then
  128. mkdir -p ${_me_destination%/*}
  129. fi
  130. if [ -d "${appdir}" ]; then
  131. rm -r ${appdir}
  132. fi
  133. if [ -f "${_me_destination}" ]; then
  134. printf 'me already downloaded\n'
  135. return 0
  136. fi
  137. printf 'extracting and stripping intel management engine\n'
  138. innoextract ${dl_path} -d ${blobdir} \
  139. || 7z x ${dl_path} -o${appdir} \
  140. || Fail 'could not extract me executable with innoextract'
  141. Bruteforce_extract_me "$(pwd)/${_me_destination}" "$(pwd)/${appdir}" \
  142. || return 1
  143. printf "Truncated and cleaned me output to ${_me_destination}\n"
  144. return 0
  145. }
  146. # cursed, carcinogenic code. TODO rewrite it better
  147. Bruteforce_extract_me() {
  148. _me_destination="${1}"
  149. cdir="${2}" # must be an absolute path, not relative
  150. if [ -f "${_me_destination}" ]; then
  151. return 0
  152. fi
  153. (
  154. printf "Entering %s\n" "${cdir}"
  155. cd "${cdir}" || exit 1
  156. for i in *; do
  157. if [ -f "${_me_destination}" ]; then
  158. # me.bin found, so avoid needless further traversal
  159. break
  160. elif [ -L "${i}" ]; then
  161. # symlinks are a security risk, in this context
  162. continue
  163. elif [ -f "${i}" ]; then
  164. "${mecleaner}" -r -t -O "${_me_destination}" "${i}" \
  165. && break # (we found me.bin)
  166. "${me7updateparser}" -O ${_me_destination} "${i}" \
  167. && break
  168. _7ztest="${_7ztest}a"
  169. 7z x "${i}" -o${_7ztest} || continue
  170. Bruteforce_extract_me "${_me_destination}" "${cdir}/${_7ztest}"
  171. cdir="${1}"
  172. cd "${cdir}"
  173. elif [ -d "$i" ]; then
  174. Bruteforce_extract_me "${_me_destination}" "${cdir}/${i}"
  175. cdir="${1}"
  176. cd "${cdir}"
  177. else
  178. printf "SKIPPING: %s\n" "${i}"
  179. fi
  180. done
  181. )
  182. if [ ! -f "${_me_destination}" ]; then
  183. printf "me.bin not found in vendor update for board: `%s`\n" ${board}
  184. return 1
  185. else
  186. return 0
  187. fi
  188. }
  189. Main