├── LICENSE ├── README.md ├── firmware-util.sh ├── firmware.sh ├── functions.sh ├── setup-kodi.sh └── sources.sh /LICENSE: -------------------------------------------------------------------------------- 1 | This is free and unencumbered software released into the public domain. 2 | 3 | Anyone is free to copy, modify, publish, use, compile, sell, or 4 | distribute this software, either in source code form or as a compiled 5 | binary, for any purpose, commercial or non-commercial, and by any 6 | means. 7 | 8 | In jurisdictions that recognize copyright laws, the author or authors 9 | of this software dedicate any and all copyright interest in the 10 | software to the public domain. We make this dedication for the benefit 11 | of the public at large and to the detriment of our heirs and 12 | successors. We intend this dedication to be an overt act of 13 | relinquishment in perpetuity of all present and future rights to this 14 | software under copyright law. 15 | 16 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 17 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 18 | MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 19 | IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR 20 | OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, 21 | ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 22 | OTHER DEALINGS IN THE SOFTWARE. 23 | 24 | For more information, please refer to 25 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | Home of the ChromeOS Firmware Utility script and Kodi E-Z Setup script. 2 | 3 | For home info, please visit https://mrchromebox.tech 4 | -------------------------------------------------------------------------------- /firmware-util.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | # 3 | # This script offers provides the ability to update the 4 | # Legacy Boot payload, set boot options, and install 5 | # a custom coreboot firmware for supported 6 | # ChromeOS devices 7 | # 8 | # Created by Mr.Chromebox 9 | # 10 | # May be freely distributed and modified as needed, 11 | # as long as proper attribution is given. 12 | # 13 | 14 | #path to directory where script is saved 15 | script_dir="$(dirname $(readlink -f $0))" 16 | 17 | #where the stuff is 18 | script_url="https://raw.githubusercontent.com/MrChromebox/scripts/main/" 19 | 20 | #ensure output of system tools in en-us for parsing 21 | export LC_ALL=C 22 | 23 | #set working dir 24 | if grep -q "Chrom" /etc/lsb-release ; then 25 | # needed for ChromeOS/ChromiumOS v82+ 26 | mkdir -p /usr/local/bin 27 | cd /usr/local/bin 28 | else 29 | cd /tmp 30 | fi 31 | 32 | # clear screen / show banner 33 | printf "\ec" 34 | echo -e "\nMrChromebox Firmware Utility Script starting up" 35 | 36 | #check for cmd line param, expired CrOS certs 37 | if ! curl -sLo /dev/null https://mrchromebox.tech/index.html || [[ "$1" = "-k" ]]; then 38 | export CURL="curl -k" 39 | else 40 | export CURL="curl" 41 | fi 42 | 43 | if [ ! -d "$script_dir/.git" ]; then 44 | script_dir="." 45 | 46 | #get support scripts 47 | echo -e "\nDownloading supporting files..." 48 | rm -rf firmware.sh >/dev/null 2>&1 49 | rm -rf functions.sh >/dev/null 2>&1 50 | rm -rf sources.sh >/dev/null 2>&1 51 | $CURL -sLO ${script_url}firmware.sh 52 | rc0=$? 53 | $CURL -sLO ${script_url}functions.sh 54 | rc1=$? 55 | $CURL -sLO ${script_url}sources.sh 56 | rc2=$? 57 | if [[ $rc0 -ne 0 || $rc1 -ne 0 || $rc2 -ne 0 ]]; then 58 | echo -e "Error downloading one or more required files; cannot continue" 59 | exit 1 60 | fi 61 | fi 62 | 63 | source $script_dir/sources.sh 64 | source $script_dir/firmware.sh 65 | source $script_dir/functions.sh 66 | 67 | #set working dir 68 | cd /tmp 69 | 70 | #do setup stuff 71 | prelim_setup 72 | prelim_setup_result="$?" 73 | 74 | #saving setup state for troubleshooting 75 | diagnostic_report_save 76 | troubleshooting_msg=( 77 | " * diagnosics report has been saved to /tmp/mrchromebox_diag.txt" 78 | " * go to https://forum.chrultrabook.com/ for help" 79 | ) 80 | if [ "$prelim_setup_result" -ne 0 ]; then 81 | IFS=$'\n' 82 | echo "MrChromebox Firmware Utility setup was unsuccessful" > /dev/stderr 83 | echo "${troubleshooting_msg[*]}" > /dev/stderr 84 | exit 1 85 | fi 86 | 87 | #show menu 88 | 89 | trap 'check_unsupported' EXIT 90 | function check_unsupported() { 91 | if [ "$isUnsupported" = true ]; then 92 | IFS=$'\n' 93 | echo "MrChromebox Firmware Utility didn't recognize your device" > /dev/stderr 94 | echo "${troubleshooting_msg[*]}" > /dev/stderr 95 | fi 96 | } 97 | 98 | menu_fwupdate 99 | -------------------------------------------------------------------------------- /firmware.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | # 3 | 4 | # shellcheck disable=SC2154,SC2086,SC2059 5 | 6 | ################### 7 | # flash RW_LEGACY # 8 | ################### 9 | function flash_rwlegacy() 10 | { 11 | #set working dir 12 | cd /tmp || { exit_red "Error changing to tmp dir; cannot proceed"; return 1; } 13 | 14 | # set dev mode legacy boot / AltFw flags 15 | if [ "${isChromeOS}" = true ]; then 16 | crossystem dev_boot_legacy=1 > /dev/null 2>&1 17 | crossystem dev_boot_altfw=1 > /dev/null 2>&1 18 | fi 19 | 20 | #determine proper file 21 | if [ "$device" = "link" ]; then 22 | rwlegacy_file=$seabios_link 23 | elif [[ "$isHswBox" = true || "$isBdwBox" = true ]]; then 24 | rwlegacy_file=$seabios_hswbdw_box 25 | elif [[ "$isHswBook" = true || "$isBdwBook" = true ]]; then 26 | rwlegacy_file=$seabios_hswbdw_book 27 | elif [ "$isByt" = true ]; then 28 | rwlegacy_file=$seabios_baytrail 29 | elif [ "$isBsw" = true ]; then 30 | rwlegacy_file=$seabios_braswell 31 | elif [ "$isSkl" = true ]; then 32 | rwlegacy_file=$seabios_skylake 33 | elif [ "$isApl" = true ]; then 34 | rwlegacy_file=$seabios_apl 35 | elif [ "$isKbl" = true ]; then 36 | # prompt for SeaBIOS/edk2 selection 37 | echo -e "" 38 | echo_yellow "Firmware Type Selection" 39 | echo -e "Your device has the option of two RW_LEGACY firmware types." 40 | REPLY="" 41 | while [[ "$REPLY" != "L" && "$REPLY" != "l" && "$REPLY" != "U" && "$REPLY" != "u" ]] 42 | do 43 | read -rep "Enter 'L' for Legacy BIOS (SeaBIOS), 'U' for UEFI (edk2/Tianocore): " 44 | if [[ "$REPLY" = "U" || "$REPLY" = "u" ]]; then 45 | if [ "$kbl_use_rwl18" = true ]; then 46 | rwlegacy_file=$rwl_altfw_kbl_18 47 | else 48 | rwlegacy_file=$rwl_altfw_kbl 49 | fi 50 | else 51 | if [ "$kbl_use_rwl18" = true ]; then 52 | rwlegacy_file=$seabios_kbl_18 53 | else 54 | rwlegacy_file=$seabios_kbl 55 | fi 56 | fi 57 | done 58 | elif [ "$isWhl" = true ]; then 59 | rwlegacy_file=$rwl_altfw_whl 60 | elif [ "$device" = "drallion" ]; then 61 | rwlegacy_file=$rwl_altfw_drallion 62 | elif [ "$isCmlBox" = true ]; then 63 | rwlegacy_file=$rwl_altfw_cml 64 | elif [ "$isJsl" = true ]; then 65 | rwlegacy_file=$rwl_altfw_jsl 66 | elif [ "$isTgl" = true ]; then 67 | rwlegacy_file=$rwl_altfw_tgl 68 | elif [ "$isGlk" = true ]; then 69 | rwlegacy_file=$rwl_altfw_glk 70 | elif [ "$isAdl_2" = true ]; then 71 | rwlegacy_file=$rwl_altfw_adl_2 72 | elif [ "$isAdl" = true ]; then 73 | rwlegacy_file=$rwl_altfw_adl 74 | elif [ "$isAdlN" = true ]; then 75 | rwlegacy_file=$rwl_altfw_adl_n 76 | elif [ "$isMtl" = true ]; then 77 | rwlegacy_file=$rwl_altfw_mtl 78 | elif [ "$isStr" = true ]; then 79 | rwlegacy_file=$rwl_altfw_stoney 80 | elif [ "$isPco" = true ]; then 81 | rwlegacy_file=$rwl_altfw_pco 82 | elif [ "$isCzn" = true ]; then 83 | rwlegacy_file=$rwl_altfw_czn 84 | elif [ "$isMdn" = true ]; then 85 | rwlegacy_file=$rwl_altfw_mdn 86 | else 87 | echo_red "Unknown or unsupported device (${device}); cannot update RW_LEGACY firmware." 88 | echo_red "If your device is listed as supported on https://mrchromebox.tech/#devices,\n 89 | then email MrChromebox@gmail.com and include a screenshot of the main menu." 90 | read -rep "Press enter to return to the main menu" 91 | return 1 92 | fi 93 | 94 | if [[ "$rwlegacy_file" = *"altfw"* ]]; then 95 | echo_green "\nInstall/Update RW_LEGACY Firmware (AltFw / edk2)" 96 | else 97 | echo_green "\nInstall/Update RW_LEGACY Firmware (Legacy BIOS / SeaBIOS)" 98 | fi 99 | 100 | echo_yellow " 101 | NOTE: RW_LEGACY firmware cannot be used to run Windows. Period. 102 | If you are looking to run Windows, see the documentation on coolstar.org. 103 | MrChromebox does not provide any support for running Windows." 104 | REPLY="" 105 | read -rep "Press Y to continue or any other key to return to the main menu. " 106 | [[ "$REPLY" = "y" || "$REPLY" = "Y" ]] || return 107 | 108 | preferUSB=false 109 | if [[ "$rwlegacy_file" != *"altfw"* ]]; then 110 | echo -e "" 111 | #USB boot priority 112 | echo_yellow "Default to booting from USB?" 113 | read -rep "If N, always boot from internal storage unless selected from boot menu. [y/N] " 114 | [[ "$REPLY" = "y" || "$REPLY" = "Y" ]] && preferUSB=true 115 | echo -e "" 116 | fi 117 | 118 | #download RW_LEGACY update 119 | echo_yellow "\nDownloading RW_LEGACY firmware update\n(${rwlegacy_file})" 120 | $CURL -sLO "${rwlegacy_source}${rwlegacy_file}.md5" 121 | $CURL -sLO "${rwlegacy_source}${rwlegacy_file}" 122 | #verify checksum on downloaded file 123 | if ! md5sum -c "${rwlegacy_file}.md5" > /dev/null 2>&1; then 124 | exit_red "RW_LEGACY download checksum fail; download corrupted, cannot flash" 125 | return 1 126 | fi 127 | 128 | #preferUSB? 129 | if [ "$preferUSB" = true ]; then 130 | if ! $CURL -sLo bootorder "${cbfs_source}bootorder.usb"; then 131 | echo_red "Unable to download bootorder file; boot order cannot be changed." 132 | else 133 | ${cbfstoolcmd} "${rwlegacy_file}" remove -n bootorder > /dev/null 2>&1 134 | ${cbfstoolcmd} "${rwlegacy_file}" add -n bootorder -f /tmp/bootorder -t raw > /dev/null 2>&1 135 | fi 136 | fi 137 | 138 | #flash updated RW_LEGACY firmware 139 | echo_yellow "Installing RW_LEGACY firmware" 140 | [[ "$isChromeOS" = false ]] && FMAP="--fmap" 141 | if ! ${flashromcmd} -w $FMAP -i RW_LEGACY:${rwlegacy_file} ${noverify} -o /tmp/flashrom.log > /dev/null 2>&1; then 142 | cat /tmp/flashrom.log 143 | echo_red "An error occurred flashing the RW_LEGACY firmware." 144 | else 145 | echo_green "RW_LEGACY firmware successfully installed/updated." 146 | # update firmware type 147 | firmwareType="Stock ChromeOS w/RW_LEGACY" 148 | #Prevent from trying to boot stock ChromeOS install 149 | [[ "$boot_mounted" = true ]] && rm -rf /tmp/boot/syslinux > /dev/null 2>&1 150 | fi 151 | 152 | read -rep "Press [Enter] to return to the main menu." 153 | } 154 | 155 | 156 | ############################# 157 | # Install Full ROM Firmware # 158 | ############################# 159 | function flash_full_rom() 160 | { 161 | echo_green "\nInstall/Update UEFI Full ROM Firmware" 162 | echo_yellow "IMPORTANT: flashing the firmware has the potential to brick your device, 163 | requiring relatively inexpensive hardware and some technical knowledge to 164 | recover.Not all boards can be tested prior to release, and even then slight 165 | differences in hardware can lead to unforseen failures. 166 | If you don't have the ability to recover from a bad flash, you're taking a risk. 167 | 168 | You have been warned." 169 | 170 | [[ "$isChromeOS" = true ]] && echo_yellow "Also, flashing Full ROM firmware will remove your ability to run ChromeOS." 171 | 172 | read -rep "Do you wish to continue? [y/N] " 173 | [[ "$REPLY" = "y" || "$REPLY" = "Y" ]] || return 174 | 175 | #spacing 176 | echo -e "" 177 | 178 | # ensure hardware write protect disabled 179 | [[ "$wpEnabled" = true ]] && { exit_red "\nHardware write-protect enabled, cannot flash Full ROM firmware."; return 1; } 180 | 181 | #special warning for CR50 devices 182 | if [[ "$isStock" = true && "$hasCR50" = true ]]; then 183 | echo_yellow "NOTICE: flashing your Chromebook is serious business. 184 | To ensure recovery in case something goes wrong when flashing, 185 | be sure to set the ccd capability 'FlashAP Always' using your 186 | USB-C debug cable, otherwise recovery will involve disassembling 187 | your device (which is very difficult in some cases)." 188 | 189 | echo_yellow "If you wish to continue, type: 'I ACCEPT' and press enter." 190 | read -re 191 | [[ "$REPLY" = "I ACCEPT" ]] || return 192 | fi 193 | 194 | #UEFI notice if flashing from ChromeOS or Legacy 195 | if [[ ! -d /sys/firmware/efi ]]; then 196 | [[ "$isChromeOS" = true ]] && currOS="ChromeOS" || currOS="Your Legacy-installed OS" 197 | echo_yellow " 198 | NOTE: After flashing UEFI firmware, you will need to install a UEFI-compatible 199 | OS; ${currOS} will no longer be bootable. See https://mrchromebox.tech/#faq" 200 | REPLY="" 201 | read -rep "Press Y to continue or any other key to abort. " 202 | [[ "$REPLY" = "y" || "$REPLY" = "Y" ]] || return 203 | fi 204 | 205 | # PCO boot device notice 206 | if [[ "$isPCO" = true && ! -d /sys/firmware/efi ]]; then 207 | echo_yellow " 208 | NOTE: Booting from eMMC on AMD Picasso-based devices does not currently work -- 209 | only NVMe, SD and USB. If you have a device with eMMC storage you will not be 210 | able to boot from it after installing the UEFI Full ROM firmware." 211 | REPLY="" 212 | read -rep "Press Y to continue or any other key to abort. " 213 | [[ "$REPLY" = "y" || "$REPLY" = "Y" ]] || return 214 | fi 215 | 216 | #determine correct file / URL 217 | firmware_source=${fullrom_source} 218 | eval coreboot_file="$`echo "coreboot_uefi_${device}"`" 219 | 220 | #rammus special case (upgrade from older UEFI firmware) 221 | if [ "$device" = "rammus" ]; then 222 | echo -e "" 223 | echo_yellow "Unable to determine Chromebook model" 224 | echo -e "Because of your current firmware, I'm unable to 225 | determine the exact mode of your Chromebook. Are you using 226 | an Asus C425 (LEONA) or Asus C433/C434 (SHYVANA)? 227 | " 228 | REPLY="" 229 | while [[ "$REPLY" != "L" && "$REPLY" != "l" && "$REPLY" != "S" && "$REPLY" != "s" ]] 230 | do 231 | read -rep "Enter 'L' for LEONA, 'S' for SHYVANA: " 232 | if [[ "$REPLY" = "S" || "$REPLY" = "s" ]]; then 233 | coreboot_file=${coreboot_uefi_shyvana} 234 | else 235 | coreboot_file=${coreboot_uefi_leona} 236 | fi 237 | done 238 | fi 239 | 240 | #coral special case (variant not correctly identified) 241 | if [ "$device" = "coral" ]; then 242 | echo -e "" 243 | echo_yellow "Unable to determine correct Chromebook model" 244 | echo -e "Because of your current firmware, I'm unable to determine the exact mode of your Chromebook. 245 | Please select the number for the correct option from the list below:" 246 | 247 | coral_boards=( 248 | "ASTRONAUT (Acer Chromebook 11 [C732])" 249 | "BABYMEGA (Asus Chromebook C223NA)" 250 | "BABYTIGER (Asus Chromebook C523NA)" 251 | "BLACKTIP (CTL Chromebook NL7/NL7T)" 252 | "BLUE (Acer Chromebook 15 [CB315])" 253 | "BRUCE (Acer Chromebook Spin 15 [CP315])" 254 | "EPAULETTE (Acer Chromebook 514)" 255 | "LAVA (Acer Chromebook Spin 11 [CP311])" 256 | "NASHER (Dell Chromebook 11 5190)" 257 | "NASHER360 (Dell Chromebook 11 5190 2-in-1)" 258 | "RABBID (Asus Chromebook C423)" 259 | "ROBO (Lenovo 100e Chromebook)" 260 | "ROBO360 (Lenovo 500e Chromebook)" 261 | "SANTA (Acer Chromebook 11 [CB311-8H])" 262 | "WHITETIP (CTL Chromebook J41/J41T)" 263 | ) 264 | 265 | select board in "${coral_boards[@]}"; do 266 | board=$(echo ${board,,} | cut -f1 -d ' ') 267 | eval coreboot_file=$`echo "coreboot_uefi_${board}"` 268 | break; 269 | done 270 | fi 271 | 272 | # ensure we have a file to flash 273 | if [[ "$coreboot_file" = "" ]]; then 274 | exit_red "The script does not currently have a firmware file for your device (${device^^}); cannot continue."; return 1 275 | fi 276 | 277 | #extract device serial if present in cbfs 278 | ${cbfstoolcmd} /tmp/bios.bin extract -n serial_number -f /tmp/serial.txt >/dev/null 2>&1 279 | 280 | #extract device HWID 281 | if [[ "$isStock" = "true" ]]; then 282 | ${gbbutilitycmd} /tmp/bios.bin --get --hwid | sed 's/[^ ]* //' > /tmp/hwid.txt 2>/dev/null 283 | else 284 | ${cbfstoolcmd} /tmp/bios.bin extract -n hwid -f /tmp/hwid.txt >/dev/null 2>&1 285 | fi 286 | 287 | # create backup if existing firmware is stock 288 | if [[ "$isStock" = "true" ]]; then 289 | if [[ "$isEOL" = "false" ]]; then 290 | REPLY=y 291 | else 292 | echo_yellow "\nCreate a backup copy of your stock firmware?" 293 | read -erp "This is highly recommended in case you wish to return your device to stock 294 | configuration/run ChromeOS, or in the (unlikely) event that things go south 295 | and you need to recover using an external EEPROM programmer. [Y/n] " 296 | fi 297 | [[ "$REPLY" = "n" || "$REPLY" = "N" ]] && true || backup_firmware 298 | #check that backup succeeded 299 | [ $? -ne 0 ] && return 1 300 | fi 301 | 302 | #download firmware file 303 | cd /tmp || { exit_red "Error changing to tmp dir; cannot proceed"; return 1; } 304 | echo_yellow "\nDownloading Full ROM firmware\n(${coreboot_file})" 305 | if ! $CURL -sLO "${firmware_source}${coreboot_file}"; then 306 | exit_red "Firmware download failed; cannot flash. curl error code $?"; return 1 307 | fi 308 | if ! $CURL -sLO "${firmware_source}${coreboot_file}.sha1"; then 309 | exit_red "Firmware checksum download failed; cannot flash."; return 1 310 | fi 311 | 312 | #verify checksum on downloaded file 313 | if ! sha1sum -c "${coreboot_file}.sha1" > /dev/null 2>&1; then 314 | exit_red "Firmware image checksum verification failed; download corrupted, cannot flash."; return 1 315 | fi 316 | 317 | #persist serial number? 318 | if [ -f /tmp/serial.txt ]; then 319 | echo_yellow "Persisting device serial number" 320 | ${cbfstoolcmd} "${coreboot_file}" add -n serial_number -f /tmp/serial.txt -t raw > /dev/null 2>&1 321 | fi 322 | 323 | #persist device HWID? 324 | if [ -f /tmp/hwid.txt ]; then 325 | echo_yellow "Persisting device HWID" 326 | ${cbfstoolcmd} "${coreboot_file}" add -n hwid -f /tmp/hwid.txt -t raw > /dev/null 2>&1 327 | fi 328 | 329 | #Persist RW_MRC_CACHE UEFI Full ROM firmware 330 | ${cbfstoolcmd} /tmp/bios.bin read -r RW_MRC_CACHE -f /tmp/mrc.cache > /dev/null 2>&1 331 | if [[ $isFullRom = "true" && $? -eq 0 ]]; then 332 | ${cbfstoolcmd} "${coreboot_file}" write -r RW_MRC_CACHE -f /tmp/mrc.cache > /dev/null 2>&1 333 | fi 334 | 335 | #Persist SMMSTORE if exists 336 | if ${cbfstoolcmd} /tmp/bios.bin read -r SMMSTORE -f /tmp/smmstore > /dev/null 2>&1; then 337 | ${cbfstoolcmd} "${coreboot_file}" write -r SMMSTORE -f /tmp/smmstore > /dev/null 2>&1 338 | fi 339 | 340 | # persist VPD if possible 341 | if extract_vpd /tmp/bios.bin; then 342 | # try writing to RO_VPD FMAP region 343 | if ! ${cbfstoolcmd} "${coreboot_file}" write -r RO_VPD -f /tmp/vpd.bin > /dev/null 2>&1; then 344 | # fall back to vpd.bin in CBFS 345 | ${cbfstoolcmd} "${coreboot_file}" add -n vpd.bin -f /tmp/vpd.bin -t raw > /dev/null 2>&1 346 | fi 347 | fi 348 | 349 | #disable software write-protect 350 | echo_yellow "Disabling software write-protect and clearing the WP range" 351 | if ! ${flashromcmd} --wp-disable > /dev/null 2>&1 && [[ "$swWp" = "enabled" ]]; then 352 | exit_red "Error disabling software write-protect; unable to flash firmware."; return 1 353 | fi 354 | 355 | #clear SW WP range 356 | if ! ${flashromcmd} --wp-range 0 0 > /dev/null 2>&1; then 357 | # use new command format as of commit 99b9550 358 | if ! ${flashromcmd} --wp-range 0,0 > /dev/null 2>&1 && [[ "$swWp" = "enabled" ]]; then 359 | exit_red "Error clearing software write-protect range; unable to flash firmware."; return 1 360 | fi 361 | fi 362 | 363 | #flash Full ROM firmware 364 | 365 | # clear log file 366 | rm -f /tmp/flashrom.log 367 | 368 | echo_yellow "Installing Full ROM firmware (may take up to 90s)" 369 | #check if flashrom supports logging to file 370 | if ${flashromcmd} -V -o /dev/null > /dev/null 2>&1; then 371 | output_params=">/dev/null 2>&1 -o /tmp/flashrom.log" 372 | ${flashromcmd} ${flashrom_params} ${noverify} -w ${coreboot_file} >/dev/null 2>&1 -o /tmp/flashrom.log 373 | else 374 | output_params=">/tmp/flashrom.log 2>&1" 375 | ${flashromcmd} ${flashrom_params} ${noverify} -w ${coreboot_file} >/tmp/flashrom.log 2>&1 376 | fi 377 | if [ $? -ne 0 ]; then 378 | echo_red "Error running cmd: ${flashromcmd} ${flashrom_params} ${noverify} -w ${coreboot_file} ${output_params}" 379 | if [ -f /tmp/flashrom.log ]; then 380 | read -rp "Press enter to view the flashrom log file, then space for next page, q to quit" 381 | more /tmp/flashrom.log 382 | fi 383 | exit_red "An error occurred flashing the Full ROM firmware. DO NOT REBOOT!"; return 1 384 | else 385 | echo_green "Full ROM firmware successfully installed/updated." 386 | 387 | #Prevent from trying to boot stock ChromeOS install 388 | if [[ "$isStock" = true && "$isChromeOS" = true && "$boot_mounted" = true ]]; then 389 | rm -rf /tmp/boot/efi > /dev/null 2>&1 390 | rm -rf /tmp/boot/syslinux > /dev/null 2>&1 391 | fi 392 | 393 | #Warn about long RAM training time 394 | echo_yellow "IMPORTANT:\nThe first boot after flashing may take substantially 395 | longer than subsequent boots -- up to 30s or more. 396 | Be patient and eventually your device will boot :)" 397 | 398 | # Add note on touchpad firmware for EVE 399 | if [[ "${device^^}" = "EVE" && "$isStock" = true ]]; then 400 | echo_yellow "IMPORTANT:\n 401 | If you're going to run Windows on your Pixelbook, you must downgrade 402 | the touchpad firmware now (before rebooting) otherwise it will not work. 403 | Select the D option from the main main in order to do so." 404 | fi 405 | #set vars to indicate new firmware type 406 | isStock=false 407 | isFullRom=true 408 | # Add NVRAM reset note for 4.12 release 409 | if [[ "$isUEFI" = true && "$useUEFI" = true ]]; then 410 | echo_yellow "IMPORTANT:\n 411 | This update uses a new format to store UEFI NVRAM data, and 412 | will reset your BootOrder and boot entries. You may need to 413 | manually Boot From File and reinstall your bootloader if 414 | booting from the internal storage device fails." 415 | fi 416 | firmwareType="Full ROM / UEFI (pending reboot)" 417 | isUEFI=true 418 | fi 419 | 420 | read -rep "Press [Enter] to return to the main menu." 421 | } 422 | 423 | ############################# 424 | # Set Touchpad type in SSFC # 425 | ############################# 426 | function set_touchpad_in_ssfc() 427 | { 428 | echo_green "\nSet Touchpad type in SSFC" 429 | echo_yellow "NOTE: This operation only needs to be done once for GALTIC-based devices 430 | on which you want to run Windows; Linux is not affected either way. 431 | Setting the touchpad type in SSFC requires hardware WP to be disabled." 432 | 433 | read -rep "Do you wish to continue? [y/N] " 434 | [[ "$REPLY" = "y" || "$REPLY" = "Y" ]] || return 435 | 436 | # GALTIC boards update SSFC if needed for touchpad type 437 | echo -e "" 438 | echo_yellow "Checking if touchpad type set in SSFC" 439 | echo_yellow "Downloading ectool" 440 | if ! get_ectool; then 441 | echo_red "Unable to download ectool; cannot continue" 442 | read -rep "Press enter to return to the main menu" 443 | return 1 444 | fi 445 | if ! $ectoolcmd cbi get 8 >/dev/null 2>&1; then 446 | # SSFC not initialized 447 | echo_yellow "Initializing SSFC" 448 | if ! $ectoolcmd cbi set 8 0x0 4 1; then 449 | echo_red "Unable to initialize SSFC; if HW WP is enabled, please disable and retry" 450 | read -rep "Press enter to return to the main menu" 451 | return 1 452 | fi 453 | fi 454 | ssfc_val=$($ectoolcmd cbi get 8 | grep -m1 'uint' | cut -f3 -d ' ') 455 | echo_yellow "Current SSFC value is $ssfc_val" 456 | # TOUCHPAD_OPTION is bits 44-45 in SSFC, so bits 12-13 here 457 | if [[ $((ssfc_val & 0x3000)) == 0 ]]; then 458 | #touchpad unset, so detect and set it 459 | if dmesg | grep "input:" | grep -q "ELAN0000"; then 460 | #ELAN0000 touchpad, set bit 12 461 | ssfc_val=$((ssfc_val | 0x1000)) 462 | else 463 | #ELAN2712 touchpad, set bit 13 464 | ssfc_val=$((ssfc_val | 0x2000)) 465 | fi 466 | echo_yellow "Setting new SSFC value $ssfc_val" 467 | if ! $ectoolcmd cbi set 8 $ssfc_val 4; then 468 | echo_red "Error setting new SSFC value; if HW WP is enabled, please disable and retry" 469 | read -rep "Press enter to return to the main menu" 470 | return 1 471 | fi 472 | echo_green "Touchpad type successfully set in SSFC" 473 | else 474 | echo_yellow "Touchpad type is already set in SSFC; nothing to do" 475 | fi 476 | 477 | read -rep "Press [Enter] to return to the main menu." 478 | 479 | } 480 | 481 | 482 | ######################### 483 | # Downgrade Touchpad FW # 484 | ######################### 485 | function downgrade_touchpad_fw() 486 | { 487 | # offer to downgrade touchpad firmware on EVE 488 | if [[ "${device^^}" = "EVE" ]]; then 489 | echo_green "\nDowngrade Touchpad Firmware" 490 | echo_yellow "If you plan to run Windows on your Pixelbook, it is necessary to downgrade 491 | the touchpad firmware, otherwise the touchpad will not work." 492 | echo_yellow "You should do this after flashing the UEFI firmware, but before rebooting." 493 | read -rep "Do you wish to downgrade the touchpad firmware now? [y/N] " 494 | if [[ "$REPLY" = "y" || "$REPLY" = "Y" ]] ; then 495 | # ensure firmware write protect disabled 496 | [[ "$wpEnabled" = true ]] && { exit_red "\nHardware write-protect enabled, cannot downgrade touchpad firmware."; return 1; } 497 | # download TP firmware 498 | echo_yellow "\nDownloading touchpad firmware\n(${touchpad_eve_fw})" 499 | $CURL -s -LO "${other_source}${touchpad_eve_fw}" 500 | $CURL -s -LO "${other_source}${touchpad_eve_fw}.sha1" 501 | #verify checksum on downloaded file 502 | if sha1sum -c ${touchpad_eve_fw}.sha1 > /dev/null 2>&1; then 503 | # flash TP firmware 504 | echo_green "Flashing touchpad firmware -- do not touch the touchpad while updating!" 505 | if ${flashromcmd/${flashrom_programmer}} -p ec:type=tp -i EC_RW -w ${touchpad_eve_fw} -o /tmp/flashrom.log >/dev/null 2>&1; then 506 | echo_green "Touchpad firmware successfully downgraded." 507 | echo_yellow "Please reboot your Pixelbook now." 508 | else 509 | # try with older eve flashrom 510 | [[ "$isChromeOS" == "true" ]] && tpPath="/usr/local/bin" || tpPath="/tmp" 511 | ( 512 | cd $tpPath 513 | $CURL -sLO "${util_source}flashrom_eve_tp" 514 | chmod +x flashrom_eve_tp 515 | ) 516 | if $tpPath/flashrom_eve_tp -p ec:type=tp -i EC_RW -w ${touchpad_eve_fw} -o /tmp/flashrom.log >/dev/null 2>&1; then 517 | echo_green "Touchpad firmware successfully downgraded." 518 | echo_yellow "Please reboot your Pixelbook now." 519 | else 520 | echo_red "Error flashing touchpad firmware:" 521 | cat /tmp/flashrom.log 522 | echo_yellow "\nThis function sometimes doesn't work under Linux, in which case it is\nrecommended to try under ChromiumOS." 523 | fi 524 | fi 525 | else 526 | echo_red "Touchpad firmware download checksum fail; download corrupted, cannot flash." 527 | fi 528 | fi 529 | read -rep "Press [Enter] to return to the main menu." 530 | fi 531 | } 532 | 533 | ####################### 534 | # Upgrade Touchpad FW # 535 | ####################### 536 | function upgrade_touchpad_fw() 537 | { 538 | # offer to upgrade touchpad firmware on EVE 539 | if [[ "${device^^}" = "EVE" ]]; then 540 | echo_green "\nUpgrade Touchpad Firmware" 541 | echo_yellow "If you plan to restore ChromeOS on your Pixelbook, it is necessary to upgrade 542 | the touchpad firmware, otherwise the touchpad will not work." 543 | echo_yellow "You should do this after restoring the stock firmware, but before rebooting." 544 | read -rep "Do you wish to upgrade the touchpad firmware now? [y/N] " 545 | if [[ "$REPLY" = "y" || "$REPLY" = "Y" ]] ; then 546 | # ensure firmware write protect disabled 547 | [[ "$wpEnabled" = true ]] && { exit_red "\nHardware write-protect enabled, cannot upgrade touchpad firmware."; return 1; } 548 | # download TP firmware 549 | echo_yellow "\nDownloading touchpad firmware\n(${touchpad_eve_fw_stock})" 550 | $CURL -s -LO "${other_source}${touchpad_eve_fw_stock}" 551 | $CURL -s -LO "${other_source}${touchpad_eve_fw_stock}.sha1" 552 | #verify checksum on downloaded file 553 | if sha1sum -c ${touchpad_eve_fw_stock}.sha1 > /dev/null 2>&1; then 554 | # flash TP firmware 555 | echo_green "Flashing touchpad firmware -- do not touch the touchpad while updating!" 556 | if ${flashromcmd/${flashrom_programmer}} -p ec:type=tp -i EC_RW -w ${touchpad_eve_fw_stock} -o /tmp/flashrom.log >/dev/null 2>&1; then 557 | echo_green "Touchpad firmware successfully upgraded." 558 | echo_yellow "Please reboot your Pixelbook now." 559 | else 560 | # try with older eve flashrom 561 | [[ "$isChromeOS" == "true" ]] && tpPath="/usr/local/bin" || tpPath="/tmp" 562 | ( 563 | cd $tpPath 564 | $CURL -sLO "${util_source}flashrom_eve_tp" 565 | chmod +x flashrom_eve_tp 566 | ) 567 | if $tpPath/flashrom_eve_tp -p ec:type=tp -i EC_RW -w ${touchpad_eve_fw_stock} -o /tmp/flashrom.log >/dev/null 2>&1; then 568 | echo_green "Touchpad firmware successfully upgraded." 569 | echo_yellow "Please reboot your Pixelbook now." 570 | else 571 | echo_red "Error flashing touchpad firmware:" 572 | cat /tmp/flashrom.log 573 | echo_yellow "\nThis function sometimes doesn't work under Linux, in which case it is\nrecommended to try under ChromeOS." 574 | fi 575 | fi 576 | else 577 | echo_red "Touchpad firmware download checksum fail; download corrupted, cannot flash." 578 | fi 579 | fi 580 | read -rep "Press [Enter] to return to the main menu." 581 | fi 582 | } 583 | 584 | ########################## 585 | # Restore Stock Firmware # 586 | ########################## 587 | function restore_stock_firmware() 588 | { 589 | echo_green "\nRestore Stock Firmware" 590 | echo_yellow "Standard disclaimer: flashing the firmware has the potential to 591 | brick your device, requiring relatively inexpensive hardware and some 592 | technical knowledge to recover. You have been warned." 593 | 594 | read -rep "Do you wish to continue? [y/N] " 595 | [[ "$REPLY" = "Y" || "$REPLY" = "y" ]] || return 596 | 597 | # check if EOL 598 | if [ "$isEOL" = true ]; then 599 | echo_yellow "\nVERY IMPORTANT: 600 | Your device has reached end of life (EOL) and is no longer supported by Google. 601 | Returning the to stock firmware **IS NOT RECOMMENDED**. 602 | MrChromebox will not provide any support for EOL devices running anything 603 | other than the latest UEFI Full ROM firmware release." 604 | 605 | read -rep "Do you wish to continue? [y/N] " 606 | [[ "$REPLY" = "Y" || "$REPLY" = "y" ]] || return 607 | fi 608 | 609 | #spacing 610 | echo -e "" 611 | 612 | # ensure hardware write protect disabled 613 | [[ "$wpEnabled" = true ]] && { exit_red "\nHardware write-protect enabled, cannot restore stock firmware."; return 1; } 614 | 615 | # default file to download to 616 | firmware_file="/tmp/stock-firmware.rom" 617 | 618 | echo -e "" 619 | echo_yellow "Please select an option below for restoring the stock firmware:" 620 | echo -e "1) Restore using a firmware backup on USB" 621 | echo -e "2) Restore using a ChromeOS Recovery USB" 622 | echo -e "Q) Quit and return to main menu" 623 | echo -e "" 624 | 625 | restore_option=-1 626 | while : 627 | do 628 | read -rep "? " restore_option 629 | case $restore_option in 630 | 631 | 1) restore_fw_from_usb || return 1; 632 | break; 633 | ;; 634 | 2) restore_fw_from_recovery || return 1; 635 | break; 636 | ;; 637 | Q|q) restore_option="Q"; 638 | break; 639 | ;; 640 | esac 641 | done 642 | [[ "$restore_option" = "Q" ]] && return 643 | 644 | if [[ $restore_option -eq 2 ]]; then 645 | #extract VPD from current firmware if present 646 | if extract_vpd /tmp/bios.bin ; then 647 | #merge with recovery image firmware 648 | if [ -f /tmp/vpd.bin ]; then 649 | echo_yellow "Merging VPD into recovery image firmware" 650 | ${cbfstoolcmd} ${firmware_file} write -r RO_VPD -f /tmp/vpd.bin > /dev/null 2>&1 651 | fi 652 | fi 653 | 654 | #extract hwid from current firmware if present 655 | if ${cbfstoolcmd} /tmp/bios.bin extract -n hwid -f /tmp/hwid.txt > /dev/null 2>&1; then 656 | #merge with recovery image firmware 657 | hwid="$(sed 's/^hardware_id: //' /tmp/hwid.txt 2>/dev/null)" 658 | if [[ "$hwid" != "" ]]; then 659 | echo_yellow "Injecting HWID into recovery image firmware" 660 | ${gbbutilitycmd} ${firmware_file} --set --hwid="$hwid" > /dev/null 2>&1 661 | fi 662 | fi 663 | fi 664 | 665 | #clear GBB flags before flashing 666 | ${gbbutilitycmd} ${firmware_file} --set --flags=0x0 > /dev/null 2>&1 667 | 668 | #flash stock firmware 669 | echo_yellow "Restoring stock firmware" 670 | # only verify part of flash we write 671 | if ! ${flashromcmd} ${flashrom_params} ${noverify} -w "${firmware_file}" -o /tmp/flashrom.log > /dev/null 2>&1; then 672 | cat /tmp/flashrom.log 673 | exit_red "An error occurred restoring the stock firmware. DO NOT REBOOT!"; return 1 674 | fi 675 | 676 | #re-enable software WP to prevent recovery issues 677 | echo_yellow "Re-enabling software write-protect" 678 | ${flashromcmd} --wp-region WP_RO --fmap > /dev/null 2>&1 679 | if ! ${flashromcmd} --wp-enable > /dev/null 2>&1; then 680 | echo_red "Warning: unable to re-enable software write-protect; 681 | you may need to perform ChromeOS recovery with the battery disconnected." 682 | fi 683 | 684 | #all good 685 | echo_green "Stock firmware successfully restored." 686 | echo_green "After rebooting, you need to restore ChromeOS using ChromeOS Recovery media. 687 | See: https://google.com/chromeos/recovery for more info." 688 | read -rep "Press [Enter] to return to the main menu." 689 | #set vars to indicate new firmware type 690 | isStock=true 691 | isFullRom=false 692 | isUEFI=false 693 | firmwareType="Stock ChromeOS (pending reboot)" 694 | } 695 | 696 | function restore_fw_from_usb() 697 | { 698 | read -rep " 699 | Connect the USB/SD device which contains the backed-up stock firmware and press [Enter] to continue. " 700 | 701 | list_usb_devices || { exit_red "No USB devices available to read firmware backup."; return 1; } 702 | usb_dev_index="" 703 | while [[ "$usb_dev_index" = "" || ($usb_dev_index -le 0 && $usb_dev_index -gt $num_usb_devs) ]]; do 704 | read -rep "Enter the number for the device which contains the stock firmware backup: " usb_dev_index 705 | if [[ "$usb_dev_index" = "" || ($usb_dev_index -le 0 && $usb_dev_index -gt $num_usb_devs) ]]; then 706 | echo -e "Error: Invalid option selected; enter a number from the list above." 707 | fi 708 | done 709 | usb_device="${usb_devs[${usb_dev_index}-1]}" 710 | mkdir /tmp/usb > /dev/null 2>&1 711 | mount "${usb_device}" /tmp/usb > /dev/null 2>&1 712 | if [ $? -ne 0 ]; then 713 | mount "${usb_device}1" /tmp/usb 714 | fi 715 | if [ $? -ne 0 ]; then 716 | echo_red "USB device failed to mount; cannot proceed." 717 | read -rep "Press [Enter] to return to the main menu." 718 | umount /tmp/usb > /dev/null 2>&1 719 | return 720 | fi 721 | #select file from USB device 722 | echo_yellow "\n(Potential) Firmware Files on USB:" 723 | if ! ls /tmp/usb/*.{rom,ROM,bin,BIN} 2>/dev/null | xargs -n 1 basename 2>/dev/null; then 724 | echo_red "No firmware files found on USB device." 725 | read -rep "Press [Enter] to return to the main menu." 726 | umount /tmp/usb > /dev/null 2>&1 727 | return 1 728 | fi 729 | echo -e "" 730 | read -rep "Enter the firmware filename: " firmware_file 731 | firmware_file=/tmp/usb/${firmware_file} 732 | if [ ! -f ${firmware_file} ]; then 733 | echo_red "Invalid filename entered; unable to restore stock firmware." 734 | read -rep "Press [Enter] to return to the main menu." 735 | umount /tmp/usb > /dev/null 2>&1 736 | return 1 737 | fi 738 | #text spacing 739 | echo -e "" 740 | } 741 | 742 | function restore_fw_from_recovery() 743 | { 744 | echo -e "\nConnect a USB which contains a ChromeOS Recovery Image" 745 | read -rep "and press [Enter] to continue. " 746 | 747 | list_usb_devices || { exit_red "No USB devices available to read from."; return 1; } 748 | usb_dev_index="" 749 | while [[ "$usb_dev_index" = "" || ($usb_dev_index -le 0 && ! $usb_dev_index -gt $num_usb_devs) ]]; do 750 | read -rep "Enter the number which corresponds your ChromeOS Recovery USB: " usb_dev_index 751 | if [[ "$usb_dev_index" = "" || ($usb_dev_index -le 0 && $usb_dev_index -gt $num_usb_devs) ]]; then 752 | echo -e "Error: Invalid option selected; enter a number from the list above." 753 | fi 754 | done 755 | usb_device="${usb_devs[${usb_dev_index}-1]}" 756 | echo -e "" 757 | echo_yellow "Using USB device: $usb_device" 758 | if ! extract_firmware_from_recovery_usb ${boardName,,} $usb_device ; then 759 | exit_red "Error: failed to extract firmware for ${boardName^^} from this ChromeOS recovery USB" 760 | return 1 761 | fi 762 | mv coreboot-Google_* ${firmware_file} 763 | # set a semi-legit HWID in case we don't have a backup below 764 | ${gbbutilitycmd} --set --hwid="${boardName^^} ABC-123-XYZ-456" ${firmware_file} > /dev/null 765 | echo_yellow "Stock firmware successfully extracted from ChromeOS recovery image" 766 | } 767 | 768 | ###################################### 769 | # Extract firmware from recovery usb # 770 | ###################################### 771 | function extract_firmware_from_recovery_usb() 772 | { 773 | _board=$1 774 | _debugfs=${2}3 775 | _firmware=chromeos-firmwareupdate-$_board 776 | _unpacked=$(mktemp -d) 777 | 778 | if [[ "$1" = "" || "$2" = "" ]]; then 779 | echo_red "Invalid or missing function parameters: [$@]" 780 | return 1 781 | fi 782 | 783 | echo_yellow "Extracting firmware from recovery USB" 784 | printf "cd /usr/sbin\ndump chromeos-firmwareupdate $_firmware\nquit" | debugfs $_debugfs >/dev/null 2>&1 785 | 786 | if [ ! -f $_firmware ]; then 787 | echo_red "Failed to copy file 'chromeos-firmwareupdate' from Recovery USB" 788 | return 1 789 | fi 790 | 791 | if ! sh $_firmware --unpack $_unpacked >/dev/null 2>&1; then 792 | if ! sh $_firmware --sb_extract $_unpacked >/dev/null 2>&1; then 793 | echo_red "Failed to extract shellball from 'chromeos-firmwareupdate'" 794 | return 1 795 | fi 796 | fi 797 | 798 | if [ -d $_unpacked/models/ ]; then 799 | _version=$(cat $_unpacked/VERSION | grep -m 1 -e Model.*$_board -A5 | grep "BIOS (RW) version:" | cut -f2 -d: | tr -d \ ) 800 | if [ "$_version" = "" ]; then 801 | _version=$(cat $_unpacked/VERSION | grep -m 1 -e Model.*$_board -A5 | grep "BIOS version:" | cut -f2 -d: | tr -d \ ) 802 | fi 803 | if [ -f $_unpacked/models/$_board/setvars.sh ]; then 804 | _bios_image=$(grep "IMAGE_MAIN" $_unpacked/models/$_board/setvars.sh | cut -f2 -d'"') 805 | else 806 | # special case for REEF, others? 807 | _version=$(grep -m1 "host" "$_unpacked/manifest.json" | cut -f12 -d'"') 808 | _bios_image=$(grep -m1 "image" "$_unpacked/manifest.json" | cut -f4 -d'"') 809 | fi 810 | elif [ -f "$_unpacked/manifest.json" ]; then 811 | _version=$(grep -m1 -A4 "$_board\":" "$_unpacked/manifest.json" | grep -m1 "rw" | sed 's/.*\(rw.*\)/\1/' | sed 's/.*\("Google.*\)/\1/' | cut -f2 -d'"') 812 | _bios_image=$(grep -m1 -A10 "$_board\":" "$_unpacked/manifest.json" | grep -m1 "image" | sed 's/.*"image": //' | cut -f2 -d'"') 813 | else 814 | if [ -f $_unpacked/VERSION ]; then 815 | _version=$(cat $_unpacked/VERSION | grep BIOS\ version: | cut -f2 -d: | tr -d \ ) 816 | _bios_image=bios.bin 817 | else 818 | echo_red "Recovery image missing VERSION file. Shellball directory Contents:" 819 | ls -lart $_unpacked 820 | return 1 821 | fi 822 | fi 823 | if ! cp $_unpacked/$_bios_image coreboot-$_version.bin; then 824 | return 1 825 | fi 826 | rm -rf "$_unpacked" 827 | rm $_firmware 828 | } 829 | 830 | 831 | ######################## 832 | # Extract firmware VPD # 833 | ######################## 834 | function extract_vpd() 835 | { 836 | #check params 837 | [[ -z "$1" ]] && { exit_red "Error: extract_vpd(): missing function parameter"; return 1; } 838 | 839 | local firmware_file="$1" 840 | 841 | #try FMAP extraction 842 | if ! ${cbfstoolcmd} ${firmware_file} read -r RO_VPD -f /tmp/vpd.bin >/dev/null 2>&1 ; then 843 | #try CBFS extraction 844 | if ! ${cbfstoolcmd} ${firmware_file} extract -n vpd.bin -f /tmp/vpd.bin >/dev/null 2>&1 ; then 845 | echo_yellow "No VPD found in current firmware" 846 | return 1 847 | fi 848 | fi 849 | echo_yellow "VPD extracted from current firmware" 850 | return 0 851 | } 852 | 853 | 854 | ######################### 855 | # Backup stock firmware # 856 | ######################### 857 | function backup_firmware() 858 | { 859 | echo -e "" 860 | read -rep "Connect the USB/SD device to store the firmware backup and press [Enter] 861 | to continue. This is non-destructive, but it is best to ensure no other 862 | USB/SD devices are connected. " 863 | 864 | if ! list_usb_devices; then 865 | backup_fail "No USB devices available to store firmware backup." 866 | return 1 867 | fi 868 | 869 | usb_dev_index="" 870 | while [[ "$usb_dev_index" = "" || ($usb_dev_index -le 0 && $usb_dev_index -gt $num_usb_devs) ]]; do 871 | read -rep "Enter the number for the device to be used for firmware backup: " usb_dev_index 872 | if [[ "$usb_dev_index" = "" || ($usb_dev_index -le 0 && $usb_dev_index -gt $num_usb_devs) ]]; then 873 | echo -e "Error: Invalid option selected; enter a number from the list above." 874 | fi 875 | done 876 | 877 | usb_device="${usb_devs[${usb_dev_index}-1]}" 878 | mkdir /tmp/usb > /dev/null 2>&1 879 | if ! mount -o rw "${usb_device}" /tmp/usb > /dev/null 2>&1; then 880 | if ! mount -o rw "${usb_device}1" /tmp/usb > /dev/null 2>&1; then 881 | backup_fail "USB backup device failed to mount; cannot proceed. Ensure your USB is FAT32-formatted and try again." 882 | return 1 883 | fi 884 | fi 885 | backupname="stock-firmware-${boardName}-$(date +%Y%m%d).rom" 886 | echo_yellow "\nSaving firmware backup as ${backupname}" 887 | if ! cp /tmp/bios.bin /tmp/usb/${backupname}; then 888 | backup_fail "Failure copying stock firmware to USB; cannot proceed." 889 | return 1 890 | fi 891 | sync 892 | umount /tmp/usb > /dev/null 2>&1 893 | rmdir /tmp/usb 894 | echo_green "Firmware backup complete. Remove the USB stick and press [Enter] to continue." 895 | read -rep "" 896 | } 897 | 898 | function backup_fail() 899 | { 900 | umount /tmp/usb > /dev/null 2>&1 901 | rmdir /tmp/usb > /dev/null 2>&1 902 | exit_red "\n$@" 903 | } 904 | 905 | 906 | #################### 907 | # Set Boot Options # 908 | #################### 909 | function set_boot_options() 910 | { 911 | # set boot options via firmware boot flags 912 | 913 | # ensure hardware write protect disabled 914 | [[ "$wpEnabled" = true ]] && { exit_red "\nHardware write-protect enabled, cannot set Boot Options / GBB Flags."; return 1; } 915 | 916 | echo_green "\nSet Firmware Boot Options (GBB Flags)" 917 | echo_yellow "Select your preferred boot delay and default boot option. 918 | You can always override the default using [CTRL+D] or 919 | [CTRL+L] on the Developer Mode boot screen" 920 | 921 | echo -e "1) Short boot delay (1s) + Legacy Boot/AltFw default 922 | 2) Long boot delay (30s) + Legacy Boot/AltFw default 923 | 3) Short boot delay (1s) + ChromeOS default 924 | 4) Long boot delay (30s) + ChromeOS default 925 | 5) Reset to factory default 926 | 6) Cancel/exit 927 | " 928 | local _flags=0x0 929 | while : 930 | do 931 | read -rep "? " n 932 | case $n in 933 | 1) _flags=0x4A9; break;; 934 | 2) _flags=0x4A8; break;; 935 | 3) _flags=0xA9; break;; 936 | 4) _flags=0xA8; break;; 937 | 5) _flags=0x0; break;; 938 | 6) read -rep "Press [Enter] to return to the main menu."; break;; 939 | *) echo -e "invalid option";; 940 | esac 941 | done 942 | [[ $n -eq 6 ]] && return 943 | echo_yellow "\nSetting boot options..." 944 | 945 | #disable software write-protect 946 | if ! ${flashromcmd} --wp-disable > /dev/null 2>&1; then 947 | exit_red "Error disabling software write-protect; unable to set GBB flags."; return 1 948 | fi 949 | [[ "$isChromeOS" = false ]] && FMAP="--fmap" 950 | if ! ${flashromcmd} -r $FMAP -i GBB:/tmp/gbb.temp > /dev/null 2>&1; then 951 | exit_red "\nError reading firmware (non-stock?); unable to set boot options."; return 1 952 | fi 953 | if ! ${gbbutilitycmd} --set --flags="${_flags}" /tmp/gbb.temp > /dev/null; then 954 | exit_red "\nError setting boot options."; return 1 955 | fi 956 | if ! ${flashromcmd} -w $FMAP -i GBB:/tmp/gbb.temp ${noverify} -o /tmp/flashrom.log > /dev/null 2>&1; then 957 | cat /tmp/flashrom.log 958 | exit_red "\nError writing back firmware; unable to set boot options."; return 1 959 | fi 960 | 961 | echo_green "\nFirmware Boot options successfully set." 962 | 963 | read -rep "Press [Enter] to return to the main menu." 964 | } 965 | 966 | 967 | ################### 968 | # Set Hardware ID # 969 | ################### 970 | function set_hwid() 971 | { 972 | # set HWID using gbb_utility 973 | 974 | # ensure hardware write protect disabled 975 | [[ "$wpEnabled" = true ]] && { exit_red "\nHardware write-protect enabled, cannot set HWID."; return 1; } 976 | 977 | echo_green "Set Hardware ID (HWID) using gbb_utility" 978 | 979 | #get current HWID 980 | _hwid="$(crossystem hwid)" >/dev/null 2>&1 981 | if [[ "$_hwid" != "" ]]; then 982 | echo_yellow "Current HWID is $_hwid" 983 | fi 984 | 985 | echo_yellow "Are you sure you know what you're doing here? 986 | Changing this is not normally needed, and if you mess it up, 987 | MrChromebox is not going to help you fix it. This won't let 988 | you run a different/newer version of ChromeOS. 989 | Proceed at your own risk." 990 | 991 | read -rep "Really change your HWID? [y/N] " confirm 992 | [[ "$confirm" = "Y" || "$confirm" = "y" ]] || return 993 | 994 | read -rep "This is serious. Are you really sure? [y/N] " confirm 995 | [[ "$confirm" = "Y" || "$confirm" = "y" ]] || return 996 | 997 | read -rep "Enter a new HWID (use all caps): " hwid 998 | echo -e "" 999 | read -rep "Confirm changing HWID to $hwid [y/N] " confirm 1000 | if [[ "$confirm" = "Y" || "$confirm" = "y" ]]; then 1001 | echo_yellow "\nSetting hardware ID..." 1002 | #disable software write-protect 1003 | if ! ${flashromcmd} --wp-disable > /dev/null 2>&1; then 1004 | exit_red "Error disabling software write-protect; unable to set HWID."; return 1 1005 | fi 1006 | [[ "$isChromeOS" = false ]] && FMAP="--fmap" 1007 | if ! ${flashromcmd} -r $FMAP -i GBB:/tmp/gbb.temp > /dev/null 2>&1; then 1008 | exit_red "\nError reading firmware (non-stock?); unable to set HWID."; return 1 1009 | fi 1010 | if ! ${gbbutilitycmd} --set --hwid="${hwid}" /tmp/gbb.temp > /dev/null 2>&1; then 1011 | exit_red "\nError setting HWID."; return 1 1012 | fi 1013 | if ! ${flashromcmd} -w $FMAP -i GBB:/tmp/gbb.temp ${noverify} -o /tmp/flashrom.log > /dev/null 2>&1; then 1014 | cat /tmp/flashrom.log 1015 | exit_red "\nError writing back firmware; unable to set HWID."; return 1 1016 | fi 1017 | 1018 | echo_green "Hardware ID successfully set." 1019 | fi 1020 | read -rep "Press [Enter] to return to the main menu." 1021 | } 1022 | 1023 | ############### 1024 | # Clear NVRAM # 1025 | ############### 1026 | function clear_nvram() { 1027 | echo_green "\nClear UEFI NVRAM" 1028 | echo_yellow "Clearing the NVRAM will remove all EFI variables\nand reset the boot order to the default." 1029 | read -rep "Would you like to continue? [y/N] " 1030 | [[ "$REPLY" = "y" || "$REPLY" = "Y" ]] || return 1031 | 1032 | echo_yellow "\nClearing NVRAM..." 1033 | if ! ${flashromcmd} -E -i SMMSTORE --fmap > /tmp/flashrom.log 2>&1; then 1034 | cat /tmp/flashrom.log 1035 | exit_red "\nFailed to erase SMMSTORE firmware region; NVRAM not cleared." 1036 | return 1; 1037 | fi 1038 | #all done 1039 | echo_green "NVRAM has been cleared." 1040 | read -rep "Press Enter to continue" 1041 | } 1042 | 1043 | ######################## 1044 | # Firmware Update Menu # 1045 | ######################## 1046 | function menu_fwupdate() { 1047 | 1048 | if [[ "$isFullRom" = true ]]; then 1049 | uefi_menu 1050 | else 1051 | stock_menu 1052 | fi 1053 | } 1054 | 1055 | function show_header() { 1056 | printf "\ec" 1057 | echo -e "${NORMAL}\n ChromeOS Device Firmware Utility Script ${script_date} ${NORMAL}" 1058 | echo -e "${NORMAL} (c) Mr Chromebox ${NORMAL}" 1059 | echo -e "${MENU}*********************************************************${NORMAL}" 1060 | echo -e "${MENU}**${NUMBER} Device: ${NORMAL}${deviceDesc}" 1061 | echo -e "${MENU}**${NUMBER} Board Name: ${NORMAL}${boardName^^}" 1062 | echo -e "${MENU}**${NUMBER} Platform: ${NORMAL}$deviceCpuType" 1063 | echo -e "${MENU}**${NUMBER} Fw Type: ${NORMAL}$firmwareType" 1064 | echo -e "${MENU}**${NUMBER} Fw Ver: ${NORMAL}$fwVer ($fwDate)" 1065 | if [[ $isUEFI = true && $hasUEFIoption = true ]]; then 1066 | # check if update available 1067 | curr_yy=$(echo $fwDate | cut -f 3 -d '/') 1068 | curr_mm=$(echo $fwDate | cut -f 1 -d '/') 1069 | curr_dd=$(echo $fwDate | cut -f 2 -d '/') 1070 | eval coreboot_file=$`echo "coreboot_uefi_${device}"` 1071 | date=$(echo $coreboot_file | grep -o "mrchromebox.*" | cut -f 2 -d '_' | cut -f 1 -d '.') 1072 | uefi_yy=$(echo $date | cut -c1-4) 1073 | uefi_mm=$(echo $date | cut -c5-6) 1074 | uefi_dd=$(echo $date | cut -c7-8) 1075 | if [[ ("$firmwareType" != *"pending"*) && (($uefi_yy > $curr_yy) || \ 1076 | ("$uefi_yy" = "$curr_yy" && "$uefi_mm" > "$curr_mm") || \ 1077 | ("$uefi_yy" = "$curr_yy" && "$uefi_mm" = "$curr_mm" && "$uefi_dd" > "$curr_dd")) ]]; then 1078 | echo -e "${MENU}**${NORMAL} ${GREEN_TEXT}Update Available ($uefi_mm/$uefi_dd/$uefi_yy)${NORMAL}" 1079 | fi 1080 | fi 1081 | if [ "$wpEnabled" = true ]; then 1082 | echo -e "${MENU}**${NUMBER} Fw WP: ${RED_TEXT}Enabled${NORMAL}" 1083 | WP_TEXT=${RED_TEXT} 1084 | else 1085 | echo -e "${MENU}**${NUMBER} Fw WP: ${NORMAL}Disabled" 1086 | WP_TEXT=${GREEN_TEXT} 1087 | fi 1088 | echo -e "${MENU}*********************************************************${NORMAL}" 1089 | } 1090 | 1091 | function stock_menu() { 1092 | 1093 | show_header 1094 | 1095 | if [[ "$unlockMenu" = true || ( "$isFullRom" = false && "$isBootStub" = false && "$isUnsupported" = false \ 1096 | && "$isCmlBook" = false && "$isEOL" = false ) ]]; then 1097 | echo -e "${MENU}**${WP_TEXT} ${NUMBER} 1)${MENU} Install/Update RW_LEGACY Firmware ${NORMAL}" 1098 | else 1099 | echo -e "${GRAY_TEXT}** ${GRAY_TEXT} 1)${GRAY_TEXT} Install/Update RW_LEGACY Firmware ${NORMAL}" 1100 | fi 1101 | 1102 | if [[ "$unlockMenu" = true || "$hasUEFIoption" = true ]]; then 1103 | echo -e "${MENU}**${WP_TEXT} [WP]${NUMBER} 2)${MENU} Install/Update UEFI (Full ROM) Firmware ${NORMAL}" 1104 | else 1105 | echo -e "${GRAY_TEXT}** ${GRAY_TEXT} 2)${GRAY_TEXT} Install/Update UEFI (Full ROM) Firmware${NORMAL}" 1106 | fi 1107 | if [[ "${device^^}" = "EVE" ]]; then 1108 | echo -e "${MENU}**${WP_TEXT} [WP]${NUMBER} D)${MENU} Downgrade Touchpad Firmware ${NORMAL}" 1109 | echo -e "${MENU}**${WP_TEXT} [WP]${NUMBER} U)${MENU} Upgrade Touchpad Firmware ${NORMAL}" 1110 | fi 1111 | if [[ "$isJsl" = true && "$device" =~ "gal" ]]; then 1112 | echo -e "${MENU}**${WP_TEXT} [WP]${NUMBER} T)${MENU} Set Touchpad Type in SSFC ${NORMAL}" 1113 | fi 1114 | if [[ "$unlockMenu" = true || ( "$isFullRom" = false && "$isBootStub" = false ) ]]; then 1115 | echo -e "${MENU}**${WP_TEXT} [WP]${NUMBER} 3)${MENU} Set Boot Options (GBB flags) ${NORMAL}" 1116 | echo -e "${MENU}**${WP_TEXT} [WP]${NUMBER} 4)${MENU} Set Hardware ID (HWID) ${NORMAL}" 1117 | else 1118 | echo -e "${GRAY_TEXT}** ${GRAY_TEXT} 3)${GRAY_TEXT} Set Boot Options (GBB flags)${NORMAL}" 1119 | echo -e "${GRAY_TEXT}** ${GRAY_TEXT} 4)${GRAY_TEXT} Set Hardware ID (HWID) ${NORMAL}" 1120 | fi 1121 | if [[ "$unlockMenu" = true || ( "$isChromeOS" = false && "$isFullRom" = true ) ]]; then 1122 | echo -e "${MENU}**${WP_TEXT} [WP]${NUMBER} 5)${MENU} Restore Stock Firmware (full) ${NORMAL}" 1123 | fi 1124 | if [[ "$unlockMenu" = true || "$isUEFI" = true ]]; then 1125 | echo -e "${MENU}**${WP_TEXT} ${NUMBER} C)${MENU} Clear UEFI NVRAM ${NORMAL}" 1126 | fi 1127 | echo -e "${MENU}*********************************************************${NORMAL}" 1128 | echo -e "${ENTER_LINE}Select a numeric menu option or${NORMAL}" 1129 | echo -e "${nvram}${RED_TEXT}R${NORMAL} to reboot ${NORMAL} ${RED_TEXT}P${NORMAL} to poweroff ${NORMAL} ${RED_TEXT}Q${NORMAL} to quit ${NORMAL}" 1130 | 1131 | read -re opt 1132 | case $opt in 1133 | 1134 | 1) if [[ "$unlockMenu" = true || "$isEOL" = false && ("$isCmlBook" = false \ 1135 | && "$isFullRom" = false && "$isBootStub" = false && "$isUnsupported" = false) ]]; then 1136 | flash_rwlegacy 1137 | elif [[ "$isEOL" = "true" ]]; then 1138 | echo_red "The RW_LEGACY firmware update is not supported for devices which have reached end-of-life" 1139 | read -rep "Press enter to return to the main menu" 1140 | fi 1141 | menu_fwupdate 1142 | ;; 1143 | 1144 | 2) if [[ "$unlockMenu" = true || "$hasUEFIoption" = true ]]; then 1145 | flash_full_rom 1146 | fi 1147 | menu_fwupdate 1148 | ;; 1149 | 1150 | [dD]) if [[ "${device^^}" = "EVE" ]]; then 1151 | downgrade_touchpad_fw 1152 | fi 1153 | menu_fwupdate 1154 | ;; 1155 | 1156 | [uU]) if [[ "${device^^}" = "EVE" ]]; then 1157 | upgrade_touchpad_fw 1158 | fi 1159 | menu_fwupdate 1160 | ;; 1161 | 1162 | [tT]) if [[ "$isJsl" = true && "$device" =~ "gal" ]]; then 1163 | set_touchpad_in_ssfc 1164 | fi 1165 | menu_fwupdate 1166 | ;; 1167 | 1168 | 3) if [[ "$unlockMenu" = true || "$isChromeOS" = true || "$isUnsupported" = false \ 1169 | && "$isFullRom" = false && "$isBootStub" = false ]]; then 1170 | set_boot_options 1171 | fi 1172 | menu_fwupdate 1173 | ;; 1174 | 1175 | 4) if [[ "$unlockMenu" = true || "$isChromeOS" = true || "$isUnsupported" = false \ 1176 | && "$isFullRom" = false && "$isBootStub" = false ]]; then 1177 | set_hwid 1178 | fi 1179 | menu_fwupdate 1180 | ;; 1181 | 1182 | 5) if [[ "$unlockMenu" = true || "$isChromeOS" = false && "$isUnsupported" = false \ 1183 | && "$isFullRom" = true ]]; then 1184 | restore_stock_firmware 1185 | fi 1186 | menu_fwupdate 1187 | ;; 1188 | 1189 | [rR]) echo -e "\nRebooting...\n"; 1190 | cleanup 1191 | reboot 1192 | exit 1193 | ;; 1194 | 1195 | [pP]) echo -e "\nPowering off...\n"; 1196 | cleanup 1197 | poweroff 1198 | exit 1199 | ;; 1200 | 1201 | [qQ]) cleanup; 1202 | exit; 1203 | ;; 1204 | 1205 | [lL]) if [ "$unlockMenu" = false ]; then 1206 | echo_yellow "\nAre you sure you wish to unlock all menu functions?" 1207 | read -rep "Only do this if you really know what you are doing... [y/N]? " 1208 | [[ "$REPLY" = "y" || "$REPLY" = "Y" ]] && unlockMenu=true 1209 | fi 1210 | menu_fwupdate 1211 | ;; 1212 | 1213 | [cC]) if [[ "$unlockMenu" = true || "$isUEFI" = true ]]; then 1214 | clear_nvram 1215 | fi 1216 | menu_fwupdate 1217 | ;; 1218 | 1219 | *) clear 1220 | menu_fwupdate; 1221 | ;; 1222 | esac 1223 | } 1224 | 1225 | function uefi_menu() { 1226 | 1227 | show_header 1228 | 1229 | if [[ "$hasUEFIoption" = true ]]; then 1230 | echo -e "${MENU}**${WP_TEXT} [WP]${NUMBER} 1)${MENU} Install/Update UEFI (Full ROM) Firmware ${NORMAL}" 1231 | else 1232 | echo -e "${GRAY_TEXT}** ${GRAY_TEXT} 1)${GRAY_TEXT} Install/Update UEFI (Full ROM) Firmware${NORMAL}" 1233 | fi 1234 | if [[ "$isChromeOS" = false && "$isFullRom" = true ]]; then 1235 | echo -e "${MENU}**${WP_TEXT} [WP]${NUMBER} 2)${MENU} Restore Stock Firmware ${NORMAL}" 1236 | else 1237 | echo -e "${GRAY_TEXT}** ${GRAY_TEXT} 2)${GRAY_TEXT} Restore Stock ChromeOS Firmware ${NORMAL}" 1238 | fi 1239 | if [[ "${device^^}" = "EVE" ]]; then 1240 | echo -e "${MENU}**${WP_TEXT} [WP]${NUMBER} D)${MENU} Downgrade Touchpad Firmware ${NORMAL}" 1241 | echo -e "${MENU}**${WP_TEXT} [WP]${NUMBER} U)${MENU} Upgrade Touchpad Firmware ${NORMAL}" 1242 | fi 1243 | if [[ "$isJsl" = true && "$device" =~ "gal" ]]; then 1244 | echo -e "${MENU}**${WP_TEXT} [WP]${NUMBER} T)${MENU} Set Touchpad Type in SSFC ${NORMAL}" 1245 | fi 1246 | if [[ "$unlockMenu" = true || "$isUEFI" = true ]]; then 1247 | echo -e "${MENU}**${WP_TEXT} ${NUMBER} C)${MENU} Clear UEFI NVRAM ${NORMAL}" 1248 | fi 1249 | echo -e "${MENU}*********************************************************${NORMAL}" 1250 | echo -e "${ENTER_LINE}Select a numeric menu option or${NORMAL}" 1251 | echo -e "${nvram}${RED_TEXT}R${NORMAL} to reboot ${NORMAL} ${RED_TEXT}P${NORMAL} to poweroff ${NORMAL} ${RED_TEXT}Q${NORMAL} to quit ${NORMAL}" 1252 | 1253 | read -re opt 1254 | case $opt in 1255 | 1256 | 1) if [[ "$hasUEFIoption" = true ]]; then 1257 | flash_full_rom 1258 | fi 1259 | uefi_menu 1260 | ;; 1261 | 1262 | 2) if [[ "$isChromeOS" = false && "$isUnsupported" = false \ 1263 | && "$isFullRom" = true ]]; then 1264 | restore_stock_firmware 1265 | menu_fwupdate 1266 | else 1267 | uefi_menu 1268 | fi 1269 | ;; 1270 | 1271 | [dD]) if [[ "${device^^}" = "EVE" ]]; then 1272 | downgrade_touchpad_fw 1273 | fi 1274 | uefi_menu 1275 | ;; 1276 | 1277 | [uU]) if [[ "${device^^}" = "EVE" ]]; then 1278 | upgrade_touchpad_fw 1279 | fi 1280 | uefi_menu 1281 | ;; 1282 | 1283 | [tT]) if [[ "$isJsl" = true && "$device" =~ "gal" ]]; then 1284 | set_touchpad_in_ssfc 1285 | fi 1286 | uefi_menu 1287 | ;; 1288 | 1289 | [rR]) echo -e "\nRebooting...\n"; 1290 | cleanup 1291 | reboot 1292 | exit 1293 | ;; 1294 | 1295 | [pP]) echo -e "\nPowering off...\n"; 1296 | cleanup 1297 | poweroff 1298 | exit 1299 | ;; 1300 | 1301 | [qQ]) cleanup; 1302 | exit; 1303 | ;; 1304 | 1305 | [cC]) if [[ "$isUEFI" = true ]]; then 1306 | clear_nvram 1307 | fi 1308 | uefi_menu 1309 | ;; 1310 | 1311 | *) clear 1312 | uefi_menu; 1313 | ;; 1314 | esac 1315 | } 1316 | -------------------------------------------------------------------------------- /functions.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | # 3 | 4 | # shellcheck disable=SC2164 5 | 6 | #misc globals 7 | usb_devs="" 8 | num_usb_devs=0 9 | usb_device="" 10 | isChromeOS=true 11 | isChromiumOS=false 12 | isCloudready=false 13 | flashromcmd="" 14 | flashrom_params="" 15 | flashrom_programmer="-p internal:boardmismatch=force" 16 | cbfstoolcmd="" 17 | gbbutilitycmd="" 18 | ectoolcmd="" 19 | preferUSB=false 20 | isHswBox=false 21 | isBdwBox=false 22 | isHswBook=false 23 | isBdwBook=false 24 | isHsw=false 25 | isBdw=false 26 | isByt=false 27 | isBsw=false 28 | isSkl=false 29 | isSnbIvb=false 30 | isApl=false 31 | isKbl=false 32 | isGlk=false 33 | isStr=false 34 | isWhl=false 35 | isCml=false 36 | isCmlBox=false 37 | isCmlBook=false 38 | isPco=false 39 | isCzn=false 40 | isMdn=false 41 | isJsl=false 42 | isTgl=false 43 | isAdl=false 44 | isAdl_2=false 45 | isAdlN=false 46 | isMtl=false 47 | isUnsupported=false 48 | firmwareType="" 49 | isStock=true 50 | isFullRom=false 51 | isBootStub=false 52 | isUEFI=false 53 | hasRwLegacy=false 54 | unlockMenu=false 55 | hasUEFIoption=false 56 | wpEnabled=false 57 | hasLAN=false 58 | hasCR50=false 59 | kbl_use_rwl18=false 60 | useAltfwStd=false 61 | isMusl=false 62 | 63 | snb_ivb=('butterfly' 'link' 'lumpy' 'parrot' 'stout' 'stumpy') 64 | hsw_boxes=('mccloud' 'panther' 'tricky' 'zako') 65 | hsw_books=('falco' 'leon' 'monroe' 'peppy' 'wolf') 66 | bdw_boxes=('guado' 'rikku' 'tidus') 67 | bdw_books=('auron_paine' 'auron_yuna' 'buddy' 'gandof' 'lulu' 'samus') 68 | baytrail=('banjo' 'candy' 'clapper' 'enguarde' 'glimmer' 'gnawty' 'heli' \ 69 | 'kip' 'ninja' 'orco' 'quawks' 'squawks' 'sumo' 'swanky' 'winky') 70 | braswell=('banon' 'celes' 'cyan' 'edgar' 'kefka' 'reks' 'relm' \ 71 | 'setzer' 'terra' 'ultima' 'wizpig') 72 | skylake=('asuka' 'caroline' 'cave' 'chell' 'lars' 'lili' 'sentry') 73 | apl=('astronaut' 'babymega' 'babytiger' 'blacktip' 'blue' 'bruce' 'coral' \ 74 | 'electro' 'epaulette' 'lava' 'nasher' 'nasher360' 'pyro' 'rabbid' 'reef' \ 75 | 'robo' 'robo360' 'sand' 'santa' 'snappy' 'whitetip') 76 | kbl_boxes=('bleemo' 'endeavour' 'excelsior' 'fizz' 'jax' 'kench' 'sion' 'teemo' 'wukong') 77 | kbl_rwl_20=('akali' 'bard' 'ekko' 'eve' 'nami' 'nautilus' \ 78 | 'pantheon' 'sona' 'soraka' 'syndra' 'vayne') 79 | kbl_rwl_18=('atlas' 'endeavour' 'karma' 'leona' 'nocturne' 'rammus' 'shyvana') 80 | kbl=($(printf "%s " "${kbl_boxes[@]}" "${kbl_rwl_20[@]}" "${kbl_rwl_18[@]}")) 81 | glk=('ampton' 'apel' 'apele' 'bloog' 'blooglet' 'blooguard' 'blorb' 'bluebird' 'bobba' \ 82 | 'bobba360' 'casta' 'dood' 'droid' 'dorp' 'fleex' 'foob' 'foob360' 'garg' \ 83 | 'garg360' 'garfour' 'glk' 'glk360' 'grabbiter' 'laser' 'laser14' 'lick' \ 84 | 'meep' 'mimrock' 'nospike' 'octopus' 'orbatrix' 'phaser' 'phaser360' \ 85 | 'phaser360s' 'sparky' 'sparky360' 'vorticon' 'vortininja') 86 | whl=('arcada' 'sarien') 87 | cml_boxes=('ambassador' 'dooly' 'duffy' 'faffy' 'genesis' 'kaisa' 'moonbuggy' 'noibat' 'puff' 'scout' 'wyvern') 88 | cml_books=('akemi' 'dragonair' 'drallion' 'dratini' 'hatch' 'helios' 'jinlon' 'kindred' 'kled' \ 89 | 'kohaku' 'nightfury') 90 | cml=($(printf "%s " "${cml_boxes[@]}" "${cml_books[@]}")) 91 | jsl=('beadrix' 'beetley' 'blipper' 'bookem' 'boten' 'botenflex' 'boxy' 'bugzzy' 'cret' 'cret360' \ 92 | 'dexi' 'drawcia' 'drawlat' 'drawman' 'drawper' 'galith' 'galith360' 'gallop' 'galnat' 'galnat360' \ 93 | 'galtic' 'galtic360' 'kracko' 'kracko360' 'landia' 'landrid' 'lantis' 'madoo' 'magister' \ 94 | 'maglet' 'maglia' 'maglith' 'magma' 'magneto' 'magolor' 'magpie' 'metaknight' 'palutena' \ 95 | 'pasara' 'peezer' 'pirette' 'pirika' 'sasuke' 'sasukette' 'storo' 'storo360' 'taranza') 96 | tgl=('chronicler' 'collis' 'copano' 'delbin' 'drobit' 'eldrid' 'elemi' 'lillipup' 'lindar' \ 97 | 'voema' 'volet' 'volta' 'voxel') 98 | adl=('anahera' 'aurash' 'brya' 'banshee' 'constitution' 'crota' 'crota360' 'dochi' 'felwinter' 'gimble' \ 99 | 'gladios' 'intrepid' 'kano' 'kinox' 'kuldax' 'lisbon' 'marasov' 'mithrax' 'moli' 'omnigul' 'omniknight' \ 100 | 'osiris' 'primus' 'redrix' 'redrix4es' 'taeko' 'taniks' 'tarlo' 'vell' 'volmar' 'zavala') 101 | adl_2=('aurash' 'banshee' 'constitution' 'gladios' 'intrepid' 'kinox' 'kuldax' 'lisbon' 'marasov' 'moli' 'omnigul') 102 | adl_n=('anraggar' 'anraggar360' 'craask' 'craaskana' 'craaskbowl' 'craaskino' 'craaskov' 'craaskvin' 'craasneto' \ 103 | 'craaswell' 'joxer' 'joxero' 'nereid' 'nirwin' 'nivviks' 'pujjo1e' 'pujjo' 'pujjoflex' 'pujjoteen' 'pujjoteen15w' \ 104 | 'quandiso' 'quandiso360' 'riven' 'rudriks' 'uldren' 'uldren360' 'xivu' 'xivu360' 'yahiko' 'yavijo' 'yaviks' \ 105 | 'yavikso' 'yavilla' 'yavilly') 106 | mtl=('karis' 'rex' 'screebo') 107 | 108 | str=('aleena' 'barla' 'careena' 'grunt' 'kasumi' 'liara' 'treeya' 'treeya360') 109 | pco=('berknip' 'dirinboz' 'ezkinil' 'gumboz' 'jelboz360' 'morphius' 'vilboz' 'woomax') 110 | czn=('dewatt' 'guybrush' 'nipperkin') 111 | mdn=('crystaldrift' 'frostflow' 'markarth' 'skyrim' 'whiterun') 112 | 113 | purism=('librem13v1' 'librem13v2' 'librem13v4' 'librem15v2' 'librem15v3' 'librem15v4' \ 114 | 'librem_mini' 'librem_mini_v2' 'librem_14'); 115 | 116 | UEFI_ROMS=($(printf "%s " "${hsw_boxes[@]}" "${hsw_books[@]}" "${bdw_boxes[@]}" \ 117 | "${bdw_books[@]}" "${baytrail[@]}" "${snb_ivb[@]}" "${braswell[@]}" \ 118 | "${skylake[@]}" "${kbl[@]}" "${purism[@]}" "${str[@]}" "${cml[@]}" \ 119 | "${glk[@]}" "${apl[@]}" "${tgl[@]}" "${jsl[@]}" "${adl[@]}" "${adl_n[@]}" \ 120 | "${pco[@]}" "${czn[@]}" "${mdn[@]}" )) 121 | eol_devices=($(printf "%s " "${hsw_boxes[@]}" "${hsw_books[@]}" "${bdw_boxes[@]}" \ 122 | "${bdw_books[@]}" "${baytrail[@]}" "${snb_ivb[@]}" "${braswell[@]}" "${skylake[@]}" )) 123 | 124 | #menu text output 125 | NORMAL=$(echo "\033[m") 126 | MENU=$(echo "\033[36m") #Blue 127 | NUMBER=$(echo "\033[33m") #yellow 128 | FGRED=$(echo "\033[41m") 129 | RED_TEXT=$(echo "\033[31m") 130 | GRAY_TEXT=$(echo "\033[1;30m") 131 | GREEN_TEXT=$(echo "\033[1;32m") 132 | ENTER_LINE=$(echo "\033[33m") 133 | 134 | function echo_red() 135 | { 136 | echo -e "\E[0;31m$1" 137 | echo -e '\e[0m' 138 | } 139 | 140 | function echo_green() 141 | { 142 | echo -e "\E[0;32m$1" 143 | echo -e '\e[0m' 144 | } 145 | 146 | function echo_yellow() 147 | { 148 | echo -e "\E[1;33m$1" 149 | echo -e '\e[0m' 150 | } 151 | 152 | function exit_red() 153 | { 154 | echo_red "$@" 155 | read -rep "Press [Enter] to return to the main menu." 156 | } 157 | 158 | function die() 159 | { 160 | echo_red "$@" 161 | exit 1 162 | } 163 | 164 | 165 | #################### 166 | # list USB devices # 167 | #################### 168 | function list_usb_devices() 169 | { 170 | stat -c %N /sys/block/sd* 2>/dev/null | grep usb | cut -f1 -d ' ' | sed "s/[']//g;s|/sys/block|/dev|" > /tmp/usb_block_devices 171 | eval usb_devs="($(cat /tmp/usb_block_devices))" 172 | [ "$usb_devs" != "" ] || return 1 173 | echo -e "\nDevices available:\n" 174 | num_usb_devs=0 175 | for dev in "${usb_devs[@]}" 176 | do 177 | ((num_usb_devs+=1)) 178 | vendor=$(udevadm info --query=all --name=${dev#"/dev/"} | grep -E "ID_VENDOR=" | awk -F"=" '{print $2}') 179 | model=$(udevadm info --query=all --name=${dev#"/dev/"} | grep -E "ID_MODEL=" | awk -F"=" '{print $2}') 180 | sz=$(fdisk -l 2> /dev/null | grep "Disk ${dev}" | awk '{print $3}') 181 | echo -n "$num_usb_devs)" 182 | if [ -n "${vendor}" ]; then 183 | echo -n " ${vendor}" 184 | fi 185 | if [ -n "${model}" ]; then 186 | echo -n " ${model}" 187 | fi 188 | echo -e " (${sz} GB)" 189 | done 190 | echo -e "" 191 | return 0 192 | } 193 | 194 | 195 | ################ 196 | # Get cbfstool # 197 | ################ 198 | function get_cbfstool() 199 | { 200 | if [ ! -f ${cbfstoolcmd} ]; then 201 | working_dir=$(pwd) 202 | 203 | cd $(dirname ${cbfstoolcmd}) 204 | 205 | #echo_yellow "Downloading cbfstool utility" 206 | util_file="" 207 | if [[ "$isMusl" = true ]]; then 208 | util_file="cbfstool-musl.tar.gz" 209 | else 210 | util_file="cbfstool.tar.gz" 211 | fi 212 | $CURL -sLo "cbfstool.tar.gz" "${util_source}${util_file}" 213 | if [ $? -ne 0 ]; then 214 | echo_red "Error downloading cbfstool; cannot proceed." 215 | #restore working dir 216 | cd ${working_dir} 217 | return 1 218 | fi 219 | tar -zxf cbfstool.tar.gz --no-same-owner 220 | if [ $? -ne 0 ]; then 221 | echo_red "Error extracting cbfstool; cannot proceed." 222 | #restore working dir 223 | cd ${working_dir} 224 | return 1 225 | fi 226 | #set +x 227 | chmod +x cbfstool 228 | #restore working dir 229 | cd ${working_dir} 230 | fi 231 | return 0 232 | } 233 | 234 | 235 | ################ 236 | # Get flashrom # 237 | ################ 238 | function get_flashrom() 239 | { 240 | if [ ! -f "${flashromcmd}" ]; then 241 | working_dir=$(pwd) 242 | 243 | cd $(dirname ${flashromcmd}) 244 | 245 | util_file="" 246 | if [[ "$isChromeOS" = true ]]; then 247 | #needed to avoid dependencies not found on older ChromeOS 248 | util_file="flashrom_old.tar.gz" 249 | else 250 | flashrom_programmer="${flashrom_programmer} --use-first-chip" 251 | if [[ "$isMusl" = true ]]; then 252 | util_file="flashrom-musl.tar.gz" 253 | else 254 | util_file="flashrom_ups_int_20241214.tar.gz" 255 | fi 256 | fi 257 | $CURL -sLo "flashrom.tar.gz" "${util_source}${util_file}" 258 | if [[ $? -ne 0 ]]; then 259 | echo_red "Error downloading flashrom; cannot proceed." 260 | #restore working dir 261 | cd "${working_dir}" 262 | return 1 263 | fi 264 | 265 | if ! tar -zxf flashrom.tar.gz --no-same-owner; then 266 | echo_red "Error extracting flashrom; cannot proceed." 267 | #restore working dir 268 | cd "${working_dir}" 269 | return 1 270 | fi 271 | #set +x 272 | chmod +x flashrom 273 | 274 | #restore working dir 275 | cd "${working_dir}" 276 | fi 277 | #check if flashrom supports --noverify-all 278 | if ${flashromcmd} -h | grep -q "noverify-all" ; then 279 | export noverify="-N" 280 | else 281 | export noverify="-n" 282 | fi 283 | # append programmer type 284 | flashromcmd="${flashromcmd} ${flashrom_programmer}" 285 | return 0 286 | } 287 | 288 | 289 | ################### 290 | # Get gbb_utility # 291 | ################### 292 | function get_gbb_utility() 293 | { 294 | if [ ! -f ${gbbutilitycmd} ]; then 295 | working_dir=$(pwd) 296 | 297 | cd $(dirname ${gbbutilitycmd}) 298 | 299 | util_file="" 300 | if [[ "$isMusl" = true ]]; then 301 | util_file="gbb_utility-musl.tar.gz" 302 | else 303 | util_file="gbb_utility.tar.gz" 304 | fi 305 | $CURL -sLo "gbb_utility.tar.gz" "${util_source}${util_file}" 306 | if [ $? -ne 0 ]; then 307 | echo_red "Error downloading gbb_utility; cannot proceed." 308 | #restore working dir 309 | cd ${working_dir} 310 | return 1 311 | fi 312 | tar -zxf gbb_utility.tar.gz 313 | if [ $? -ne 0 ]; then 314 | echo_red "Error extracting gbb_utility; cannot proceed." 315 | #restore working dir 316 | cd ${working_dir} 317 | return 1 318 | fi 319 | #set +x 320 | chmod +x gbb_utility 321 | #restore working dir 322 | cd ${working_dir} 323 | fi 324 | return 0 325 | } 326 | 327 | ############## 328 | # Get ectool # 329 | ############## 330 | function get_ectool() 331 | { 332 | # Regardless if running under ChromeOS or Linux, can put ectool 333 | # in same place as cbfstool 334 | ectoolcmd="$(dirname $cbfstoolcmd)/ectool" 335 | if [ ! -f ${ectoolcmd} ]; then 336 | working_dir=$(pwd) 337 | 338 | cd $(dirname ${ectoolcmd}) 339 | 340 | $CURL -sLO "${util_source}ectool.tar.gz" 341 | if [ $? -ne 0 ]; then 342 | echo_red "Error downloading ectool; cannot proceed." 343 | #restore working dir 344 | cd ${working_dir} 345 | return 1 346 | fi 347 | tar -zxf ectool.tar.gz 348 | if [ $? -ne 0 ]; then 349 | echo_red "Error extracting ectool; cannot proceed." 350 | #restore working dir 351 | cd ${working_dir} 352 | return 1 353 | fi 354 | #set +x 355 | chmod +x ectool 356 | #restore working dir 357 | cd ${working_dir} 358 | fi 359 | return 0 360 | } 361 | 362 | ################################################## 363 | # Diagnostic report for troubleshooting purposes # 364 | ################################################## 365 | 366 | function diagnostic_report_save() { 367 | ( 368 | echo "mrchromebox firmware-util diagnostic report" 369 | date 370 | echo 371 | for key in ${!diagnostic_report_data[@]}; do 372 | echo "[$key]" 373 | echo "${diagnostic_report_data[$key]}" 374 | echo 375 | done 376 | ) > /tmp/mrchromebox_diag.txt 377 | } 378 | 379 | function diagnostic_report_set() { 380 | declare -gA diagnostic_report_data 381 | local key="$1" 382 | shift 383 | diagnostic_report_data[$key]="$*" 384 | } 385 | 386 | 387 | ################ 388 | # Prelim Setup # 389 | ################ 390 | 391 | function prelim_setup() 392 | { 393 | 394 | # Must run as root 395 | [ "$(whoami)" = "root" ] || die "You need to run this script as root; use 'sudo bash