# # Copyright (C) 2025 Amlogic, Inc. All rights reserved. # #!/bin/bash EXEC_BASEDIR=$(dirname $(readlink -f $0)) BASEDIR_TOP=$(readlink -f ${EXEC_BASEDIR}/..) VENDOR_KEYTOOL=${EXEC_BASEDIR}/../binary-tool/vendor-keytool # # Settings # VERSION=0.1 # Check file check_file() { if [ ! -f "$2" ]; then echo Error: Unable to open $1: \""$2"\"; exit 1 ; fi } # Check file is size or exit. $1: file, $2: size check_size() { local filesize=$(wc -c < "$1") if [ $filesize -ne $2 ]; then echo "Error: File \"$1\" incorrect size. Was $filesize, expected $2" exit 1 fi } # Check optional file argument exists and is given size # $1 arg name # $2 size # $3 file check_opt_file() { if [ -n "$3" ]; then check_file "$1" "$3" local filesize=$(wc -c < "$3") if [ $filesize -ne $2 ]; then echo "Incorrect size $filesize != $2 for $1 $3" exit 1 fi fi } check_opt_boolean() { if [ -n "$2" ]; then if [ "$2" != "true" ] && [ "$2" != "false" ]; then echo Error: invalid value $1: \""$2"\" exit 1 fi fi } usage() { cat << EOF Usage: $(basename $0) --help $(basename $0) --version $(basename $0) [--input base.efuse.bin] \\ [--dvuk dvuk.bin] \\ -o pattern.efuse EOF exit 1 } #typedef struct{ # unsigned int nMRKType; //RDVG,EDVG,RDVU,EDVU 0x47564452, 0x47564445 # unsigned char szReserved[12]; //reserved # unsigned char szTimeStamp[16]; # unsigned char szMRK[16]; # unsigned char szContent[32]; //80 #}t_mrk; #typedef struct{ # unsigned char szSHA2[32]; # unsigned int nMagic; //MRKT 0X544B524D # unsigned char byVer; //1 # unsigned char bySoC; //A1:0x2C; C1:0x30 # unsigned short nTotalSize; # unsigned char szReserved1[8]; # unsigned char szTimeUpdate[16]; # t_mrk arrMRK[4]; #}t_mrk_table; #define AML_MRK_TABLE_MAGIC (0x544B524D) #define AML_MRK_RDVGK_MAGIC (0x47564452) //raw DVGK #define AML_MRK_EDVGK_MAGIC (0x47564445) //encrypt DVGK #define AML_MRK_RDVUK_MAGIC (0x55564452) //raw DVUK #define AML_MRK_EDVGK_MAGIC (0x55564445) //encrypt DVUK #enum { # e_t_RDVGK = 0, # e_t_EDVGK, # e_t_RDVUK, # e_t_EDVUK, #}; append_uint32_le() { local input=$1 local output=$2 local v= local vrev= v=$(printf %08x $input) # 00010001 vrev=${v:6:2}${v:4:2}${v:2:2}${v:0:2} echo $vrev | xxd -r -p >> $output } append_uint16_le() { local input=$1 local output=$2 local v= local vrev= v=$(printf %04x $input) # 00010001 vrev=${v:2:2}${v:0:2} echo $vrev | xxd -r -p >> $output } function generate_efuse_device_pattern() { local argv=("$@") local i=0 local patt=$(mktemp --tmpdir) local wrlock=$(mktemp --tmpdir) local license0=$(mktemp --tmpdir) local efusebit=$(mktemp --tmpdir) local mrk_table=$(mktemp --tmpdir) local mrk_table_hdr=$(mktemp --tmpdir) local mrk_table_dvuk=$(mktemp --tmpdir) local mrk_table_sha=$(mktemp --tmpdir) local patt_final=$(mktemp --tmpdir) # Parse args while [ $i -lt $# ]; do arg="${argv[$i]}" #echo "i=$i argv[$i]=${argv[$i]}" i=$((i + 1)) case "$arg" in --input) input="${argv[$i]}" ;; -o) output="${argv[$i]}" ;; --dvuk) dvuk="${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 check_opt_file input 1024 "$input" check_opt_file dvuk 16 "$dvuk" # Generate empty eFUSE pattern data if [ -n "$input" ]; then dd if="$input" of=$patt count=256 bs=1 &> /dev/null dd if="$input" of=$mrk_table skip=256 bs=1 count=384 &> /dev/null else dd if=/dev/zero of=$patt count=256 bs=1 &> /dev/null dd if=/dev/urandom of=$mrk_table skip=256 bs=1 count=384 &> /dev/null fi dd if=/dev/zero of=$patt_final count=1024 bs=1 &> /dev/null # Construct wrlock bits b_1d=$(xxd -ps -s29 -l1 $patt) if [ "$dvuk" != "" ]; then # Create mrk_table # nMagic, byVer, bySoC, nTotalSize dd if=/dev/zero of=$mrk_table_hdr bs=1 count=32 conv=notrunc >& /dev/null append_uint32_le 0x544B524D $mrk_table_hdr echo 01 | xxd -r -p >> $mrk_table_hdr echo 2C | xxd -r -p >> $mrk_table_hdr append_uint16_le 384 $mrk_table_hdr dd if=/dev/urandom of=$mrk_table_hdr seek=40 bs=1 count=8 conv=notrunc &> /dev/null echo -n "$(date +%Y%m%d%H%M%S%S)" >> $mrk_table_hdr dd if=$mrk_table_hdr of=$mrk_table bs=1 count=64 conv=notrunc &> /dev/null append_uint32_le 0x55564452 $mrk_table_dvuk dd if=/dev/urandom of=$mrk_table_dvuk seek=4 bs=1 count=12 conv=notrunc &> /dev/null echo -n "$(date +%Y%m%d%H%M%S%S)" >> $mrk_table_dvuk dd if="$dvuk" of="$mrk_table_dvuk" bs=1 seek=32 count=16 conv=notrunc >& /dev/null dd if=/dev/urandom of=$mrk_table_dvuk seek=48 bs=1 count=32 conv=notrunc &> /dev/null dd if=$mrk_table_dvuk of=$mrk_table bs=1 seek=224 count=80 conv=notrunc &> /dev/null b_1d="$(printf %02x $(( 0x$b_1d | 0x08 )))" # Hash payload openssl dgst -sha256 -binary $mrk_table > $mrk_table_sha dd if=$mrk_table_sha of=$mrk_table bs=1 count=32 conv=notrunc &> /dev/null fi echo $b_1d | xxd -r -p > $efusebit dd if=$efusebit of=$patt bs=1 seek=29 count=1 conv=notrunc >& /dev/null dd if=$patt of=$patt_final bs=1 count=256 conv=notrunc >& /dev/null dd if=$mrk_table of=$patt_final bs=1 seek=256 count=384 conv=notrunc >& /dev/null ${EXEC_BASEDIR}/aml_encrypt_a1 --efsproc --input $patt_final --output $output --option=debug rm -f $patt rm -f $wrlock rm -f $license0 rm -f $efusebit rm -f $mrk_table rm -f $mrk_table_hdr rm -f $mrk_table_dvuk rm -f $mrk_table_sha rm -f $patt_final } parse_main() { case "$@" in --help) usage ;; --version) echo "$(basename $0) version $VERSION" ;; *-o*) generate_efuse_device_pattern "$@" ;; *) usage "$@" ;; esac } parse_main "$@"