# RSHIN Scratchpad
read_RshimSP2_path=/sys/firmware/efi/efivars/RshimSP2R-f3ce977e-c17f-493e-a3cd-5731d386e505
write_RshimSP2_path=/sys/firmware/efi/efivars/RshimSP2W-f3ce977e-c17f-493e-a3cd-5731d386e505

status_clear_mask=$(( ~((1 << 11) | (1 << 12)) ))
progress_clear_mask=$(( ~((1 << 13) | (1 << 14) | (1 << 15)) ))

IN_PROGRESS=0x1
COMPLETED=0x2
FAILED=0x3

# Function to read 8 bytes from a specific offset and convert from little-endian to UINT64
read_SP2() {
    # Read 8 bytes starting from the specified offset
    bytes=$(dd if="$read_RshimSP2_path" bs=1 skip=4 count=8 2>/dev/null | xxd -p -c 8)

    # Convert the bytes from little-endian to UINT64
    local hex=""
    for (( i=${#bytes}-2; i>=0; i-=2 )); do
        hex+="${bytes:$i:2}"
    done

    # Convert hex to decimal
    echo "$((16#$hex))"
}

# Function to write a UINT64 value with a specific prefix to a file
write_uint64_with_prefix() {
    local value="$1"
    local file=/tmp/output.bin
    local log=/tmp/write_uint64_with_prefix.log

    # Prefix in hexadecimal
    local prefix="06000000"
    # Convert the UINT64 value to little-endian hexadecimal format
    local value_hex=$(printf "%016x" $value | sed 's/\(..\)/\1 /g' | awk '{for(i=NF;i>=1;i--) printf "%s ", $i}')
    local prefix_hex=$(echo "$prefix" | sed 's/\(..\)/\1 /g')
    local hex_value="${prefix_hex}${value_hex}"
    ilog "write_uint64_with_prefix: hex_value: $hex_value"

    # Write the prefix and the binary value to the file
    echo -n "$hex_value" | xxd -r -p > $file

    /bin/rm -f $write_RshimSP2_path

    cp $file $write_RshimSP2_path > $log 2>&1
    rc=$?
    if [ $rc -ne 0 ]; then
        ilog "Failed command: cp $file $write_RshimSP2_path"
        ilog "write_uint64_with_prefix: $rc output: $(cat $log)"
        ilog "write_uint64_with_prefix: $file: $(hexdump -C $file)"
        ilog "write_uint64_with_prefix: prefix: $prefix"
        ilog "write_uint64_with_prefix: value: $value"
    fi
    /bin/rm -f $file $log $write_RshimSP2_path
}

is_mode_upgrade() {
    # SP2.BIT2
    if (( ($1 & 4 ) == 4 )); then
        return 0;
    else
        return 1;
    fi
}

is_mode_activate() {
    # SP2.BIT6
    if (( ($1 & 64 ) == 64 )); then
        return 0;
    else
        return 1;
    fi
}

is_mode_cancel() {
    # SP2.BIT7
    if (( ($1 & 128) == 128)); then
        return 0;
    else
        return 1;
    fi
}

set_upgrade_progress() {
    # bits 13, 14, 15
    # b000 - 0%, b001 - 20%, b010 - 40%, b011 - 60%, b100 - 80%, b101 - 100%
    local progress=$1
    local status=$2
    local percent
    local result
    local SP2
    SP2=$(read_SP2)
    result=$(( SP2 & progress_clear_mask ))
    result=$(( result & status_clear_mask ))
    if [ $progress -lt 100 ]; then
        percent=$(( progress / 20 ))
        [ $percent -lt 0 ] && percent=0
        result=$(( result | (IN_PROGRESS << 11) ))
    else
        percent=5
        if [ $status -eq 0 ]; then
            result=$(( result | (COMPLETED << 11) ))
        else
            result=$(( result | (FAILED << 11) ))
        fi
    fi

    result=$(( result | (percent << 13) ))
    ilog "set_upgrade_progress: $result"
    write_uint64_with_prefix "$result"
}
