murkmod-devmode.sh 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283
  1. #!/bin/bash
  2. CURRENT_MAJOR=6
  3. CURRENT_MINOR=0
  4. CURRENT_VERSION=0
  5. show_logo() {
  6. clear
  7. echo -e " __ .___\n _____ __ _________| | __ _____ ____ __| _/\n / \| | \_ __ \ |/ // \ / _ \ / __ | \n| Y Y \ | /| | \/ <| Y Y ( <_> ) /_/ | \n|__|_| /____/ |__| |__|_ \__|_| /\____/\____ | \n \/ \/ \/ \/\n"
  8. echo "The fakemurk plugin manager - v$CURRENT_MAJOR.$CURRENT_MINOR.$CURRENT_VERSION - Developer mode installer"
  9. }
  10. lsbval() {
  11. local key="$1"
  12. local lsbfile="${2:-/etc/lsb-release}"
  13. if ! echo "${key}" | grep -Eq '^[a-zA-Z0-9_]+$'; then
  14. return 1
  15. fi
  16. sed -E -n -e \
  17. "/^[[:space:]]*${key}[[:space:]]*=/{
  18. s:^[^=]+=[[:space:]]*::
  19. s:[[:space:]]+$::
  20. p
  21. }" "${lsbfile}"
  22. }
  23. get_asset() {
  24. curl -s -f "https://api.github.com/repos/rainestorme/murkmod/contents/$1" | jq -r ".content" | base64 -d
  25. }
  26. install() {
  27. TMP=$(mktemp)
  28. get_asset "$1" >"$TMP"
  29. if [ "$?" == "1" ] || ! grep -q '[^[:space:]]' "$TMP"; then
  30. echo "Failed to install $1 to $2"
  31. rm -f "$TMP"
  32. exit
  33. fi
  34. # Don't mv, that would break permissions
  35. cat "$TMP" >"$2"
  36. rm -f "$TMP"
  37. }
  38. get_largest_nvme_namespace() {
  39. # this function doesn't exist if the version is old enough, so we redefine it
  40. local largest size tmp_size dev
  41. size=0
  42. dev=$(basename "$1")
  43. for nvme in /sys/block/"${dev%n*}"*; do
  44. tmp_size=$(cat "${nvme}"/size)
  45. if [ "${tmp_size}" -gt "${size}" ]; then
  46. largest="${nvme##*/}"
  47. size="${tmp_size}"
  48. fi
  49. done
  50. echo "${largest}"
  51. }
  52. get_booted_kernnum() {
  53. if (($(cgpt show -n "$dst" -i 2 -P) > $(cgpt show -n "$dst" -i 4 -P))); then
  54. echo -n 2
  55. else
  56. echo -n 4
  57. fi
  58. }
  59. opposite_num() {
  60. if [ "$1" == "2" ]; then
  61. echo -n 4
  62. elif [ "$1" == "4" ]; then
  63. echo -n 2
  64. elif [ "$1" == "3" ]; then
  65. echo -n 5
  66. elif [ "$1" == "5" ]; then
  67. echo -n 3
  68. else
  69. return 1
  70. fi
  71. }
  72. defog() {
  73. echo "Defogging..."
  74. futility gbb --set --flash --flags=0x8091 # we use futility here instead of the commented out command below because we expect newer chromeos versions and don't want to wait 30 seconds
  75. # /usr/share/vboot/bin/set_gbb_flags.sh 0x8091
  76. crossystem block_devmode=0
  77. vpd -i RW_VPD -s block_devmode=0
  78. vpd -i RW_VPD -s check_enrollment=1
  79. }
  80. murkmod() {
  81. show_logo
  82. if [ -f /sbin/fakemurk-daemon.sh ]; then
  83. echo "!!! Your system already has a fakemurk installation! Continuing anyway, but emergency revert will not work correctly. !!!"
  84. fi
  85. if [ -f /sbin/murkmod-daemon.sh ]; then
  86. echo "!!! Your system already has a murkmod installation! Continuing anyway, but emergency revert will not work correctly. !!!"
  87. fi
  88. echo "What version of murkmod do you want to install?"
  89. echo "If you're not sure, choose pheonix (v118) or the latest version. If you know what your original enterprise version was, specify that manually."
  90. echo " 1) og (chromeOS v105)"
  91. echo " 2) mercury (chromeOS v107)"
  92. echo " 3) john (chromeOS v117)"
  93. echo " 4) pheonix (chromeOS v118)"
  94. echo " 5) latest version"
  95. echo " 6) custom milestone"
  96. read -p "(1-6) > " choice
  97. case $choice in
  98. 1) VERSION="105" ;;
  99. 2) VERSION="107" ;;
  100. 3) VERSION="117" ;;
  101. 4) VERSION="118" ;;
  102. 5) VERSION="latest" ;;
  103. 6) read -p "Enter milestone to target (e.g. 105, 107, 117, 118): " VERSION ;;
  104. *) echo "Invalid choice, exiting." && exit ;;
  105. esac
  106. show_logo
  107. read -p "Do you want to use the default ChromeOS bootsplash? [y/N] " use_orig_bootsplash
  108. case "$use_orig_bootsplash" in
  109. [yY][eE][sS]|[yY])
  110. USE_ORIG_SPLASH="1"
  111. ;;
  112. *)
  113. USE_ORIG_SPLASH="0"
  114. ;;
  115. esac
  116. show_logo
  117. echo "Finding recovery image..."
  118. local release_board=$(lsbval CHROMEOS_RELEASE_BOARD)
  119. #local release_board="hatch"
  120. local board=${release_board%%-*}
  121. if [ $VERSION == "latest" ]; then
  122. local builds=$(curl -ks "https://chromiumdash.appspot.com/cros/fetch_serving_builds?deviceCategory=Chrome%20OS\\")
  123. local hwid=$(jq "(.builds.$board[] | keys)[0]" <<<"$builds")
  124. local hwid=${hwid:1:-1}
  125. local milestones=$(jq ".builds.$board[].$hwid.pushRecoveries | keys | .[]" <<<"$builds")
  126. local VERSION=$(echo "$milestones" | tail -n 1 | tr -d '"')
  127. echo "Latest version is $VERSION"
  128. fi
  129. local url="https://raw.githubusercontent.com/rainestorme/chrome100-json/main/boards/$board.json"
  130. local json=$(curl -ks "$url")
  131. chrome_versions=$(echo "$json" | jq -r '.pageProps.images[].chrome')
  132. echo "Found $(echo "$chrome_versions" | wc -l) versions of chromeOS for your board on chrome100."
  133. echo "Searching for a match..."
  134. MATCH_FOUND=0
  135. for cros_version in $chrome_versions; do
  136. platform=$(echo "$json" | jq -r --arg version "$cros_version" '.pageProps.images[] | select(.chrome == $version) | .platform')
  137. channel=$(echo "$json" | jq -r --arg version "$cros_version" '.pageProps.images[] | select(.chrome == $version) | .channel')
  138. mp_token=$(echo "$json" | jq -r --arg version "$cros_version" '.pageProps.images[] | select(.chrome == $version) | .mp_token')
  139. mp_key=$(echo "$json" | jq -r --arg version "$cros_version" '.pageProps.images[] | select(.chrome == $version) | .mp_key')
  140. last_modified=$(echo "$json" | jq -r --arg version "$cros_version" '.pageProps.images[] | select(.chrome == $version) | .last_modified')
  141. # if $cros_version starts with $VERSION, then we have a match
  142. if [[ $cros_version == $VERSION* ]]; then
  143. echo "Found a $VERSION match on platform $platform from $last_modified."
  144. MATCH_FOUND=1
  145. #https://dl.google.com/dl/edgedl/chromeos/recovery/chromeos_15117.112.0_hatch_recovery_stable-channel_mp-v6.bin.zip
  146. FINAL_URL="https://dl.google.com/dl/edgedl/chromeos/recovery/chromeos_${platform}_${board}_recovery_${channel}_${mp_token}-v${mp_key}.bin.zip"
  147. break
  148. fi
  149. done
  150. if [ $MATCH_FOUND -eq 0 ]; then
  151. echo "No match found on chrome100. Falling back to Chromium Dash."
  152. local builds=$(curl -ks "https://chromiumdash.appspot.com/cros/fetch_serving_builds?deviceCategory=Chrome%20OS\\")
  153. local hwid=$(jq "(.builds.$board[] | keys)[0]" <<<"$builds")
  154. local hwid=${hwid:1:-1}
  155. # Get all milestones for the specified hwid
  156. milestones=$(jq ".builds.$board[].$hwid.pushRecoveries | keys | .[]" <<<"$builds")
  157. # Loop through all milestones
  158. echo "Searching for a match..."
  159. for milestone in $milestones; do
  160. milestone=$(echo "$milestone" | tr -d '"')
  161. if [[ $milestone == $VERSION* ]]; then
  162. MATCH_FOUND=1
  163. FINAL_URL=$(jq -r ".builds.$board[].$hwid.pushRecoveries[\"$milestone\"]" <<<"$builds")
  164. echo "Found a match!"
  165. break
  166. fi
  167. done
  168. fi
  169. if [ $MATCH_FOUND -eq 0 ]; then
  170. echo "No recovery image found for your board and target version. Exiting."
  171. exit
  172. fi
  173. echo "Installing unzip (this may take up to 2 minutes)..."
  174. dev_install --reinstall <<EOF > /dev/null
  175. y
  176. n
  177. EOF
  178. emerge unzip > /dev/null
  179. mkdir -p /usr/local/tmp
  180. pushd /mnt/stateful_partition
  181. set -e
  182. echo "Downloading recovery image from '$FINAL_URL'..."
  183. curl --progress-bar -k "$FINAL_URL" -o recovery.zip
  184. echo "Unzipping image... (this may take a while)"
  185. unzip -o recovery.zip
  186. rm recovery.zip
  187. FILENAME=$(find . -maxdepth 2 -name "chromeos_*.bin") # 2 incase the zip format changes
  188. echo "Found recovery image from archive at $FILENAME"
  189. pushd /usr/local/tmp # /usr/local is mounted as exec, so we can run scripts from here
  190. echo "Installing image_patcher.sh..."
  191. install "image_patcher.sh" ./image_patcher.sh
  192. chmod 777 ./image_patcher.sh
  193. echo "Installing ssd_util.sh..."
  194. mkdir -p ./lib
  195. install "ssd_util.sh" ./lib/ssd_util.sh
  196. chmod 777 ./lib/ssd_util.sh
  197. echo "Installing common_minimal.sh..."
  198. install "common_minimal.sh" ./lib/common_minimal.sh
  199. chmod 777 ./lib/common_minimal.sh
  200. popd
  201. echo "Invoking image_patcher.sh..."
  202. if [ "$USE_ORIG_SPLASH" == 0 ]; then
  203. bash /usr/local/tmp/image_patcher.sh "$FILENAME"
  204. else
  205. bash /usr/local/tmp/image_patcher.sh "$FILENAME" cros
  206. fi
  207. echo "Patching complete. Determining target partitions..."
  208. local dst=/dev/$(get_largest_nvme_namespace)
  209. if [[ $dst == /dev/sd* ]]; then
  210. echo "WARNING: get_largest_nvme_namespace returned $dst - this doesn't seem correct!"
  211. echo "Press enter to view output from fdisk - find the correct drive and enter it below"
  212. read -r
  213. fdisk -l | more
  214. echo "Enter the target drive to use:"
  215. read dst
  216. fi
  217. local tgt_kern=$(opposite_num $(get_booted_kernnum))
  218. local tgt_root=$(( $tgt_kern + 1 ))
  219. local kerndev=${dst}p${tgt_kern}
  220. local rootdev=${dst}p${tgt_root}
  221. echo "Targeting $kerndev and $rootdev"
  222. local loop=$(losetup -f | tr -d '\r')
  223. losetup -P "$loop" "$FILENAME"
  224. echo "Press enter if nothing broke, otherwise press Ctrl+C"
  225. read -r
  226. printf "Nuking partitions in 3 (this is your last chance to cancel)..."
  227. sleep 1
  228. printf "2..."
  229. sleep 1
  230. echo "1..."
  231. sleep 1
  232. echo "Bomb has been planted! Overwriting ChromeOS..."
  233. echo "Installing kernel patch to ${kerndev}..."
  234. dd if="${loop}p4" of="$kerndev" status=progress
  235. echo "Installing root patch to ${rootdev}..."
  236. dd if="${loop}p3" of="$rootdev" status=progress
  237. echo "Setting kernel priority..."
  238. cgpt add "$dst" -i 4 -P 0
  239. cgpt add "$dst" -i 2 -P 0
  240. cgpt add "$dst" -i "$tgt_kern" -P 1
  241. echo "Defogging... (if write-protect is disabled, this will set GBB flags to 0x8091)"
  242. defog
  243. echo "Cleaning up..."
  244. losetup -d "$loop"
  245. rm -f "$FILENAME"
  246. popd
  247. read -n 1 -s -r -p "Done! Press any key to continue and your system will reboot automatically."
  248. reboot
  249. echo "Bye!"
  250. sleep 10
  251. echo "Your system should have rebooted. If it didn't, please perform an EC reset (Refresh+Power)."
  252. sleep 1d
  253. exit
  254. }
  255. if [ "$0" = "$BASH_SOURCE" ]; then
  256. if [ "$EUID" -ne 0 ]; then
  257. echo "Please run as root."
  258. exit
  259. fi
  260. murkmod
  261. fi