murkmod-devmode.sh 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317
  1. #!/bin/bash
  2. CURRENT_MAJOR=6
  3. CURRENT_MINOR=1
  4. CURRENT_VERSION=2
  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. arch=$(uname -m)
  183. case "$arch" in
  184. x86_64)
  185. busybox_url="https://raw.githubusercontent.com/shutingrz/busybox-static-binaries-fat/refs/heads/main/busybox-x86_64-linux-gnu" ;;
  186. aarch64)
  187. busybox_url="https://raw.githubusercontent.com/shutingrz/busybox-static-binaries-fat/refs/heads/main/busybox-aarch64-linux-gnu" ;;
  188. armv7l)
  189. busybox_url="https://raw.githubusercontent.com/shutingrz/busybox-static-binaries-fat/refs/heads/main/busybox-arm-linux-gnueabihf" ;;
  190. armv6l)
  191. busybox_url="https://raw.githubusercontent.com/shutingrz/busybox-static-binaries-fat/refs/heads/main/busybox-arm-linux-gnueabi" ;;
  192. mips)
  193. busybox_url="https://raw.githubusercontent.com/shutingrz/busybox-static-binaries-fat/refs/heads/main/busybox-mips-linux-gnu" ;;
  194. mips64)
  195. busybox_url="https://raw.githubusercontent.com/shutingrz/busybox-static-binaries-fat/refs/heads/main/busybox-mips64-linux-gnuabi64" ;;
  196. mipsel)
  197. busybox_url="https://raw.githubusercontent.com/shutingrz/busybox-static-binaries-fat/refs/heads/main/busybox-mipsel-linux-gnu" ;;
  198. mips64el)
  199. busybox_url="https://raw.githubusercontent.com/shutingrz/busybox-static-binaries-fat/refs/heads/main/busybox-mips64el-linux-gnuabi64" ;;
  200. powerpc64le)
  201. busybox_url="https://raw.githubusercontent.com/shutingrz/busybox-static-binaries-fat/refs/heads/main/busybox-powerpc64le-linux-gnu" ;;
  202. riscv32)
  203. busybox_url="https://raw.githubusercontent.com/shutingrz/busybox-static-binaries-fat/refs/heads/main/busybox-riscv32-linux-gnu" ;;
  204. riscv64)
  205. busybox_url="https://raw.githubusercontent.com/shutingrz/busybox-static-binaries-fat/refs/heads/main/busybox-riscv64-linux-gnu" ;;
  206. *)
  207. echo "Unsupported architecture: $arch"; exit 1 ;;
  208. esac
  209. curl --progress-bar -Lko /usr/local/tmp/unzip "$busybox_url"
  210. chmod 777 /usr/local/tmp/unzip
  211. echo "Downloading recovery image from '$FINAL_URL'..."
  212. curl --progress-bar -k "$FINAL_URL" -o recovery.zip
  213. echo "Unzipping image... (this may take a while)"
  214. /usr/local/tmp/unzip -o recovery.zip
  215. rm recovery.zip
  216. FILENAME=$(find . -maxdepth 2 -name "chromeos_*.bin") # 2 incase the zip format changes
  217. echo "Found recovery image from archive at $FILENAME"
  218. pushd /usr/local/tmp # /usr/local is mounted as exec, so we can run scripts from here
  219. echo "Installing image_patcher.sh..."
  220. install "image_patcher.sh" ./image_patcher.sh
  221. chmod 777 ./image_patcher.sh
  222. echo "Installing ssd_util.sh..."
  223. mkdir -p ./lib
  224. install "ssd_util.sh" ./lib/ssd_util.sh
  225. chmod 777 ./lib/ssd_util.sh
  226. echo "Installing common_minimal.sh..."
  227. install "common_minimal.sh" ./lib/common_minimal.sh
  228. chmod 777 ./lib/common_minimal.sh
  229. popd
  230. echo "Invoking image_patcher.sh..."
  231. if [ "$USE_ORIG_SPLASH" == 0 ]; then
  232. bash /usr/local/tmp/image_patcher.sh "$FILENAME"
  233. else
  234. bash /usr/local/tmp/image_patcher.sh "$FILENAME" cros
  235. fi
  236. echo "Patching complete. Determining target partitions..."
  237. local dst=$(get_largest_cros_blockdev)
  238. if [[ $dst == /dev/sd* ]]; then
  239. echo "WARNING: get_largest_cros_blockdev returned $dst - this doesn't seem correct!"
  240. echo "Press enter to view output from fdisk - find the correct drive and enter it below"
  241. read -r
  242. fdisk -l | more
  243. echo "Enter the target drive to use:"
  244. read dst
  245. fi
  246. local tgt_kern=$(opposite_num $(get_booted_kernnum))
  247. local tgt_root=$(( $tgt_kern + 1 ))
  248. local kerndev=${dst}p${tgt_kern}
  249. local rootdev=${dst}p${tgt_root}
  250. echo "Targeting $kerndev and $rootdev"
  251. local loop=$(losetup -f | tail -1)
  252. if [[ -z "$loop" ]]; then
  253. echo "No free loop device. Exiting..."
  254. exit 1
  255. else
  256. echo $loop
  257. fi
  258. echo "Setting up loop with $loop and $bin"
  259. losetup -P "$loop" "$FILENAME"
  260. echo "Press enter if nothing broke, otherwise press Ctrl+C"
  261. read -r
  262. printf "Nuking partitions in 3 (this is your last chance to cancel)..."
  263. sleep 1
  264. printf "2..."
  265. sleep 1
  266. echo "1..."
  267. sleep 1
  268. echo "Bomb has been planted! Overwriting ChromeOS..."
  269. echo "Installing kernel patch to ${kerndev}..."
  270. dd if="${loop}p4" of="$kerndev" status=progress
  271. echo "Installing root patch to ${rootdev}..."
  272. dd if="${loop}p3" of="$rootdev" status=progress
  273. echo "Setting kernel priority..."
  274. cgpt add "$dst" -i 4 -P 0
  275. cgpt add "$dst" -i 2 -P 0
  276. cgpt add "$dst" -i "$tgt_kern" -P 1
  277. echo "Defogging... (if write-protect is disabled, this will set GBB flags to 0x8091)"
  278. defog
  279. echo "Cleaning up..."
  280. losetup -d "$loop"
  281. rm -f "$FILENAME"
  282. popd
  283. read -n 1 -s -r -p "Done! Press any key to continue and your system will reboot automatically."
  284. reboot
  285. echo "Bye!"
  286. sleep 10
  287. echo "Your system should have rebooted. If it didn't, please perform an EC reset (Refresh+Power)."
  288. sleep 1d
  289. exit
  290. }
  291. if [ "$0" = "$BASH_SOURCE" ]; then
  292. if [ "$EUID" -ne 0 ]; then
  293. echo "Please run as root."
  294. exit
  295. fi
  296. murkmod
  297. fi