murkmod-devmode.sh 11 KB

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