diff --git a/database/cros-hwid.json b/database/cros-hwid.json new file mode 100644 index 0000000..a4743b3 --- /dev/null +++ b/database/cros-hwid.json @@ -0,0 +1,233 @@ +{ + "_meta": { + "schema": "codename_to_hwid_min.v1", + "updated": "2026-01-20", + "fields": { + "hwid": "string", + "owner_history": "enum: clean|unknown|suspected_bad|proven_bad", + "confidence_valid": "0.0-1.0", + "confidence_allegation": "0.0-1.0", + "notes": "short string (optional)" + } + }, + "devices": { + "HANA": [ + { + "hwid": "HANA L4A-D75-C2H-E2Q-P2U-B4Q", + "owner_history": "proven_bad", + "confidence_valid": 1, + "confidence_allegation": 1, + "notes": "Proven enrolled/linked to an organization" + }, + { + "hwid": "HANA 14A-D7K-A2A-G2Q-B2W-A83", + "owner_history": "suspected_bad", + "confidence_valid": 1, + "confidence_allegation": 0.1, + "notes": "Suspected org enrollment" + }, + { + "hwid": "HANA 14A-D7Z-A6E-A2I-D2E-B9K", + "owner_history": "suspected_bad", + "confidence_valid": 1, + "confidence_allegation": 0.1, + "notes": "Suspected org enrollment" + } + ], + "SHYVANA": [ + { + "hwid": "SHYVANA C5B-A4G-C4Q-S24-A9U", + "owner_history": "unknown", + "confidence_valid": 1, + "confidence_allegation": 0.5 + } + ], + "JINLON-YTGY": [ + { + "hwid": "JINLON-YTGY C5B-O5B-E4E-S3Q-E9L", + "owner_history": "unknown", + "confidence_valid": 1, + "confidence_allegation": 0.5, + "notes": "Unsure" + } + ], + "KIP": [ + { + "hwid": "KIP C5A-G2O-H6A-A5V", + "owner_history": "unknown", + "confidence_valid": 1, + "confidence_allegation": 0.5 + } + ], + "EVE": [ + { + "hwid": "EVE D6B-A6A-C4C-F8N-P8A-A37", + "owner_history": "unknown", + "confidence_valid": 1, + "confidence_allegation": 0.5 + } + ], + "GRABBITER": [ + { + "hwid": "GRABBITER G7B-B4E-O57-L8M-E6T-Q8Q-A2K", + "owner_history": "unknown", + "confidence_valid": 0.5, + "confidence_allegation": 0.3, + "notes": "Suspected org enrollment; reason: owner's tpm BAD" + }, + { + "hwid": "GRABBITER D6B-B3C-C5P-M8I-C6Y-A72", + "owner_history": "suspected_bad", + "confidence_valid": 1, + "confidence_allegation": 0.3, + "notes": "Suspected org enrollment; reason: owner's tpm BAD" + }, + { + "hwid": "GRABBITER G7C-B4C-O52-M4Y-C8T-Q8Q-A2M", + "owner_history": "suspected_bad", + "confidence_valid": 1, + "confidence_allegation": 0.3, + "notes": "Suspected org enrollment" + } + ], + "NASHER": [ + { + "hwid": "NASHER D5F-B4K-C47-W5K-S4C-I6A-A9A", + "owner_history": "unknown", + "confidence_valid": 1, + "confidence_allegation": 0.5, + "notes": "Unsure" + } + ], + "BARLA": [ + { + "hwid": "BARLA C4B-A4L-F3V-M8G-I2Q-C2E-A8B", + "owner_history": "unknown", + "confidence_valid": 1, + "confidence_allegation": 0.5 + } + ], + "FLEEX": [ + { + "hwid": "FLEEX D7B-B4D-G57-N8N-J4M-G2Q-A6D", + "owner_history": "proven_bad", + "confidence_valid": 1, + "confidence_allegation": 1, + "notes": "Proven enrolled/linked to an organization" + }, + { + "hwid": "FLEEX D7B-B4B-H5V-N2B-A4M-H2M", + "owner_history": "suspected_bad", + "confidence_valid": 1, + "confidence_allegation": 0.3, + "notes": "Suspected org enrollment; reason: owner's tpm BAD" + }, + { + "hwid": "FLEEX D6B-B3D-G5V-P3J-B4E-B7K", + "owner_history": "suspected_bad", + "confidence_valid": 1, + "confidence_allegation": 0.3, + "notes": "Suspected org enrollment; reason: owner's tpm BAD" + } + ], + "FALCO": [ + { + "hwid": "FALCO C3J-C3I-P8N", + "owner_history": "unknown", + "confidence_valid": 1, + "confidence_allegation": 0.5 + }, + { + "hwid": "FALCO C2A-U6Y-D95", + "owner_history": "unknown", + "confidence_valid": 1, + "confidence_allegation": 0.5 + } + ], + "BLOOGET": [ + { + "hwid": "BLOOGET C2Q-A4D-D2K-T7X-U8A-A9N", + "owner_history": "suspected_bad", + "confidence_valid": 1, + "confidence_allegation": 0.3, + "notes": "Suspected org enrollment; reason: owner's tpm BAD" + } + ], + "GNAWTY": [ + { + "hwid": "GNAWTY C2Q-E55-A5B", + "owner_history": "unknown", + "confidence_valid": 1, + "confidence_allegation": 0.5 + } + ], + "MINNIE": [ + { + "hwid": "MINNIE F25-S2E-Q4G-A3C", + "owner_history": "unknown", + "confidence_valid": 1, + "confidence_allegation": 0.5 + } + ], + "NAUTILUS": [ + { + "hwid": "NAUTILUS D5B-A2E-B5M-D97-Q34", + "owner_history": "suspected_bad", + "confidence_valid": 1, + "confidence_allegation": 0.3, + "notes": "Suspected org enrollment; reason: owner's tpm BAD" + } + ], + "AKALI360": [ + { + "hwid": "AKALI360 C4B-A2C-F3K-65U-I8T", + "owner_history": "suspected_bad", + "confidence_valid": 1, + "confidence_allegation": 0.3, + "notes": "Suspected org enrollment; reason: owner's tpm BAD" + } + ], + "PEPPY": [ + { + "hwid": "PEPPY C3A-B3E-A3D", + "owner_history": "unknown", + "confidence_valid": 1, + "confidence_allegation": 0.5 + } + ], + "BANJO": [ + { + "hwid": "BANJO C7A-C2I-A65", + "owner_history": "unknown", + "confidence_valid": 1, + "confidence_allegation": 0.5 + } + ], + "LASER14": [ + { + "hwid": "LASER14 C3J-A2E-A3K-I4Q-I4I", + "owner_history": "suspected_bad", + "confidence_valid": 1, + "confidence_allegation": 0.3, + "notes": "Suspected org enrollment; reason: owner's tpm BAD" + } + ], + "GANDOF": [ + { + "hwid": "GANDOF D25-A4W-B3Q-A6E", + "owner_history": "unknown", + "confidence_valid": 1, + "confidence_allegation": 0.5 + } + ], + "CAREENA": [ + { + "hwid": "CAREENA C5B-A41-D4Q-A3Y-O6R-A2B-E9E", + "owner_history": "suspected_bad", + "confidence_valid": 0.8, + "confidence_allegation": 0.3, + "notes": "Suspected org enrollment; reason: owner's tpm BAD" + } + ] + } +} diff --git a/firmware.sh b/firmware.sh index 658cddd..a228912 100644 --- a/firmware.sh +++ b/firmware.sh @@ -1422,6 +1422,382 @@ You can always override the default using [CTRL+D] or ################### # Set Hardware ID # ################### +function fixcraft_hwid_db_path() { + local script_dir + script_dir=$(CDPATH= cd -- "$(dirname -- "${BASH_SOURCE[0]}")" && pwd) + echo "${script_dir}/database/cros-hwid.json" +} + +function fixcraft_hwid_download_db() { + local url="https://www.fixcraft.jp/database/cros-hwid.json" + local out="/tmp/fixcraft-cros-hwid.json" + + if [[ -n "${CURL:-}" ]]; then + if ${CURL} -fsSL "${url}" -o "${out}" >/dev/null 2>&1; then + echo "${out}" + return 0 + fi + fi + + if command -v curl >/dev/null 2>&1; then + if curl -fsSL "${url}" -o "${out}" >/dev/null 2>&1; then + echo "${out}" + return 0 + fi + fi + + if command -v wget >/dev/null 2>&1; then + if wget -qO "${out}" "${url}" >/dev/null 2>&1; then + echo "${out}" + return 0 + fi + fi + + return 1 +} + +function fixcraft_hwid_select_predefined() { + local db_file="$1" + local board="$2" + local lines="" + local status=0 + + lines=$(awk -v board="$board" ' + BEGIN { + in_block=0 + count=0 + } + $0 ~ "\"" board "\"[[:space:]]*:[[:space:]]*\\[" { in_block=1; next } + in_block { + if ($0 ~ /"hwid"[[:space:]]*:/) { + hwid=$0 + sub(/.*"hwid"[[:space:]]*:[[:space:]]*"/, "", hwid) + sub(/".*/, "", hwid) + valid=1 + allegation=1 + } else if ($0 ~ /"confidence_valid"[[:space:]]*:/) { + val=$0 + sub(/.*"confidence_valid"[[:space:]]*:[[:space:]]*/, "", val) + sub(/[^0-9.].*/, "", val) + if (val != "") valid=val+0 + } else if ($0 ~ /"confidence_allegation"[[:space:]]*:/) { + val=$0 + sub(/.*"confidence_allegation"[[:space:]]*:[[:space:]]*/, "", val) + sub(/[^0-9.].*/, "", val) + if (val != "") allegation=val+0 + } + if ($0 ~ /}/ && hwid != "") { + count++ + hwid_arr[count]=hwid + valid_arr[count]=valid+0 + allegation_arr[count]=allegation+0 + hwid="" + } + if ($0 ~ /]/) { exit } + } + END { + if (count == 0) exit 1 + best=1 + for (i=2; i<=count; i++) { + if (allegation_arr[i] < allegation_arr[best] || (allegation_arr[i] == allegation_arr[best] && valid_arr[i] > valid_arr[best])) { + best=i + } + } + for (i=1; i<=count; i++) { + rec = (i == best) ? 1 : 0 + printf "%d|%s|%s|%s|%d\n", i, hwid_arr[i], valid_arr[i], allegation_arr[i], rec + } + } + ' "$db_file") || status=$? + status=${status:-0} + if [[ $status -eq 1 ]]; then + return 1 + fi + if [[ $status -ne 0 || -z "${lines}" ]]; then + echo_yellow "Unable to read FixCraft database; skipping pre-defined IDs." >&2 + return 3 + fi + echo "Pick an HWID:" >&2 + while IFS='|' read -r idx hwid valid allegation rec; do + [[ -z "${idx}" || -z "${hwid}" ]] && continue + local label="" + if [[ "${rec}" = "1" ]]; then + label=" [RECOMMENDED]" + fi + printf "%s. %s (valid %s, allegation %s)%s\n" "${idx}" "${hwid}" "${valid}" "${allegation}" "${label}" >&2 + done <<< "${lines}" + + local choice="" + local selected="" + while true; do + read -rep "Select a number (or press Enter to cancel): " choice + if [[ -z "${choice}" ]]; then + return 2 + fi + if ! [[ "${choice}" =~ ^[0-9]+$ ]]; then + echo_yellow "Invalid selection." >&2 + continue + fi + selected=$(awk -F'|' -v pick="${choice}" '$1==pick {print $2; exit}' <<< "${lines}") + if [[ -n "${selected}" ]]; then + echo "${selected}" + return 0 + fi + echo_yellow "Invalid selection." >&2 + done +} + +function fixcraft_hwid_lookup_predefined() { + local db_file="$1" + local board="$2" + + awk -v board="$board" ' + $0 ~ "\"" board "\"[[:space:]]*:[[:space:]]*\\[" { in_block=1; next } + in_block && /"hwid"[[:space:]]*:/ { + match($0, /"hwid"[[:space:]]*:[[:space:]]*"[^"]+"/) + if (RSTART) { + hwid=substr($0, RSTART, RLENGTH) + sub(/.*"hwid"[[:space:]]*:[[:space:]]*"/, "", hwid) + sub(/"$/, "", hwid) + print hwid + exit + } + } + in_block && /]/ { exit } + ' "${db_file}" +} + +function fixcraft_hwid_rand_digit() { + printf '%d' $((RANDOM % 10)) +} + +function fixcraft_hwid_rand_letter() { + local letters="ABCDEFGHIJKLMNOPQRSTUVWXYZ" + printf '%s' "${letters:RANDOM%26:1}" +} + +function fixcraft_hwid_rand_hex_letter() { + local letters="ABCDEF" + printf '%s' "${letters:RANDOM%6:1}" +} + +function fixcraft_hwid_rand_hex() { + local chars="0123456789ABCDEF" + printf '%s' "${chars:RANDOM%16:1}" +} + +function fixcraft_hwid_rand_alnum() { + local chars="ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789" + printf '%s' "${chars:RANDOM%36:1}" +} + +function fixcraft_hwid_gen_group() { + local tmpl="$1" + local out="" + local i="" + local ch="" + local hex_only=0 + + if [[ "${tmpl}" =~ ^[0-9A-F]+$ ]]; then + hex_only=1 + fi + + for ((i=0; i<${#tmpl}; i++)); do + ch="${tmpl:i:1}" + if [[ "${ch}" =~ [0-9] ]]; then + out+=$(fixcraft_hwid_rand_digit) + elif [[ "${ch}" =~ [A-Z] ]]; then + if (( hex_only )); then + out+=$(fixcraft_hwid_rand_hex_letter) + else + out+=$(fixcraft_hwid_rand_letter) + fi + else + if (( hex_only )); then + out+=$(fixcraft_hwid_rand_hex) + else + out+=$(fixcraft_hwid_rand_alnum) + fi + fi + done + + if [[ -z "${out}" ]]; then + if (( hex_only )); then + out="$(fixcraft_hwid_rand_hex)$(fixcraft_hwid_rand_hex)$(fixcraft_hwid_rand_hex)" + else + out="$(fixcraft_hwid_rand_alnum)$(fixcraft_hwid_rand_alnum)$(fixcraft_hwid_rand_alnum)" + fi + fi + + printf '%s' "${out}" +} + +function fixcraft_hwid_generate_fallback() { + local board="$1" + local template="$2" + local groups_str="" + local groups=() + local prefix_len=2 + local out_groups=() + local i="" + + board=$(printf '%s' "${board}" | tr '[:lower:]' '[:upper:]') + + if [[ -n "${template}" ]]; then + if [[ "${template}" == *" "* ]]; then + groups_str="${template#* }" + fi + fi + + if [[ -n "${groups_str}" ]]; then + IFS='-' read -r -a groups <<< "${groups_str}" + fi + + if [[ ${#groups[@]} -eq 0 ]]; then + groups=("A0Z" "A0Z" "A0Z" "A0Z") + prefix_len=0 + elif (( prefix_len > ${#groups[@]} )); then + prefix_len=${#groups[@]} + fi + + for ((i=0; i<${#groups[@]}; i++)); do + if (( i < prefix_len )); then + out_groups+=("${groups[i]}") + else + out_groups+=("$(fixcraft_hwid_gen_group "${groups[i]}")") + fi + done + + echo "${board} $(IFS=-; echo "${out_groups[*]}")" +} + +function fixcraft_hwid_generate() { + local board="$1" + local script_dir + script_dir=$(CDPATH= cd -- "$(dirname -- "${BASH_SOURCE[0]}")" && pwd) + local gen_script="${script_dir}/generate-hwid.sh" + local hwid="" + local db_file="" + local template="" + + if [[ -x "${gen_script}" ]]; then + hwid=$("${gen_script}" --board "${board}") || true + if [[ -n "${hwid}" ]]; then + echo "${hwid}" + return 0 + fi + fi + + db_file=$(fixcraft_hwid_db_path) + if [[ ! -s "${db_file}" ]]; then + db_file=$(fixcraft_hwid_download_db) || true + fi + if [[ -n "${db_file}" && -s "${db_file}" ]]; then + template=$(fixcraft_hwid_lookup_predefined "${db_file}" "${board}") + fi + + fixcraft_hwid_generate_fallback "${board}" "${template}" +} + +function fixcraft_hwid_manual() { + local confirm="" + local hwid="" + + read -rep "Type 'I KNOW WHAT IM DOING' to continue: " confirm + if [[ "${confirm}" != "I KNOW WHAT IM DOING" ]]; then + echo_red "Confirmation phrase not entered; operation cancelled." >&2 + return 1 + fi + read -rep "Enter a new HWID (use all caps): " hwid + if [[ -z "${hwid}" ]]; then + echo_red "No HWID entered; operation cancelled." >&2 + return 1 + fi + echo "${hwid}" +} + +function fixcraft_hwid_disclaimer() { + echo_yellow "FixCraft, Inc. provides hardware IDs AS IS with no warranty." >&2 + echo_yellow "Use at your own risk; no guarantees of fitness or support." >&2 +} + +function select_new_hwid() { + local current_hwid="$1" + local board="" + local hwid="" + local confirm="" + + if [[ -n "${current_hwid}" ]]; then + board=$(echo "${current_hwid^^}" | cut -f1 -d ' ') + elif [[ -n "${boardName:-}" ]]; then + board="${boardName^^}" + elif [[ -n "${device:-}" ]]; then + board="${device^^}" + fi + + if [[ -z "${board}" ]]; then + read -rep "Enter your board name: " board + board=$(printf '%s' "${board}" | tr '[:lower:]' '[:upper:]') + fi + if [[ -z "${board}" ]]; then + echo_red "No board name provided; operation cancelled." + return 1 + fi + + read -rep "Do you want to try using a working, pre-defined ID? [y/N] " confirm + if [[ "${confirm}" = "Y" || "${confirm}" = "y" ]]; then + local db_file="" + local status=0 + db_file=$(fixcraft_hwid_download_db) || true + if [[ -z "${db_file}" ]]; then + db_file=$(fixcraft_hwid_db_path) + fi + + if [[ -s "${db_file}" ]]; then + hwid=$(fixcraft_hwid_select_predefined "${db_file}" "${board}") || status=$? + if [[ -n "${hwid}" ]]; then + fixcraft_hwid_disclaimer + echo "${hwid}" + return 0 + fi + fi + + if [[ ${status} -eq 1 ]]; then + echo_yellow "looks like your device isnt in the FixCraft Database!" >&2 + hwid=$(fixcraft_hwid_generate "${board}") || true + if [[ -n "${hwid}" ]]; then + fixcraft_hwid_disclaimer + echo "${hwid}" + return 0 + fi + fi + fi + + while true; do + read -rep "Auto-generate for your board or enter manually? [A/M] " confirm + if [[ "${confirm}" = "A" || "${confirm}" = "a" ]]; then + hwid=$(fixcraft_hwid_generate "${board}") || true + if [[ -n "${hwid}" ]]; then + fixcraft_hwid_disclaimer + echo "${hwid}" + return 0 + fi + echo_yellow "Unable to auto-generate HWID." >&2 + read -rep "Enter manually instead? [y/N] " confirm + if [[ "${confirm}" = "Y" || "${confirm}" = "y" ]]; then + hwid=$(fixcraft_hwid_manual) || return 1 + echo "${hwid}" + return 0 + fi + return 1 + elif [[ "${confirm}" = "M" || "${confirm}" = "m" ]]; then + hwid=$(fixcraft_hwid_manual) || return 1 + echo "${hwid}" + return 0 + fi + done +} + function set_hwid() { # set HWID using gbb_utility @@ -1438,9 +1814,11 @@ function set_hwid() echo_yellow "Are you sure you know what you're doing here? Changing this is not normally needed, and if you mess it up, -MrChromebox is not going to help you fix it. This won't let -you run a different/newer version of ChromeOS. -Proceed at your own risk." +MrChromebox is not going to help you fix it. +* This won't let you run a different/newer version of ChromeOS. +Proceed at your own risk. +P.S. using a pre-defined HWID may allow updates +to work correctly." read -rep "Really change your HWID? [y/N] " confirm [[ "$confirm" = "Y" || "$confirm" = "y" ]] || return @@ -1448,7 +1826,14 @@ Proceed at your own risk." read -rep "This is serious. Are you really sure? [y/N] " confirm [[ "$confirm" = "Y" || "$confirm" = "y" ]] || return - read -rep "Enter a new HWID (use all caps): " hwid + local hwid="" + if ! hwid=$(select_new_hwid "${_hwid}"); then + return + fi + if [[ -z "${hwid}" ]]; then + exit_red "No HWID selected; operation cancelled."; return 1 + fi + echo -e "" read -rep "Confirm changing HWID to $hwid [y/N] " confirm if [[ "$confirm" = "Y" || "$confirm" = "y" ]]; then @@ -1508,9 +1893,11 @@ Proceed at your own risk." [[ "$confirm" = "Y" || "$confirm" = "y" ]] || return local hwid="" - read -rep "Enter a new HWID: " hwid - if [[ -z "$hwid" ]]; then - exit_red "No HWID entered; operation cancelled."; return 1 + if ! hwid=$(select_new_hwid "${_current_hwid}"); then + return + fi + if [[ -z "${hwid}" ]]; then + exit_red "No HWID selected; operation cancelled."; return 1 fi echo -e "" diff --git a/generate-hwid.sh b/generate-hwid.sh new file mode 100755 index 0000000..5d59c94 --- /dev/null +++ b/generate-hwid.sh @@ -0,0 +1,176 @@ +#!/usr/bin/env bash +set -euo pipefail + +usage() { + echo "Usage: $0 --board BOARD" >&2 +} + +board="" +while [ "$#" -gt 0 ]; do + case "$1" in + --board) + board=${2:-} + shift 2 + ;; + --help|-h) + usage + exit 0 + ;; + *) + usage + exit 1 + ;; + esac +done + +if [ -z "$board" ]; then + usage + exit 1 +fi + +board=$(printf '%s' "$board" | tr '[:lower:]' '[:upper:]') +script_dir=$(CDPATH= cd -- "$(dirname -- "$0")" && pwd) +data_file="$script_dir/database/cros-hwid.json" + +if [[ ! -s "${data_file}" ]]; then + echo "Error: database file not found: ${data_file}" >&2 + exit 1 +fi + +get_hwids_for_board() { + awk -v board="$board" ' + $0 ~ "\"" board "\"[[:space:]]*:[[:space:]]*\\[" { in_block=1; next } + in_block && /"hwid"[[:space:]]*:/ { + hwid=$0 + sub(/.*"hwid"[[:space:]]*:[[:space:]]*"/, "", hwid) + sub(/".*/, "", hwid) + if (hwid != "") print hwid + } + in_block && /]/ { exit } + ' "${data_file}" +} + +get_all_hwids() { + awk ' + /"hwid"[[:space:]]*:/ { + hwid=$0 + sub(/.*"hwid"[[:space:]]*:[[:space:]]*"/, "", hwid) + sub(/".*/, "", hwid) + if (hwid != "") print hwid + } + ' "${data_file}" +} + +rand_digit() { + printf '%d' $((RANDOM % 10)) +} + +rand_letter() { + local letters="ABCDEFGHIJKLMNOPQRSTUVWXYZ" + printf '%s' "${letters:RANDOM%26:1}" +} + +rand_hex_letter() { + local letters="ABCDEF" + printf '%s' "${letters:RANDOM%6:1}" +} + +rand_hex() { + local chars="0123456789ABCDEF" + printf '%s' "${chars:RANDOM%16:1}" +} + +rand_alnum() { + local chars="ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789" + printf '%s' "${chars:RANDOM%36:1}" +} + +gen_group() { + local tmpl="$1" + local out="" + local i="" + local ch="" + local hex_only=0 + + if [[ "${tmpl}" =~ ^[0-9A-F]+$ ]]; then + hex_only=1 + fi + + for ((i=0; i<${#tmpl}; i++)); do + ch="${tmpl:i:1}" + if [[ "${ch}" =~ [0-9] ]]; then + out+=$(rand_digit) + elif [[ "${ch}" =~ [A-Z] ]]; then + if (( hex_only )); then + out+=$(rand_hex_letter) + else + out+=$(rand_letter) + fi + else + if (( hex_only )); then + out+=$(rand_hex) + else + out+=$(rand_alnum) + fi + fi + done + + if [[ -z "${out}" ]]; then + if (( hex_only )); then + out="$(rand_hex)$(rand_hex)$(rand_hex)" + else + out="$(rand_alnum)$(rand_alnum)$(rand_alnum)" + fi + fi + + printf '%s' "${out}" +} + +hwids=() +while IFS= read -r line; do + [[ -n "${line}" ]] && hwids+=("${line}") +done < <(get_hwids_for_board) + +if [[ ${#hwids[@]} -eq 0 ]]; then + echo "Board unsupported, trying random" >&2 + while IFS= read -r line; do + [[ -n "${line}" ]] && hwids+=("${line}") + done < <(get_all_hwids) +fi + +if [[ ${#hwids[@]} -eq 0 ]]; then + echo "Error: no HWIDs available in database." >&2 + exit 1 +fi + +template="${hwids[RANDOM % ${#hwids[@]}]}" +groups_str="" +if [[ "${template}" == *" "* ]]; then + groups_str="${template#* }" +fi + +groups=() +if [[ -n "${groups_str}" ]]; then + IFS='-' read -r -a groups <<< "${groups_str}" +fi + +if [[ ${#groups[@]} -eq 0 ]]; then + groups=("A0Z" "A0Z" "A0Z" "A0Z") + prefix_len=0 +else + prefix_len=2 + if (( prefix_len > ${#groups[@]} )); then + prefix_len=${#groups[@]} + fi +fi + +out_groups=() +for ((i=0; i<${#groups[@]}; i++)); do + if (( i < prefix_len )); then + out_groups+=("${groups[i]}") + else + out_groups+=("$(gen_group "${groups[i]}")") + fi +done + +echo "${board} $(IFS=-; echo "${out_groups[*]}")"