| #!/bin/bash -e |
| |
| # Copyright (c) 2018 Amlogic, Inc. All rights reserved. |
| # |
| # This source code is subject to the terms and conditions defined in the |
| # file 'LICENSE' which is part of this source code package. |
| |
| #set -x |
| |
| VERSION=1.6 |
| |
| # Path to aml_encrypt_gxl |
| TOOL_PATH=$(dirname $(readlink -f $0)) |
| |
| SCRIPT_PATH=$(dirname $(readlink -f $0)) |
| |
| if [ -z "$EXTERNAL_ENCRYPT_PATH" ]; then |
| EXTERNAL_ENCRYPT_PATH=. |
| fi |
| |
| if [ -z "$PRIVATE_KEY_PATH" ]; then |
| PRIVATE_KEY_PATH=. |
| fi |
| |
| usage() { |
| cat << EOF |
| Usage: $(basename $0) --help |
| $(basename $0) --version |
| $(basename $0) --generate-efuse-pattern \\ |
| --soc [gxl | txlx | axg] \\ |
| [--root-hash rootkeys.hash] \\ |
| [--password-hash password.hash] \\ |
| [--aes-key aeskey.bin] \\ |
| [--enable-sb true] \\ |
| [--enable-aes true] \\ |
| [--enable-jtag-password true] \\ |
| [--enable-usb-password true] \\ |
| [--enable-scan-password true] \\ |
| [--enable-anti-rollback true] \\ |
| [--disable-boot-usb true] \\ |
| [--disable-boot-spi true] \\ |
| [--disable-boot-sdcard true] \\ |
| [--disable-boot-nand-emmc true] \\ |
| [--disable-boot-recover true] \\ |
| [--disable-scan-chain true] \\ |
| [--disable-print true] \\ |
| [--disable-jtag true] \\ |
| [--revoke-rsk-0 true] \\ |
| [--revoke-rsk-1 true] \\ |
| [--revoke-rsk-2 true] \\ |
| [--revoke-rsk-3 true] \\ |
| [--user-efuse-file <path-to-general-purpose-user-efuse-data>] \\ |
| [--key-hash-ver [1 | 2]] \\ |
| [--raw-otp-pattern true] \\ |
| -o pattern.efuse |
| |
| EOF |
| exit 1 |
| } |
| |
| check_file() { |
| if [ ! -f "$2" ]; then echo Error: Unable to open $1: \""$2"\"; exit 1 ; fi |
| } |
| |
| check_boolean() { |
| if [ "$2" != "true" ] && [ "$2" != "false" ]; then |
| echo Error: invalid value $1: \""$2"\" |
| exit 1 |
| fi |
| } |
| |
| # Pad file to len by adding 0's to end of file |
| # $1: file |
| # $2: len |
| pad_file() { |
| local file=$1 |
| local len=$2 |
| if [ ! -f "$1" ] || [ -z "$2" ]; then |
| echo "Argument error, \"$1\", \"$2\" " |
| exit 1 |
| fi |
| local filesize=$(wc -c < ${file}) |
| local padlen=$(( $len - $filesize )) |
| if [ $len -lt $filesize ]; then |
| echo "File larger than expected. $filesize, $len" |
| exit 1 |
| fi |
| dd if=/dev/zero of=$file oflag=append conv=notrunc bs=1 \ |
| count=$padlen >& /dev/null |
| } |
| |
| # $1: input |
| # $2: output |
| # $3: aes key file |
| # $4: aes iv file |
| internal_encrypt() { |
| local input=$1 |
| local output=$2 |
| local keyfile=$3 |
| local ivfile=$4 |
| if [ ! -f "$1" ] || [ -z "$2" ] || [ -z "$3" ] || [ -z "$4" ]; then |
| echo "Argument error" |
| exit 1 |
| fi |
| local key=$(xxd -p -c64 $keyfile) |
| local iv=$(xxd -p -c64 $ivfile) |
| local imagesize=$(wc -c < ${input}) |
| local rem=$(( $imagesize % 16 )) |
| if [ $rem -ne 0 ]; then |
| echo "Input $input not 16 byte aligned?" |
| exit 1 |
| fi |
| openssl enc -aes-256-cbc -K $key -iv $iv -e -in $input -out $output -nopad |
| } |
| |
| # $1: input |
| # $2: output |
| external_encrypt() { |
| local input=$1 |
| local output=$2 |
| if [ ! -f "$1" ] || [ -z "$2" ]; then |
| echo "Argument error, \"$1\", \"$2\" " |
| exit 1 |
| fi |
| local imagesize=$(wc -c < ${input}) |
| local rem=$(( $imagesize % 16 )) |
| if [ $rem -ne 0 ]; then |
| echo "Input $input not 16 byte aligned?" |
| exit 1 |
| fi |
| |
| echo Not implemented |
| #cp $input $output |
| exit 1 |
| } |
| |
| # Get key len in bytes of private PEM RSA key |
| # $1: PEM file |
| get_pem_key_len() { |
| local pem=$1 |
| local bits=0 |
| if [ ! -f "$1" ]; then |
| echo "Argument error, \"$1\"" |
| exit 1 |
| fi |
| bits=$(openssl rsa -in $pem -text -noout | \ |
| grep 'Private-Key: (' | \ |
| sed -r 's/(RSA )?Private-Key: \(//'| \ |
| sed -r 's/ bit(,.?[0-9].?primes)?\)//') |
| if [ "$bits" -ne 1024 ] && [ "$bits" -ne 2048 ] && |
| [ "$bits" -ne 4096 ] && [ "$bits" -ne 8192]; then |
| echo "Unexpected key size $bits" |
| exit 1 |
| fi |
| echo $(( $bits / 8 )) |
| } |
| |
| kwrap="" |
| wrlock_kwrap="false" |
| roothash="" |
| passwordhash="" |
| userefusefile="" |
| aeskey="" |
| enablesb="false" |
| enableaes="false" |
| enablejtagpassword="false" |
| enableusbpassword="false" |
| enablescanpassword="false" |
| enableantirollback="false" |
| disablebootusb="false" |
| disablebootspi="false" |
| disablebootsdcard="false" |
| disablebootnandemmc="false" |
| disablebootrecover="false" |
| disableprint="false" |
| disablejtag="false" |
| disablescanchain="false" |
| revokersk0="false" |
| revokersk1="false" |
| revokersk2="false" |
| revokersk3="false" |
| output="" |
| sigver="" |
| keyhashver="" |
| soc="gxl" |
| opt_raw_otp_pattern="false" |
| |
| # SBC option ONLY applicable to GXL |
| # Enabled automatically if SoC is GXL using this script |
| enablesbc="false" |
| |
| # FKC option ONLY applicable to GXL *AND* TXLX Rev-A |
| # FKC *MUST* use keyhash v2 in GXL and TXLX Rev-A |
| # FKC automatically enable SBC in GXL |
| enablefkc="false" |
| |
| generate_efuse_pattern() { |
| local argv=("$@") |
| local i=0 |
| |
| local patt=$(mktemp --tmpdir) |
| local license=$(mktemp --tmpdir) |
| local license2=$(mktemp --tmpdir) |
| local wrlock=$(mktemp --tmpdir) |
| |
| # Parse args |
| i=0 |
| while [ $i -lt $# ]; do |
| arg="${argv[$i]}" |
| #echo "i=$i arg=\"$arg\"" |
| i=$((i + 1)) |
| #echo "i=$i argv[$i]=${argv[$i]}" |
| case "$arg" in |
| --kwrap) |
| kwrap="${argv[$i]}" ;; |
| --root-hash) |
| roothash="${argv[$i]}" ;; |
| --password-hash) |
| passwordhash="${argv[$i]}" ;; |
| --aes-key) |
| aeskey="${argv[$i]}" ;; |
| --enable-sb) |
| enablesb="${argv[$i]}" ;; |
| --enable-aes) |
| enableaes="${argv[$i]}" ;; |
| --enable-jtag-password) |
| enablejtagpassword="${argv[$i]}" ;; |
| --enable-usb-password) |
| enableusbpassword="${argv[$i]}" ;; |
| --enable-scan-password) |
| enablescanpassword="${argv[$i]}" ;; |
| --enable-anti-rollback) |
| enableantirollback="${argv[$i]}" ;; |
| --disable-boot-usb) |
| disablebootusb="${argv[$i]}" ;; |
| --disable-boot-spi) |
| disablebootspi="${argv[$i]}" ;; |
| --disable-boot-sdcard) |
| disablebootsdcard="${argv[$i]}" ;; |
| --disable-boot-nand-emmc) |
| disablebootnandemmc="${argv[$i]}" ;; |
| --disable-boot-recover) |
| disablebootrecover="${argv[$i]}" ;; |
| --disable-print) |
| disableprint="${argv[$i]}" ;; |
| --disable-jtag) |
| disablejtag="${argv[$i]}" ;; |
| --disable-scan-chain) |
| disablescanchain="${argv[$i]}" ;; |
| --revoke-rsk-0) |
| revokersk0="${argv[$i]}" ;; |
| --revoke-rsk-1) |
| revokersk1="${argv[$i]}" ;; |
| --revoke-rsk-2) |
| revokersk2="${argv[$i]}" ;; |
| --revoke-rsk-3) |
| revokersk3="${argv[$i]}" ;; |
| --user-efuse-file) |
| userefusefile="${argv[$i]}" ;; |
| -o) |
| output="${argv[$i]}" ;; |
| --sig-ver) |
| sigver="${argv[$i]}" ;; |
| --key-hash-ver) |
| keyhashver="${argv[$i]}" ;; |
| --generate-efuse-pattern) |
| i=$((i - 1)) |
| ;; |
| --raw-otp-pattern) |
| opt_raw_otp_pattern="${argv[$i]}" ;; |
| --soc) |
| soc="${argv[$i]}" ;; |
| --soc-rev) |
| socrev="${argv[$i]}" ;; |
| *) |
| echo "Unknown option $arg"; exit 1 |
| ;; |
| esac |
| i=$((i + 1)) |
| done |
| |
| # Verify args |
| if [ -z "$output" ]; then echo Error: Missing output file option -o; exit 1; fi |
| |
| if [ -z "$sigver" ]; then |
| sigver=1 |
| fi |
| |
| if [ -z "$keyhashver" ]; then |
| keyhashver=1 |
| fi |
| |
| # Alias |
| if [ "$soc" == "a112" ]; then |
| soc=gxl |
| fi |
| |
| if [ "$soc" == "a113" ]; then |
| soc=axg |
| fi |
| if [ "$soc" == "s905d2" ]; then |
| soc=g12a |
| fi |
| |
| if [ "$soc" != "gxl" ] && [ "$soc" != "axg" ] && [ "$soc" != "txlx" ] && [ "$soc" != "g12a" ]; then |
| echo Error: invalid soc: \"$soc\" |
| exit 1 |
| fi |
| |
| # Starting from TXLX and AXG, only full key hash (v2) is supported |
| if [ "$soc" == "txlx" ] || [ "$soc" == "axg" ] || [ "$soc" == "g12a" ]; then |
| keyhashver=2 |
| fi |
| |
| if [ "$soc" == "gxl" ]; then |
| # Safe to enable SBC for *ALL* version of GXL |
| # SBC has no effect on pre-Rev-D GXL |
| enablesbc="true" |
| |
| # Keyhash v2 requires enable FKC in GXL |
| # FKC is *ONLY* available in GXL Rev-D or later |
| # Pre-Rev-D GXL should *NOT* use FKC |
| if [ $keyhashver -eq 2 ]; then |
| enablefkc="true" |
| fi |
| fi |
| |
| if [ "$soc" == "txlx" ]; then |
| if [ -z "$socver" ]; then |
| socver="b" |
| fi |
| |
| if [ "$socrev" == "a" ]; then |
| enablefkc="true" |
| fi |
| fi |
| |
| if [ "$kwrap" != "" ]; then |
| check_file kwrap "$kwrap" |
| filesize=$(wc -c < ${kwrap}) |
| if [ $filesize -ne 16 ]; then |
| echo "kwrap incorrect size $filesize != 16" |
| exit 1 |
| fi |
| wrlock_kwrap=true |
| fi |
| |
| check_boolean enable-sb "$enablesb" |
| check_boolean enable-aes "$enableaes" |
| check_boolean enable-jtag-password "$enablejtagpassword" |
| check_boolean enable-usb-password "$enableusbpassword" |
| check_boolean enable-jtag-password "$enablescanpassword" |
| check_boolean enable-anti-rollback "$enableantirollback" |
| check_boolean disable-boot-usb "$disablebootusb" |
| check_boolean disable-boot-spi "$disablebootspi" |
| check_boolean disable-boot-sdcard "$disablebootsdcard" |
| check_boolean disable-boot-nand-emmc "$disablebootnandemmc" |
| check_boolean disable-boot-recover "$disablebootrecover" |
| check_boolean disable-print "$disableprint" |
| check_boolean disable-jtag "$disablejtag" |
| check_boolean disable-scan-chain "$disablescanchain" |
| check_boolean revoke-rsk-0 "$revokersk0" |
| check_boolean revoke-rsk-1 "$revokersk1" |
| check_boolean revoke-rsk-2 "$revokersk2" |
| check_boolean revoke-rsk-3 "$revokersk3" |
| check_boolean fkc "$enablefkc" |
| check_boolean raw-otp-pattern "$opt_raw_otp_pattern" |
| |
| if [ "$roothash" != "" ]; then |
| check_file roothash "$roothash" |
| # Check size |
| local filesize=$(wc -c < ${roothash}) |
| if [ $filesize -ne 32 ]; then |
| echo "Root key hash incorrect size $filesize != 32" |
| exit 1 |
| fi |
| fi |
| if [ "$passwordhash" != "" ]; then |
| check_file passwordhash "$passwordhash" |
| # Check size |
| local filesize=$(wc -c < ${passwordhash}) |
| if [ $filesize -ne 32 ]; then |
| echo "Password key hash incorrect size $filesize != 32" |
| exit 1 |
| fi |
| fi |
| if [ "$aeskey" != "" ]; then |
| check_file aeskey "$aeskey" |
| filesize=$(wc -c < ${aeskey}) |
| if [ $filesize -ne 32 ]; then |
| echo "AES key incorrect size $filesize != 32" |
| exit 1 |
| fi |
| fi |
| |
| if [ "$soc" == "gxl" ] || [ "$soc" == "txlx" ]; then |
| generate_efuse_pattern_gxl |
| elif [ "$soc" == "g12a" ]; then |
| generate_efuse_pattern_g12a |
| else |
| generate_efuse_pattern_axg |
| fi |
| |
| rm -f $patt |
| rm -f $license |
| rm -f $license2 |
| rm -f $wrlock |
| } |
| |
| generate_efuse_pattern_gxl() { |
| echo -n "Generate OTP pattern for GXL (A112, S905X, S905D) ... " |
| |
| # Additional args check |
| if [ "$userefusefile" != "" ]; then |
| check_file userefusefile "$userefusefile" |
| local filesize=$(wc -c < ${userefusefile}) |
| if [ $filesize -ne 192 ]; then |
| echo "User efuse file incorrect size $filesize != 192" |
| exit 1 |
| fi |
| fi |
| |
| # Create input pattern |
| |
| # OTP write lock control |
| b_1b="00" |
| b_18="00" |
| b_19="00" |
| |
| # Construct license bits |
| b4="00" |
| if [ "$disablebootusb" == "true" ]; then |
| b4="$(printf %02x $(( 0x$b4 | 0x10 )))" |
| fi |
| if [ "$disablebootspi" == "true" ]; then |
| b4="$(printf %02x $(( 0x$b4 | 0x20 )))" |
| fi |
| if [ "$disablebootsdcard" == "true" ]; then |
| b4="$(printf %02x $(( 0x$b4 | 0x40 )))" |
| fi |
| if [ "$disablebootnandemmc" == "true" ]; then |
| b4="$(printf %02x $(( 0x$b4 | 0x80 )))" |
| fi |
| |
| b5="00" |
| if [ "$disablebootrecover" == "true" ]; then |
| b5="$(printf %02x $(( 0x$b5 | 0x01 )))" |
| fi |
| if [ "$disableprint" == "true" ]; then |
| b5="$(printf %02x $(( 0x$b5 | 0x02 )))" |
| fi |
| if [ "$disablejtag" == "true" ]; then |
| b5="$(printf %02x $(( 0x$b5 | 0x04 )))" |
| fi |
| if $revokersk0; then |
| b5="$(printf %02x $(( 0x$b5 | 0x10 )))" |
| fi |
| if $revokersk1; then |
| b5="$(printf %02x $(( 0x$b5 | 0x20 )))" |
| fi |
| if $revokersk2; then |
| b5="$(printf %02x $(( 0x$b5 | 0x40 )))" |
| fi |
| if $revokersk3; then |
| b5="$(printf %02x $(( 0x$b5 | 0x80 )))" |
| fi |
| |
| b6="00" |
| if [ "$enablesb" == "true" ]; then |
| b6="$(printf %02x $(( 0x$b6 | 0x04 )))" |
| fi |
| if [ "$enablescanpassword" == "true" ]; then |
| b6="$(printf %02x $(( 0x$b6 | 0x08 )))" |
| fi |
| if [ "$enablejtagpassword" == "true" ]; then |
| b6="$(printf %02x $(( 0x$b6 | 0x10 )))" |
| fi |
| |
| b7="00" |
| if [ "$enableaes" == "true" ]; then |
| b7="$(printf %02x $(( 0x$b7 | 0x10 )))" |
| fi |
| |
| b8="00" |
| if [ "$enableantirollback" == "true" ]; then |
| b8="$(printf %02x $(( 0x$b8 | 0x01 )))" |
| fi |
| if [ "$enableusbpassword" == "true" ]; then |
| b8="$(printf %02x $(( 0x$b8 | 0x02 )))" |
| fi |
| if [ "$enablesbc" == "true" ]; then |
| b8="$(printf %02x $(( 0x$b8 | 0x10 )))" |
| fi |
| if [ "$enablefkc" == "true" ]; then |
| b8="$(printf %02x $(( 0x$b8 | 0x30 )))" |
| fi |
| |
| b9="00" |
| if [ "$disablescanchain" == "true" ]; then |
| b9="$(printf %02x $(( 0x$b9 | 0x04 )))" |
| fi |
| |
| # Generate empty eFUSE pattern data |
| dd if=/dev/zero of=$patt count=512 bs=1 &> /dev/null |
| |
| # Create and write license block |
| if [ ${#b4} -ne 2 ] || [ ${#b5} -ne 2 ] || [ ${#b6} -ne 2 ] || [ ${#b7} -ne 2 ] || [ ${#b8} -ne 2 ] || [ ${#b9} -ne 2 ]; then |
| echo Internal Error |
| exit 1 |
| fi |
| |
| echo 00 00 00 00 $b4 $b5 $b6 $b7 $b8 $b9 00 00 00 00 00 00 | xxd -r -p > $license |
| filesize=$(wc -c < $license) |
| if [ $filesize -ne 16 ]; then |
| echo Internal Error -- Invalid license pattern length |
| exit 1 |
| fi |
| |
| dd if=$license of=$patt bs=1 seek=0 count=16 \ |
| conv=notrunc >& /dev/null |
| |
| if [ "$roothash" != "" ]; then |
| dd if=$roothash of=$patt bs=1 seek=48 count=32 \ |
| conv=notrunc >& /dev/null |
| #TODO lock root hash block |
| b_18="$(printf %02x $(( 0x$b_18 | 0x18 )))" |
| fi |
| |
| if [ "$aeskey" != "" ]; then |
| dd if=$aeskey of=$patt bs=1 seek=80 count=32 \ |
| conv=notrunc >& /dev/null |
| #TODO lock aes key block |
| b_18="$(printf %02x $(( 0x$b_18 | 0x60 )))" |
| fi |
| |
| if [ "$passwordhash" != "" ]; then |
| dd if=$passwordhash of=$patt bs=1 seek=128 count=32 \ |
| conv=notrunc >& /dev/null |
| #TODO lock jtag password hash block |
| b_19="$(printf %02x $(( 0x$b_19 | 0x03 )))" |
| fi |
| |
| if [ "$userefusefile" != "" ]; then |
| dd if=$userefusefile of=$patt bs=1 seek=320 count=192 \ |
| conv=notrunc >& /dev/null |
| fi |
| |
| # Write kwrap (in user data area) last |
| if [ "$kwrap" != "" ]; then |
| dd if=$kwrap of=$patt bs=1 seek=496 count=16 \ |
| conv=notrunc >& /dev/null |
| |
| if $wrlock_kwrap; then |
| b_1b="$(printf %02x $(( 0x$b_1b | 0x80 )))" |
| fi |
| fi |
| |
| # Create and write write-lock |
| if [ ${#b_1b} -ne 2 ]; then |
| echo Internal Error |
| exit 1 |
| fi |
| |
| echo 00 00 00 00 00 00 00 00 $b_18 $b_19 00 $b_1b 00 00 00 00 | xxd -r -p > $wrlock |
| filesize=$(wc -c < $wrlock) |
| if [ $filesize -ne 16 ]; then |
| echo Internal Error -- Invalid write-lock pattern length |
| exit 1 |
| fi |
| |
| dd if=$wrlock of=$patt bs=1 seek=16 count=16 \ |
| conv=notrunc >& /dev/null |
| |
| if [ "$opt_raw_otp_pattern" == "true" ]; then |
| cp $patt $output |
| else |
| ${TOOL_PATH}/aml_encrypt_gxl --efsgen3 --input $patt --output $output |
| fi |
| |
| echo "done" |
| } |
| |
| generate_efuse_pattern_axg() { |
| echo -n "Generate OTP pattern for AXG (A113) ... " |
| |
| # Additional args check |
| if [ "$userefusefile" != "" ]; then |
| check_file userefusefile "$userefusefile" |
| local filesize=$(wc -c < ${userefusefile}) |
| if [ $filesize -ne 16 ]; then |
| echo "User efuse file incorrect size $filesize != 16" |
| exit 1 |
| fi |
| fi |
| |
| if [ "$disablebootrecover" == "true" ]; then |
| echo Boot recovery is not supported on $soc, option ignored |
| fi |
| |
| # Create input pattern |
| |
| # OTP write lock control |
| b_b1="00" |
| |
| # Construct license bits |
| b5="00" |
| if [ "$disablebootusb" == "true" ]; then |
| b5="$(printf %02x $(( 0x$b5 | 0x01 )))" |
| fi |
| if [ "$disablebootspi" == "true" ]; then |
| b5="$(printf %02x $(( 0x$b5 | 0x02 )))" |
| fi |
| if [ "$disablebootsdcard" == "true" ]; then |
| b5="$(printf %02x $(( 0x$b5 | 0x04 )))" |
| fi |
| if [ "$disablebootnandemmc" == "true" ]; then |
| b5="$(printf %02x $(( 0x$b5 | 0x08 )))" |
| fi |
| if [ "$disableprint" == "true" ]; then |
| b5="$(printf %02x $(( 0x$b5 | 0x10 )))" |
| fi |
| if [ "$disablejtag" == "true" ]; then |
| b5="$(printf %02x $(( 0x$b5 | 0x20 )))" |
| fi |
| if [ "$enablejtagpassword" == "true" ]; then |
| b5="$(printf %02x $(( 0x$b5 | 0x40 )))" |
| fi |
| if [ "$enableusbpassword" == "true" ]; then |
| b5="$(printf %02x $(( 0x$b5 | 0x80 )))" |
| fi |
| |
| b6="00" |
| if [ "$enablesb" == "true" ]; then |
| b6="$(printf %02x $(( 0x$b6 | 0x01 )))" |
| fi |
| if [ "$enableaes" == "true" ]; then |
| b6="$(printf %02x $(( 0x$b6 | 0x02 )))" |
| fi |
| if $revokersk0; then |
| b6="$(printf %02x $(( 0x$b6 | 0x04 )))" |
| fi |
| if $revokersk1; then |
| b6="$(printf %02x $(( 0x$b6 | 0x08 )))" |
| fi |
| if $revokersk2; then |
| b6="$(printf %02x $(( 0x$b6 | 0x10 )))" |
| fi |
| if $revokersk3; then |
| b6="$(printf %02x $(( 0x$b6 | 0x20 )))" |
| fi |
| if [ "$enableantirollback" == "true" ]; then |
| b6="$(printf %02x $(( 0x$b6 | 0x80 )))" |
| fi |
| |
| b7="00" |
| if [ "$disablescanchain" == "true" ]; then |
| b7="$(printf %02x $(( 0x$b7 | 0x01 )))" |
| fi |
| if [ "$enablescanpassword" == "true" ]; then |
| b7="$(printf %02x $(( 0x$b7 | 0x02 )))" |
| fi |
| |
| # Generate empty eFUSE pattern data |
| dd if=/dev/zero of=$patt count=256 bs=1 &> /dev/null |
| |
| if [ "$roothash" != "" ]; then |
| dd if=$roothash of=$patt bs=1 seek=32 count=32 \ |
| conv=notrunc >& /dev/null |
| #TODO lock root hash block |
| fi |
| |
| if [ "$aeskey" != "" ]; then |
| dd if=$aeskey of=$patt bs=1 seek=64 count=32 \ |
| conv=notrunc >& /dev/null |
| #TODO lock aes key block |
| fi |
| |
| if [ "$passwordhash" != "" ]; then |
| dd if=$passwordhash of=$patt bs=1 seek=96 count=32 \ |
| conv=notrunc >& /dev/null |
| #TODO lock jtag password hash block |
| fi |
| |
| if [ "$userefusefile" != "" ]; then |
| dd if=$userefusefile of=$patt bs=1 seek=240 count=16 \ |
| conv=notrunc >& /dev/null |
| fi |
| |
| # Write kwrap (in user data area) last |
| if [ "$kwrap" != "" ]; then |
| dd if=$kwrap of=$patt bs=1 seek=240 count=16 \ |
| conv=notrunc >& /dev/null |
| |
| # Lock kwrap block |
| if $wrlock_kwrap; then |
| b_b1="$(printf %02x $(( 0x$b_b1 | 0x80 )))" |
| fi |
| fi |
| |
| # Create and write license (including write-lock) |
| if [ ${#b5} -ne 2 ] || [ ${#b6} -ne 2 ] || [ ${#b7} -ne 2 ] || [ ${#b_b1} -ne 2 ]; then |
| echo Internal Error |
| exit 1 |
| fi |
| |
| echo 00 $b_b1 00 00 00 $b5 $b6 $b7 00 00 00 00 00 00 00 00 | xxd -r -p > $license |
| filesize=$(wc -c < $license) |
| if [ $filesize -ne 16 ]; then |
| echo Internal Error -- Invalid license pattern length |
| exit 1 |
| fi |
| |
| dd if=$license of=$patt bs=1 seek=176 count=16 \ |
| conv=notrunc >& /dev/null |
| |
| if [ "$opt_raw_otp_pattern" == "true" ]; then |
| cp $patt $output |
| else |
| ${TOOL_PATH}/aml_encrypt_axg --efsproc --input $patt --output $output |
| fi |
| |
| echo "done" |
| } |
| |
| generate_efuse_pattern_g12a() { |
| echo -n "Generate OTP pattern for G12A (S905X2, S905D2) ... " |
| |
| # Additional args check |
| if [ "$userefusefile" != "" ]; then |
| check_file userefusefile "$userefusefile" |
| local filesize=$(wc -c < ${userefusefile}) |
| if [ $filesize -ne 96 ]; then |
| echo "User efuse file incorrect size $filesize != 96" |
| exit 1 |
| fi |
| fi |
| |
| # Create input pattern |
| |
| # OTP write lock control |
| b_b0="00" |
| b_b2="00" |
| b_b3="00" |
| |
| # Construct license bits |
| b_a3="00" |
| if [ "$disablejtag" == "true" ]; then |
| # Disable *ALL* JTAG (M3, M4, AP) in G12A |
| b_a3="$(printf %02x $(( 0x$b_a3 | 0x80 )))" |
| b_a3="$(printf %02x $(( 0x$b_a3 | 0x40 )))" |
| b_a3="$(printf %02x $(( 0x$b_a3 | 0x20 )))" |
| fi |
| |
| b_a2="00" |
| if [ "$disableprint" == "true" ]; then |
| b_a2="$(printf %02x $(( 0x$b_a2 | 0x40 )))" |
| fi |
| if [ "$disablebootusb" == "true" ]; then |
| b_a2="$(printf %02x $(( 0x$b_a2 | 0x20 )))" |
| fi |
| if [ "$disablebootspi" == "true" ]; then |
| b_a2="$(printf %02x $(( 0x$b_a2 | 0x10 )))" |
| fi |
| if [ "$disablebootsdcard" == "true" ]; then |
| b_a2="$(printf %02x $(( 0x$b_a2 | 0x08 )))" |
| fi |
| if [ "$disablebootnandemmc" == "true" ]; then |
| b_a2="$(printf %02x $(( 0x$b_a2 | 0x04 )))" |
| fi |
| if [ "$disablebootrecover" == "true" ]; then |
| b_a2="$(printf %02x $(( 0x$b_a2 | 0x02 )))" |
| fi |
| if [ "$disablescanchain" == "true" ]; then |
| b_a2="$(printf %02x $(( 0x$b_a2 | 0x01 )))" |
| fi |
| |
| b_a1="00" |
| if [ "$enableusbpassword" == "true" ]; then |
| b_a1="$(printf %02x $(( 0x$b_a1 | 0x02 )))" |
| fi |
| if [ "$enablejtagpassword" == "true" ]; then |
| b_a1="$(printf %02x $(( 0x$b_a1 | 0x01 )))" |
| fi |
| |
| b_a0="00" |
| if [ "$enablescanpassword" == "true" ]; then |
| b_a0="$(printf %02x $(( 0x$b_a0 | 0x80 )))" |
| fi |
| if [ "$enableantirollback" == "true" ]; then |
| b_a0="$(printf %02x $(( 0x$b_a0 | 0x40 )))" |
| fi |
| if [ "$enablesb" == "true" ]; then |
| # Enable both M3 and AP secure boot |
| b_a0="$(printf %02x $(( 0x$b_a0 | 0x01 )))" |
| b_a0="$(printf %02x $(( 0x$b_a0 | 0x04 )))" |
| fi |
| if [ "$enableaes" == "true" ]; then |
| # Enable both M3 and AP encryption |
| b_a0="$(printf %02x $(( 0x$b_a0 | 0x02 )))" |
| b_a0="$(printf %02x $(( 0x$b_a0 | 0x08 )))" |
| fi |
| |
| b_196="00" |
| if $revokersk0; then |
| b_196="$(printf %02x $(( 0x$b_196 | 0x10 )))" |
| fi |
| if $revokersk1; then |
| b_196="$(printf %02x $(( 0x$b_196 | 0x08 )))" |
| fi |
| if $revokersk2; then |
| b_196="$(printf %02x $(( 0x$b_196 | 0x04 )))" |
| fi |
| if $revokersk3; then |
| b_196="$(printf %02x $(( 0x$b_196 | 0x02 )))" |
| fi |
| |
| # Generate empty eFUSE pattern data |
| dd if=/dev/zero of=$patt count=512 bs=1 &> /dev/null |
| |
| # Create and write license block |
| if [ ${#b_a0} -ne 2 ] || [ ${#b_a1} -ne 2 ] || [ ${#b_a2} -ne 2 ] || [ ${#b_a3} -ne 2 ] || [ ${#b_196} -ne 2 ]; then |
| echo Internal Error |
| exit 1 |
| fi |
| |
| echo $b_a0 $b_a1 $b_a2 $b_a3 00 00 00 00 00 00 00 00 00 00 00 00 | xxd -r -p > $license |
| echo 00 00 00 00 00 00 $b_196 00 00 00 00 00 00 00 00 00 | xxd -r -p > $license2 |
| |
| filesize=$(wc -c < $license) |
| if [ $filesize -ne 16 ]; then |
| echo Internal Error -- Invalid license pattern length |
| exit 1 |
| fi |
| |
| filesize=$(wc -c < $license2) |
| if [ $filesize -ne 16 ]; then |
| echo Internal Error -- Invalid license pattern length |
| exit 1 |
| fi |
| |
| dd if=$license of=$patt bs=16 seek=10 count=1 \ |
| conv=notrunc >& /dev/null |
| |
| dd if=$license2 of=$patt bs=16 seek=25 count=1 \ |
| conv=notrunc >& /dev/null |
| |
| if [ "$roothash" != "" ]; then |
| dd if=$roothash of=$patt bs=16 seek=20 count=2 \ |
| conv=notrunc >& /dev/null |
| |
| # Lock root hash blocks |
| b_b2="$(printf %02x $(( 0x$b_b2 | 0x30 )))" |
| fi |
| |
| if [ "$aeskey" != "" ]; then |
| dd if=$aeskey of=$patt bs=16 seek=2 count=2 \ |
| conv=notrunc >& /dev/null |
| |
| # Lock aes key blocks |
| b_b0="$(printf %02x $(( 0x$b_b0 | 0x0c )))" |
| fi |
| |
| if [ "$passwordhash" != "" ]; then |
| dd if=$passwordhash of=$patt bs=16 seek=6 count=2 \ |
| conv=notrunc >& /dev/null |
| |
| # Lock jtag password hash blocks |
| b_b0="$(printf %02x $(( 0x$b_b0 | 0xc0 )))" |
| fi |
| |
| if [ "$userefusefile" != "" ]; then |
| dd if=$userefusefile of=$patt bs=16 seek=26 count=6 \ |
| conv=notrunc >& /dev/null |
| fi |
| |
| # Write kwrap (in user data area) last |
| if [ "$kwrap" != "" ]; then |
| dd if=$kwrap of=$patt bs=16 seek=31 count=1 \ |
| conv=notrunc >& /dev/null |
| |
| if $wrlock_kwrap; then |
| b_b3="$(printf %02x $(( 0x$b_b3 | 0x80 )))" |
| fi |
| fi |
| |
| # Create and write write-lock |
| if [ ${#b_b0} -ne 2 ] || [ ${#b_b2} -ne 2 ] || [ ${#b_b3} -ne 2 ]; then |
| echo Internal Error |
| exit 1 |
| fi |
| |
| echo $b_b0 00 $b_b2 $b_b3 00 00 00 00 00 00 00 00 00 00 00 00 | xxd -r -p > $wrlock |
| filesize=$(wc -c < $wrlock) |
| if [ $filesize -ne 16 ]; then |
| echo Internal Error -- Invalid write-lock pattern length |
| exit 1 |
| fi |
| dd if=$wrlock of=$patt bs=16 seek=11 count=1 conv=notrunc >& /dev/null |
| |
| if [ "$opt_raw_otp_pattern" == "true" ]; then |
| cp $patt $output |
| else |
| ${TOOL_PATH}/aml_encrypt_g12a --efsgen3 --input $patt --output $output |
| fi |
| |
| echo "done" |
| } |
| |
| parse_main() { |
| case "$@" in |
| --help) |
| usage |
| ;; |
| --version) |
| echo "$(basename $0) version $VERSION" |
| ;; |
| *-o*) |
| generate_efuse_pattern "$@" |
| ;; |
| *) |
| usage "$@" |
| ;; |
| esac |
| } |
| |
| parse_main "$@" |